void Serpent_KeySchedule(word32 *k, unsigned int rounds, const byte *userKey, size_t keylen) { FixedSizeSecBlock<word32, 8> k0; GetUserKey(LITTLE_ENDIAN_ORDER, k0.begin(), 8, userKey, keylen); if (keylen < 32) k0[keylen/4] |= word32(1) << ((keylen%4)*8); word32 t = k0[7]; unsigned int i; for (i = 0; i < 8; ++i) k[i] = k0[i] = t = rotlFixed(k0[i] ^ k0[(i+3)%8] ^ k0[(i+5)%8] ^ t ^ 0x9e3779b9 ^ i, 11); for (i = 8; i < 4*(rounds+1); ++i) k[i] = t = rotlFixed(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); k -= 20; word32 a,b,c,d,e; for (i=0; i<rounds/8; i++) { afterS2(LK); afterS2(S3); afterS3(SK); afterS1(LK); afterS1(S2); afterS2(SK); afterS0(LK); afterS0(S1); afterS1(SK); beforeS0(LK); beforeS0(S0); afterS0(SK); k += 8*4; afterS6(LK); afterS6(S7); afterS7(SK); afterS5(LK); afterS5(S6); afterS6(SK); afterS4(LK); afterS4(S5); afterS5(SK); afterS3(LK); afterS3(S4); afterS4(SK); } afterS2(LK); afterS2(S3); afterS3(SK); }
void serpent_encrypt(const unsigned __int8 *inBlock, unsigned __int8 *outBlock, unsigned __int8 *ks) { unsigned __int32 a, b, c, d, e; unsigned int i=1; const unsigned __int32 *k = (unsigned __int32 *)ks + 8; unsigned __int32 *in = (unsigned __int32 *) inBlock; unsigned __int32 *out = (unsigned __int32 *) outBlock; a = LE32(in[0]); b = LE32(in[1]); c = LE32(in[2]); d = LE32(in[3]); do { beforeS0(KX); beforeS0(S0); afterS0(LT); afterS0(KX); afterS0(S1); afterS1(LT); afterS1(KX); afterS1(S2); afterS2(LT); afterS2(KX); afterS2(S3); afterS3(LT); afterS3(KX); afterS3(S4); afterS4(LT); afterS4(KX); afterS4(S5); afterS5(LT); afterS5(KX); afterS5(S6); afterS6(LT); afterS6(KX); afterS6(S7); if (i == 4) break; ++i; c = b; b = e; e = d; d = a; a = e; k += 32; beforeS0(LT); } while (1); afterS7(KX); out[0] = LE32(d); out[1] = LE32(e); out[2] = LE32(b); out[3] = LE32(a); }
void serpent_set_key(const unsigned __int8 userKey[], int keylen, unsigned __int8 *ks) { unsigned __int32 a,b,c,d,e; unsigned __int32 *k = (unsigned __int32 *)ks; unsigned __int32 t; int i; for (i = 0; i < keylen / (int)sizeof(__int32); i++) k[i] = LE32(((unsigned __int32*)userKey)[i]); if (keylen < 32) k[keylen/4] |= (unsigned __int32)1 << ((keylen%4)*8); k += 8; t = k[-1]; for (i = 0; i < 132; ++i) k[i] = t = rotlFixed(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); k -= 20; #define LK(r, a, b, c, d, e) {\ a = k[(8-r)*4 + 0]; \ b = k[(8-r)*4 + 1]; \ c = k[(8-r)*4 + 2]; \ d = k[(8-r)*4 + 3];} #define SK(r, a, b, c, d, e) {\ k[(8-r)*4 + 4] = a; \ k[(8-r)*4 + 5] = b; \ k[(8-r)*4 + 6] = c; \ k[(8-r)*4 + 7] = d;} \ for (i=0; i<4; i++) { afterS2(LK); afterS2(S3); afterS3(SK); afterS1(LK); afterS1(S2); afterS2(SK); afterS0(LK); afterS0(S1); afterS1(SK); beforeS0(LK); beforeS0(S0); afterS0(SK); k += 8*4; afterS6(LK); afterS6(S7); afterS7(SK); afterS5(LK); afterS5(S6); afterS6(SK); afterS4(LK); afterS4(S5); afterS5(SK); afterS3(LK); afterS3(S4); afterS4(SK); } afterS2(LK); afterS2(S3); afterS3(SK); }
void Serpent::Base::UncheckedSetKey(const byte *userKey, unsigned int keylen, const NameValuePairs &) { AssertValidKeyLength(keylen); word32 *k = m_key; GetUserKey(LITTLE_ENDIAN_ORDER, k, 8, userKey, keylen); if (keylen < 32) k[keylen/4] |= word32(1) << ((keylen%4)*8); k += 8; word32 t = k[-1]; signed int i; for (i = 0; i < 132; ++i) k[i] = t = rotlFixed(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); k -= 20; #define LK(r, a, b, c, d, e) {\ a = k[(8-r)*4 + 0]; \ b = k[(8-r)*4 + 1]; \ c = k[(8-r)*4 + 2]; \ d = k[(8-r)*4 + 3];} #define SK(r, a, b, c, d, e) {\ k[(8-r)*4 + 4] = a; \ k[(8-r)*4 + 5] = b; \ k[(8-r)*4 + 6] = c; \ k[(8-r)*4 + 7] = d;} \ word32 a,b,c,d,e; for (i=0; i<4; i++) { afterS2(LK); afterS2(S3); afterS3(SK); afterS1(LK); afterS1(S2); afterS2(SK); afterS0(LK); afterS0(S1); afterS1(SK); beforeS0(LK); beforeS0(S0); afterS0(SK); k += 8*4; afterS6(LK); afterS6(S7); afterS7(SK); afterS5(LK); afterS5(S6); afterS6(SK); afterS4(LK); afterS4(S5); afterS5(SK); afterS3(LK); afterS3(S4); afterS4(SK); } afterS2(LK); afterS2(S3); afterS3(SK); }
void serpent_encrypt_block(block128_t* block, uint32_t* subkey) { //char* function_name = "serpent_encrypt_block()"; //exception_t* exception; uint32_t a, b, c, d, e; int j; // Change to little endian. a = mirror_bytes32(block->x0); b = mirror_bytes32(block->x1); c = mirror_bytes32(block->x2); d = mirror_bytes32(block->x3); // Do the actual encryption. j = 1; do { beforeS0(KX); beforeS0(S0); afterS0(linear_transformation); afterS0(KX); afterS0(S1); afterS1(linear_transformation); afterS1(KX); afterS1(S2); afterS2(linear_transformation); afterS2(KX); afterS2(S3); afterS3(linear_transformation); afterS3(KX); afterS3(S4); afterS4(linear_transformation); afterS4(KX); afterS4(S5); afterS5(linear_transformation); afterS5(KX); afterS5(S6); afterS6(linear_transformation); afterS6(KX); afterS6(S7); if (j == 4) break; ++j; c = b; b = e; e = d; d = a; a = e; subkey += 32; beforeS0(linear_transformation); } while (1); afterS7(KX); // Restore to big endian. block->x0 = mirror_bytes32(d); block->x1 = mirror_bytes32(e); block->x2 = mirror_bytes32(b); block->x3 = mirror_bytes32(a); }
void Serpent::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const { word32 a, b, c, d, e; Block::Get(inBlock)(a)(b)(c)(d); const word32 *k = m_key; unsigned int i=1; do { beforeS0(KX); beforeS0(S0); afterS0(LT); afterS0(KX); afterS0(S1); afterS1(LT); afterS1(KX); afterS1(S2); afterS2(LT); afterS2(KX); afterS2(S3); afterS3(LT); afterS3(KX); afterS3(S4); afterS4(LT); afterS4(KX); afterS4(S5); afterS5(LT); afterS5(KX); afterS5(S6); afterS6(LT); afterS6(KX); afterS6(S7); if (i == 4) break; ++i; c = b; b = e; e = d; d = a; a = e; k += 32; beforeS0(LT); } while (true); afterS7(KX); Block::Put(xorBlock, outBlock)(d)(e)(b)(a); }
exception_t* serpent_init_subkey(key256_t* user_key, uint32_t** subkey) { char* function_name = "serpent_init_subkey()"; const int PREKEY_SIZE = 140; exception_t* exception; uint32_t* genkey; uint32_t a, b, c, d, e; // Validate parameters. #ifdef DEBUG_SERPENT if ( user_key == NULL ) { return exception_throw("user_key was NULL.", function_name); } if ( subkey == NULL ) { return exception_throw("subkey was NULL.", function_name); } #endif // Allocate space for genkey. genkey = (uint32_t*)malloc(sizeof(uint32_t) * PREKEY_SIZE); if ( genkey == NULL ) { return exception_throw("Unable to allocate genkey.", function_name); } // Assign user_key to the genkey; making sure to properly little-endianized the user key. for ( int i = 0; i < 8; i++ ) { uint32_t word; // Get the key value. exception = key256_get_word(user_key, i, &word); if ( exception != NULL ) { return exception_append(exception, function_name); } // Endianize the key value. word = mirror_bytes32(word); // Set the key value. genkey[i] = word; } // Generate the prekey by the following affine recurrence. genkey += 8; uint32_t t = genkey[-1]; for ( int i = 0; i < 132; ++i ) { genkey[i] = t = rotl_fixed(genkey[i-8] ^ genkey[i-5] ^ genkey[i-3] ^ t ^ 0x9E3779B9 ^ i, 11); } genkey -= 20; #define LK(r, a, b, c, d, e) {\ a = genkey[(8-r)*4 + 0]; \ b = genkey[(8-r)*4 + 1]; \ c = genkey[(8-r)*4 + 2]; \ d = genkey[(8-r)*4 + 3];} #define SK(r, a, b, c, d, e) {\ genkey[(8-r)*4 + 4] = a; \ genkey[(8-r)*4 + 5] = b; \ genkey[(8-r)*4 + 6] = c; \ genkey[(8-r)*4 + 7] = d;} \ // Generare the subkey using the prekey. for ( int i = 0; i < 4 ; i++ ) { afterS2(LK); afterS2(S3); afterS3(SK); afterS1(LK); afterS1(S2); afterS2(SK); afterS0(LK); afterS0(S1); afterS1(SK); beforeS0(LK); beforeS0(S0); afterS0(SK); genkey += 8*4; afterS6(LK); afterS6(S7); afterS7(SK); afterS5(LK); afterS5(S6); afterS6(SK); afterS4(LK); afterS4(S5); afterS5(SK); afterS3(LK); afterS3(S4); afterS4(SK); } afterS2(LK); afterS2(S3); afterS3(SK); genkey -= 108; // Assign output parameter. (*subkey) = genkey; // Return success. return NULL; }