diff --git a/lib/include/srslte/common/liblte_security.h b/lib/include/srslte/common/liblte_security.h index 7f5eaadc2..4e0d02fbd 100644 --- a/lib/include/srslte/common/liblte_security.h +++ b/lib/include/srslte/common/liblte_security.h @@ -179,6 +179,13 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_up(uint8* // Enums // Structs // Functions +LIBLTE_ERROR_ENUM liblte_security_128_eia1(const uint8* key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8* msg, + uint32 msg_len, + uint8* mac); LIBLTE_ERROR_ENUM liblte_security_128_eia2(const uint8* key, uint32 count, uint8 bearer, @@ -186,19 +193,26 @@ LIBLTE_ERROR_ENUM liblte_security_128_eia2(const uint8* key, uint8* msg, uint32 msg_len, uint8* mac); -LIBLTE_ERROR_ENUM liblte_security_128_eia2(uint8* key, +LIBLTE_ERROR_ENUM liblte_security_128_eia2(const uint8* key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8* msg, + uint32 msg_len, + uint8* mac); +LIBLTE_ERROR_ENUM liblte_security_128_eia2(const uint8* key, uint32 count, uint8 bearer, uint8 direction, LIBLTE_BIT_MSG_STRUCT* msg, uint8* mac); -LIBLTE_ERROR_ENUM liblte_security_128_eia3(uint8* key, - uint32 count, - uint8 bearer, - uint8 direction, - uint8* msg, - uint32 msg_len, - uint8* mac); +LIBLTE_ERROR_ENUM liblte_security_128_eia3(const uint8* key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8* msg, + uint32 msg_len, + uint8* mac); /********************************************************************* Name: liblte_security_encryption_eea1 diff --git a/lib/include/srslte/common/snow_3g.h b/lib/include/srslte/common/s3g.h similarity index 52% rename from lib/include/srslte/common/snow_3g.h rename to lib/include/srslte/common/s3g.h index 7053621e2..612ca894d 100644 --- a/lib/include/srslte/common/snow_3g.h +++ b/lib/include/srslte/common/s3g.h @@ -1,6 +1,25 @@ -/*--------------------------------------------------------- - * snow_3g.h +/* + * Copyright 2013-2020 Software Radio Systems Limited * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +/* * Adapted from ETSI/SAGE specifications: * "Specification of the 3GPP Confidentiality and * Integrity Algorithms UEA2 & UIA2. @@ -8,18 +27,21 @@ * "Specification of the 3GPP Confidentiality * and Integrity Algorithms UEA2 & UIA2. * Document 2: SNOW 3G Specification" - *---------------------------------------------------------*/ -#ifndef SRSLTE_SNOW_3G_H -#define SRSLTE_SNOW_3G_H + */ + +#ifndef SRSLTE_S3G_H +#define SRSLTE_S3G_H #include +#include #include #include #include -typedef unsigned char u8; -typedef unsigned int u32; -typedef unsigned long long u64; +typedef struct { + uint32_t* lfsr; + uint32_t* fsm; +} S3G_STATE; /* Initialization. * Input k[4]: Four 32-bit words making up 128-bit key. @@ -28,7 +50,17 @@ typedef unsigned long long u64; * See Section 4.1. */ -void snow3g_initialize(u32 k[4], u32 IV[4]); +void s3g_initialize(S3G_STATE* state, uint32_t k[4], uint32_t iv[4]); + +/********************************************************************* + Name: s3g_deinitialize + + Description: Deinitialization. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 +*********************************************************************/ +void s3g_deinitialize(S3G_STATE* state); /* Generation of Keystream. * input n: number of 32-bit words of keystream. @@ -38,7 +70,7 @@ void snow3g_initialize(u32 k[4], u32 IV[4]); * See section 4.2. */ -void snow3g_generate_keystream(u32 n, u32* z); +void s3g_generate_keystream(S3G_STATE* state, uint32_t n, uint32_t* ks); /* f8. * Input key: 128 bit Confidentiality Key. @@ -54,7 +86,7 @@ void snow3g_generate_keystream(u32 n, u32* z); * defined in Section 3. */ -void snow3g_f8(u8* key, u32 count, u32 bearer, u32 dir, u8* data, u32 length); +// void snow3g_f8(u8* key, u32 count, u32 bearer, u32 dir, u8* data, u32 length); /* f9. * Input key: 128 bit Integrity Key. @@ -67,6 +99,6 @@ void snow3g_f8(u8* key, u32 count, u32 bearer, u32 dir, u8* data, u32 length); * Generates 32-bit MAC using UIA2 algorithm as defined in Section 4. */ -u8* snow3g_f9(u8* key, u32 count, u32 fresh, u32 dir, u8* data, u64 length); +uint8_t* s3g_f9(const uint8_t* key, uint32_t count, uint32_t fresh, uint32_t dir, uint8_t* data, uint64_t length); -#endif // SRSLTE_SNOW_3G_H \ No newline at end of file +#endif // SRSLTE_S3G_H \ No newline at end of file diff --git a/lib/include/srslte/common/security.h b/lib/include/srslte/common/security.h index 846f20c28..e32a5153b 100644 --- a/lib/include/srslte/common/security.h +++ b/lib/include/srslte/common/security.h @@ -125,13 +125,13 @@ uint8_t security_128_eia2(const uint8_t* key, uint32_t msg_len, uint8_t* mac); -uint8_t security_128_eia3(uint8_t* key, - uint32_t count, - uint32_t bearer, - uint8_t direction, - uint8_t* msg, - uint32_t msg_len, - uint8_t* mac); +uint8_t security_128_eia3(const uint8_t* key, + uint32_t count, + uint32_t bearer, + uint8_t direction, + uint8_t* msg, + uint32_t msg_len, + uint8_t* mac); uint8_t security_md5(const uint8_t* input, size_t len, uint8_t* output); diff --git a/lib/include/srslte/common/zuc.h b/lib/include/srslte/common/zuc.h index 7385ea601..4fdc53c2c 100644 --- a/lib/include/srslte/common/zuc.h +++ b/lib/include/srslte/common/zuc.h @@ -42,7 +42,7 @@ typedef struct { u32 BRC_X3; } zuc_state_t; -void zuc_initialize(zuc_state_t* state, u8* k, u8* iv); +void zuc_initialize(zuc_state_t* state, const u8* k, u8* iv); void zuc_generate_keystream(zuc_state_t* state, int key_stream_len, u32* p_keystream); #endif // SRSLTE_ZUC_H diff --git a/lib/src/common/CMakeLists.txt b/lib/src/common/CMakeLists.txt index 501fb29e5..3bef21aed 100644 --- a/lib/src/common/CMakeLists.txt +++ b/lib/src/common/CMakeLists.txt @@ -35,13 +35,13 @@ set(SOURCES arch_select.cc rlc_pcap.cc s1ap_pcap.cc security.cc - snow_3g.cc thread_pool.cc threads.c tti_sync_cv.cc time_prof.cc version.c - zuc.cc) + zuc.cc + s3g.cc) if (ENABLE_5GNR) set(SOURCES ${SOURCES} mac_nr_pcap.cc) diff --git a/lib/src/common/liblte_security.cc b/lib/src/common/liblte_security.cc index 6166d4ca8..faf2ce17a 100644 --- a/lib/src/common/liblte_security.cc +++ b/lib/src/common/liblte_security.cc @@ -37,173 +37,13 @@ #include "srslte/common/liblte_security.h" #include "math.h" #include "srslte/common/liblte_ssl.h" +#include "srslte/common/s3g.h" #include "srslte/common/zuc.h" -/******************************************************************************* - DEFINES -*******************************************************************************/ - -/******************************************************************************* - TYPEDEFS -*******************************************************************************/ - -typedef struct { - uint8 rk[11][4][4]; -} ROUND_KEY_STRUCT; - -typedef struct { - uint8 state[4][4]; -} STATE_STRUCT; - -typedef struct { - uint32* lfsr; - uint32* fsm; -} S3G_STATE; - -/******************************************************************************* - GLOBAL VARIABLES -*******************************************************************************/ - -static const uint8 S[256] = { - 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, - 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, - 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, - 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, - 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, - 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, - 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, - 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, - 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, - 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, - 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, - 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22}; - -/* S-box SQ */ -static const uint8 SQ[256] = { - 0x25, 0x24, 0x73, 0x67, 0xD7, 0xAE, 0x5C, 0x30, 0xA4, 0xEE, 0x6E, 0xCB, 0x7D, 0xB5, 0x82, 0xDB, 0xE4, 0x8E, 0x48, - 0x49, 0x4F, 0x5D, 0x6A, 0x78, 0x70, 0x88, 0xE8, 0x5F, 0x5E, 0x84, 0x65, 0xE2, 0xD8, 0xE9, 0xCC, 0xED, 0x40, 0x2F, - 0x11, 0x28, 0x57, 0xD2, 0xAC, 0xE3, 0x4A, 0x15, 0x1B, 0xB9, 0xB2, 0x80, 0x85, 0xA6, 0x2E, 0x02, 0x47, 0x29, 0x07, - 0x4B, 0x0E, 0xC1, 0x51, 0xAA, 0x89, 0xD4, 0xCA, 0x01, 0x46, 0xB3, 0xEF, 0xDD, 0x44, 0x7B, 0xC2, 0x7F, 0xBE, 0xC3, - 0x9F, 0x20, 0x4C, 0x64, 0x83, 0xA2, 0x68, 0x42, 0x13, 0xB4, 0x41, 0xCD, 0xBA, 0xC6, 0xBB, 0x6D, 0x4D, 0x71, 0x21, - 0xF4, 0x8D, 0xB0, 0xE5, 0x93, 0xFE, 0x8F, 0xE6, 0xCF, 0x43, 0x45, 0x31, 0x22, 0x37, 0x36, 0x96, 0xFA, 0xBC, 0x0F, - 0x08, 0x52, 0x1D, 0x55, 0x1A, 0xC5, 0x4E, 0x23, 0x69, 0x7A, 0x92, 0xFF, 0x5B, 0x5A, 0xEB, 0x9A, 0x1C, 0xA9, 0xD1, - 0x7E, 0x0D, 0xFC, 0x50, 0x8A, 0xB6, 0x62, 0xF5, 0x0A, 0xF8, 0xDC, 0x03, 0x3C, 0x0C, 0x39, 0xF1, 0xB8, 0xF3, 0x3D, - 0xF2, 0xD5, 0x97, 0x66, 0x81, 0x32, 0xA0, 0x00, 0x06, 0xCE, 0xF6, 0xEA, 0xB7, 0x17, 0xF7, 0x8C, 0x79, 0xD6, 0xA7, - 0xBF, 0x8B, 0x3F, 0x1F, 0x53, 0x63, 0x75, 0x35, 0x2C, 0x60, 0xFD, 0x27, 0xD3, 0x94, 0xA5, 0x7C, 0xA1, 0x05, 0x58, - 0x2D, 0xBD, 0xD9, 0xC7, 0xAF, 0x6B, 0x54, 0x0B, 0xE0, 0x38, 0x04, 0xC8, 0x9D, 0xE7, 0x14, 0xB1, 0x87, 0x9C, 0xDF, - 0x6F, 0xF9, 0xDA, 0x2A, 0xC4, 0x59, 0x16, 0x74, 0x91, 0xAB, 0x26, 0x61, 0x76, 0x34, 0x2B, 0xAD, 0x99, 0xFB, 0x72, - 0xEC, 0x33, 0x12, 0xDE, 0x98, 0x3B, 0xC0, 0x9B, 0x3E, 0x18, 0x10, 0x3A, 0x56, 0xE1, 0x77, 0xC9, 0x1E, 0x9E, 0x95, - 0xA3, 0x90, 0x19, 0xA8, 0x6C, 0x09, 0xD0, 0xF0, 0x86}; - -static const uint8 X_TIME[256] = { - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, - 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, - 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, - 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, - 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, - 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 27, 25, 31, 29, - 19, 17, 23, 21, 11, 9, 15, 13, 3, 1, 7, 5, 59, 57, 63, 61, 51, 49, 55, 53, 43, 41, - 47, 45, 35, 33, 39, 37, 91, 89, 95, 93, 83, 81, 87, 85, 75, 73, 79, 77, 67, 65, 71, 69, - 123, 121, 127, 125, 115, 113, 119, 117, 107, 105, 111, 109, 99, 97, 103, 101, 155, 153, 159, 157, 147, 145, - 151, 149, 139, 137, 143, 141, 131, 129, 135, 133, 187, 185, 191, 189, 179, 177, 183, 181, 171, 169, 175, 173, - 163, 161, 167, 165, 219, 217, 223, 221, 211, 209, 215, 213, 203, 201, 207, 205, 195, 193, 199, 197, 251, 249, - 255, 253, 243, 241, 247, 245, 235, 233, 239, 237, 227, 225, 231, 229}; - /******************************************************************************* LOCAL FUNCTION PROTOTYPES *******************************************************************************/ -/********************************************************************* - Name: compute_OPc - - Description: Computes OPc from OP and K. - - Document Reference: 35.206 v10.0.0 Annex 3 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -void compute_OPc(ROUND_KEY_STRUCT* rk, uint8* op, uint8* op_c); - -/********************************************************************* - Name: rijndael_key_schedule - - Description: Computes all Rijndael's internal subkeys from key. - - Document Reference: 35.206 v10.0.0 Annex 3 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -void rijndael_key_schedule(uint8* key, ROUND_KEY_STRUCT* rk); - -/********************************************************************* - Name: rijndael_encrypt - - Description: Computes output using input and round keys. - - Document Reference: 35.206 v10.0.0 Annex 3 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -void rijndael_encrypt(uint8* input, ROUND_KEY_STRUCT* rk, uint8* output); - -/********************************************************************* - Name: key_add - - Description: Round key addition function. - - Document Reference: 35.206 v10.0.0 Annex 3 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -void key_add(STATE_STRUCT* state, ROUND_KEY_STRUCT* rk, uint32 round); - -/********************************************************************* - Name: byte_sub - - Description: Byte substitution transformation. - - Document Reference: 35.206 v10.0.0 Annex 3 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -void byte_sub(STATE_STRUCT* state); - -/********************************************************************* - Name: shift_row - - Description: Row shift transformation. - - Document Reference: 35.206 v10.0.0 Annex 3 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -void shift_row(STATE_STRUCT* state); - -/********************************************************************* - Name: mix_column - - Description: Mix column transformation. - - Document Reference: 35.206 v10.0.0 Annex 3 -*********************************************************************/ -// Defines -// Enums -// Structs -// Functions -void mix_column(STATE_STRUCT* state); - /********************************************************************* Name: zero_tailing_bits @@ -213,126 +53,6 @@ void mix_column(STATE_STRUCT* state); *********************************************************************/ void zero_tailing_bits(uint8* data, uint32 length_bits); -/********************************************************************* - Name: s3g_mul_x - - Description: Multiplication with reduction. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.1.1 -*********************************************************************/ -uint8 s3g_mul_x(uint8 v, uint8 c); - -/********************************************************************* - Name: s3g_mul_x_pow - - Description: Recursive multiplication with reduction. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.1.2 -*********************************************************************/ -uint8 s3g_mul_x_pow(uint8 v, uint8 i, uint8 c); - -/********************************************************************* - Name: s3g_mul_alpha - - Description: Multiplication with alpha. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.4.2 -*********************************************************************/ -uint32 s3g_mul_alpha(uint8 c); - -/********************************************************************* - Name: s3g_div_alpha - - Description: Division by alpha. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.4.3 -*********************************************************************/ -uint32 s3g_div_alpha(uint8 c); - -/********************************************************************* - Name: s3g_s1 - - Description: S-Box S1. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.3.1 -*********************************************************************/ -uint32 s3g_s1(uint32 w); - -/********************************************************************* - Name: s3g_s2 - - Description: S-Box S2. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.3.2 -*********************************************************************/ -uint32 s3g_s2(uint32 w); - -/********************************************************************* - Name: s3g_clock_lfsr - - Description: Clocking LFSR. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.4.4 and Section 3.4.5 -*********************************************************************/ -void s3g_clock_lfsr(S3G_STATE* state, uint32 f); - -/********************************************************************* - Name: s3g_clock_fsm - - Description: Clocking FSM. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.4.6 -*********************************************************************/ -uint32 s3g_clock_fsm(S3G_STATE* state); - -/********************************************************************* - Name: s3g_initialize - - Description: Initialization. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 4.1 -*********************************************************************/ -void s3g_initialize(S3G_STATE* state, uint32 k[4], uint32 iv[4]); - -/********************************************************************* - Name: s3g_deinitialize - - Description: Deinitialization. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 -*********************************************************************/ -void s3g_deinitialize(S3G_STATE* state); - -/********************************************************************* - Name: s3g_generate_keystream - - Description: Generation of Keystream. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 4.2 -*********************************************************************/ -void s3g_generate_keystream(S3G_STATE* state, uint32 n, uint32* ks); - /******************************************************************************* FUNCTIONS *******************************************************************************/ @@ -617,6 +337,31 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_up(uint8* return (err); } +LIBLTE_ERROR_ENUM liblte_security_128_eia1(const uint8* key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8* msg, + uint32 msg_len, + uint8* mac) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if (key != NULL && msg != NULL && mac != NULL) { + uint32_t msg_len_bits = 0; + uint32_t i = 0; + uint8_t* m_ptr; + + msg_len_bits = msg_len * 8; + m_ptr = s3g_f9(key, count, bearer << 27, direction, msg, msg_len_bits); + for (i = 0; i < 4; i++) { + mac[i] = m_ptr[i]; + } + err = LIBLTE_SUCCESS; + } + return (err); +} + /********************************************************************* Name: liblte_security_128_eia2 @@ -717,7 +462,7 @@ LIBLTE_ERROR_ENUM liblte_security_128_eia2(const uint8* key, return (err); } -LIBLTE_ERROR_ENUM liblte_security_128_eia2(uint8* key, +LIBLTE_ERROR_ENUM liblte_security_128_eia2(const uint8* key, uint32 count, uint8 bearer, uint8 direction, @@ -817,9 +562,9 @@ LIBLTE_ERROR_ENUM liblte_security_128_eia2(uint8* key, return (err); } -u32 GET_WORD(u32* DATA, u32 i) +uint32_t GET_WORD(uint32_t* DATA, uint32_t i) { - u32 WORD, ti; + uint32_t WORD, ti; ti = i % 32; if (ti == 0) WORD = DATA[i / 32]; @@ -828,18 +573,18 @@ u32 GET_WORD(u32* DATA, u32 i) return WORD; } -u8 GET_BIT(uint8_t* DATA, u32 i) +uint8_t GET_BIT(uint8_t* DATA, uint32_t i) { return (DATA[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0; } -LIBLTE_ERROR_ENUM liblte_security_128_eia3(uint8* key, - uint32 count, - uint8 bearer, - uint8 direction, - uint8* msg, - uint32 msg_len, - uint8* mac) +LIBLTE_ERROR_ENUM liblte_security_128_eia3(const uint8* key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8* msg, + uint32 msg_len, + uint8* mac) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; @@ -1174,22 +919,22 @@ LIBLTE_ERROR_ENUM liblte_security_decryption_eea3(uint8* key, LIBLTE_ERROR_ENUM liblte_security_milenage_f1(uint8* k, uint8* op_c, uint8* rand, uint8* sqn, uint8* amf, uint8* mac_a) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - ROUND_KEY_STRUCT round_keys; uint32 i; + aes_context ctx; uint8 temp[16]; uint8 in1[16]; uint8 out1[16]; - uint8 rijndael_input[16]; + uint8 input[16]; if (k != NULL && op_c != NULL && rand != NULL && sqn != NULL && amf != NULL && mac_a != NULL) { // Initialize the round keys - rijndael_key_schedule(k, &round_keys); + aes_setkey_enc(&ctx, k, 128); // Compute temp for (i = 0; i < 16; i++) { - rijndael_input[i] = rand[i] ^ op_c[i]; + input[i] = rand[i] ^ op_c[i]; } - rijndael_encrypt(rijndael_input, &round_keys, temp); + aes_crypt_ecb(&ctx, AES_ENCRYPT, input, temp); // Construct in1 for (i = 0; i < 6; i++) { @@ -1203,12 +948,12 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1(uint8* k, uint8* op_c, uint8* rand // Compute out1 for (i = 0; i < 16; i++) { - rijndael_input[(i + 8) % 16] = in1[i] ^ op_c[i]; + input[(i + 8) % 16] = in1[i] ^ op_c[i]; } for (i = 0; i < 16; i++) { - rijndael_input[i] ^= temp[i]; + input[i] ^= temp[i]; } - rijndael_encrypt(rijndael_input, &round_keys, out1); + aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out1); for (i = 0; i < 16; i++) { out1[i] ^= op_c[i]; } @@ -1238,23 +983,22 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1_star(uint8* k, uint8* op_c, uint8* rand, uint8* sqn, uint8* amf, uint8* mac_s) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - ROUND_KEY_STRUCT round_keys; + aes_context ctx; uint32 i; uint8 temp[16]; uint8 in1[16]; uint8 out1[16]; - uint8 rijndael_input[16]; + uint8 input[16]; if (k != NULL && op_c != NULL && rand != NULL && sqn != NULL && amf != NULL && mac_s != NULL) { // Initialize the round keys - rijndael_key_schedule(k, &round_keys); + aes_setkey_enc(&ctx, k, 128); // Compute temp for (i = 0; i < 16; i++) { - rijndael_input[i] = rand[i] ^ op_c[i]; + input[i] = rand[i] ^ op_c[i]; } - rijndael_encrypt(rijndael_input, &round_keys, temp); - + aes_crypt_ecb(&ctx, AES_ENCRYPT, input, temp); // Construct in1 for (i = 0; i < 6; i++) { in1[i] = sqn[i]; @@ -1267,12 +1011,12 @@ liblte_security_milenage_f1_star(uint8* k, uint8* op_c, uint8* rand, uint8* sqn, // Compute out1 for (i = 0; i < 16; i++) { - rijndael_input[(i + 8) % 16] = in1[i] ^ op_c[i]; + input[(i + 8) % 16] = in1[i] ^ op_c[i]; } for (i = 0; i < 16; i++) { - rijndael_input[i] ^= temp[i]; + input[i] ^= temp[i]; } - rijndael_encrypt(rijndael_input, &round_keys, out1); + aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out1); for (i = 0; i < 16; i++) { out1[i] ^= op_c[i]; } @@ -1302,28 +1046,26 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f2345(uint8* k, uint8* op_c, uint8* rand, uint8* res, uint8* ck, uint8* ik, uint8* ak) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - ROUND_KEY_STRUCT round_keys; uint32 i; uint8 temp[16]; uint8 out[16]; - uint8 rijndael_input[16]; + uint8 input[16]; + aes_context ctx; if (k != NULL && op_c != NULL && rand != NULL && res != NULL && ck != NULL && ik != NULL && ak != NULL) { // Initialize the round keys - rijndael_key_schedule(k, &round_keys); - + aes_setkey_enc(&ctx, k, 128); // Compute temp for (i = 0; i < 16; i++) { - rijndael_input[i] = rand[i] ^ op_c[i]; + input[i] = rand[i] ^ op_c[i]; } - rijndael_encrypt(rijndael_input, &round_keys, temp); - + mbedtls_aes_crypt_ecb(&ctx, AES_ENCRYPT, input, temp); // Compute out for RES and AK for (i = 0; i < 16; i++) { - rijndael_input[i] = temp[i] ^ op_c[i]; + input[i] = temp[i] ^ op_c[i]; } - rijndael_input[15] ^= 1; - rijndael_encrypt(rijndael_input, &round_keys, out); + input[15] ^= 1; + mbedtls_aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out); for (i = 0; i < 16; i++) { out[i] ^= op_c[i]; } @@ -1340,10 +1082,10 @@ liblte_security_milenage_f2345(uint8* k, uint8* op_c, uint8* rand, uint8* res, u // Compute out for CK for (i = 0; i < 16; i++) { - rijndael_input[(i + 12) % 16] = temp[i] ^ op_c[i]; + input[(i + 12) % 16] = temp[i] ^ op_c[i]; } - rijndael_input[15] ^= 2; - rijndael_encrypt(rijndael_input, &round_keys, out); + input[15] ^= 2; + mbedtls_aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out); for (i = 0; i < 16; i++) { out[i] ^= op_c[i]; } @@ -1355,10 +1097,10 @@ liblte_security_milenage_f2345(uint8* k, uint8* op_c, uint8* rand, uint8* res, u // Compute out for IK for (i = 0; i < 16; i++) { - rijndael_input[(i + 8) % 16] = temp[i] ^ op_c[i]; + input[(i + 8) % 16] = temp[i] ^ op_c[i]; } - rijndael_input[15] ^= 4; - rijndael_encrypt(rijndael_input, &round_keys, out); + input[15] ^= 4; + mbedtls_aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out); for (i = 0; i < 16; i++) { out[i] ^= op_c[i]; } @@ -1386,28 +1128,27 @@ liblte_security_milenage_f2345(uint8* k, uint8* op_c, uint8* rand, uint8* res, u LIBLTE_ERROR_ENUM liblte_security_milenage_f5_star(uint8* k, uint8* op_c, uint8* rand, uint8* ak) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; - ROUND_KEY_STRUCT round_keys; + aes_context ctx; uint32 i; uint8 temp[16]; uint8 out[16]; - uint8 rijndael_input[16]; + uint8 input[16]; if (k != NULL && op_c != NULL && rand != NULL && ak != NULL) { // Initialize the round keys - rijndael_key_schedule(k, &round_keys); + aes_setkey_enc(&ctx, k, 128); // Compute temp for (i = 0; i < 16; i++) { - rijndael_input[i] = rand[i] ^ op_c[i]; + input[i] = rand[i] ^ op_c[i]; } - rijndael_encrypt(rijndael_input, &round_keys, temp); - + aes_crypt_ecb(&ctx, AES_ENCRYPT, input, temp); // Compute out for (i = 0; i < 16; i++) { - rijndael_input[(i + 4) % 16] = temp[i] ^ op_c[i]; + input[(i + 4) % 16] = temp[i] ^ op_c[i]; } - rijndael_input[15] ^= 8; - rijndael_encrypt(rijndael_input, &round_keys, out); + input[15] ^= 8; + aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out); for (i = 0; i < 16; i++) { out[i] ^= op_c[i]; } @@ -1432,13 +1173,12 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f5_star(uint8* k, uint8* op_c, uint8* LIBLTE_ERROR_ENUM liblte_compute_opc(uint8* k, uint8* op, uint8* op_c) { uint32 i; - ROUND_KEY_STRUCT round_keys; + aes_context ctx; LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; if (k != NULL && op != NULL && op_c != NULL) { - - rijndael_key_schedule(k, &round_keys); - rijndael_encrypt(op, &round_keys, op_c); + aes_setkey_enc(&ctx, k, 128); + aes_crypt_ecb(&ctx, AES_ENCRYPT, op, op_c); for (i = 0; i < 16; i++) { op_c[i] ^= op[i]; } @@ -1447,189 +1187,6 @@ LIBLTE_ERROR_ENUM liblte_compute_opc(uint8* k, uint8* op, uint8* op_c) return err; } -/******************************************************************************* - LOCAL FUNCTIONS -*******************************************************************************/ - -/********************************************************************* - Name: rijndael_key_schedule - - Description: Computes all Rijndael's internal subkeys from key. - - Document Reference: 35.206 v10.0.0 Annex 3 -*********************************************************************/ -void rijndael_key_schedule(uint8* key, ROUND_KEY_STRUCT* rk) -{ - uint32 i; - uint32 j; - uint8 round_const; - - // Set first round key to key - for (i = 0; i < 16; i++) { - rk->rk[0][i & 0x03][i >> 2] = key[i]; - } - - round_const = 1; - - // Compute the remaining round keys - for (i = 1; i < 11; i++) { - rk->rk[i][0][0] = S[rk->rk[i - 1][1][3]] ^ rk->rk[i - 1][0][0] ^ round_const; - rk->rk[i][1][0] = S[rk->rk[i - 1][2][3]] ^ rk->rk[i - 1][1][0]; - rk->rk[i][2][0] = S[rk->rk[i - 1][3][3]] ^ rk->rk[i - 1][2][0]; - rk->rk[i][3][0] = S[rk->rk[i - 1][0][3]] ^ rk->rk[i - 1][3][0]; - - for (j = 0; j < 4; j++) { - rk->rk[i][j][1] = rk->rk[i - 1][j][1] ^ rk->rk[i][j][0]; - rk->rk[i][j][2] = rk->rk[i - 1][j][2] ^ rk->rk[i][j][1]; - rk->rk[i][j][3] = rk->rk[i - 1][j][3] ^ rk->rk[i][j][2]; - } - - round_const = X_TIME[round_const]; - } -} - -/********************************************************************* - Name: rijndael_encrypt - - Description: Computes output using input and round keys. - - Document Reference: 35.206 v10.0.0 Annex 3 -*********************************************************************/ -void rijndael_encrypt(uint8* input, ROUND_KEY_STRUCT* rk, uint8* output) -{ - STATE_STRUCT state; - uint32 i; - uint32 r; - - // Initialize and perform round 0 - for (i = 0; i < 16; i++) { - state.state[i & 0x03][i >> 2] = input[i]; - } - key_add(&state, rk, 0); - - // Perform rounds 1 through 9 - for (r = 1; r <= 9; r++) { - byte_sub(&state); - shift_row(&state); - mix_column(&state); - key_add(&state, rk, r); - } - - // Perform round 10 - byte_sub(&state); - shift_row(&state); - key_add(&state, rk, r); - - // Return output - for (i = 0; i < 16; i++) { - output[i] = state.state[i & 0x03][i >> 2]; - } -} - -/********************************************************************* - Name: key_add - - Description: Round key addition function. - - Document Reference: 35.206 v10.0.0 Annex 3 -*********************************************************************/ -void key_add(STATE_STRUCT* state, ROUND_KEY_STRUCT* rk, uint32 round) -{ - uint32 i; - uint32 j; - - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - state->state[i][j] ^= rk->rk[round][i][j]; - } - } -} - -/********************************************************************* - Name: byte_sub - - Description: Byte substitution transformation. - - Document Reference: 35.206 v10.0.0 Annex 3 -*********************************************************************/ -void byte_sub(STATE_STRUCT* state) -{ - uint32 i; - uint32 j; - - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - state->state[i][j] = S[state->state[i][j]]; - } - } -} - -/********************************************************************* - Name: shift_row - - Description: Row shift transformation. - - Document Reference: 35.206 v10.0.0 Annex 3 -*********************************************************************/ -void shift_row(STATE_STRUCT* state) -{ - uint8 temp; - - // Left rotate row 1 by 1 - temp = state->state[1][0]; - state->state[1][0] = state->state[1][1]; - state->state[1][1] = state->state[1][2]; - state->state[1][2] = state->state[1][3]; - state->state[1][3] = temp; - - // Left rotate row 2 by 2 - temp = state->state[2][0]; - state->state[2][0] = state->state[2][2]; - state->state[2][2] = temp; - temp = state->state[2][1]; - state->state[2][1] = state->state[2][3]; - state->state[2][3] = temp; - - // Left rotate row 3 by 3 - temp = state->state[3][0]; - state->state[3][0] = state->state[3][3]; - state->state[3][3] = state->state[3][2]; - state->state[3][2] = state->state[3][1]; - state->state[3][1] = temp; -} - -/********************************************************************* - Name: mix_column - - Description: Mix column transformation. - - Document Reference: 35.206 v10.0.0 Annex 3 -*********************************************************************/ -void mix_column(STATE_STRUCT* state) -{ - uint32 i; - uint8 temp; - uint8 tmp0; - uint8 tmp; - - for (i = 0; i < 4; i++) { - temp = state->state[0][i] ^ state->state[1][i] ^ state->state[2][i] ^ state->state[3][i]; - tmp0 = state->state[0][i]; - - tmp = X_TIME[state->state[0][i] ^ state->state[1][i]]; - state->state[0][i] ^= temp ^ tmp; - - tmp = X_TIME[state->state[1][i] ^ state->state[2][i]]; - state->state[1][i] ^= temp ^ tmp; - - tmp = X_TIME[state->state[2][i] ^ state->state[3][i]]; - state->state[2][i] ^= temp ^ tmp; - - tmp = X_TIME[state->state[3][i] ^ tmp0]; - state->state[3][i] ^= temp ^ tmp; - } -} - /********************************************************************* Name: zero_tailing_bits @@ -1642,251 +1199,3 @@ void zero_tailing_bits(uint8* data, uint32 length_bits) uint8 bits = (8 - (length_bits & 0x07)) & 0x07; data[(length_bits + 7) / 8 - 1] &= (uint8)(0xFF << bits); } - -/********************************************************************* - Name: s3g_mul_x - - Description: Multiplication with reduction. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.1.1 -*********************************************************************/ -uint8 s3g_mul_x(uint8 v, uint8 c) -{ - if (v & 0x80) - return ((v << 1) ^ c); - else - return (v << 1); -} - -/********************************************************************* - Name: s3g_mul_x_pow - - Description: Recursive multiplication with reduction. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.1.2 -*********************************************************************/ -uint8 s3g_mul_x_pow(uint8 v, uint8 i, uint8 c) -{ - if (i == 0) - return v; - else - return s3g_mul_x(s3g_mul_x_pow(v, i - 1, c), c); -} - -/********************************************************************* - Name: s3g_mul_alpha - - Description: Multiplication with alpha. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.4.2 -*********************************************************************/ -uint32 s3g_mul_alpha(uint8 c) -{ - return ((((uint32)s3g_mul_x_pow(c, 23, 0xa9)) << 24) | (((uint32)s3g_mul_x_pow(c, 245, 0xa9)) << 16) | - (((uint32)s3g_mul_x_pow(c, 48, 0xa9)) << 8) | (((uint32)s3g_mul_x_pow(c, 239, 0xa9)))); -} - -/********************************************************************* - Name: s3g_div_alpha - - Description: Division by alpha. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.4.3 -*********************************************************************/ -uint32 s3g_div_alpha(uint8 c) -{ - return ((((uint32)s3g_mul_x_pow(c, 16, 0xa9)) << 24) | (((uint32)s3g_mul_x_pow(c, 39, 0xa9)) << 16) | - (((uint32)s3g_mul_x_pow(c, 6, 0xa9)) << 8) | (((uint32)s3g_mul_x_pow(c, 64, 0xa9)))); -} - -/********************************************************************* - Name: s3g_s1 - - Description: S-Box S1. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.3.1 -*********************************************************************/ -uint32 s3g_s1(uint32 w) -{ - uint8 r0 = 0, r1 = 0, r2 = 0, r3 = 0; - uint8 srw0 = S[(uint8)((w >> 24) & 0xff)]; - uint8 srw1 = S[(uint8)((w >> 16) & 0xff)]; - uint8 srw2 = S[(uint8)((w >> 8) & 0xff)]; - uint8 srw3 = S[(uint8)((w)&0xff)]; - - r0 = ((s3g_mul_x(srw0, 0x1b)) ^ (srw1) ^ (srw2) ^ ((s3g_mul_x(srw3, 0x1b)) ^ srw3)); - - r1 = (((s3g_mul_x(srw0, 0x1b)) ^ srw0) ^ (s3g_mul_x(srw1, 0x1b)) ^ (srw2) ^ (srw3)); - - r2 = ((srw0) ^ ((s3g_mul_x(srw1, 0x1b)) ^ srw1) ^ (s3g_mul_x(srw2, 0x1b)) ^ (srw3)); - - r3 = ((srw0) ^ (srw1) ^ ((s3g_mul_x(srw2, 0x1b)) ^ srw2) ^ (s3g_mul_x(srw3, 0x1b))); - - return ((((uint32)r0) << 24) | (((uint32)r1) << 16) | (((uint32)r2) << 8) | (((uint32)r3))); -} - -/********************************************************************* - Name: s3g_s2 - - Description: S-Box S2. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.3.2 -*********************************************************************/ -uint32 s3g_s2(uint32 w) -{ - uint8 r0 = 0, r1 = 0, r2 = 0, r3 = 0; - uint8 sqw0 = SQ[(uint8)((w >> 24) & 0xff)]; - uint8 sqw1 = SQ[(uint8)((w >> 16) & 0xff)]; - uint8 sqw2 = SQ[(uint8)((w >> 8) & 0xff)]; - uint8 sqw3 = SQ[(uint8)((w)&0xff)]; - - r0 = ((s3g_mul_x(sqw0, 0x69)) ^ (sqw1) ^ (sqw2) ^ ((s3g_mul_x(sqw3, 0x69)) ^ sqw3)); - - r1 = (((s3g_mul_x(sqw0, 0x69)) ^ sqw0) ^ (s3g_mul_x(sqw1, 0x69)) ^ (sqw2) ^ (sqw3)); - - r2 = ((sqw0) ^ ((s3g_mul_x(sqw1, 0x69)) ^ sqw1) ^ (s3g_mul_x(sqw2, 0x69)) ^ (sqw3)); - - r3 = ((sqw0) ^ (sqw1) ^ ((s3g_mul_x(sqw2, 0x69)) ^ sqw2) ^ (s3g_mul_x(sqw3, 0x69))); - - return ((((uint32)r0) << 24) | (((uint32)r1) << 16) | (((uint32)r2) << 8) | (((uint32)r3))); -} - -/********************************************************************* - Name: s3g_clock_lfsr - - Description: Clocking LFSR. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.4.4 and Section 3.4.5 -*********************************************************************/ -void s3g_clock_lfsr(S3G_STATE* state, uint32 f) -{ - uint32 v = (((state->lfsr[0] << 8) & 0xffffff00) ^ (s3g_mul_alpha((uint8)((state->lfsr[0] >> 24) & 0xff))) ^ - (state->lfsr[2]) ^ ((state->lfsr[11] >> 8) & 0x00ffffff) ^ - (s3g_div_alpha((uint8)((state->lfsr[11]) & 0xff))) ^ (f)); - uint8 i; - - for (i = 0; i < 15; i++) { - state->lfsr[i] = state->lfsr[i + 1]; - } - state->lfsr[15] = v; -} - -/********************************************************************* - Name: s3g_clock_fsm - - Description: Clocking FSM. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 3.4.6 -*********************************************************************/ -uint32 s3g_clock_fsm(S3G_STATE* state) -{ - uint32 f = ((state->lfsr[15] + state->fsm[0]) & 0xffffffff) ^ state->fsm[1]; - uint32 r = (state->fsm[1] + (state->fsm[2] ^ state->lfsr[5])) & 0xffffffff; - - state->fsm[2] = s3g_s2(state->fsm[1]); - state->fsm[1] = s3g_s1(state->fsm[0]); - state->fsm[0] = r; - - return f; -} - -/********************************************************************* - Name: s3g_initialize - - Description: Initialization. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 4.1 -*********************************************************************/ -void s3g_initialize(S3G_STATE* state, uint32 k[4], uint32 iv[4]) -{ - uint8 i = 0; - uint32 f = 0x0; - - state->lfsr = (uint32*)calloc(16, sizeof(uint32)); - state->fsm = (uint32*)calloc(3, sizeof(uint32)); - - state->lfsr[15] = k[3] ^ iv[0]; - state->lfsr[14] = k[2]; - state->lfsr[13] = k[1]; - state->lfsr[12] = k[0] ^ iv[1]; - - state->lfsr[11] = k[3] ^ 0xffffffff; - state->lfsr[10] = k[2] ^ 0xffffffff ^ iv[2]; - state->lfsr[9] = k[1] ^ 0xffffffff ^ iv[3]; - state->lfsr[8] = k[0] ^ 0xffffffff; - state->lfsr[7] = k[3]; - state->lfsr[6] = k[2]; - state->lfsr[5] = k[1]; - state->lfsr[4] = k[0]; - state->lfsr[3] = k[3] ^ 0xffffffff; - state->lfsr[2] = k[2] ^ 0xffffffff; - state->lfsr[1] = k[1] ^ 0xffffffff; - state->lfsr[0] = k[0] ^ 0xffffffff; - - state->fsm[0] = 0x0; - state->fsm[1] = 0x0; - state->fsm[2] = 0x0; - for (i = 0; i < 32; i++) { - f = s3g_clock_fsm(state); - s3g_clock_lfsr(state, f); - } -} - -/********************************************************************* - Name: s3g_deinitialize - - Description: Deinitialization. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 -*********************************************************************/ -void s3g_deinitialize(S3G_STATE* state) -{ - free(state->lfsr); - free(state->fsm); -} - -/********************************************************************* - Name: s3g_generate_keystream - - Description: Generation of Keystream. - - Document Reference: Specification of the 3GPP Confidentiality and - Integrity Algorithms UEA2 & UIA2 D2 v1.1 - Section 4.2 -*********************************************************************/ -void s3g_generate_keystream(S3G_STATE* state, uint32 n, uint32* ks) -{ - uint32 t = 0; - uint32 f = 0x0; - - // Clock FSM once. Discard the output. - s3g_clock_fsm(state); - // Clock LFSR in keystream mode once. - s3g_clock_lfsr(state, 0x0); - - for (t = 0; t < n; t++) { - f = s3g_clock_fsm(state); - // Note that ks[t] corresponds to z_{t+1} in section 4.2 - ks[t] = f ^ state->lfsr[0]; - s3g_clock_lfsr(state, 0x0); - } -} diff --git a/lib/src/common/s3g.cc b/lib/src/common/s3g.cc new file mode 100644 index 000000000..f773c787b --- /dev/null +++ b/lib/src/common/s3g.cc @@ -0,0 +1,568 @@ +/* + * Copyright 2013-2020 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "srslte/common/s3g.h" + +/* S-box SQ */ +static const uint8_t SQ[256] = { + 0x25, 0x24, 0x73, 0x67, 0xD7, 0xAE, 0x5C, 0x30, 0xA4, 0xEE, 0x6E, 0xCB, 0x7D, 0xB5, 0x82, 0xDB, 0xE4, 0x8E, 0x48, + 0x49, 0x4F, 0x5D, 0x6A, 0x78, 0x70, 0x88, 0xE8, 0x5F, 0x5E, 0x84, 0x65, 0xE2, 0xD8, 0xE9, 0xCC, 0xED, 0x40, 0x2F, + 0x11, 0x28, 0x57, 0xD2, 0xAC, 0xE3, 0x4A, 0x15, 0x1B, 0xB9, 0xB2, 0x80, 0x85, 0xA6, 0x2E, 0x02, 0x47, 0x29, 0x07, + 0x4B, 0x0E, 0xC1, 0x51, 0xAA, 0x89, 0xD4, 0xCA, 0x01, 0x46, 0xB3, 0xEF, 0xDD, 0x44, 0x7B, 0xC2, 0x7F, 0xBE, 0xC3, + 0x9F, 0x20, 0x4C, 0x64, 0x83, 0xA2, 0x68, 0x42, 0x13, 0xB4, 0x41, 0xCD, 0xBA, 0xC6, 0xBB, 0x6D, 0x4D, 0x71, 0x21, + 0xF4, 0x8D, 0xB0, 0xE5, 0x93, 0xFE, 0x8F, 0xE6, 0xCF, 0x43, 0x45, 0x31, 0x22, 0x37, 0x36, 0x96, 0xFA, 0xBC, 0x0F, + 0x08, 0x52, 0x1D, 0x55, 0x1A, 0xC5, 0x4E, 0x23, 0x69, 0x7A, 0x92, 0xFF, 0x5B, 0x5A, 0xEB, 0x9A, 0x1C, 0xA9, 0xD1, + 0x7E, 0x0D, 0xFC, 0x50, 0x8A, 0xB6, 0x62, 0xF5, 0x0A, 0xF8, 0xDC, 0x03, 0x3C, 0x0C, 0x39, 0xF1, 0xB8, 0xF3, 0x3D, + 0xF2, 0xD5, 0x97, 0x66, 0x81, 0x32, 0xA0, 0x00, 0x06, 0xCE, 0xF6, 0xEA, 0xB7, 0x17, 0xF7, 0x8C, 0x79, 0xD6, 0xA7, + 0xBF, 0x8B, 0x3F, 0x1F, 0x53, 0x63, 0x75, 0x35, 0x2C, 0x60, 0xFD, 0x27, 0xD3, 0x94, 0xA5, 0x7C, 0xA1, 0x05, 0x58, + 0x2D, 0xBD, 0xD9, 0xC7, 0xAF, 0x6B, 0x54, 0x0B, 0xE0, 0x38, 0x04, 0xC8, 0x9D, 0xE7, 0x14, 0xB1, 0x87, 0x9C, 0xDF, + 0x6F, 0xF9, 0xDA, 0x2A, 0xC4, 0x59, 0x16, 0x74, 0x91, 0xAB, 0x26, 0x61, 0x76, 0x34, 0x2B, 0xAD, 0x99, 0xFB, 0x72, + 0xEC, 0x33, 0x12, 0xDE, 0x98, 0x3B, 0xC0, 0x9B, 0x3E, 0x18, 0x10, 0x3A, 0x56, 0xE1, 0x77, 0xC9, 0x1E, 0x9E, 0x95, + 0xA3, 0x90, 0x19, 0xA8, 0x6C, 0x09, 0xD0, 0xF0, 0x86}; + +static const uint8_t S[256] = { + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, + 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, + 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, + 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, + 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, + 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, + 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, + 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, + 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, + 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, + 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, + 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22}; +/********************************************************************* + Name: s3g_mul_x + + Description: Multiplication with reduction. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.1.1 +*********************************************************************/ +uint8_t s3g_mul_x(uint8_t v, uint8_t c); + +/********************************************************************* + Name: s3g_mul_x_pow + + Description: Recursive multiplication with reduction. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.1.2 +*********************************************************************/ +uint8_t s3g_mul_x_pow(uint8_t v, uint8_t i, uint8_t c); + +/********************************************************************* + Name: s3g_mul_alpha + + Description: Multiplication with alpha. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.2 +*********************************************************************/ +uint32_t s3g_mul_alpha(uint8_t c); + +/********************************************************************* + Name: s3g_div_alpha + + Description: Division by alpha. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.3 +*********************************************************************/ +uint32_t s3g_div_alpha(uint8_t c); + +/********************************************************************* + Name: s3g_s1 + + Description: S-Box S1. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.3.1 +*********************************************************************/ +uint32_t s3g_s1(uint32_t w); + +/********************************************************************* + Name: s3g_s2 + + Description: S-Box S2. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.3.2 +*********************************************************************/ +uint32_t s3g_s2(uint32_t w); + +/********************************************************************* + Name: s3g_clock_lfsr + + Description: Clocking LFSR. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.4 and Section 3.4.5 +*********************************************************************/ +void s3g_clock_lfsr(S3G_STATE* state, uint32_t f); + +/********************************************************************* + Name: s3g_clock_fsm + + Description: Clocking FSM. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.6 +*********************************************************************/ +uint32_t s3g_clock_fsm(S3G_STATE* state); + +/********************************************************************* + Name: s3g_deinitialize + + Description: Deinitialization. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 +*********************************************************************/ +void s3g_deinitialize(S3G_STATE* state); + +/********************************************************************* + Name: s3g_generate_keystream + + Description: Generation of Keystream. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 4.2 +*********************************************************************/ +void s3g_generate_keystream(S3G_STATE* state, uint32_t n, uint32_t* ks); + +/********************************************************************* + Name: s3g_mul_x + + Description: Multiplication with reduction. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.1.1 +*********************************************************************/ +uint8_t s3g_mul_x(uint8_t v, uint8_t c) +{ + if (v & 0x80) + return ((v << 1) ^ c); + else + return (v << 1); +} + +/********************************************************************* + Name: s3g_mul_x_pow + + Description: Recursive multiplication with reduction. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.1.2 +*********************************************************************/ +uint8_t s3g_mul_x_pow(uint8_t v, uint8_t i, uint8_t c) +{ + if (i == 0) + return v; + else + return s3g_mul_x(s3g_mul_x_pow(v, i - 1, c), c); +} + +/********************************************************************* + Name: s3g_mul_alpha + + Description: Multiplication with alpha. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.2 +*********************************************************************/ +uint32_t s3g_mul_alpha(uint8_t c) +{ + return ((((uint32_t)s3g_mul_x_pow(c, 23, 0xa9)) << 24) | (((uint32_t)s3g_mul_x_pow(c, 245, 0xa9)) << 16) | + (((uint32_t)s3g_mul_x_pow(c, 48, 0xa9)) << 8) | (((uint32_t)s3g_mul_x_pow(c, 239, 0xa9)))); +} + +/********************************************************************* + Name: s3g_div_alpha + + Description: Division by alpha. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.3 +*********************************************************************/ +uint32_t s3g_div_alpha(uint8_t c) +{ + return ((((uint32_t)s3g_mul_x_pow(c, 16, 0xa9)) << 24) | (((uint32_t)s3g_mul_x_pow(c, 39, 0xa9)) << 16) | + (((uint32_t)s3g_mul_x_pow(c, 6, 0xa9)) << 8) | (((uint32_t)s3g_mul_x_pow(c, 64, 0xa9)))); +} + +/********************************************************************* + Name: s3g_s1 + + Description: S-Box S1. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.3.1 +*********************************************************************/ +uint32_t s3g_s1(uint32_t w) +{ + uint8_t r0 = 0, r1 = 0, r2 = 0, r3 = 0; + uint8_t srw0 = S[(uint8_t)((w >> 24) & 0xff)]; + uint8_t srw1 = S[(uint8_t)((w >> 16) & 0xff)]; + uint8_t srw2 = S[(uint8_t)((w >> 8) & 0xff)]; + uint8_t srw3 = S[(uint8_t)((w)&0xff)]; + + r0 = ((s3g_mul_x(srw0, 0x1b)) ^ (srw1) ^ (srw2) ^ ((s3g_mul_x(srw3, 0x1b)) ^ srw3)); + + r1 = (((s3g_mul_x(srw0, 0x1b)) ^ srw0) ^ (s3g_mul_x(srw1, 0x1b)) ^ (srw2) ^ (srw3)); + + r2 = ((srw0) ^ ((s3g_mul_x(srw1, 0x1b)) ^ srw1) ^ (s3g_mul_x(srw2, 0x1b)) ^ (srw3)); + + r3 = ((srw0) ^ (srw1) ^ ((s3g_mul_x(srw2, 0x1b)) ^ srw2) ^ (s3g_mul_x(srw3, 0x1b))); + + return ((((uint32_t)r0) << 24) | (((uint32_t)r1) << 16) | (((uint32_t)r2) << 8) | (((uint32_t)r3))); +} + +/********************************************************************* + Name: s3g_s2 + + Description: S-Box S2. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.3.2 +*********************************************************************/ +uint32_t s3g_s2(uint32_t w) +{ + uint8_t r0 = 0, r1 = 0, r2 = 0, r3 = 0; + uint8_t sqw0 = SQ[(uint8_t)((w >> 24) & 0xff)]; + uint8_t sqw1 = SQ[(uint8_t)((w >> 16) & 0xff)]; + uint8_t sqw2 = SQ[(uint8_t)((w >> 8) & 0xff)]; + uint8_t sqw3 = SQ[(uint8_t)((w)&0xff)]; + + r0 = ((s3g_mul_x(sqw0, 0x69)) ^ (sqw1) ^ (sqw2) ^ ((s3g_mul_x(sqw3, 0x69)) ^ sqw3)); + + r1 = (((s3g_mul_x(sqw0, 0x69)) ^ sqw0) ^ (s3g_mul_x(sqw1, 0x69)) ^ (sqw2) ^ (sqw3)); + + r2 = ((sqw0) ^ ((s3g_mul_x(sqw1, 0x69)) ^ sqw1) ^ (s3g_mul_x(sqw2, 0x69)) ^ (sqw3)); + + r3 = ((sqw0) ^ (sqw1) ^ ((s3g_mul_x(sqw2, 0x69)) ^ sqw2) ^ (s3g_mul_x(sqw3, 0x69))); + + return ((((uint32_t)r0) << 24) | (((uint32_t)r1) << 16) | (((uint32_t)r2) << 8) | (((uint32_t)r3))); +} + +/********************************************************************* + Name: s3g_clock_lfsr + + Description: Clocking LFSR. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.4 and Section 3.4.5 +*********************************************************************/ +void s3g_clock_lfsr(S3G_STATE* state, uint32_t f) +{ + uint32_t v = (((state->lfsr[0] << 8) & 0xffffff00) ^ (s3g_mul_alpha((uint8_t)((state->lfsr[0] >> 24) & 0xff))) ^ + (state->lfsr[2]) ^ ((state->lfsr[11] >> 8) & 0x00ffffff) ^ + (s3g_div_alpha((uint8_t)((state->lfsr[11]) & 0xff))) ^ (f)); + uint8_t i; + + for (i = 0; i < 15; i++) { + state->lfsr[i] = state->lfsr[i + 1]; + } + state->lfsr[15] = v; +} + +/********************************************************************* + Name: s3g_clock_fsm + + Description: Clocking FSM. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 3.4.6 +*********************************************************************/ +uint32_t s3g_clock_fsm(S3G_STATE* state) +{ + uint32_t f = ((state->lfsr[15] + state->fsm[0]) & 0xffffffff) ^ state->fsm[1]; + uint32_t r = (state->fsm[1] + (state->fsm[2] ^ state->lfsr[5])) & 0xffffffff; + + state->fsm[2] = s3g_s2(state->fsm[1]); + state->fsm[1] = s3g_s1(state->fsm[0]); + state->fsm[0] = r; + + return f; +} + +/********************************************************************* + Name: s3g_initialize + + Description: Initialization. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 4.1 +*********************************************************************/ +void s3g_initialize(S3G_STATE* state, uint32_t k[4], uint32_t iv[4]) +{ + uint8_t i = 0; + uint32_t f = 0x0; + + state->lfsr = (uint32_t*)calloc(16, sizeof(uint32_t)); + state->fsm = (uint32_t*)calloc(3, sizeof(uint32_t)); + + state->lfsr[15] = k[3] ^ iv[0]; + state->lfsr[14] = k[2]; + state->lfsr[13] = k[1]; + state->lfsr[12] = k[0] ^ iv[1]; + + state->lfsr[11] = k[3] ^ 0xffffffff; + state->lfsr[10] = k[2] ^ 0xffffffff ^ iv[2]; + state->lfsr[9] = k[1] ^ 0xffffffff ^ iv[3]; + state->lfsr[8] = k[0] ^ 0xffffffff; + state->lfsr[7] = k[3]; + state->lfsr[6] = k[2]; + state->lfsr[5] = k[1]; + state->lfsr[4] = k[0]; + state->lfsr[3] = k[3] ^ 0xffffffff; + state->lfsr[2] = k[2] ^ 0xffffffff; + state->lfsr[1] = k[1] ^ 0xffffffff; + state->lfsr[0] = k[0] ^ 0xffffffff; + + state->fsm[0] = 0x0; + state->fsm[1] = 0x0; + state->fsm[2] = 0x0; + for (i = 0; i < 32; i++) { + f = s3g_clock_fsm(state); + s3g_clock_lfsr(state, f); + } +} + +/********************************************************************* + Name: s3g_deinitialize + + Description: Deinitialization. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 +*********************************************************************/ +void s3g_deinitialize(S3G_STATE* state) +{ + free(state->lfsr); + free(state->fsm); +} + +/********************************************************************* + Name: s3g_generate_keystream + + Description: Generation of Keystream. + + Document Reference: Specification of the 3GPP Confidentiality and + Integrity Algorithms UEA2 & UIA2 D2 v1.1 + Section 4.2 +*********************************************************************/ +void s3g_generate_keystream(S3G_STATE* state, uint32_t n, uint32_t* ks) +{ + uint32_t t = 0; + uint32_t f = 0x0; + + // Clock FSM once. Discard the output. + s3g_clock_fsm(state); + // Clock LFSR in keystream mode once. + s3g_clock_lfsr(state, 0x0); + + for (t = 0; t < n; t++) { + f = s3g_clock_fsm(state); + // Note that ks[t] corresponds to z_{t+1} in section 4.2 + ks[t] = f ^ state->lfsr[0]; + s3g_clock_lfsr(state, 0x0); + } +} + +/* MUL64x. + * Input V: a 64-bit input. + * Input c: a 64-bit input. + * Output : a 64-bit output. + * A 64-bit memory is allocated which is to be freed by the calling + * function. + * See section 4.3.2 for details. + */ +uint64_t s3g_MUL64x(uint64_t V, uint64_t c) +{ + if (V & 0x8000000000000000) + return (V << 1) ^ c; + else + return V << 1; +} + +/* MUL64xPOW. + * Input V: a 64-bit input. + * Input i: a positive integer. + * Input c: a 64-bit input. + * Output : a 64-bit output. + * A 64-bit memory is allocated which is to be freed by the calling function. + * See section 4.3.3 for details. + */ +uint64_t s3g_MUL64xPOW(uint64_t V, uint8_t i, uint64_t c) +{ + if (i == 0) + return V; + else + return s3g_MUL64x(s3g_MUL64xPOW(V, i - 1, c), c); +} + +/* MUL64. + * Input V: a 64-bit input. + * Input P: a 64-bit input. + * Input c: a 64-bit input. + * Output : a 64-bit output. + * A 64-bit memory is allocated which is to be freed by the calling + * function. + * See section 4.3.4 for details. + */ +uint64_t s3g_MUL64(uint64_t V, uint64_t P, uint64_t c) +{ + uint64_t result = 0; + int i = 0; + + for (i = 0; i < 64; i++) { + if ((P >> i) & 0x1) + result ^= s3g_MUL64xPOW(V, i, c); + } + return result; +} + +/* mask8bit. + * Input n: an integer in 1-7. + * Output : an 8 bit mask. + * Prepares an 8 bit mask with required number of 1 bits on the MSB side. + */ +uint8_t mask8bit(int n) +{ + return 0xFF ^ ((1 << (8 - n)) - 1); +} + +/* f9. + * Input key: 128 bit Integrity Key. + * Input count:32-bit Count, Frame dependent input. + * Input fresh: 32-bit Random number. + * Input dir:1 bit, direction of transmission (in the LSB). + * Input data: length number of bits, input bit stream. + * Input length: 64 bit Length, i.e., the number of bits to be MAC'd. + * Output : 32 bit block used as MAC + * Generates 32-bit MAC using UIA2 algorithm as defined in Section 4. + */ +uint8_t* s3g_f9(const uint8_t* key, uint32_t count, uint32_t fresh, uint32_t dir, uint8_t* data, uint64_t length) +{ + uint32_t K[4], IV[4], z[5]; + uint32_t i = 0, D; + static uint8_t MAC_I[4] = {0, 0, 0, 0}; /* static memory for the result */ + uint64_t EVAL; + uint64_t V; + uint64_t P; + uint64_t Q; + uint64_t c; + S3G_STATE state, *state_ptr; + + uint64_t M_D_2; + int rem_bits = 0; + state_ptr = &state; + /* Load the Integrity Key for SNOW3G initialization as in section 4.4. */ + for (i = 0; i < 4; i++) + K[3 - i] = (key[4 * i] << 24) ^ (key[4 * i + 1] << 16) ^ (key[4 * i + 2] << 8) ^ (key[4 * i + 3]); + + /* Prepare the Initialization Vector (IV) for SNOW3G initialization as + in section 4.4. */ + IV[3] = count; + IV[2] = fresh; + IV[1] = count ^ (dir << 31); + IV[0] = fresh ^ (dir << 15); + + z[0] = z[1] = z[2] = z[3] = z[4] = 0; + + /* Run SNOW 3G to produce 5 keystream words z_1, z_2, z_3, z_4 and z_5. */ + s3g_initialize(state_ptr, K, IV); + s3g_generate_keystream(state_ptr, 5, z); + s3g_deinitialize(state_ptr); + P = (uint64_t)z[0] << 32 | (uint64_t)z[1]; + Q = (uint64_t)z[2] << 32 | (uint64_t)z[3]; + + /* Calculation */ + if ((length % 64) == 0) + D = (length >> 6) + 1; + else + D = (length >> 6) + 2; + EVAL = 0; + c = 0x1b; + + /* for 0 <= i <= D-3 */ + for (i = 0; i < D - 2; i++) { + V = EVAL ^ ((uint64_t)data[8 * i] << 56 | (uint64_t)data[8 * i + 1] << 48 | (uint64_t)data[8 * i + 2] << 40 | + (uint64_t)data[8 * i + 3] << 32 | (uint64_t)data[8 * i + 4] << 24 | (uint64_t)data[8 * i + 5] << 16 | + (uint64_t)data[8 * i + 6] << 8 | (uint64_t)data[8 * i + 7]); + EVAL = s3g_MUL64(V, P, c); + } + + /* for D-2 */ + rem_bits = length % 64; + if (rem_bits == 0) + rem_bits = 64; + + M_D_2 = 0; + i = 0; + while (rem_bits > 7) { + M_D_2 |= (uint64_t)data[8 * (D - 2) + i] << (8 * (7 - i)); + rem_bits -= 8; + i++; + } + if (rem_bits > 0) + M_D_2 |= (uint64_t)(data[8 * (D - 2) + i] & mask8bit(rem_bits)) << (8 * (7 - i)); + + V = EVAL ^ M_D_2; + EVAL = s3g_MUL64(V, P, c); + + /* for D-1 */ + EVAL ^= length; + + /* Multiply by Q */ + EVAL = s3g_MUL64(EVAL, Q, c); + + /* XOR with z_5: this is a modification to the reference C code, + which forgot to XOR z[5] */ + for (i = 0; i < 4; i++) + /* + MAC_I[i] = (mac32 >> (8*(3-i))) & 0xff; + */ + MAC_I[i] = ((EVAL >> (56 - (i * 8))) ^ (z[4] >> (24 - (i * 8)))) & 0xff; + + return MAC_I; +} \ No newline at end of file diff --git a/lib/src/common/security.cc b/lib/src/common/security.cc index 3423bc67a..eb7833d01 100644 --- a/lib/src/common/security.cc +++ b/lib/src/common/security.cc @@ -21,7 +21,7 @@ #include "srslte/common/security.h" #include "srslte/common/liblte_security.h" -#include "srslte/common/snow_3g.h" +#include "srslte/common/s3g.h" #ifdef HAVE_MBEDTLS #include "mbedtls/md5.h" @@ -113,16 +113,7 @@ uint8_t security_128_eia1(const uint8_t* key, uint32_t msg_len, uint8_t* mac) { - uint32_t msg_len_bits; - uint32_t i; - uint8_t* m_ptr; - - msg_len_bits = msg_len * 8; - m_ptr = snow3g_f9(const_cast(key), count, bearer << 27, direction, msg, msg_len_bits); - for (i = 0; i < 4; i++) { - mac[i] = m_ptr[i]; - } - return SRSLTE_SUCCESS; + return liblte_security_128_eia1(key, count, bearer, direction, msg, msg_len, mac); } uint8_t security_128_eia2(const uint8_t* key, @@ -136,13 +127,13 @@ uint8_t security_128_eia2(const uint8_t* key, return liblte_security_128_eia2(key, count, bearer, direction, msg, msg_len, mac); } -uint8_t security_128_eia3(uint8_t* key, - uint32_t count, - uint32_t bearer, - uint8_t direction, - uint8_t* msg, - uint32_t msg_len, - uint8_t* mac) +uint8_t security_128_eia3(const uint8_t* key, + uint32_t count, + uint32_t bearer, + uint8_t direction, + uint8_t* msg, + uint32_t msg_len, + uint8_t* mac) { return liblte_security_128_eia3(key, count, bearer, direction, msg, msg_len * 8, mac); } diff --git a/lib/src/common/snow_3g.cc b/lib/src/common/snow_3g.cc deleted file mode 100644 index 13ab0c102..000000000 --- a/lib/src/common/snow_3g.cc +++ /dev/null @@ -1,515 +0,0 @@ -/*------------------------------------------------------------------------ - * snow_3g.c - * - * Adapted from ETSI/SAGE specifications: - * "Specification of the 3GPP Confidentiality and - * Integrity Algorithms UEA2 & UIA2. - * Document 1: UEA2 and UIA2 Specification" - * "Specification of the 3GPP Confidentiality - * and Integrity Algorithms UEA2 & UIA2. - * Document 2: SNOW 3G Specification" - *------------------------------------------------------------------------*/ - -#include "srslte/common/snow_3g.h" - -/* LFSR */ - -u32 LFSR_S0 = 0x00; -u32 LFSR_S1 = 0x00; -u32 LFSR_S2 = 0x00; -u32 LFSR_S3 = 0x00; -u32 LFSR_S4 = 0x00; -u32 LFSR_S5 = 0x00; -u32 LFSR_S6 = 0x00; -u32 LFSR_S7 = 0x00; -u32 LFSR_S8 = 0x00; -u32 LFSR_S9 = 0x00; -u32 LFSR_S10 = 0x00; -u32 LFSR_S11 = 0x00; -u32 LFSR_S12 = 0x00; -u32 LFSR_S13 = 0x00; -u32 LFSR_S14 = 0x00; -u32 LFSR_S15 = 0x00; - -/* FSM */ - -u32 FSM_R1 = 0x00; -u32 FSM_R2 = 0x00; -u32 FSM_R3 = 0x00; - -/* Rijndael S-box SR */ - -static u8 snow_3g_SR[256] = { - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, - 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, - 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, - 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, - 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, - 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, - 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, - 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, - 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, - 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, - 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, - 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, - 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, - 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16}; - -/* S-box SQ */ - -static u8 snow_3g_SQ[256] = { - 0x25, 0x24, 0x73, 0x67, 0xD7, 0xAE, 0x5C, 0x30, 0xA4, 0xEE, 0x6E, 0xCB, 0x7D, 0xB5, 0x82, 0xDB, 0xE4, 0x8E, 0x48, - 0x49, 0x4F, 0x5D, 0x6A, 0x78, 0x70, 0x88, 0xE8, 0x5F, 0x5E, 0x84, 0x65, 0xE2, 0xD8, 0xE9, 0xCC, 0xED, 0x40, 0x2F, - 0x11, 0x28, 0x57, 0xD2, 0xAC, 0xE3, 0x4A, 0x15, 0x1B, 0xB9, 0xB2, 0x80, 0x85, 0xA6, 0x2E, 0x02, 0x47, 0x29, 0x07, - 0x4B, 0x0E, 0xC1, 0x51, 0xAA, 0x89, 0xD4, 0xCA, 0x01, 0x46, 0xB3, 0xEF, 0xDD, 0x44, 0x7B, 0xC2, 0x7F, 0xBE, 0xC3, - 0x9F, 0x20, 0x4C, 0x64, 0x83, 0xA2, 0x68, 0x42, 0x13, 0xB4, 0x41, 0xCD, 0xBA, 0xC6, 0xBB, 0x6D, 0x4D, 0x71, 0x21, - 0xF4, 0x8D, 0xB0, 0xE5, 0x93, 0xFE, 0x8F, 0xE6, 0xCF, 0x43, 0x45, 0x31, 0x22, 0x37, 0x36, 0x96, 0xFA, 0xBC, 0x0F, - 0x08, 0x52, 0x1D, 0x55, 0x1A, 0xC5, 0x4E, 0x23, 0x69, 0x7A, 0x92, 0xFF, 0x5B, 0x5A, 0xEB, 0x9A, 0x1C, 0xA9, 0xD1, - 0x7E, 0x0D, 0xFC, 0x50, 0x8A, 0xB6, 0x62, 0xF5, 0x0A, 0xF8, 0xDC, 0x03, 0x3C, 0x0C, 0x39, 0xF1, 0xB8, 0xF3, 0x3D, - 0xF2, 0xD5, 0x97, 0x66, 0x81, 0x32, 0xA0, 0x00, 0x06, 0xCE, 0xF6, 0xEA, 0xB7, 0x17, 0xF7, 0x8C, 0x79, 0xD6, 0xA7, - 0xBF, 0x8B, 0x3F, 0x1F, 0x53, 0x63, 0x75, 0x35, 0x2C, 0x60, 0xFD, 0x27, 0xD3, 0x94, 0xA5, 0x7C, 0xA1, 0x05, 0x58, - 0x2D, 0xBD, 0xD9, 0xC7, 0xAF, 0x6B, 0x54, 0x0B, 0xE0, 0x38, 0x04, 0xC8, 0x9D, 0xE7, 0x14, 0xB1, 0x87, 0x9C, 0xDF, - 0x6F, 0xF9, 0xDA, 0x2A, 0xC4, 0x59, 0x16, 0x74, 0x91, 0xAB, 0x26, 0x61, 0x76, 0x34, 0x2B, 0xAD, 0x99, 0xFB, 0x72, - 0xEC, 0x33, 0x12, 0xDE, 0x98, 0x3B, 0xC0, 0x9B, 0x3E, 0x18, 0x10, 0x3A, 0x56, 0xE1, 0x77, 0xC9, 0x1E, 0x9E, 0x95, - 0xA3, 0x90, 0x19, 0xA8, 0x6C, 0x09, 0xD0, 0xF0, 0x86}; - -/* MULx. - * Input V: an 8-bit input. - * Input c: an 8-bit input. - * Output : an 8-bit output. - * See section 3.1.1 for details. - */ - -u8 MULx(u8 V, u8 c) -{ - if (V & 0x80) - return ((V << 1) ^ c); - else - return (V << 1); -} - -/* MULxPOW. - * Input V: an 8-bit input. - * Input i: a positive integer. - * Input c: an 8-bit input. - * Output : an 8-bit output. - * See section 3.1.2 for details. - */ - -u8 MULxPOW(u8 V, u8 i, u8 c) -{ - if (i == 0) - return V; - else - return MULx(MULxPOW(V, i - 1, c), c); -} - -/* The function MUL alpha. - * Input c: 8-bit input. - * Output : 32-bit output. - * See section 3.4.2 for details. - */ - -u32 MULalpha(u8 c) -{ - return ((((u32)MULxPOW(c, 23, 0xa9)) << 24) | (((u32)MULxPOW(c, 245, 0xa9)) << 16) | - (((u32)MULxPOW(c, 48, 0xa9)) << 8) | (((u32)MULxPOW(c, 239, 0xa9)))); -} - -/* The function DIV alpha. - * Input c: 8-bit input. - * Output : 32-bit output. - * See section 3.4.3 for details. - */ - -u32 DIValpha(u8 c) -{ - return ((((u32)MULxPOW(c, 16, 0xa9)) << 24) | (((u32)MULxPOW(c, 39, 0xa9)) << 16) | - (((u32)MULxPOW(c, 6, 0xa9)) << 8) | (((u32)MULxPOW(c, 64, 0xa9)))); -} - -/* The 32x32-bit S-Box S1 - * Input: a 32-bit input. - * Output: a 32-bit output of S1 box. - * See section 3.3.1. - */ - -u32 S1(u32 w) -{ - u8 r0 = 0, r1 = 0, r2 = 0, r3 = 0; - u8 srw0 = snow_3g_SR[(u8)((w >> 24) & 0xff)]; - u8 srw1 = snow_3g_SR[(u8)((w >> 16) & 0xff)]; - u8 srw2 = snow_3g_SR[(u8)((w >> 8) & 0xff)]; - u8 srw3 = snow_3g_SR[(u8)((w)&0xff)]; - r0 = ((MULx(srw0, 0x1b)) ^ (srw1) ^ (srw2) ^ ((MULx(srw3, 0x1b)) ^ srw3)); - r1 = (((MULx(srw0, 0x1b)) ^ srw0) ^ (MULx(srw1, 0x1b)) ^ (srw2) ^ (srw3)); - r2 = ((srw0) ^ ((MULx(srw1, 0x1b)) ^ srw1) ^ (MULx(srw2, 0x1b)) ^ (srw3)); - r3 = ((srw0) ^ (srw1) ^ ((MULx(srw2, 0x1b)) ^ srw2) ^ (MULx(srw3, 0x1b))); - - return ((((u32)r0) << 24) | (((u32)r1) << 16) | (((u32)r2) << 8) | (((u32)r3))); -} - -/* The 32x32-bit S-Box S2 - * Input: a 32-bit input. - * Output: a 32-bit output of S2 box. - * See section 3.3.2. - */ - -u32 S2(u32 w) -{ - u8 r0 = 0, r1 = 0, r2 = 0, r3 = 0; - u8 sqw0 = snow_3g_SQ[(u8)((w >> 24) & 0xff)]; - u8 sqw1 = snow_3g_SQ[(u8)((w >> 16) & 0xff)]; - u8 sqw2 = snow_3g_SQ[(u8)((w >> 8) & 0xff)]; - u8 sqw3 = snow_3g_SQ[(u8)((w)&0xff)]; - r0 = ((MULx(sqw0, 0x69)) ^ (sqw1) ^ (sqw2) ^ ((MULx(sqw3, 0x69)) ^ sqw3)); - r1 = (((MULx(sqw0, 0x69)) ^ sqw0) ^ (MULx(sqw1, 0x69)) ^ (sqw2) ^ (sqw3)); - r2 = ((sqw0) ^ ((MULx(sqw1, 0x69)) ^ sqw1) ^ (MULx(sqw2, 0x69)) ^ (sqw3)); - r3 = ((sqw0) ^ (sqw1) ^ ((MULx(sqw2, 0x69)) ^ sqw2) ^ (MULx(sqw3, 0x69))); - return ((((u32)r0) << 24) | (((u32)r1) << 16) | (((u32)r2) << 8) | (((u32)r3))); -} - -/* Clocking LFSR in initialization mode. - * LFSR Registers S0 to S15 are updated as the LFSR receives a single clock. - * Input F: a 32-bit word comes from output of FSM. - * See section 3.4.4. - */ - -void ClockLFSRInitializationMode(u32 F) -{ - u32 v = (((LFSR_S0 << 8) & 0xffffff00) ^ (MULalpha((u8)((LFSR_S0 >> 24) & 0xff))) ^ (LFSR_S2) ^ - ((LFSR_S11 >> 8) & 0x00ffffff) ^ (DIValpha((u8)((LFSR_S11)&0xff))) ^ (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 = v; -} - -/* Clocking LFSR in keystream mode. - * LFSR Registers S0 to S15 are updated as the LFSR receives a single clock. - * See section 3.4.5. - */ - -void ClockLFSRKeyStreamMode() -{ - u32 v = (((LFSR_S0 << 8) & 0xffffff00) ^ (MULalpha((u8)((LFSR_S0 >> 24) & 0xff))) ^ (LFSR_S2) ^ - ((LFSR_S11 >> 8) & 0x00ffffff) ^ (DIValpha((u8)((LFSR_S11)&0xff)))); - 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 = v; -} - -/* Clocking FSM. - * Produces a 32-bit word F. - * Updates FSM registers R1, R2, R3. - * See Section 3.4.6. - */ - -u32 ClockFSM() -{ - u32 F = ((LFSR_S15 + FSM_R1) & 0xffffffff) ^ FSM_R2; - u32 r = (FSM_R2 + (FSM_R3 ^ LFSR_S5)) & 0xffffffff; - FSM_R3 = S2(FSM_R2); - FSM_R2 = S1(FSM_R1); - FSM_R1 = r; - return F; -} - -/* Initialization. - * Input k[4]: Four 32-bit words making up 128-bit key. - * Input IV[4]: Four 32-bit words making 128-bit initialization variable. - * Output: All the LFSRs and FSM are initialized for key generation. - * See Section 4.1. - */ - -void snow3g_initialize(u32 k[4], u32 IV[4]) -{ - u8 i = 0; - u32 F = 0x0; - LFSR_S15 = k[3] ^ IV[0]; - LFSR_S14 = k[2]; - LFSR_S13 = k[1]; - LFSR_S12 = k[0] ^ IV[1]; - LFSR_S11 = k[3] ^ 0xffffffff; - LFSR_S10 = k[2] ^ 0xffffffff ^ IV[2]; - LFSR_S9 = k[1] ^ 0xffffffff ^ IV[3]; - LFSR_S8 = k[0] ^ 0xffffffff; - LFSR_S7 = k[3]; - LFSR_S6 = k[2]; - LFSR_S5 = k[1]; - LFSR_S4 = k[0]; - LFSR_S3 = k[3] ^ 0xffffffff; - LFSR_S2 = k[2] ^ 0xffffffff; - LFSR_S1 = k[1] ^ 0xffffffff; - LFSR_S0 = k[0] ^ 0xffffffff; - FSM_R1 = 0x0; - FSM_R2 = 0x0; - FSM_R3 = 0x0; - for (i = 0; i < 32; i++) { - F = ClockFSM(); - ClockLFSRInitializationMode(F); - } -} - -/* Generation of Keystream. - * input n: number of 32-bit words of keystream. - * input z: space for the generated keystream, assumes - * memory is allocated already. - * output: generated keystream which is filled in z - * See section 4.2. - */ - -void snow3g_generate_keystream(u32 n, u32* ks) -{ - u32 t = 0; - u32 F = 0x0; - ClockFSM(); /* Clock FSM once. Discard the output. */ - ClockLFSRKeyStreamMode(); /* Clock LFSR in keystream mode once. */ - for (t = 0; t < n; t++) { - F = ClockFSM(); /* STEP 1 */ - ks[t] = F ^ LFSR_S0; /* STEP 2 */ - /* Note that ks[t] corresponds to z_{t+1} in section 4.2 - */ - ClockLFSRKeyStreamMode(); /* STEP 3 */ - } -} - -/* f8. - * Input key: 128 bit Confidentiality Key. - * Input count:32-bit Count, Frame dependent input. - * Input bearer: 5-bit Bearer identity (in the LSB side). - * Input dir:1 bit, direction of transmission. - * Input data: length number of bits, input bit stream. - * Input length: 32 bit Length, i.e., the number of bits to be encrypted or - * decrypted. - * Output data: Output bit stream. Assumes data is suitably memory - * allocated. - * Encrypts/decrypts blocks of data between 1 and 2^32 bits in length as - * defined in Section 3. - */ - -void snow3g_f8(u8* key, u32 count, u32 bearer, u32 dir, u8* data, u32 length) -{ - u32 K[4], IV[4]; - int n = (length + 31) / 32; - int i = 0; - int lastbits = (8 - (length % 8)) % 8; - u32* KS; - - /*Initialisation*/ - /* Load the confidentiality key for SNOW 3G initialization as in section - 3.4. */ - for (i = 0; i < 4; i++) - K[3 - i] = (key[4 * i] << 24) ^ (key[4 * i + 1] << 16) ^ (key[4 * i + 2] << 8) ^ (key[4 * i + 3]); - - /* Prepare the initialization vector (IV) for SNOW 3G initialization as in - section 3.4. */ - IV[3] = count; - IV[2] = (bearer << 27) | ((dir & 0x1) << 26); - IV[1] = IV[3]; - IV[0] = IV[2]; - - /* Run SNOW 3G algorithm to generate sequence of key stream bits KS*/ - snow3g_initialize(K, IV); - KS = (u32*)malloc(4 * n); - snow3g_generate_keystream(n, (u32*)KS); - - /* Exclusive-OR the input data with keystream to generate the output bit - stream */ - for (i = 0; i < n; i++) { - data[4 * i + 0] ^= (u8)(KS[i] >> 24) & 0xff; - data[4 * i + 1] ^= (u8)(KS[i] >> 16) & 0xff; - data[4 * i + 2] ^= (u8)(KS[i] >> 8) & 0xff; - data[4 * i + 3] ^= (u8)(KS[i]) & 0xff; - } - - free(KS); - - /* zero last bits of data in case its length is not byte-aligned - this is an addition to the C reference code, which did not handle it */ - if (lastbits) - data[length / 8] &= 256 - (1 << lastbits); -} - -/* MUL64x. - * Input V: a 64-bit input. - * Input c: a 64-bit input. - * Output : a 64-bit output. - * A 64-bit memory is allocated which is to be freed by the calling - * function. - * See section 4.3.2 for details. - */ -u64 MUL64x(u64 V, u64 c) -{ - if (V & 0x8000000000000000) - return (V << 1) ^ c; - else - return V << 1; -} - -/* MUL64xPOW. - * Input V: a 64-bit input. - * Input i: a positive integer. - * Input c: a 64-bit input. - * Output : a 64-bit output. - * A 64-bit memory is allocated which is to be freed by the calling function. - * See section 4.3.3 for details. - */ -u64 MUL64xPOW(u64 V, u8 i, u64 c) -{ - if (i == 0) - return V; - else - return MUL64x(MUL64xPOW(V, i - 1, c), c); -} - -/* MUL64. - * Input V: a 64-bit input. - * Input P: a 64-bit input. - * Input c: a 64-bit input. - * Output : a 64-bit output. - * A 64-bit memory is allocated which is to be freed by the calling - * function. - * See section 4.3.4 for details. - */ -u64 MUL64(u64 V, u64 P, u64 c) -{ - u64 result = 0; - int i = 0; - - for (i = 0; i < 64; i++) { - if ((P >> i) & 0x1) - result ^= MUL64xPOW(V, i, c); - } - return result; -} - -/* mask8bit. - * Input n: an integer in 1-7. - * Output : an 8 bit mask. - * Prepares an 8 bit mask with required number of 1 bits on the MSB side. - */ -u8 mask8bit(int n) -{ - return 0xFF ^ ((1 << (8 - n)) - 1); -} - -/* f9. - * Input key: 128 bit Integrity Key. - * Input count:32-bit Count, Frame dependent input. - * Input fresh: 32-bit Random number. - * Input dir:1 bit, direction of transmission (in the LSB). - * Input data: length number of bits, input bit stream. - * Input length: 64 bit Length, i.e., the number of bits to be MAC'd. - * Output : 32 bit block used as MAC - * Generates 32-bit MAC using UIA2 algorithm as defined in Section 4. - */ -u8* snow3g_f9(u8* key, u32 count, u32 fresh, u32 dir, u8* data, u64 length) -{ - u32 K[4], IV[4], z[5]; - u32 i = 0, D; - static u8 MAC_I[4] = {0, 0, 0, 0}; /* static memory for the result */ - u64 EVAL; - u64 V; - u64 P; - u64 Q; - u64 c; - - u64 M_D_2; - int rem_bits = 0; - - /* Load the Integrity Key for SNOW3G initialization as in section 4.4. */ - for (i = 0; i < 4; i++) - K[3 - i] = (key[4 * i] << 24) ^ (key[4 * i + 1] << 16) ^ (key[4 * i + 2] << 8) ^ (key[4 * i + 3]); - - /* Prepare the Initialization Vector (IV) for SNOW3G initialization as - in section 4.4. */ - IV[3] = count; - IV[2] = fresh; - IV[1] = count ^ (dir << 31); - IV[0] = fresh ^ (dir << 15); - - z[0] = z[1] = z[2] = z[3] = z[4] = 0; - - /* Run SNOW 3G to produce 5 keystream words z_1, z_2, z_3, z_4 and z_5. */ - snow3g_initialize(K, IV); - snow3g_generate_keystream(5, z); - - P = (u64)z[0] << 32 | (u64)z[1]; - Q = (u64)z[2] << 32 | (u64)z[3]; - - /* Calculation */ - if ((length % 64) == 0) - D = (length >> 6) + 1; - else - D = (length >> 6) + 2; - EVAL = 0; - c = 0x1b; - - /* for 0 <= i <= D-3 */ - for (i = 0; i < D - 2; i++) { - V = EVAL ^ - ((u64)data[8 * i] << 56 | (u64)data[8 * i + 1] << 48 | (u64)data[8 * i + 2] << 40 | (u64)data[8 * i + 3] << 32 | - (u64)data[8 * i + 4] << 24 | (u64)data[8 * i + 5] << 16 | (u64)data[8 * i + 6] << 8 | (u64)data[8 * i + 7]); - EVAL = MUL64(V, P, c); - } - - /* for D-2 */ - rem_bits = length % 64; - if (rem_bits == 0) - rem_bits = 64; - - M_D_2 = 0; - i = 0; - while (rem_bits > 7) { - M_D_2 |= (u64)data[8 * (D - 2) + i] << (8 * (7 - i)); - rem_bits -= 8; - i++; - } - if (rem_bits > 0) - M_D_2 |= (u64)(data[8 * (D - 2) + i] & mask8bit(rem_bits)) << (8 * (7 - i)); - - V = EVAL ^ M_D_2; - EVAL = MUL64(V, P, c); - - /* for D-1 */ - EVAL ^= length; - - /* Multiply by Q */ - EVAL = MUL64(EVAL, Q, c); - - /* XOR with z_5: this is a modification to the reference C code, - which forgot to XOR z[5] */ - for (i = 0; i < 4; i++) - /* - MAC_I[i] = (mac32 >> (8*(3-i))) & 0xff; - */ - MAC_I[i] = ((EVAL >> (56 - (i * 8))) ^ (z[4] >> (24 - (i * 8)))) & 0xff; - - return MAC_I; -} diff --git a/lib/src/common/zuc.cc b/lib/src/common/zuc.cc index 0823379c0..494e10cb1 100644 --- a/lib/src/common/zuc.cc +++ b/lib/src/common/zuc.cc @@ -183,7 +183,7 @@ u32 F(zuc_state_t* state) /* initialize */ -void zuc_initialize(zuc_state_t* state, u8* k, u8* iv) +void zuc_initialize(zuc_state_t* state, const u8* k, u8* iv) { u32 w, nCount;