Loading ccsrc/Externals/NG_security_ext.cc +183 −119 File changed.Preview size limit exceeded, changes collapsed. Show changes ccsrc/Externals/ia3_128.cc +134 −90 Original line number Diff line number Diff line Loading @@ -23,28 +23,28 @@ namespace { constexpr size_t IV_SIZE = 16; // Initialization vector size } uint32_t ia3_128::LFSR_S0 = 0; uint32_t ia3_128::LFSR_S1 = 0; uint32_t ia3_128::LFSR_S2 = 0; uint32_t ia3_128::LFSR_S3 = 0; uint32_t ia3_128::LFSR_S4 = 0; uint32_t ia3_128::LFSR_S5 = 0; uint32_t ia3_128::LFSR_S6 = 0; uint32_t ia3_128::LFSR_S7 = 0; uint32_t ia3_128::LFSR_S8 = 0; uint32_t ia3_128::LFSR_S9 = 0; uint32_t ia3_128::LFSR_S10 = 0; uint32_t ia3_128::LFSR_S11 = 0; uint32_t ia3_128::LFSR_S12 = 0; uint32_t ia3_128::LFSR_S13 = 0; uint32_t ia3_128::LFSR_S14 = 0; uint32_t ia3_128::LFSR_S15 = 0; uint32_t ia3_128::F_R1 = 0; uint32_t ia3_128::F_R2 = 0; uint32_t ia3_128::BRC_X0 = 0; uint32_t ia3_128::BRC_X1 = 0; uint32_t ia3_128::BRC_X2 = 0; uint32_t ia3_128::BRC_X3 = 0; uint32_t ia3_128::lfsr_s0 = 0; uint32_t ia3_128::lfsr_s1 = 0; uint32_t ia3_128::lfsr_s2 = 0; uint32_t ia3_128::lfsr_s3 = 0; uint32_t ia3_128::lfsr_s4 = 0; uint32_t ia3_128::lfsr_s5 = 0; uint32_t ia3_128::lfsr_s6 = 0; uint32_t ia3_128::lfsr_s7 = 0; uint32_t ia3_128::lfsr_s8 = 0; uint32_t ia3_128::lfsr_s9 = 0; uint32_t ia3_128::lfsr_s10 = 0; uint32_t ia3_128::lfsr_s11 = 0; uint32_t ia3_128::lfsr_s12 = 0; uint32_t ia3_128::lfsr_s13 = 0; uint32_t ia3_128::lfsr_s14 = 0; uint32_t ia3_128::lfsr_s15 = 0; uint32_t ia3_128::f_r1 = 0; uint32_t ia3_128::f_r2 = 0; uint32_t ia3_128::brc_x0 = 0; uint32_t ia3_128::brc_x1 = 0; uint32_t ia3_128::brc_x2 = 0; uint32_t ia3_128::brc_x3 = 0; int ia3_128::encrypt(const uint8_t algo_id, const unsigned char* knas_enc, Loading Loading @@ -105,103 +105,147 @@ int ia3_128::decrypt(const uint8_t algo_id, cyphered, cyphered_length, payload, payload_length); } void ia3_128::zuc_eea3(const uint8_t* CK, const uint32_t COUNT, const uint32_t BEARER, const uint32_t DIRECTION, const uint32_t LENGTH, const uint8_t* M, uint8_t* C) { loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: knas_enc", CK, KEY_SIZE); loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: payload", M, LENGTH / 8); loggers::get_instance().log(">>> ia3_128::zuc_eea3: count: %u", COUNT); loggers::get_instance().log(">>> ia3_128::zuc_eea3: bearer: %d", BEARER); loggers::get_instance().log(">>> ia3_128::zuc_eea3: direction: %d", DIRECTION); int ia3_128::mac(const uint8_t algo_id, const unsigned char* knas_int, const uint32_t count, const uint8_t bearer, const uint8_t direction, const unsigned char* payload, const uint32_t payload_length, unsigned char** mac, uint32_t* mac_length) { loggers::get_instance().log_to_hexa(">>> ia3_128::mac: knas_int", knas_int, KEY_SIZE); loggers::get_instance().log(">>> ia3_128::mac: payload_length: %d", payload_length); loggers::get_instance().log_to_hexa(">>> ia3_128::mac: payload", payload, payload_length); loggers::get_instance().log(">>> ia3_128::mac: algo_id: %d", algo_id); loggers::get_instance().log(">>> ia3_128::mac: count: %u", count); loggers::get_instance().log(">>> ia3_128::mac: bearer: %d", bearer); loggers::get_instance().log(">>> ia3_128::mac: direction: %d", direction); // Input validation if (!knas_int || !payload || !mac || !mac_length) { loggers::get_instance().error("ia3_128::mac: Wrong input parameters"); return -1; } if (payload_length == 0) { loggers::get_instance().error("ia3_128::mac: Wrong payload length"); *mac = nullptr; *mac_length = 0; return 0; } uint32_t *z, L, L8, i; uint8_t IV[KEY_SIZE]; uint32_t lastbits = (8-(LENGTH%8))%8; // Allocate memory for ciphertext *mac = static_cast<unsigned char*>(std::malloc(4)); if (!*mac) { loggers::get_instance().error("ia3_128::mac: Failed to allocate memory"); return -1; } *mac_length = 4; uint32_t wmac = 0; zuc_eia3(knas_int, count, bearer, direction, payload_length * 8, payload, &wmac); (*mac)[0] = (wmac >> 24) & 0xFF; (*mac)[1] = (wmac >> 16) & 0xFF; (*mac)[2] = (wmac >> 8) & 0xFF; (*mac)[3] = wmac & 0xFF; loggers::get_instance().log_to_hexa("ia3_128::mac: mac: ", *mac, *mac_length); loggers::get_instance().log("<<< ia3_128::mac: ret: 0"); return 0; } L = (LENGTH+31)/32; z = static_cast<uint32_t*>(std::malloc(L*sizeof(uint32_t))); void ia3_128::zuc_eea3(const uint8_t* p_knas_enc, const uint32_t count, const uint32_t bearer, const uint32_t direction, const uint32_t payload_length, const uint8_t* payload, uint8_t* ciphered) { loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: knas_enc", p_knas_enc, KEY_SIZE); loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: payload", payload, payload_length / 8); loggers::get_instance().log(">>> ia3_128::zuc_eea3: count: %u", count); loggers::get_instance().log(">>> ia3_128::zuc_eea3: bearer: %d", bearer); loggers::get_instance().log(">>> ia3_128::zuc_eea3: direction: %d", direction); uint32_t *z, lenght, lenght_in_bytes, i; uint8_t iv[KEY_SIZE]; uint32_t lastbits = (8-(payload_length%8))%8; L8 = (LENGTH+7)/8; lenght = (payload_length+31)/32; z = static_cast<uint32_t*>(std::malloc(lenght*sizeof(uint32_t))); IV[0] = (COUNT>>24) & 0xFF; IV[1] = (COUNT>>16) & 0xFF; IV[2] = (COUNT>>8) & 0xFF; IV[3] = COUNT & 0xFF; IV[4] = ((BEARER << 3) | ((DIRECTION&1)<<2)) & 0xFC; IV[5] = 0; IV[6] = 0; IV[7] = 0; lenght_in_bytes = (payload_length+7)/8; IV[8] = IV[0]; IV[9] = IV[1]; IV[10] = IV[2]; IV[11] = IV[3]; iv[0] = (count>>24) & 0xFF; iv[1] = (count>>16) & 0xFF; iv[2] = (count>>8) & 0xFF; iv[3] = count & 0xFF; IV[12] = IV[4]; IV[13] = IV[5]; IV[14] = IV[6]; IV[15] = IV[7]; loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: IV", IV, KEY_SIZE); iv[4] = ((bearer << 3) | ((direction&1)<<2)) & 0xFC; iv[5] = 0; iv[6] = 0; iv[7] = 0; ZUC(CK, IV, z, L); loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: z", (uint8_t*)z, L*sizeof(uint32_t)); iv[8] = iv[0]; iv[9] = iv[1]; iv[10] = iv[2]; iv[11] = iv[3]; for (i=0; i<L8; i++) { C[i] = M[i] ^ ((z[i/4] >> (3-i%4)*8) & 0xff); } iv[12] = iv[4]; iv[13] = iv[5]; iv[14] = iv[6]; iv[15] = iv[7]; loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: iv", iv, KEY_SIZE); /* * Issues #3349 * Valgrind memcheck: Invalid read & write: Add {}. */ zuc(p_knas_enc, iv, z, lenght); loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: z", (uint8_t*)z, lenght*sizeof(uint32_t)); for (i=0; i<lenght_in_bytes; i++) { ciphered[i] = payload[i] ^ ((z[i/4] >> (3-i%4)*8) & 0xff); } /* zero last bits of data in case its length is not word-aligned (32 bits) this is an addition to the C reference code, which did not handle it */ this is an addition to the ciphered reference code, which did not handle it */ if (lastbits) { i--; C[i] &= 0x100 - (1<<lastbits); ciphered[i] &= 0x100 - (1<<lastbits); } loggers::get_instance().log_to_hexa("ia3_128::zuc_eea3: C", C, LENGTH / 8); loggers::get_instance().log_to_hexa("ia3_128::zuc_eea3: ciphered", ciphered, payload_length / 8); std::free(z); } void ia3_128::zuc_eia3(const uint8_t* IK, const uint32_t COUNT, const uint32_t BEARER, const uint32_t DIRECTION, const uint32_t LENGTH, const uint8_t* M, uint32_t* MAC) { uint32_t *z, N, L, T, i; uint8_t IV[16]; void ia3_128::zuc_eia3(const uint8_t* p_knas_int, const uint32_t count, const uint32_t bearer, const uint32_t direction, const uint32_t payload_length, const uint8_t* payload, uint32_t* mac) { uint32_t *z, N, lenght, T, i; uint8_t iv[16]; IV[0] = (COUNT>>24) & 0xFF; IV[1] = (COUNT>>16) & 0xFF; IV[2] = (COUNT>>8) & 0xFF; IV[3] = COUNT & 0xFF; iv[0] = (count>>24) & 0xFF; iv[1] = (count>>16) & 0xFF; iv[2] = (count>>8) & 0xFF; iv[3] = count & 0xFF; IV[4] = (BEARER << 3) & 0xF8; IV[5] = IV[6] = IV[7] = 0; iv[4] = (bearer << 3) & 0xF8; iv[5] = iv[6] = iv[7] = 0; IV[8] = ((COUNT>>24) & 0xFF) ^ ((DIRECTION&1)<<7); IV[9] = (COUNT>>16) & 0xFF; IV[10] = (COUNT>>8) & 0xFF; IV[11] = COUNT & 0xFF; iv[8] = ((count>>24) & 0xFF) ^ ((direction&1)<<7); iv[9] = (count>>16) & 0xFF; iv[10] = (count>>8) & 0xFF; iv[11] = count & 0xFF; IV[12] = IV[4]; IV[13] = IV[5]; IV[14] = IV[6] ^ ((DIRECTION&1)<<7); IV[15] = IV[7]; iv[12] = iv[4]; iv[13] = iv[5]; iv[14] = iv[6] ^ ((direction&1)<<7); iv[15] = iv[7]; N = LENGTH + 64; L = (N + 31) / 32; z = static_cast<uint32_t*>(std::malloc(L*sizeof(uint32_t))); N = payload_length + 64; lenght = (N + 31) / 32; z = static_cast<uint32_t*>(std::malloc(lenght*sizeof(uint32_t))); ZUC(IK, IV, z, L); zuc(p_knas_int, iv, z, lenght); T = 0; for (i=0; i<LENGTH; i++) { if (GET_BIT(M,i)) { T ^= GET_WORD(z,i); for (i=0; i<payload_length; i++) { if (get_bit(payload,i)) { T ^= get_word(z,i); } } T ^= GET_WORD(z,LENGTH); T ^= get_word(z,payload_length); *MAC = T ^ z[L-1]; *mac = T ^ z[lenght-1]; std::free(z); } ccsrc/Externals/ia3_128.hh +164 −135 Original line number Diff line number Diff line Loading @@ -114,8 +114,37 @@ public: unsigned char** payload, uint32_t* payload_length); /** * @brief Compute NAS integrity protection using ZUC algorithm * * This method computes the integrity protection using the ZUC stream cipher. * * @param algo_id Algorithm identifier (should be 3 for ZUC) * @param knas_enc Pointer to the 16-byte NAS encryption key * @param count 32-bit NAS count value * @param bearer 5-bit bearer identifier (only lower 5 bits are used) * @param direction Direction bit (0 = uplink, 1 = downlink) * @param cyphered Pointer to the ciphertext data to decrypt * @param cyphered_length Length of the ciphertext data in bytes * @param payload Pointer to pointer that will receive the decrypted data (caller must free) * @param payload_length Pointer to variable that will receive the decrypted data length * @return 0 on success, negative value on error * * @note The caller is responsible for freeing the memory allocated for payload * @note payload_length will be equal to cyphered_length for stream ciphers */ int mac(const uint8_t algo_id, const unsigned char* knas_int, const uint32_t count, const uint8_t bearer, const uint8_t direction, const unsigned char* payload, const uint32_t payload_length, unsigned char** cyphered, uint32_t* cyphered_length); private: const uint8_t S0[256] = { const uint8_t s0[256] = { 0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb, 0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90, 0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac, Loading @@ -134,7 +163,7 @@ private: 0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60 }; const uint8_t S1[256] = { const uint8_t s1[256] = { 0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77, 0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42, 0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1, Loading @@ -160,32 +189,32 @@ private: }; /* the state registers of LFSR */ static uint32_t LFSR_S0; static uint32_t LFSR_S1; static uint32_t LFSR_S2; static uint32_t LFSR_S3; static uint32_t LFSR_S4; static uint32_t LFSR_S5; static uint32_t LFSR_S6; static uint32_t LFSR_S7; static uint32_t LFSR_S8; static uint32_t LFSR_S9; static uint32_t LFSR_S10; static uint32_t LFSR_S11; static uint32_t LFSR_S12; static uint32_t LFSR_S13; static uint32_t LFSR_S14; static uint32_t LFSR_S15; static uint32_t lfsr_s0; static uint32_t lfsr_s1; static uint32_t lfsr_s2; static uint32_t lfsr_s3; static uint32_t lfsr_s4; static uint32_t lfsr_s5; static uint32_t lfsr_s6; static uint32_t lfsr_s7; static uint32_t lfsr_s8; static uint32_t lfsr_s9; static uint32_t lfsr_s10; static uint32_t lfsr_s11; static uint32_t lfsr_s12; static uint32_t lfsr_s13; static uint32_t lfsr_s14; static uint32_t lfsr_s15; /* the registers of F */ static uint32_t F_R1; static uint32_t F_R2; static uint32_t f_r1; static uint32_t f_r2; /* the outputs of BitReorganization */ static uint32_t BRC_X0; static uint32_t BRC_X1; static uint32_t BRC_X2; static uint32_t BRC_X3; /* the outputs of bit_reorganization */ static uint32_t brc_x0; static uint32_t brc_x1; static uint32_t brc_x2; static uint32_t brc_x3; /* c = a + b mod (2^31 - 1) */ inline uint32_t AddM(uint32_t a, uint32_t b) { Loading @@ -195,83 +224,83 @@ private: /* LFSR with initialization mode */ #define MulByPow2(x, k) ((((x) << k) | ((x) >> (31 - k))) & 0x7FFFFFFF) inline void LFSRWithInitialisationMode(uint32_t u) { inline void lfsr_with_initialisation_mode(uint32_t u) { uint32_t f, v; f = LFSR_S0; f = lfsr_s0; v = MulByPow2(LFSR_S0, 8); v = MulByPow2(lfsr_s0, 8); f = AddM(f, v); v = MulByPow2(LFSR_S4, 20); v = MulByPow2(lfsr_s4, 20); f = AddM(f, v); v = MulByPow2(LFSR_S10, 21); v = MulByPow2(lfsr_s10, 21); f = AddM(f, v); v = MulByPow2(LFSR_S13, 17); v = MulByPow2(lfsr_s13, 17); f = AddM(f, v); v = MulByPow2(LFSR_S15, 15); v = MulByPow2(lfsr_s15, 15); f = AddM(f, v); f = AddM(f, u); /* update the state */ LFSR_S0 = LFSR_S1; LFSR_S1 = LFSR_S2; LFSR_S2 = LFSR_S3; LFSR_S3 = LFSR_S4; LFSR_S4 = LFSR_S5; LFSR_S5 = LFSR_S6; LFSR_S6 = LFSR_S7; LFSR_S7 = LFSR_S8; LFSR_S8 = LFSR_S9; LFSR_S9 = LFSR_S10; LFSR_S10 = LFSR_S11; LFSR_S11 = LFSR_S12; LFSR_S12 = LFSR_S13; LFSR_S13 = LFSR_S14; LFSR_S14 = LFSR_S15; LFSR_S15 = f; lfsr_s0 = lfsr_s1; lfsr_s1 = lfsr_s2; lfsr_s2 = lfsr_s3; lfsr_s3 = lfsr_s4; lfsr_s4 = lfsr_s5; lfsr_s5 = lfsr_s6; lfsr_s6 = lfsr_s7; lfsr_s7 = lfsr_s8; lfsr_s8 = lfsr_s9; lfsr_s9 = lfsr_s10; lfsr_s10 = lfsr_s11; lfsr_s11 = lfsr_s12; lfsr_s12 = lfsr_s13; lfsr_s13 = lfsr_s14; lfsr_s14 = lfsr_s15; lfsr_s15 = f; }; /* LFSR with work mode */ inline void LFSRWithWorkMode(void) { inline void lfsr_with_work_mode(void) { uint32_t f, v; f = LFSR_S0; f = lfsr_s0; v = MulByPow2(LFSR_S0, 8); v = MulByPow2(lfsr_s0, 8); f = AddM(f, v); v = MulByPow2(LFSR_S4, 20); v = MulByPow2(lfsr_s4, 20); f = AddM(f, v); v = MulByPow2(LFSR_S10, 21); v = MulByPow2(lfsr_s10, 21); f = AddM(f, v); v = MulByPow2(LFSR_S13, 17); v = MulByPow2(lfsr_s13, 17); f = AddM(f, v); v = MulByPow2(LFSR_S15, 15); v = MulByPow2(lfsr_s15, 15); f = AddM(f, v); /* update the state */ LFSR_S0 = LFSR_S1; LFSR_S1 = LFSR_S2; LFSR_S2 = LFSR_S3; LFSR_S3 = LFSR_S4; LFSR_S4 = LFSR_S5; LFSR_S5 = LFSR_S6; LFSR_S6 = LFSR_S7; LFSR_S7 = LFSR_S8; LFSR_S8 = LFSR_S9; LFSR_S9 = LFSR_S10; LFSR_S10 = LFSR_S11; LFSR_S11 = LFSR_S12; LFSR_S12 = LFSR_S13; LFSR_S13 = LFSR_S14; LFSR_S14 = LFSR_S15; LFSR_S15 = f; lfsr_s0 = lfsr_s1; lfsr_s1 = lfsr_s2; lfsr_s2 = lfsr_s3; lfsr_s3 = lfsr_s4; lfsr_s4 = lfsr_s5; lfsr_s5 = lfsr_s6; lfsr_s6 = lfsr_s7; lfsr_s7 = lfsr_s8; lfsr_s8 = lfsr_s9; lfsr_s9 = lfsr_s10; lfsr_s10 = lfsr_s11; lfsr_s11 = lfsr_s12; lfsr_s12 = lfsr_s13; lfsr_s13 = lfsr_s14; lfsr_s14 = lfsr_s15; lfsr_s15 = f; }; /* BitReorganization */ inline void BitReorganization(void) { BRC_X0 = ((LFSR_S15 & 0x7FFF8000) << 1) | (LFSR_S14 & 0xFFFF); BRC_X1 = ((LFSR_S11 & 0xFFFF) << 16) | (LFSR_S9 >> 15); BRC_X2 = ((LFSR_S7 & 0xFFFF) << 16) | (LFSR_S5 >> 15); BRC_X3 = ((LFSR_S2 & 0xFFFF) << 16) | (LFSR_S0 >> 15); /* bit_reorganization */ inline void bit_reorganization(void) { brc_x0 = ((lfsr_s15 & 0x7FFF8000) << 1) | (lfsr_s14 & 0xFFFF); brc_x1 = ((lfsr_s11 & 0xFFFF) << 16) | (lfsr_s9 >> 15); brc_x2 = ((lfsr_s7 & 0xFFFF) << 16) | (lfsr_s5 >> 15); brc_x3 = ((lfsr_s2 & 0xFFFF) << 16) | (lfsr_s0 >> 15); }; #define ROT(a, k) (((a) << k) | ((a) >> (32 - k))) Loading @@ -287,17 +316,17 @@ private: inline uint32_t F(void) { uint32_t W, W1, W2, u, v; W = (BRC_X0 ^ F_R1) + F_R2; W1 = F_R1 + BRC_X1; W2 = F_R2 ^ BRC_X2; W = (brc_x0 ^ f_r1) + f_r2; W1 = f_r1 + brc_x1; W2 = f_r2 ^ brc_x2; u = L1((W1 << 16) | (W2 >> 16)); v = L2((W2 << 16) | (W1 >> 16)); F_R1 = MAKEU32(S0[u >> 24], S1[(u >> 16) & 0xFF], S0[(u >> 8) & 0xFF], S1[u & 0xFF]); F_R2 = MAKEU32(S0[v >> 24], S1[(v >> 16) & 0xFF], S0[(v >> 8) & 0xFF], S1[v & 0xFF]); f_r1 = MAKEU32(s0[u >> 24], s1[(u >> 16) & 0xFF], s0[(u >> 8) & 0xFF], s1[u & 0xFF]); f_r2 = MAKEU32(s0[v >> 24], s1[(v >> 16) & 0xFF], s0[(v >> 8) & 0xFF], s1[v & 0xFF]); return W; }; Loading @@ -308,90 +337,90 @@ private: uint32_t w, nCount; /* expand key */ LFSR_S0 = MAKEU31(k[0], EK_d[0], iv[0]); LFSR_S1 = MAKEU31(k[1], EK_d[1], iv[1]); LFSR_S2 = MAKEU31(k[2], EK_d[2], iv[2]); LFSR_S3 = MAKEU31(k[3], EK_d[3], iv[3]); LFSR_S4 = MAKEU31(k[4], EK_d[4], iv[4]); LFSR_S5 = MAKEU31(k[5], EK_d[5], iv[5]); LFSR_S6 = MAKEU31(k[6], EK_d[6], iv[6]); LFSR_S7 = MAKEU31(k[7], EK_d[7], iv[7]); LFSR_S8 = MAKEU31(k[8], EK_d[8], iv[8]); LFSR_S9 = MAKEU31(k[9], EK_d[9], iv[9]); LFSR_S10 = MAKEU31(k[10], EK_d[10], iv[10]); LFSR_S11 = MAKEU31(k[11], EK_d[11], iv[11]); LFSR_S12 = MAKEU31(k[12], EK_d[12], iv[12]); LFSR_S13 = MAKEU31(k[13], EK_d[13], iv[13]); LFSR_S14 = MAKEU31(k[14], EK_d[14], iv[14]); LFSR_S15 = MAKEU31(k[15], EK_d[15], iv[15]); /* set F_R1 and F_R2 to zero */ F_R1 = 0; F_R2 = 0; lfsr_s0 = MAKEU31(k[0], EK_d[0], iv[0]); lfsr_s1 = MAKEU31(k[1], EK_d[1], iv[1]); lfsr_s2 = MAKEU31(k[2], EK_d[2], iv[2]); lfsr_s3 = MAKEU31(k[3], EK_d[3], iv[3]); lfsr_s4 = MAKEU31(k[4], EK_d[4], iv[4]); lfsr_s5 = MAKEU31(k[5], EK_d[5], iv[5]); lfsr_s6 = MAKEU31(k[6], EK_d[6], iv[6]); lfsr_s7 = MAKEU31(k[7], EK_d[7], iv[7]); lfsr_s8 = MAKEU31(k[8], EK_d[8], iv[8]); lfsr_s9 = MAKEU31(k[9], EK_d[9], iv[9]); lfsr_s10 = MAKEU31(k[10], EK_d[10], iv[10]); lfsr_s11 = MAKEU31(k[11], EK_d[11], iv[11]); lfsr_s12 = MAKEU31(k[12], EK_d[12], iv[12]); lfsr_s13 = MAKEU31(k[13], EK_d[13], iv[13]); lfsr_s14 = MAKEU31(k[14], EK_d[14], iv[14]); lfsr_s15 = MAKEU31(k[15], EK_d[15], iv[15]); /* set f_r1 and f_r2 to zero */ f_r1 = 0; f_r2 = 0; nCount = 32; while (nCount > 0) { BitReorganization(); bit_reorganization(); w = F(); LFSRWithInitialisationMode(w >> 1); lfsr_with_initialisation_mode(w >> 1); nCount --; } }; inline void zuc_generate_key_stream(uint32_t* pKeystream, uint32_t KeystreamLen) { int i; BitReorganization(); bit_reorganization(); F(); /* discard the output of F */ LFSRWithWorkMode(); lfsr_with_work_mode(); for (i = 0; i < KeystreamLen; i ++) { BitReorganization(); pKeystream[i] = F() ^ BRC_X3; LFSRWithWorkMode(); bit_reorganization(); pKeystream[i] = F() ^ brc_x3; lfsr_with_work_mode(); } }; /* The ZUC algorithm, see ref. [3]*/ inline void ZUC(const uint8_t* k, uint8_t* iv, uint32_t* ks, uint32_t len) { inline void zuc(const uint8_t* k, uint8_t* iv, uint32_t* ks, uint32_t len) { /* The initialization of ZUC, see page 17 of ref. [3]*/ zuc_initialize(k, iv); /* The procedure of generating keystream of ZUC, see page 18 of ref. [3]*/ zuc_generate_key_stream(ks, len); }; inline uint32_t GET_WORD(const uint32_t* DATA, const uint32_t i) { uint32_t WORD, ti; inline uint32_t get_word(const uint32_t* p_data, const uint32_t i) { uint32_t word, ti; ti = i % 32; if (ti == 0) WORD = DATA[i/32]; word = p_data[i/32]; else WORD = (DATA[i/32]<<ti) | (DATA[i/32+1]>>(32-ti)); return WORD; word = (p_data[i/32]<<ti) | (p_data[i/32+1]>>(32-ti)); return word; }; inline uint8_t GET_BIT(const uint8_t* DATA, const uint32_t i) { return (DATA[i/8] & (1<<(7-(i%8)))) ? 1 : 0; }; inline uint8_t get_bit(const uint8_t* p_data, const uint32_t i) { return (p_data[i/8] & (1<<(7-(i%8)))) ? 1 : 0; }; /* * CK: ciphering key * COUNT: frame counter * BEARER: radio bearer * DIRECTION * LENGTH: length of the frame in bits * M: original message (input) * C: processed message (output) * p_knas_enc: ciphering key * count: frame counter * bearer: radio bearer * direction * payload_length: length of the frame in bits * payload: original message (input) * ciphered: processed message (output) */ void zuc_eea3(const uint8_t* CK, const uint32_t COUNT, const uint32_t BEARER, const uint32_t DIRECTION, const uint32_t LENGTH, const uint8_t* M, uint8_t* C); void zuc_eea3(const uint8_t* p_knas_enc, const uint32_t count, const uint32_t bearer, const uint32_t direction, const uint32_t payload_length, const uint8_t* payload, uint8_t* ciphered); /* * IK: integrity key * COUNT: frame counter * BEARER: radio bearer * DIRECTION * LENGTH: length of the frame in bits * M: original message (input) * C: processed message (output) * p_knas_int: integrity key * count: frame counter * bearer: radio bearer * direction * payload_length: length of the frame in bits * payload: original message (input) * mac: computed integrity protection (output) */ void zuc_eia3(const uint8_t* IK, const uint32_t COUNT, const uint32_t BEARER, const uint32_t DIRECTION, const uint32_t LENGTH, const uint8_t* M, uint32_t* MAC); void zuc_eia3(const uint8_t* p_knas_int, const uint32_t count, const uint32_t bearer, const uint32_t direction, const uint32_t payload_length, const uint8_t* payload, uint32_t* mac); }; ccsrc/Externals/module.mk +0 −2 Original line number Diff line number Diff line Loading @@ -7,6 +7,4 @@ sources := \ ia3_128.cc \ # zuc.cc includes := . etc/Ats_NG_NAS/AtsNGAP_AMF.cfg_ +1 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,7 @@ system.N2_gNBaMF_P.params := "NGAP/SCTP_FILE/IP_OFFLINE/ETH(mac_src=8c554ac1eee0 #NG_NAS_TestCases.TC_5G_AKA_CRYPTO_FUNCTIONS_TEST_25_01_02 #NG_NAS_TestCases.TC_5G_AKA_CRYPTO_FUNCTIONS_TEST_25_02_01 NG_NAS_TestCases.TC_5G_AKA_CRYPTO_FUNCTIONS_TEST_25_03_01 NG_NAS_TestCases.TC_5G_AKA_CRYPTO_FUNCTIONS_TEST_26_03_01 [GROUPS] # In this section you can specify groups of hosts. These groups can be used inside the Loading Loading
ccsrc/Externals/NG_security_ext.cc +183 −119 File changed.Preview size limit exceeded, changes collapsed. Show changes
ccsrc/Externals/ia3_128.cc +134 −90 Original line number Diff line number Diff line Loading @@ -23,28 +23,28 @@ namespace { constexpr size_t IV_SIZE = 16; // Initialization vector size } uint32_t ia3_128::LFSR_S0 = 0; uint32_t ia3_128::LFSR_S1 = 0; uint32_t ia3_128::LFSR_S2 = 0; uint32_t ia3_128::LFSR_S3 = 0; uint32_t ia3_128::LFSR_S4 = 0; uint32_t ia3_128::LFSR_S5 = 0; uint32_t ia3_128::LFSR_S6 = 0; uint32_t ia3_128::LFSR_S7 = 0; uint32_t ia3_128::LFSR_S8 = 0; uint32_t ia3_128::LFSR_S9 = 0; uint32_t ia3_128::LFSR_S10 = 0; uint32_t ia3_128::LFSR_S11 = 0; uint32_t ia3_128::LFSR_S12 = 0; uint32_t ia3_128::LFSR_S13 = 0; uint32_t ia3_128::LFSR_S14 = 0; uint32_t ia3_128::LFSR_S15 = 0; uint32_t ia3_128::F_R1 = 0; uint32_t ia3_128::F_R2 = 0; uint32_t ia3_128::BRC_X0 = 0; uint32_t ia3_128::BRC_X1 = 0; uint32_t ia3_128::BRC_X2 = 0; uint32_t ia3_128::BRC_X3 = 0; uint32_t ia3_128::lfsr_s0 = 0; uint32_t ia3_128::lfsr_s1 = 0; uint32_t ia3_128::lfsr_s2 = 0; uint32_t ia3_128::lfsr_s3 = 0; uint32_t ia3_128::lfsr_s4 = 0; uint32_t ia3_128::lfsr_s5 = 0; uint32_t ia3_128::lfsr_s6 = 0; uint32_t ia3_128::lfsr_s7 = 0; uint32_t ia3_128::lfsr_s8 = 0; uint32_t ia3_128::lfsr_s9 = 0; uint32_t ia3_128::lfsr_s10 = 0; uint32_t ia3_128::lfsr_s11 = 0; uint32_t ia3_128::lfsr_s12 = 0; uint32_t ia3_128::lfsr_s13 = 0; uint32_t ia3_128::lfsr_s14 = 0; uint32_t ia3_128::lfsr_s15 = 0; uint32_t ia3_128::f_r1 = 0; uint32_t ia3_128::f_r2 = 0; uint32_t ia3_128::brc_x0 = 0; uint32_t ia3_128::brc_x1 = 0; uint32_t ia3_128::brc_x2 = 0; uint32_t ia3_128::brc_x3 = 0; int ia3_128::encrypt(const uint8_t algo_id, const unsigned char* knas_enc, Loading Loading @@ -105,103 +105,147 @@ int ia3_128::decrypt(const uint8_t algo_id, cyphered, cyphered_length, payload, payload_length); } void ia3_128::zuc_eea3(const uint8_t* CK, const uint32_t COUNT, const uint32_t BEARER, const uint32_t DIRECTION, const uint32_t LENGTH, const uint8_t* M, uint8_t* C) { loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: knas_enc", CK, KEY_SIZE); loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: payload", M, LENGTH / 8); loggers::get_instance().log(">>> ia3_128::zuc_eea3: count: %u", COUNT); loggers::get_instance().log(">>> ia3_128::zuc_eea3: bearer: %d", BEARER); loggers::get_instance().log(">>> ia3_128::zuc_eea3: direction: %d", DIRECTION); int ia3_128::mac(const uint8_t algo_id, const unsigned char* knas_int, const uint32_t count, const uint8_t bearer, const uint8_t direction, const unsigned char* payload, const uint32_t payload_length, unsigned char** mac, uint32_t* mac_length) { loggers::get_instance().log_to_hexa(">>> ia3_128::mac: knas_int", knas_int, KEY_SIZE); loggers::get_instance().log(">>> ia3_128::mac: payload_length: %d", payload_length); loggers::get_instance().log_to_hexa(">>> ia3_128::mac: payload", payload, payload_length); loggers::get_instance().log(">>> ia3_128::mac: algo_id: %d", algo_id); loggers::get_instance().log(">>> ia3_128::mac: count: %u", count); loggers::get_instance().log(">>> ia3_128::mac: bearer: %d", bearer); loggers::get_instance().log(">>> ia3_128::mac: direction: %d", direction); // Input validation if (!knas_int || !payload || !mac || !mac_length) { loggers::get_instance().error("ia3_128::mac: Wrong input parameters"); return -1; } if (payload_length == 0) { loggers::get_instance().error("ia3_128::mac: Wrong payload length"); *mac = nullptr; *mac_length = 0; return 0; } uint32_t *z, L, L8, i; uint8_t IV[KEY_SIZE]; uint32_t lastbits = (8-(LENGTH%8))%8; // Allocate memory for ciphertext *mac = static_cast<unsigned char*>(std::malloc(4)); if (!*mac) { loggers::get_instance().error("ia3_128::mac: Failed to allocate memory"); return -1; } *mac_length = 4; uint32_t wmac = 0; zuc_eia3(knas_int, count, bearer, direction, payload_length * 8, payload, &wmac); (*mac)[0] = (wmac >> 24) & 0xFF; (*mac)[1] = (wmac >> 16) & 0xFF; (*mac)[2] = (wmac >> 8) & 0xFF; (*mac)[3] = wmac & 0xFF; loggers::get_instance().log_to_hexa("ia3_128::mac: mac: ", *mac, *mac_length); loggers::get_instance().log("<<< ia3_128::mac: ret: 0"); return 0; } L = (LENGTH+31)/32; z = static_cast<uint32_t*>(std::malloc(L*sizeof(uint32_t))); void ia3_128::zuc_eea3(const uint8_t* p_knas_enc, const uint32_t count, const uint32_t bearer, const uint32_t direction, const uint32_t payload_length, const uint8_t* payload, uint8_t* ciphered) { loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: knas_enc", p_knas_enc, KEY_SIZE); loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: payload", payload, payload_length / 8); loggers::get_instance().log(">>> ia3_128::zuc_eea3: count: %u", count); loggers::get_instance().log(">>> ia3_128::zuc_eea3: bearer: %d", bearer); loggers::get_instance().log(">>> ia3_128::zuc_eea3: direction: %d", direction); uint32_t *z, lenght, lenght_in_bytes, i; uint8_t iv[KEY_SIZE]; uint32_t lastbits = (8-(payload_length%8))%8; L8 = (LENGTH+7)/8; lenght = (payload_length+31)/32; z = static_cast<uint32_t*>(std::malloc(lenght*sizeof(uint32_t))); IV[0] = (COUNT>>24) & 0xFF; IV[1] = (COUNT>>16) & 0xFF; IV[2] = (COUNT>>8) & 0xFF; IV[3] = COUNT & 0xFF; IV[4] = ((BEARER << 3) | ((DIRECTION&1)<<2)) & 0xFC; IV[5] = 0; IV[6] = 0; IV[7] = 0; lenght_in_bytes = (payload_length+7)/8; IV[8] = IV[0]; IV[9] = IV[1]; IV[10] = IV[2]; IV[11] = IV[3]; iv[0] = (count>>24) & 0xFF; iv[1] = (count>>16) & 0xFF; iv[2] = (count>>8) & 0xFF; iv[3] = count & 0xFF; IV[12] = IV[4]; IV[13] = IV[5]; IV[14] = IV[6]; IV[15] = IV[7]; loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: IV", IV, KEY_SIZE); iv[4] = ((bearer << 3) | ((direction&1)<<2)) & 0xFC; iv[5] = 0; iv[6] = 0; iv[7] = 0; ZUC(CK, IV, z, L); loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: z", (uint8_t*)z, L*sizeof(uint32_t)); iv[8] = iv[0]; iv[9] = iv[1]; iv[10] = iv[2]; iv[11] = iv[3]; for (i=0; i<L8; i++) { C[i] = M[i] ^ ((z[i/4] >> (3-i%4)*8) & 0xff); } iv[12] = iv[4]; iv[13] = iv[5]; iv[14] = iv[6]; iv[15] = iv[7]; loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: iv", iv, KEY_SIZE); /* * Issues #3349 * Valgrind memcheck: Invalid read & write: Add {}. */ zuc(p_knas_enc, iv, z, lenght); loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: z", (uint8_t*)z, lenght*sizeof(uint32_t)); for (i=0; i<lenght_in_bytes; i++) { ciphered[i] = payload[i] ^ ((z[i/4] >> (3-i%4)*8) & 0xff); } /* zero last bits of data in case its length is not word-aligned (32 bits) this is an addition to the C reference code, which did not handle it */ this is an addition to the ciphered reference code, which did not handle it */ if (lastbits) { i--; C[i] &= 0x100 - (1<<lastbits); ciphered[i] &= 0x100 - (1<<lastbits); } loggers::get_instance().log_to_hexa("ia3_128::zuc_eea3: C", C, LENGTH / 8); loggers::get_instance().log_to_hexa("ia3_128::zuc_eea3: ciphered", ciphered, payload_length / 8); std::free(z); } void ia3_128::zuc_eia3(const uint8_t* IK, const uint32_t COUNT, const uint32_t BEARER, const uint32_t DIRECTION, const uint32_t LENGTH, const uint8_t* M, uint32_t* MAC) { uint32_t *z, N, L, T, i; uint8_t IV[16]; void ia3_128::zuc_eia3(const uint8_t* p_knas_int, const uint32_t count, const uint32_t bearer, const uint32_t direction, const uint32_t payload_length, const uint8_t* payload, uint32_t* mac) { uint32_t *z, N, lenght, T, i; uint8_t iv[16]; IV[0] = (COUNT>>24) & 0xFF; IV[1] = (COUNT>>16) & 0xFF; IV[2] = (COUNT>>8) & 0xFF; IV[3] = COUNT & 0xFF; iv[0] = (count>>24) & 0xFF; iv[1] = (count>>16) & 0xFF; iv[2] = (count>>8) & 0xFF; iv[3] = count & 0xFF; IV[4] = (BEARER << 3) & 0xF8; IV[5] = IV[6] = IV[7] = 0; iv[4] = (bearer << 3) & 0xF8; iv[5] = iv[6] = iv[7] = 0; IV[8] = ((COUNT>>24) & 0xFF) ^ ((DIRECTION&1)<<7); IV[9] = (COUNT>>16) & 0xFF; IV[10] = (COUNT>>8) & 0xFF; IV[11] = COUNT & 0xFF; iv[8] = ((count>>24) & 0xFF) ^ ((direction&1)<<7); iv[9] = (count>>16) & 0xFF; iv[10] = (count>>8) & 0xFF; iv[11] = count & 0xFF; IV[12] = IV[4]; IV[13] = IV[5]; IV[14] = IV[6] ^ ((DIRECTION&1)<<7); IV[15] = IV[7]; iv[12] = iv[4]; iv[13] = iv[5]; iv[14] = iv[6] ^ ((direction&1)<<7); iv[15] = iv[7]; N = LENGTH + 64; L = (N + 31) / 32; z = static_cast<uint32_t*>(std::malloc(L*sizeof(uint32_t))); N = payload_length + 64; lenght = (N + 31) / 32; z = static_cast<uint32_t*>(std::malloc(lenght*sizeof(uint32_t))); ZUC(IK, IV, z, L); zuc(p_knas_int, iv, z, lenght); T = 0; for (i=0; i<LENGTH; i++) { if (GET_BIT(M,i)) { T ^= GET_WORD(z,i); for (i=0; i<payload_length; i++) { if (get_bit(payload,i)) { T ^= get_word(z,i); } } T ^= GET_WORD(z,LENGTH); T ^= get_word(z,payload_length); *MAC = T ^ z[L-1]; *mac = T ^ z[lenght-1]; std::free(z); }
ccsrc/Externals/ia3_128.hh +164 −135 Original line number Diff line number Diff line Loading @@ -114,8 +114,37 @@ public: unsigned char** payload, uint32_t* payload_length); /** * @brief Compute NAS integrity protection using ZUC algorithm * * This method computes the integrity protection using the ZUC stream cipher. * * @param algo_id Algorithm identifier (should be 3 for ZUC) * @param knas_enc Pointer to the 16-byte NAS encryption key * @param count 32-bit NAS count value * @param bearer 5-bit bearer identifier (only lower 5 bits are used) * @param direction Direction bit (0 = uplink, 1 = downlink) * @param cyphered Pointer to the ciphertext data to decrypt * @param cyphered_length Length of the ciphertext data in bytes * @param payload Pointer to pointer that will receive the decrypted data (caller must free) * @param payload_length Pointer to variable that will receive the decrypted data length * @return 0 on success, negative value on error * * @note The caller is responsible for freeing the memory allocated for payload * @note payload_length will be equal to cyphered_length for stream ciphers */ int mac(const uint8_t algo_id, const unsigned char* knas_int, const uint32_t count, const uint8_t bearer, const uint8_t direction, const unsigned char* payload, const uint32_t payload_length, unsigned char** cyphered, uint32_t* cyphered_length); private: const uint8_t S0[256] = { const uint8_t s0[256] = { 0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb, 0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90, 0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac, Loading @@ -134,7 +163,7 @@ private: 0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60 }; const uint8_t S1[256] = { const uint8_t s1[256] = { 0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77, 0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42, 0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1, Loading @@ -160,32 +189,32 @@ private: }; /* the state registers of LFSR */ static uint32_t LFSR_S0; static uint32_t LFSR_S1; static uint32_t LFSR_S2; static uint32_t LFSR_S3; static uint32_t LFSR_S4; static uint32_t LFSR_S5; static uint32_t LFSR_S6; static uint32_t LFSR_S7; static uint32_t LFSR_S8; static uint32_t LFSR_S9; static uint32_t LFSR_S10; static uint32_t LFSR_S11; static uint32_t LFSR_S12; static uint32_t LFSR_S13; static uint32_t LFSR_S14; static uint32_t LFSR_S15; static uint32_t lfsr_s0; static uint32_t lfsr_s1; static uint32_t lfsr_s2; static uint32_t lfsr_s3; static uint32_t lfsr_s4; static uint32_t lfsr_s5; static uint32_t lfsr_s6; static uint32_t lfsr_s7; static uint32_t lfsr_s8; static uint32_t lfsr_s9; static uint32_t lfsr_s10; static uint32_t lfsr_s11; static uint32_t lfsr_s12; static uint32_t lfsr_s13; static uint32_t lfsr_s14; static uint32_t lfsr_s15; /* the registers of F */ static uint32_t F_R1; static uint32_t F_R2; static uint32_t f_r1; static uint32_t f_r2; /* the outputs of BitReorganization */ static uint32_t BRC_X0; static uint32_t BRC_X1; static uint32_t BRC_X2; static uint32_t BRC_X3; /* the outputs of bit_reorganization */ static uint32_t brc_x0; static uint32_t brc_x1; static uint32_t brc_x2; static uint32_t brc_x3; /* c = a + b mod (2^31 - 1) */ inline uint32_t AddM(uint32_t a, uint32_t b) { Loading @@ -195,83 +224,83 @@ private: /* LFSR with initialization mode */ #define MulByPow2(x, k) ((((x) << k) | ((x) >> (31 - k))) & 0x7FFFFFFF) inline void LFSRWithInitialisationMode(uint32_t u) { inline void lfsr_with_initialisation_mode(uint32_t u) { uint32_t f, v; f = LFSR_S0; f = lfsr_s0; v = MulByPow2(LFSR_S0, 8); v = MulByPow2(lfsr_s0, 8); f = AddM(f, v); v = MulByPow2(LFSR_S4, 20); v = MulByPow2(lfsr_s4, 20); f = AddM(f, v); v = MulByPow2(LFSR_S10, 21); v = MulByPow2(lfsr_s10, 21); f = AddM(f, v); v = MulByPow2(LFSR_S13, 17); v = MulByPow2(lfsr_s13, 17); f = AddM(f, v); v = MulByPow2(LFSR_S15, 15); v = MulByPow2(lfsr_s15, 15); f = AddM(f, v); f = AddM(f, u); /* update the state */ LFSR_S0 = LFSR_S1; LFSR_S1 = LFSR_S2; LFSR_S2 = LFSR_S3; LFSR_S3 = LFSR_S4; LFSR_S4 = LFSR_S5; LFSR_S5 = LFSR_S6; LFSR_S6 = LFSR_S7; LFSR_S7 = LFSR_S8; LFSR_S8 = LFSR_S9; LFSR_S9 = LFSR_S10; LFSR_S10 = LFSR_S11; LFSR_S11 = LFSR_S12; LFSR_S12 = LFSR_S13; LFSR_S13 = LFSR_S14; LFSR_S14 = LFSR_S15; LFSR_S15 = f; lfsr_s0 = lfsr_s1; lfsr_s1 = lfsr_s2; lfsr_s2 = lfsr_s3; lfsr_s3 = lfsr_s4; lfsr_s4 = lfsr_s5; lfsr_s5 = lfsr_s6; lfsr_s6 = lfsr_s7; lfsr_s7 = lfsr_s8; lfsr_s8 = lfsr_s9; lfsr_s9 = lfsr_s10; lfsr_s10 = lfsr_s11; lfsr_s11 = lfsr_s12; lfsr_s12 = lfsr_s13; lfsr_s13 = lfsr_s14; lfsr_s14 = lfsr_s15; lfsr_s15 = f; }; /* LFSR with work mode */ inline void LFSRWithWorkMode(void) { inline void lfsr_with_work_mode(void) { uint32_t f, v; f = LFSR_S0; f = lfsr_s0; v = MulByPow2(LFSR_S0, 8); v = MulByPow2(lfsr_s0, 8); f = AddM(f, v); v = MulByPow2(LFSR_S4, 20); v = MulByPow2(lfsr_s4, 20); f = AddM(f, v); v = MulByPow2(LFSR_S10, 21); v = MulByPow2(lfsr_s10, 21); f = AddM(f, v); v = MulByPow2(LFSR_S13, 17); v = MulByPow2(lfsr_s13, 17); f = AddM(f, v); v = MulByPow2(LFSR_S15, 15); v = MulByPow2(lfsr_s15, 15); f = AddM(f, v); /* update the state */ LFSR_S0 = LFSR_S1; LFSR_S1 = LFSR_S2; LFSR_S2 = LFSR_S3; LFSR_S3 = LFSR_S4; LFSR_S4 = LFSR_S5; LFSR_S5 = LFSR_S6; LFSR_S6 = LFSR_S7; LFSR_S7 = LFSR_S8; LFSR_S8 = LFSR_S9; LFSR_S9 = LFSR_S10; LFSR_S10 = LFSR_S11; LFSR_S11 = LFSR_S12; LFSR_S12 = LFSR_S13; LFSR_S13 = LFSR_S14; LFSR_S14 = LFSR_S15; LFSR_S15 = f; lfsr_s0 = lfsr_s1; lfsr_s1 = lfsr_s2; lfsr_s2 = lfsr_s3; lfsr_s3 = lfsr_s4; lfsr_s4 = lfsr_s5; lfsr_s5 = lfsr_s6; lfsr_s6 = lfsr_s7; lfsr_s7 = lfsr_s8; lfsr_s8 = lfsr_s9; lfsr_s9 = lfsr_s10; lfsr_s10 = lfsr_s11; lfsr_s11 = lfsr_s12; lfsr_s12 = lfsr_s13; lfsr_s13 = lfsr_s14; lfsr_s14 = lfsr_s15; lfsr_s15 = f; }; /* BitReorganization */ inline void BitReorganization(void) { BRC_X0 = ((LFSR_S15 & 0x7FFF8000) << 1) | (LFSR_S14 & 0xFFFF); BRC_X1 = ((LFSR_S11 & 0xFFFF) << 16) | (LFSR_S9 >> 15); BRC_X2 = ((LFSR_S7 & 0xFFFF) << 16) | (LFSR_S5 >> 15); BRC_X3 = ((LFSR_S2 & 0xFFFF) << 16) | (LFSR_S0 >> 15); /* bit_reorganization */ inline void bit_reorganization(void) { brc_x0 = ((lfsr_s15 & 0x7FFF8000) << 1) | (lfsr_s14 & 0xFFFF); brc_x1 = ((lfsr_s11 & 0xFFFF) << 16) | (lfsr_s9 >> 15); brc_x2 = ((lfsr_s7 & 0xFFFF) << 16) | (lfsr_s5 >> 15); brc_x3 = ((lfsr_s2 & 0xFFFF) << 16) | (lfsr_s0 >> 15); }; #define ROT(a, k) (((a) << k) | ((a) >> (32 - k))) Loading @@ -287,17 +316,17 @@ private: inline uint32_t F(void) { uint32_t W, W1, W2, u, v; W = (BRC_X0 ^ F_R1) + F_R2; W1 = F_R1 + BRC_X1; W2 = F_R2 ^ BRC_X2; W = (brc_x0 ^ f_r1) + f_r2; W1 = f_r1 + brc_x1; W2 = f_r2 ^ brc_x2; u = L1((W1 << 16) | (W2 >> 16)); v = L2((W2 << 16) | (W1 >> 16)); F_R1 = MAKEU32(S0[u >> 24], S1[(u >> 16) & 0xFF], S0[(u >> 8) & 0xFF], S1[u & 0xFF]); F_R2 = MAKEU32(S0[v >> 24], S1[(v >> 16) & 0xFF], S0[(v >> 8) & 0xFF], S1[v & 0xFF]); f_r1 = MAKEU32(s0[u >> 24], s1[(u >> 16) & 0xFF], s0[(u >> 8) & 0xFF], s1[u & 0xFF]); f_r2 = MAKEU32(s0[v >> 24], s1[(v >> 16) & 0xFF], s0[(v >> 8) & 0xFF], s1[v & 0xFF]); return W; }; Loading @@ -308,90 +337,90 @@ private: uint32_t w, nCount; /* expand key */ LFSR_S0 = MAKEU31(k[0], EK_d[0], iv[0]); LFSR_S1 = MAKEU31(k[1], EK_d[1], iv[1]); LFSR_S2 = MAKEU31(k[2], EK_d[2], iv[2]); LFSR_S3 = MAKEU31(k[3], EK_d[3], iv[3]); LFSR_S4 = MAKEU31(k[4], EK_d[4], iv[4]); LFSR_S5 = MAKEU31(k[5], EK_d[5], iv[5]); LFSR_S6 = MAKEU31(k[6], EK_d[6], iv[6]); LFSR_S7 = MAKEU31(k[7], EK_d[7], iv[7]); LFSR_S8 = MAKEU31(k[8], EK_d[8], iv[8]); LFSR_S9 = MAKEU31(k[9], EK_d[9], iv[9]); LFSR_S10 = MAKEU31(k[10], EK_d[10], iv[10]); LFSR_S11 = MAKEU31(k[11], EK_d[11], iv[11]); LFSR_S12 = MAKEU31(k[12], EK_d[12], iv[12]); LFSR_S13 = MAKEU31(k[13], EK_d[13], iv[13]); LFSR_S14 = MAKEU31(k[14], EK_d[14], iv[14]); LFSR_S15 = MAKEU31(k[15], EK_d[15], iv[15]); /* set F_R1 and F_R2 to zero */ F_R1 = 0; F_R2 = 0; lfsr_s0 = MAKEU31(k[0], EK_d[0], iv[0]); lfsr_s1 = MAKEU31(k[1], EK_d[1], iv[1]); lfsr_s2 = MAKEU31(k[2], EK_d[2], iv[2]); lfsr_s3 = MAKEU31(k[3], EK_d[3], iv[3]); lfsr_s4 = MAKEU31(k[4], EK_d[4], iv[4]); lfsr_s5 = MAKEU31(k[5], EK_d[5], iv[5]); lfsr_s6 = MAKEU31(k[6], EK_d[6], iv[6]); lfsr_s7 = MAKEU31(k[7], EK_d[7], iv[7]); lfsr_s8 = MAKEU31(k[8], EK_d[8], iv[8]); lfsr_s9 = MAKEU31(k[9], EK_d[9], iv[9]); lfsr_s10 = MAKEU31(k[10], EK_d[10], iv[10]); lfsr_s11 = MAKEU31(k[11], EK_d[11], iv[11]); lfsr_s12 = MAKEU31(k[12], EK_d[12], iv[12]); lfsr_s13 = MAKEU31(k[13], EK_d[13], iv[13]); lfsr_s14 = MAKEU31(k[14], EK_d[14], iv[14]); lfsr_s15 = MAKEU31(k[15], EK_d[15], iv[15]); /* set f_r1 and f_r2 to zero */ f_r1 = 0; f_r2 = 0; nCount = 32; while (nCount > 0) { BitReorganization(); bit_reorganization(); w = F(); LFSRWithInitialisationMode(w >> 1); lfsr_with_initialisation_mode(w >> 1); nCount --; } }; inline void zuc_generate_key_stream(uint32_t* pKeystream, uint32_t KeystreamLen) { int i; BitReorganization(); bit_reorganization(); F(); /* discard the output of F */ LFSRWithWorkMode(); lfsr_with_work_mode(); for (i = 0; i < KeystreamLen; i ++) { BitReorganization(); pKeystream[i] = F() ^ BRC_X3; LFSRWithWorkMode(); bit_reorganization(); pKeystream[i] = F() ^ brc_x3; lfsr_with_work_mode(); } }; /* The ZUC algorithm, see ref. [3]*/ inline void ZUC(const uint8_t* k, uint8_t* iv, uint32_t* ks, uint32_t len) { inline void zuc(const uint8_t* k, uint8_t* iv, uint32_t* ks, uint32_t len) { /* The initialization of ZUC, see page 17 of ref. [3]*/ zuc_initialize(k, iv); /* The procedure of generating keystream of ZUC, see page 18 of ref. [3]*/ zuc_generate_key_stream(ks, len); }; inline uint32_t GET_WORD(const uint32_t* DATA, const uint32_t i) { uint32_t WORD, ti; inline uint32_t get_word(const uint32_t* p_data, const uint32_t i) { uint32_t word, ti; ti = i % 32; if (ti == 0) WORD = DATA[i/32]; word = p_data[i/32]; else WORD = (DATA[i/32]<<ti) | (DATA[i/32+1]>>(32-ti)); return WORD; word = (p_data[i/32]<<ti) | (p_data[i/32+1]>>(32-ti)); return word; }; inline uint8_t GET_BIT(const uint8_t* DATA, const uint32_t i) { return (DATA[i/8] & (1<<(7-(i%8)))) ? 1 : 0; }; inline uint8_t get_bit(const uint8_t* p_data, const uint32_t i) { return (p_data[i/8] & (1<<(7-(i%8)))) ? 1 : 0; }; /* * CK: ciphering key * COUNT: frame counter * BEARER: radio bearer * DIRECTION * LENGTH: length of the frame in bits * M: original message (input) * C: processed message (output) * p_knas_enc: ciphering key * count: frame counter * bearer: radio bearer * direction * payload_length: length of the frame in bits * payload: original message (input) * ciphered: processed message (output) */ void zuc_eea3(const uint8_t* CK, const uint32_t COUNT, const uint32_t BEARER, const uint32_t DIRECTION, const uint32_t LENGTH, const uint8_t* M, uint8_t* C); void zuc_eea3(const uint8_t* p_knas_enc, const uint32_t count, const uint32_t bearer, const uint32_t direction, const uint32_t payload_length, const uint8_t* payload, uint8_t* ciphered); /* * IK: integrity key * COUNT: frame counter * BEARER: radio bearer * DIRECTION * LENGTH: length of the frame in bits * M: original message (input) * C: processed message (output) * p_knas_int: integrity key * count: frame counter * bearer: radio bearer * direction * payload_length: length of the frame in bits * payload: original message (input) * mac: computed integrity protection (output) */ void zuc_eia3(const uint8_t* IK, const uint32_t COUNT, const uint32_t BEARER, const uint32_t DIRECTION, const uint32_t LENGTH, const uint8_t* M, uint32_t* MAC); void zuc_eia3(const uint8_t* p_knas_int, const uint32_t count, const uint32_t bearer, const uint32_t direction, const uint32_t payload_length, const uint8_t* payload, uint32_t* mac); };
ccsrc/Externals/module.mk +0 −2 Original line number Diff line number Diff line Loading @@ -7,6 +7,4 @@ sources := \ ia3_128.cc \ # zuc.cc includes := .
etc/Ats_NG_NAS/AtsNGAP_AMF.cfg_ +1 −0 Original line number Diff line number Diff line Loading @@ -155,6 +155,7 @@ system.N2_gNBaMF_P.params := "NGAP/SCTP_FILE/IP_OFFLINE/ETH(mac_src=8c554ac1eee0 #NG_NAS_TestCases.TC_5G_AKA_CRYPTO_FUNCTIONS_TEST_25_01_02 #NG_NAS_TestCases.TC_5G_AKA_CRYPTO_FUNCTIONS_TEST_25_02_01 NG_NAS_TestCases.TC_5G_AKA_CRYPTO_FUNCTIONS_TEST_25_03_01 NG_NAS_TestCases.TC_5G_AKA_CRYPTO_FUNCTIONS_TEST_26_03_01 [GROUPS] # In this section you can specify groups of hosts. These groups can be used inside the Loading