void JV_SeedRoundKey( uint32_t *pdwRoundKey, // [out] round keys for encryption or decryption uint8_t *pbUserKey) // [in] secret user key { uint32_t A, B, C, D; // Iuput/output values at each rounds uint32_t T0, T1; // Temporary variable uint32_t *K = pdwRoundKey; // Pointer of round keys // Set up input values for Key Schedule A = ((uint32_t *)pbUserKey)[0]; B = ((uint32_t *)pbUserKey)[1]; C = ((uint32_t *)pbUserKey)[2]; D = ((uint32_t *)pbUserKey)[3]; // Reorder for big endian #ifndef BIG_ENDIAN A = EndianChange(A); B = EndianChange(B); C = EndianChange(C); D = EndianChange(D); #endif // i-th round keys( K_i,0 and K_i,1 ) are denoted as K[2*(i-1)] and K[2*i-1], respectively RoundKeyUpdate0(K, A, B, C, D, KC0 ); // K_1,0 and K_1,1 RoundKeyUpdate1(K+ 2, A, B, C, D, KC1 ); // K_2,0 and K_2,1 RoundKeyUpdate0(K+ 4, A, B, C, D, KC2 ); // K_3,0 and K_3,1 RoundKeyUpdate1(K+ 6, A, B, C, D, KC3 ); // K_4,0 and K_4,1 RoundKeyUpdate0(K+ 8, A, B, C, D, KC4 ); // K_5,0 and K_5,1 RoundKeyUpdate1(K+10, A, B, C, D, KC5 ); // K_6,0 and K_6,1 RoundKeyUpdate0(K+12, A, B, C, D, KC6 ); // K_7,0 and K_7,1 RoundKeyUpdate1(K+14, A, B, C, D, KC7 ); // K_8,0 and K_8,1 RoundKeyUpdate0(K+16, A, B, C, D, KC8 ); // K_9,0 and K_9,1 RoundKeyUpdate1(K+18, A, B, C, D, KC9 ); // K_10,0 and K_10,1 RoundKeyUpdate0(K+20, A, B, C, D, KC10); // K_11,0 and K_11,1 RoundKeyUpdate1(K+22, A, B, C, D, KC11); // K_12,0 and K_12,1 RoundKeyUpdate0(K+24, A, B, C, D, KC12); // K_13,0 and K_13,1 RoundKeyUpdate1(K+26, A, B, C, D, KC13); // K_14,0 and K_14,1 RoundKeyUpdate0(K+28, A, B, C, D, KC14); // K_15,0 and K_15,1 T0 = A + C - KC15; T1 = B - D + KC15; K[30] = SS0[GetB0(T0)] ^ SS1[GetB1(T0)] ^ // K_16,0 SS2[GetB2(T0)] ^ SS3[GetB3(T0)]; K[31] = SS0[GetB0(T1)] ^ SS1[GetB1(T1)] ^ // K_16,1 SS2[GetB2(T1)] ^ SS3[GetB3(T1)]; }
// Same as encrypt, except that round keys are applied in reverse order void JV_SeedDecrypt( uint8_t *pbData, // [in] data to be decrypted uint8_t *pbPlain, // [out] uint32_t *pdwRoundKey) // [in] round keys for decryption { uint32_t L0, L1, R0, R1; // Iuput/output values at each rounds uint32_t T0, T1; // Temporary variables for round function F uint32_t *K = pdwRoundKey; // Pointer of round keys // Set up input values for first round L0 = ((uint32_t *)pbData)[0]; L1 = ((uint32_t *)pbData)[1]; R0 = ((uint32_t *)pbData)[2]; R1 = ((uint32_t *)pbData)[3]; // Reorder for big endian #ifndef __BIG_ENDIAN__ L0 = EndianChange(L0); L1 = EndianChange(L1); R0 = EndianChange(R0); R1 = EndianChange(R1); #endif SeedRound(L0, L1, R0, R1, K+30); // Round 1 SeedRound(R0, R1, L0, L1, K+28); // Round 2 SeedRound(L0, L1, R0, R1, K+26); // Round 3 SeedRound(R0, R1, L0, L1, K+24); // Round 4 SeedRound(L0, L1, R0, R1, K+22); // Round 5 SeedRound(R0, R1, L0, L1, K+20); // Round 6 SeedRound(L0, L1, R0, R1, K+18); // Round 7 SeedRound(R0, R1, L0, L1, K+16); // Round 8 SeedRound(L0, L1, R0, R1, K+14); // Round 9 SeedRound(R0, R1, L0, L1, K+12); // Round 10 SeedRound(L0, L1, R0, R1, K+10); // Round 11 SeedRound(R0, R1, L0, L1, K+ 8); // Round 12 SeedRound(L0, L1, R0, R1, K+ 6); // Round 13 SeedRound(R0, R1, L0, L1, K+ 4); // Round 14 SeedRound(L0, L1, R0, R1, K+ 2); // Round 15 SeedRound(R0, R1, L0, L1, K+ 0); // Round 16 #ifndef __BIG_ENDIAN__ L0 = EndianChange(L0); L1 = EndianChange(L1); R0 = EndianChange(R0); R1 = EndianChange(R1); #endif // Copy output values from last round to pbData ((uint32_t *)pbPlain)[0] = R0; ((uint32_t *)pbPlain)[1] = R1; ((uint32_t *)pbPlain)[2] = L0; ((uint32_t *)pbPlain)[3] = L1; }
void SeedEncrypt ( BYTE *pbData, // [in,out] data to be encrypted DWORD *pdwRoundKey) // [in] round keys for encryption { DWORD L0, L1, R0, R1; // Iuput/output values at each rounds DWORD T0, T1; // Temporary variables for round function F DWORD *K = pdwRoundKey; // Pointer of round keys // Set up input values for first round L0 = ((DWORD *)pbData)[0]; L1 = ((DWORD *)pbData)[1]; R0 = ((DWORD *)pbData)[2]; R1 = ((DWORD *)pbData)[3]; // Reorder for big endian // Because SEED use little endian order in default #ifndef BIG_ENDIAN L0 = EndianChange(L0); L1 = EndianChange(L1); R0 = EndianChange(R0); R1 = EndianChange(R1); #endif SeedRound(L0, L1, R0, R1, K ); // Round 1 SeedRound(R0, R1, L0, L1, K+ 2); // Round 2 SeedRound(L0, L1, R0, R1, K+ 4); // Round 3 SeedRound(R0, R1, L0, L1, K+ 6); // Round 4 SeedRound(L0, L1, R0, R1, K+ 8); // Round 5 SeedRound(R0, R1, L0, L1, K+10); // Round 6 SeedRound(L0, L1, R0, R1, K+12); // Round 7 SeedRound(R0, R1, L0, L1, K+14); // Round 8 SeedRound(L0, L1, R0, R1, K+16); // Round 9 SeedRound(R0, R1, L0, L1, K+18); // Round 10 SeedRound(L0, L1, R0, R1, K+20); // Round 11 SeedRound(R0, R1, L0, L1, K+22); // Round 12 SeedRound(L0, L1, R0, R1, K+24); // Round 13 SeedRound(R0, R1, L0, L1, K+26); // Round 14 SeedRound(L0, L1, R0, R1, K+28); // Round 15 SeedRound(R0, R1, L0, L1, K+30); // Round 16 #ifndef BIG_ENDIAN L0 = EndianChange(L0); L1 = EndianChange(L1); R0 = EndianChange(R0); R1 = EndianChange(R1); #endif // Copying output values from last round to pbData ((DWORD *)pbData)[0] = R0; ((DWORD *)pbData)[1] = R1; ((DWORD *)pbData)[2] = L0; ((DWORD *)pbData)[3] = L1; }
// Calculate only one block void JV_SEED_CBC128_Decrypt_OneBlock(const uint8_t *in, uint8_t *out, const uint32_t *K, const uint8_t iv[16]) { DwordByte mid; uint32_t L0, L1, R0, R1; // Iuput/output values at each rounds uint32_t T0, T1; // Temporary variables for round function F // SEED Decipher L0 = ((uint32_t *) in)[0]; L1 = ((uint32_t *) in)[1]; R0 = ((uint32_t *) in)[2]; R1 = ((uint32_t *) in)[3]; #ifndef __BIG_ENDIAN__ L0 = EndianChange(L0); L1 = EndianChange(L1); R0 = EndianChange(R0); R1 = EndianChange(R1); #endif SeedRound(L0, L1, R0, R1, K+30); // Round 1 SeedRound(R0, R1, L0, L1, K+28); // Round 2 SeedRound(L0, L1, R0, R1, K+26); // Round 3 SeedRound(R0, R1, L0, L1, K+24); // Round 4 SeedRound(L0, L1, R0, R1, K+22); // Round 5 SeedRound(R0, R1, L0, L1, K+20); // Round 6 SeedRound(L0, L1, R0, R1, K+18); // Round 7 SeedRound(R0, R1, L0, L1, K+16); // Round 8 SeedRound(L0, L1, R0, R1, K+14); // Round 9 SeedRound(R0, R1, L0, L1, K+12); // Round 10 SeedRound(L0, L1, R0, R1, K+10); // Round 11 SeedRound(R0, R1, L0, L1, K+ 8); // Round 12 SeedRound(L0, L1, R0, R1, K+ 6); // Round 13 SeedRound(R0, R1, L0, L1, K+ 4); // Round 14 SeedRound(L0, L1, R0, R1, K+ 2); // Round 15 SeedRound(R0, R1, L0, L1, K+ 0); // Round 16 #ifndef __BIG_ENDIAN__ L0 = EndianChange(L0); L1 = EndianChange(L1); R0 = EndianChange(R0); R1 = EndianChange(R1); #endif mid.dword[0] = R0; mid.dword[1] = R1; mid.dword[2] = L0; mid.dword[3] = L1; // CBC - XOR for (size_t n = 0; n < 16; n++) out[n] = mid.byte[n] ^ iv[n]; }
// Calculate all blocks at once -> Serial Logic void JV_SEED_CBC128_Decrypt_Serial(const uint8_t *in, uint8_t *out, const size_t length, const uint32_t *K, const uint8_t iv[16]) { DwordByte mid; uint32_t L0, L1, R0, R1; // Iuput/output values at each rounds uint32_t T0, T1; // Temporary variables for round function F for (size_t i = 0; i < length; i += 16) { // SEED Decipher L0 = ((uint32_t *) (in + i))[0]; L1 = ((uint32_t *) (in + i))[1]; R0 = ((uint32_t *) (in + i))[2]; R1 = ((uint32_t *) (in + i))[3]; #ifndef __BIG_ENDIAN__ L0 = EndianChange(L0); L1 = EndianChange(L1); R0 = EndianChange(R0); R1 = EndianChange(R1); #endif SeedRound(L0, L1, R0, R1, K+30); // Round 1 SeedRound(R0, R1, L0, L1, K+28); // Round 2 SeedRound(L0, L1, R0, R1, K+26); // Round 3 SeedRound(R0, R1, L0, L1, K+24); // Round 4 SeedRound(L0, L1, R0, R1, K+22); // Round 5 SeedRound(R0, R1, L0, L1, K+20); // Round 6 SeedRound(L0, L1, R0, R1, K+18); // Round 7 SeedRound(R0, R1, L0, L1, K+16); // Round 8 SeedRound(L0, L1, R0, R1, K+14); // Round 9 SeedRound(R0, R1, L0, L1, K+12); // Round 10 SeedRound(L0, L1, R0, R1, K+10); // Round 11 SeedRound(R0, R1, L0, L1, K+ 8); // Round 12 SeedRound(L0, L1, R0, R1, K+ 6); // Round 13 SeedRound(R0, R1, L0, L1, K+ 4); // Round 14 SeedRound(L0, L1, R0, R1, K+ 2); // Round 15 SeedRound(R0, R1, L0, L1, K+ 0); // Round 16 #ifndef __BIG_ENDIAN__ L0 = EndianChange(L0); L1 = EndianChange(L1); R0 = EndianChange(R0); R1 = EndianChange(R1); #endif mid.dword[0] = R0; mid.dword[1] = R1; mid.dword[2] = L0; mid.dword[3] = L1; // CBC XOR if (i == 0) // 맨 처음에는 iv 사용 { for (uint8_t x = 0; x < 16 && x < length; x++) out[x] = mid.byte[x] ^ iv[x]; } else { for (uint8_t x = 0; x < 16 && x < length; x++) out[i + x] = mid.byte[x] ^ in[i - 16 + x]; } } }