diff --git a/lib/include/srsran/common/security.h b/lib/include/srsran/common/security.h index ad9e0104b..ce1c59ed6 100644 --- a/lib/include/srsran/common/security.h +++ b/lib/include/srsran/common/security.h @@ -18,7 +18,21 @@ *****************************************************************************/ #include "srsran/common/common.h" +#include "srsran/srslog/srslog.h" +#include + +#define AKA_RAND_LEN 16 +#define AKA_AUTN_LEN 16 +#define AKA_AUTS_LEN 14 +#define RES_MAX_LEN 16 +#define MAC_LEN 8 +#define IK_LEN 16 +#define CK_LEN 16 +#define AK_LEN 6 +#define SQN_LEN 6 + +#define KEY_LEN 32 namespace srsran { typedef enum { @@ -73,16 +87,55 @@ struct as_security_config_t { CIPHERING_ALGORITHM_ID_ENUM cipher_algo; }; +template +void log_error(const char* format, Args&&... args) +{ + srslog::fetch_basic_logger("SEC").error(format, std::forward(args)...); +} + +template +void log_warning(const char* format, Args&&... args) +{ + srslog::fetch_basic_logger("SEC").warning(format, std::forward(args)...); +} + +template +void log_info(const char* format, Args&&... args) +{ + srslog::fetch_basic_logger("SEC").info(format, std::forward(args)...); +} + +template +void log_debug(const char* format, Args&&... args) +{ + srslog::fetch_basic_logger("SEC").debug(format, std::forward(args)...); +} + /****************************************************************************** * Key Generation *****************************************************************************/ -uint8_t security_generate_k_asme(uint8_t* ck, - uint8_t* ik, - uint8_t* ak, - uint8_t* sqn, - uint16_t mcc, - uint16_t mnc, - uint8_t* k_asme); + +int kdf_common(const uint8_t fc, const std::array& key, const std::vector& P, uint8_t* output); +int kdf_common(const uint8_t fc, + const std::array& key, + const std::vector& P0, + const std::vector& P1, + uint8_t* output); +int kdf_common(const uint8_t fc, + const std::array& key, + const std::vector& P0, + const std::vector& P1, + const std::vector& P3, + uint8_t* output); + +uint8_t +security_generate_k_asme(uint8_t* ck, uint8_t* ik, uint8_t* ak_xor_sqn, uint16_t mcc, uint16_t mnc, uint8_t* k_asme); + +uint8_t security_generate_k_ausf(uint8_t* ck, + uint8_t* ik, + uint8_t* ak_xor_sqn, + const char* serving_network_name, + uint8_t* k_ausf); uint8_t security_generate_k_enb(uint8_t* k_asme, uint32_t nas_count, uint8_t* k_enb); diff --git a/lib/include/srsran/common/ssl.h b/lib/include/srsran/common/ssl.h index da7f3dc03..38b6e6b5a 100644 --- a/lib/include/srsran/common/ssl.h +++ b/lib/include/srsran/common/ssl.h @@ -18,12 +18,12 @@ #include "polarssl/aes.h" #include "polarssl/sha256.h" -void sha256(const unsigned char* key, - size_t keylen, - const unsigned char* input, - size_t ilen, - unsigned char output[32], - int is224) +inline void sha256(const unsigned char* key, + size_t keylen, + const unsigned char* input, + size_t ilen, + unsigned char output[32], + int is224) { sha256_hmac(key, keylen, input, ilen, output, is224); } @@ -40,33 +40,33 @@ typedef mbedtls_aes_context aes_context; #define AES_ENCRYPT 1 #define AES_DECRYPT 0 -int aes_setkey_enc(aes_context* ctx, const unsigned char* key, unsigned int keysize) +inline int aes_setkey_enc(aes_context* ctx, const unsigned char* key, unsigned int keysize) { return mbedtls_aes_setkey_enc(ctx, key, keysize); } -int aes_crypt_ecb(aes_context* ctx, int mode, const unsigned char input[16], unsigned char output[16]) +inline int aes_crypt_ecb(aes_context* ctx, int mode, const unsigned char input[16], unsigned char output[16]) { return mbedtls_aes_crypt_ecb(ctx, mode, input, output); } -int aes_crypt_ctr(aes_context* ctx, - size_t length, - size_t* nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char* input, - unsigned char* output) +inline int aes_crypt_ctr(aes_context* ctx, + size_t length, + size_t* nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char* input, + unsigned char* output) { return mbedtls_aes_crypt_ctr(ctx, length, nc_off, nonce_counter, stream_block, input, output); } -void sha256(const unsigned char* key, - size_t keylen, - const unsigned char* input, - size_t ilen, - unsigned char output[32], - int is224) +inline void sha256(const unsigned char* key, + size_t keylen, + const unsigned char* input, + size_t ilen, + unsigned char output[32], + int is224) { mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), key, keylen, input, ilen, output); } diff --git a/lib/src/common/liblte_security.cc b/lib/src/common/liblte_security.cc index e1114e3bc..4eb9fa733 100644 --- a/lib/src/common/liblte_security.cc +++ b/lib/src/common/liblte_security.cc @@ -192,22 +192,18 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_nas(uint8* LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint8 s[7]; - if (k_asme != NULL && k_nas_enc != NULL) { //{} - if (enc_alg_id != LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_EEA0) { - // Construct S for KNASenc - s[0] = 0x15; // FC - s[1] = 0x01; // P0 - s[2] = 0x00; // First byte of L0 - s[3] = 0x01; // Second byte of L0 - s[4] = enc_alg_id; // P1 - s[5] = 0x00; // First byte of L1 - s[6] = 0x01; // Second byte of L1 + if (k_asme != NULL && k_nas_enc != NULL) { + // Construct S for KNASenc + s[0] = 0x15; // FC + s[1] = 0x01; // P0 + s[2] = 0x00; // First byte of L0 + s[3] = 0x01; // Second byte of L0 + s[4] = enc_alg_id; // P1 + s[5] = 0x00; // First byte of L1 + s[6] = 0x01; // Second byte of L1 - // Derive KNASenc - sha256(k_asme, 32, s, 7, k_nas_enc, 0); - } else { - memset(k_nas_enc, 0, 32); - } + // Derive KNASenc + sha256(k_asme, 32, s, 7, k_nas_enc, 0); } if (k_asme != NULL && k_nas_int != NULL) { diff --git a/lib/src/common/security.cc b/lib/src/common/security.cc index d1e967adc..42769e64c 100644 --- a/lib/src/common/security.cc +++ b/lib/src/common/security.cc @@ -13,8 +13,11 @@ #include "srsran/common/security.h" #include "srsran/common/liblte_security.h" #include "srsran/common/s3g.h" +#include "srsran/common/ssl.h" #include "srsran/config.h" +#include + #ifdef HAVE_MBEDTLS #include "mbedtls/md5.h" #endif @@ -22,36 +25,190 @@ #include "polarssl/md5.h" #endif +#define FC_EPS_K_ASME_DERIVATION 0x10 +#define FC_EPS_K_ENB_DERIVATION 0x11 +#define FC_EPS_NH_DERIVATION 0x12 +#define FC_EPS_K_ENB_STAR_DERIVATION 0x13 +#define FC_EPS_ALGORITHM_KEY_DERIVATION 0x15 + +#define ALGO_EPS_DISTINGUISHER_NAS_ENC_ALG 0x01 +#define ALGO_EPS_DISTINGUISHER_NAS_INT_ALG 0x02 +#define ALGO_EPS_DISTINGUISHER_RRC_ENC_ALG 0x03 +#define ALGO_EPS_DISTINGUISHER_RRC_INT_ALG 0x04 +#define ALGO_EPS_DISTINGUISHER_UP_ENC_ALG 0x05 +#define ALGO_EPS_DISTINGUISHER_UP_INT_ALG 0x06 + +#define FC_5G_ALGORITHM_KEY_DERIVATION 0x69 +#define FC_5G_KAUSF_DERIVATION 0x6A +#define FC_5G_RES_STAR_DERIVATION 0x6B +#define FC_5G_KSEAF_DERIVATION 0x6C +#define FC_5G_KAMF_DERIVATION 0x6D +#define FC_5G_KGNB_KN3IWF_DERIVATION 0x6E +#define FC_5G_NH_GNB_DERIVATION 0x6F + +#define ALGO_5G_DISTINGUISHER_NAS_ENC_ALG 0x01 +#define ALGO_5G_DISTINGUISHER_NAS_INT_ALG 0x02 +#define ALGO_5G_DISTINGUISHER_RRC_ENC_ALG 0x03 +#define ALGO_5G_DISTINGUISHER_RRC_INT_ALG 0x04 +#define ALGO_5G_DISTINGUISHER_UP_ENC_ALG 0x05 +#define ALGO_5G_DISTINGUISHER_UP_INT_ALG 0x06 namespace srsran { /****************************************************************************** * Key Generation *****************************************************************************/ -uint8_t security_generate_k_asme(uint8_t* ck, - uint8_t* ik, - uint8_t* ak, - uint8_t* sqn, - uint16_t mcc, - uint16_t mnc, - uint8_t* k_asme) +uint8_t +security_generate_k_asme(uint8_t* ck, uint8_t* ik, uint8_t* ak_xor_sqn_, uint16_t mcc, uint16_t mnc, uint8_t* k_asme) { - return liblte_security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme); + if (ck == NULL || ik == NULL || ak_xor_sqn_ == NULL || k_asme == NULL) { + log_error("Invalid inputs"); + return SRSRAN_ERROR; + } + std::array key; + + // The input key Key shall be equal to the concatenation CK || IK of CK and IK. + memcpy(key.data(), ck, 16); + memcpy(key.data() + 16, ik, 16); + + // Serving Network id + std::vector sn_id; + sn_id.resize(3); + sn_id[0] = (mcc & 0x00F0) | ((mcc & 0x0F00) >> 8); // First byte of P0 + if ((mnc & 0xFF00) == 0xFF00) { + // 2-digit MNC + sn_id[1] = 0xF0 | (mcc & 0x000F); // Second byte of P0 + sn_id[2] = ((mnc & 0x000F) << 4) | ((mnc & 0x00F0) >> 4); // Third byte of P0 + } else { + // 3-digit MNC + sn_id[1] = ((mnc & 0x000F) << 4) | (mcc & 0x000F); // Second byte of P0 + sn_id[2] = ((mnc & 0x00F0)) | ((mnc & 0x0F00) >> 8); // Third byte of P0 + } + + // AK XOR SQN + std::vector ak_xor_sqn; + ak_xor_sqn.resize(AK_LEN); + memcpy(ak_xor_sqn.data(), ak_xor_sqn_, ak_xor_sqn.size()); + + uint8_t output[32]; + if (kdf_common(FC_EPS_K_ASME_DERIVATION, key, sn_id, ak_xor_sqn, output) != SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + + memcpy(k_asme, output, 32); + return SRSRAN_SUCCESS; } -uint8_t security_generate_k_enb(uint8_t* k_asme, uint32_t nas_count, uint8_t* k_enb) +uint8_t security_generate_k_ausf(uint8_t* ck, + uint8_t* ik, + uint8_t* ak_xor_sqn_, + const char* serving_network_name, + uint8_t* k_ausf) { - return liblte_security_generate_k_enb(k_asme, nas_count, k_enb); + if (ck == NULL || ik == NULL || ak_xor_sqn_ == NULL || serving_network_name == NULL || k_ausf == NULL) { + log_error("Invalid inputs"); + return SRSRAN_ERROR; + } + + std::array key; + + // The input key Key shall be equal to the concatenation CK || IK of CK and IK. + memcpy(key.data(), ck, 16); + memcpy(key.data() + 16, ik, 16); + + // Serving Network Name + std::vector ssn; + ssn.resize(strlen(serving_network_name)); + memcpy(ssn.data(), serving_network_name, ssn.size()); + + // AK XOR SQN + std::vector ak_xor_sqn; + ak_xor_sqn.resize(AK_LEN); + memcpy(ak_xor_sqn.data(), ak_xor_sqn_, ak_xor_sqn.size()); + + uint8_t output[32]; + if (kdf_common(FC_5G_RES_STAR_DERIVATION, key, ssn, ak_xor_sqn, output) != SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + memcpy(k_ausf, output, 32); + + return SRSRAN_SUCCESS; } -uint8_t security_generate_k_enb_star(uint8_t* k_enb, uint32_t pci, uint32_t earfcn, uint8_t* k_enb_star) +uint8_t security_generate_k_enb(uint8_t* k_asme, uint32_t nas_count_, uint8_t* k_enb) { - return liblte_security_generate_k_enb_star(k_enb, pci, earfcn, k_enb_star); + if (k_asme == NULL || k_enb == NULL) { + log_error("Invalid inputs"); + return SRSRAN_ERROR; + } + std::array key; + + memcpy(key.data(), k_asme, 32); + + // NAS Count + std::vector nas_count; + nas_count.resize(4); + nas_count[0] = (nas_count_ >> 24) & 0xFF; + nas_count[1] = (nas_count_ >> 16) & 0xFF; + nas_count[2] = (nas_count_ >> 8) & 0xFF; + nas_count[3] = nas_count_ & 0xFF; + + if (kdf_common(FC_EPS_K_ENB_DERIVATION, key, nas_count, k_enb) != SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; } -uint8_t security_generate_nh(uint8_t* k_asme, uint8_t* sync, uint8_t* nh) +uint8_t security_generate_k_enb_star(uint8_t* k_enb, uint32_t pci_, uint32_t earfcn_, uint8_t* k_enb_star) { - return liblte_security_generate_nh(k_asme, sync, nh); + if (k_enb == NULL || k_enb_star == NULL) { + log_error("Invalid inputs"); + return SRSRAN_ERROR; + } + std::array key; + memcpy(key.data(), k_enb, 32); + + // PCI + std::vector pci; + pci.resize(2); + pci[0] = (pci_ >> 8) & 0xFF; + pci[1] = pci_ & 0xFF; + + // EARFCN + std::vector earfcn; + earfcn.resize(2); + earfcn[0] = (earfcn_ >> 8) & 0xFF; + earfcn[1] = earfcn_ & 0xFF; + + if (kdf_common(FC_EPS_K_ENB_STAR_DERIVATION, key, pci, earfcn, k_enb_star) != SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; +} + +uint8_t security_generate_nh(uint8_t* k_asme, uint8_t* sync_, uint8_t* nh) +{ + if (k_asme == NULL || sync_ == NULL || nh == NULL) { + log_error("Invalid inputs"); + return SRSRAN_ERROR; + } + std::array key; + memcpy(key.data(), k_asme, 32); + + // PCI + std::vector sync; + sync.resize(32); + memcpy(sync.data(), sync_, 32); + + if (kdf_common(FC_EPS_NH_DERIVATION, key, sync, nh) != SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; } uint8_t security_generate_k_nas(uint8_t* k_asme, @@ -60,11 +217,47 @@ uint8_t security_generate_k_nas(uint8_t* k_asme, uint8_t* k_nas_enc, uint8_t* k_nas_int) { - return liblte_security_generate_k_nas(k_asme, - (LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id, - (LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id, - k_nas_enc, - k_nas_int); + if (k_asme == NULL || k_nas_enc == NULL || k_nas_int == NULL) { + log_error("Invalid inputs"); + return SRSRAN_ERROR; + } + std::array key; + + memcpy(key.data(), k_asme, 32); + + // Derive NAS ENC + // algorithm type distinguisher + std::vector algo_distinguisher; + algo_distinguisher.resize(1); + algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_NAS_ENC_ALG; + + // algorithm type distinguisher + std::vector algorithm_identity; + algorithm_identity.resize(1); + algorithm_identity[0] = enc_alg_id; + + if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_nas_enc) != + SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + + // Derive NAS INT + // algorithm type distinguisher + algo_distinguisher.resize(1); + algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_NAS_INT_ALG; + + // algorithm type distinguisher + algorithm_identity.resize(1); + algorithm_identity[0] = int_alg_id; + + // Derive NAS int + if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_nas_int) != + SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; } uint8_t security_generate_k_rrc(uint8_t* k_enb, @@ -73,11 +266,47 @@ uint8_t security_generate_k_rrc(uint8_t* k_enb, uint8_t* k_rrc_enc, uint8_t* k_rrc_int) { - return liblte_security_generate_k_rrc(k_enb, - (LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id, - (LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id, - k_rrc_enc, - k_rrc_int); + if (k_enb == NULL || k_rrc_enc == NULL || k_rrc_int == NULL) { + log_error("Invalid inputs"); + return SRSRAN_ERROR; + } + std::array key; + + memcpy(key.data(), k_enb, 32); + + // Derive RRC ENC + // algorithm type distinguisher + std::vector algo_distinguisher; + algo_distinguisher.resize(1); + algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_RRC_ENC_ALG; + + // algorithm type distinguisher + std::vector algorithm_identity; + algorithm_identity.resize(1); + algorithm_identity[0] = enc_alg_id; + + if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_rrc_enc) != + SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + + // Derive RRC INT + // algorithm type distinguisher + algo_distinguisher.resize(1); + algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_RRC_INT_ALG; + + // algorithm type distinguisher + algorithm_identity.resize(1); + algorithm_identity[0] = int_alg_id; + + // Derive RRC int + if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_rrc_int) != + SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; } uint8_t security_generate_k_up(uint8_t* k_enb, @@ -86,11 +315,74 @@ uint8_t security_generate_k_up(uint8_t* k_enb, uint8_t* k_up_enc, uint8_t* k_up_int) { - return liblte_security_generate_k_up(k_enb, - (LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id, - (LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id, - k_up_enc, - k_up_int); + if (k_enb == NULL || k_up_enc == NULL || k_up_int == NULL) { + log_error("Invalid inputs"); + return SRSRAN_ERROR; + } + std::array key; + + memcpy(key.data(), k_enb, 32); + + // Derive UP ENC + // algorithm type distinguisher + std::vector algo_distinguisher; + algo_distinguisher.resize(1); + algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_UP_ENC_ALG; + + // algorithm type distinguisher + std::vector algorithm_identity; + algorithm_identity.resize(1); + algorithm_identity[0] = enc_alg_id; + + if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_up_enc) != + SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + + // Derive UP INT + // algorithm type distinguisher + algo_distinguisher.resize(1); + algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_UP_INT_ALG; + + // algorithm type distinguisher + algorithm_identity.resize(1); + algorithm_identity[0] = int_alg_id; + + // Derive UP int + if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_up_int) != + SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; +} + +uint8_t security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_count_) +{ + if (k_enb == NULL || sk_gnb == NULL) { + log_error("Invalid inputs"); + return SRSRAN_ERROR; + } + std::array key; + + memcpy(key.data(), k_enb, 32); + + // SCG Count + std::vector scg_count; + scg_count.resize(2); + scg_count[0] = (scg_count_ >> 8) & 0xFF; // first byte of P0 + scg_count[1] = scg_count_ & 0xFF; // second byte of P0 + + // Derive sk_gnb + uint8_t output[32]; + if (kdf_common(0x1C, key, scg_count, output) != SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + memcpy(sk_gnb, output, 32); + + return SRSRAN_SUCCESS; } uint8_t security_generate_k_nr_rrc(uint8_t* k_gnb, @@ -99,11 +391,47 @@ uint8_t security_generate_k_nr_rrc(uint8_t* k_gnb, uint8_t* k_rrc_enc, uint8_t* k_rrc_int) { - return liblte_security_generate_k_nr_rrc(k_gnb, - (LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id, - (LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id, - k_rrc_enc, - k_rrc_int); + if (k_gnb == NULL || k_rrc_enc == NULL || k_rrc_int == NULL) { + log_error("Invalid inputs"); + return SRSRAN_ERROR; + } + std::array key; + + memcpy(key.data(), k_gnb, 32); + + // Derive RRC ENC + // algorithm type distinguisher + std::vector algo_distinguisher; + algo_distinguisher.resize(1); + algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_RRC_ENC_ALG; + + // algorithm type distinguisher + std::vector algorithm_identity; + algorithm_identity.resize(1); + algorithm_identity[0] = enc_alg_id; + + if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_rrc_enc) != + SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + + // Derive RRC INT + // algorithm type distinguisher + algo_distinguisher.resize(1); + algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_RRC_INT_ALG; + + // algorithm type distinguisher + algorithm_identity.resize(1); + algorithm_identity[0] = int_alg_id; + + // Derive RRC int + if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_rrc_int) != + SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; } uint8_t security_generate_k_nr_up(uint8_t* k_gnb, @@ -112,18 +440,208 @@ uint8_t security_generate_k_nr_up(uint8_t* k_gnb, uint8_t* k_up_enc, uint8_t* k_up_int) { - return liblte_security_generate_k_nr_up(k_gnb, - (LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id, - (LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id, - k_up_enc, - k_up_int); + if (k_gnb == NULL || k_up_enc == NULL || k_up_int == NULL) { + log_error("Invalid inputs"); + return SRSRAN_ERROR; + } + std::array key; + + memcpy(key.data(), k_gnb, 32); + + // Derive UP ENC + // algorithm type distinguisher + std::vector algo_distinguisher; + algo_distinguisher.resize(1); + algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_UP_ENC_ALG; + + // algorithm type distinguisher + std::vector algorithm_identity; + algorithm_identity.resize(1); + algorithm_identity[0] = enc_alg_id; + + if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_up_enc) != + SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + + // Derive UP INT + // algorithm type distinguisher + algo_distinguisher.resize(1); + algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_UP_INT_ALG; + + // algorithm type distinguisher + algorithm_identity.resize(1); + algorithm_identity[0] = int_alg_id; + + // Derive UP int + if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_up_int) != + SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; } -uint8_t security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_count) +uint8_t security_generate_res_star(uint8_t* ck, + uint8_t* ik, + const char* serving_network_name, + uint8_t* rand_, + uint8_t* res_, + size_t res_len_, + uint8_t* res_star) { - return liblte_security_generate_sk_gnb(k_enb, sk_gnb, scg_count); + if (ck == NULL || ik == NULL || serving_network_name == NULL || rand_ == NULL || res_ == NULL || res_star == NULL) { + log_error("Invalid inputs"); + return SRSRAN_ERROR; + } + std::array key; + + // The input key Key shall be equal to the concatenation CK || IK of CK and IK. + memcpy(key.data(), ck, 16); + memcpy(key.data() + 16, ik, 16); + + // Serving Network Name + std::vector ssn; + ssn.resize(strlen(serving_network_name)); + memcpy(ssn.data(), serving_network_name, strlen(serving_network_name)); + + // RAND + std::vector rand; + rand.resize(AKA_RAND_LEN); + memcpy(rand.data(), rand_, rand.size()); + + // RES + std::vector res; + res.resize(res_len_); + memcpy(res.data(), res_, res.size()); + + uint8_t output[32]; + if (kdf_common(FC_5G_RES_STAR_DERIVATION, key, ssn, rand, res, output) != SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + memcpy(res_star, output + 16, 16); + + return SRSRAN_SUCCESS; } +int kdf_common(const uint8_t fc, const std::array& key, const std::vector& P0, uint8_t* output) +{ + uint8_t* s; + uint32_t s_len = 1 + P0.size() + 2; + + s = (uint8_t*)calloc(s_len, sizeof(uint8_t)); + + if (s == nullptr) { + log_error("Unable to allocate memory in %s()", __FUNCTION__); + return SRSRAN_ERROR; + } + + uint32_t i = 0; + s[i] = fc; // FC + i++; + + // P0 + memcpy(&s[i], P0.data(), P0.size()); + i += P0.size(); + uint16_t p0_length_value = htons(P0.size()); + memcpy(&s[i], &p0_length_value, sizeof(p0_length_value)); + i += sizeof(p0_length_value); + + sha256(key.data(), key.size(), s, i, output, 0); + free(s); + + return SRSRAN_SUCCESS; +} + +int kdf_common(const uint8_t fc, + const std::array& key, + const std::vector& P0, + const std::vector& P1, + uint8_t* output) +{ + uint8_t* s; + uint32_t s_len = 1 + P0.size() + 2 + P1.size() + 2; + + s = (uint8_t*)calloc(s_len, sizeof(uint8_t)); + + if (s == nullptr) { + log_error("Unable to allocate memory in %s()", __FUNCTION__); + return SRSRAN_ERROR; + } + + uint32_t i = 0; + s[i] = fc; // FC + i++; + + // P0 + memcpy(&s[i], P0.data(), P0.size()); + i += P0.size(); + uint16_t p0_length_value = htons(P0.size()); + memcpy(&s[i], &p0_length_value, sizeof(p0_length_value)); + i += sizeof(p0_length_value); + + // P1 + memcpy(&s[i], P1.data(), P1.size()); + i += P1.size(); + uint16_t p1_length_value = htons(P1.size()); + memcpy(&s[i], &p1_length_value, sizeof(p1_length_value)); + i += sizeof(p1_length_value); + + sha256(key.data(), key.size(), s, i, output, 0); + free(s); + + return SRSRAN_SUCCESS; +} + +int kdf_common(const uint8_t fc, + const std::array& key, + const std::vector& P0, + const std::vector& P1, + const std::vector& P2, + uint8_t* output) +{ + uint8_t* s; + uint32_t s_len = 1 + P0.size() + 2 + P1.size() + 2 + P2.size() + 2; + + s = (uint8_t*)calloc(s_len, sizeof(uint8_t)); + + if (s == nullptr) { + log_error("Unable to allocate memory in %s()", __FUNCTION__); + return SRSRAN_ERROR; + } + + uint32_t i = 0; + s[i] = fc; // FC + i++; + + // P0 + memcpy(&s[i], P0.data(), P0.size()); + i += P0.size(); + uint16_t p0_length_value = htons(P0.size()); + memcpy(&s[i], &p0_length_value, sizeof(p0_length_value)); + i += sizeof(p0_length_value); + + // P1 + memcpy(&s[i], P1.data(), P1.size()); + i += P1.size(); + uint16_t p1_length_value = htons(P1.size()); + memcpy(&s[i], &p1_length_value, sizeof(p1_length_value)); + i += sizeof(p1_length_value); + + // P2 + memcpy(&s[i], P2.data(), P2.size()); + i += P2.size(); + uint16_t p2_length_value = htons(P2.size()); + memcpy(&s[i], &p2_length_value, sizeof(p2_length_value)); + i += sizeof(p2_length_value); + + sha256(key.data(), key.size(), s, i, output, 0); + free(s); + + return SRSRAN_SUCCESS; +} /****************************************************************************** * Integrity Protection *****************************************************************************/ @@ -185,7 +703,6 @@ uint8_t security_128_eea1(uint8_t* key, uint32_t msg_len, uint8_t* msg_out) { - return liblte_security_encryption_eea1(key, count, bearer, direction, msg, msg_len * 8, msg_out); } @@ -197,7 +714,6 @@ uint8_t security_128_eea2(uint8_t* key, uint32_t msg_len, uint8_t* msg_out) { - return liblte_security_encryption_eea2(key, count, bearer, direction, msg, msg_len * 8, msg_out); } @@ -209,7 +725,6 @@ uint8_t security_128_eea3(uint8_t* key, uint32_t msg_len, uint8_t* msg_out) { - return liblte_security_encryption_eea3(key, count, bearer, direction, msg, msg_len * 8, msg_out); } diff --git a/lib/test/common/test_security_kdf.cc b/lib/test/common/test_security_kdf.cc index 1eca4c383..84c5a7048 100644 --- a/lib/test/common/test_security_kdf.cc +++ b/lib/test/common/test_security_kdf.cc @@ -111,8 +111,12 @@ int test_generate_k_asme() uint16_t mcc = 61441; // MCC 001 uint16_t mnc = 65281; // MNC 01 + uint8_t ak_xor_sqn[6]; + for (uint32_t i = 0; i < 6; i++) { + ak_xor_sqn[i] = sqn[i] ^ ak[i]; + } // Generate K_asme - security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme_o); + security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme_o); uint8_t k_asme[] = {0xd5, 0xef, 0x4d, 0x8f, 0x33, 0x26, 0x69, 0x02, 0x29, 0x5d, 0x42, 0xf3, 0x22, 0xa2, 0xf2, 0xcf, 0x11, 0xfb, 0x2c, 0xcc, 0x12, 0x4c, 0x09, 0xb4, 0xd8, 0x8d, 0x36, 0x15, 0x97, 0x03, 0x79, 0x90}; @@ -138,9 +142,9 @@ int test_generate_k_nas() k_nas_enc_o, k_nas_int_o) == SRSRAN_SUCCESS); - uint8_t k_nas_enc[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t k_nas_enc[] = {0xcf, 0x7a, 0x27, 0xbe, 0xab, 0x1e, 0x78, 0xbf, 0x5b, 0xb1, 0xf9, + 0x5b, 0x05, 0x82, 0x9a, 0x72, 0xe4, 0xcf, 0x7f, 0xec, 0xba, 0xd4, + 0xb8, 0xc3, 0x7d, 0xb4, 0xa1, 0x90, 0xe1, 0x19, 0x22, 0x5c}; logger.info(k_nas_enc_o, 32, "K NAS ENC output:"); TESTASSERT(arrcmp(k_nas_enc, k_nas_enc_o, sizeof(k_nas_enc_o)) == 0); @@ -236,6 +240,48 @@ int test_generate_up_keys() return SRSRAN_SUCCESS; } +int test_generate_k_enb_star() +{ + auto& logger = srslog::fetch_basic_logger("LOG", false); + uint8_t k_enb_star_o[32]; + + uint8_t k_enb[] = {0xc4, 0xc7, 0xbc, 0x79, 0x8a, 0xb9, 0x4e, 0x3d, 0x35, 0x4c, 0xd6, 0x60, 0x8e, 0x79, 0xaa, 0x92, + 0xf5, 0x56, 0x9d, 0xf4, 0x65, 0x19, 0x50, 0x78, 0x50, 0x05, 0x1e, 0x36, 0xf0, 0x18, 0xca, 0x5f}; + + TESTASSERT(srsran::security_generate_k_enb_star(k_enb, 32, 561, k_enb_star_o) == SRSRAN_SUCCESS); + + uint8_t k_enb_star[] = {0x6f, 0x04, 0x54, 0x57, 0x7f, 0x55, 0x5c, 0xa7, 0x6f, 0x44, 0x9c, + 0x2a, 0xc1, 0xda, 0x0f, 0x4f, 0xb7, 0xde, 0x4b, 0x94, 0x40, 0x11, + 0x0f, 0xfb, 0xd1, 0x2f, 0x3a, 0x5d, 0x4d, 0xe1, 0x73, 0x50}; + + logger.info(k_enb_star_o, 32, "K ENB STAR:"); + TESTASSERT(arrcmp(k_enb_star_o, k_enb_star, sizeof(k_enb_star)) == 0); + + return SRSRAN_SUCCESS; +} + +int test_generate_k_nh() +{ + auto& logger = srslog::fetch_basic_logger("LOG", false); + uint8_t nh_o[32]; + + uint8_t k_asme[] = {0xd5, 0xef, 0x4d, 0x8f, 0x33, 0x26, 0x69, 0x02, 0x29, 0x5d, 0x42, 0xf3, 0x22, 0xa2, 0xf2, 0xcf, + 0x11, 0xfb, 0x2c, 0xcc, 0x12, 0x4c, 0x09, 0xb4, 0xd8, 0x8d, 0x36, 0x15, 0x97, 0x03, 0x79, 0x90}; + + uint8_t sync[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12}; + + TESTASSERT(srsran::security_generate_nh(k_asme, sync, nh_o) == SRSRAN_SUCCESS); + + uint8_t nh[] = {0xc8, 0x55, 0x86, 0x64, 0x13, 0x07, 0x1b, 0x74, 0xab, 0xa0, 0x1c, 0x13, 0x2b, 0x94, 0x3e, 0x76, + 0x98, 0xaa, 0x5c, 0x11, 0x76, 0x0d, 0x9b, 0xb1, 0x16, 0x2a, 0xb3, 0x13, 0xb1, 0x1c, 0x60, 0x51}; + + logger.info(nh_o, 32, "NH:"); + TESTASSERT(arrcmp(nh_o, nh, sizeof(nh)) == 0); + + return SRSRAN_SUCCESS; +} + int main(int argc, char** argv) { auto& logger = srslog::fetch_basic_logger("LOG", false); @@ -249,6 +295,8 @@ int main(int argc, char** argv) TESTASSERT(test_generate_k_enb() == SRSRAN_SUCCESS); TESTASSERT(test_generate_rrc_keys() == SRSRAN_SUCCESS); TESTASSERT(test_generate_up_keys() == SRSRAN_SUCCESS); + TESTASSERT(test_generate_k_enb_star() == SRSRAN_SUCCESS); + TESTASSERT(test_generate_k_nh() == SRSRAN_SUCCESS); TESTASSERT(test_set_ksg() == SRSRAN_SUCCESS); TESTASSERT(test_set_nr_rrc_up() == SRSRAN_SUCCESS); diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index ceae22418..114d28d30 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -302,8 +302,12 @@ void hss::gen_auth_info_answer_milenage(hss_ue_ctx_t* ue_ctx, m_logger.debug(sqn, 6, "User SQN : "); m_logger.debug(mac, 8, "User MAC : "); + uint8_t ak_xor_sqn[6]; + for (int i = 0; i < 6; i++) { + ak_xor_sqn[i] = sqn[i] ^ ak[i]; + } // Generate K_asme - srsran::security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme); + srsran::security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme); m_logger.debug("User MCC : %x MNC : %x ", mcc, mnc); m_logger.debug(k_asme, 32, "User k_asme : "); @@ -396,8 +400,12 @@ void hss::gen_auth_info_answer_xor(hss_ue_ctx_t* ue_ctx, uint8_t* k_asme, uint8_ autn[8 + i] = mac[i]; } + uint8_t ak_xor_sqn[6]; + for (int i = 0; i < 6; i++) { + ak_xor_sqn[i] = sqn[i] ^ ak[i]; + } // Generate K_asme - srsran::security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme); + srsran::security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme); m_logger.debug("User MCC : %x MNC : %x ", mcc, mnc); m_logger.debug(k_asme, 32, "User k_asme : "); diff --git a/srsue/src/stack/upper/pcsc_usim.cc b/srsue/src/stack/upper/pcsc_usim.cc index 111730207..780194ca8 100644 --- a/srsue/src/stack/upper/pcsc_usim.cc +++ b/srsue/src/stack/upper/pcsc_usim.cc @@ -143,7 +143,7 @@ auth_result_t pcsc_usim::generate_authentication_response(uint8_t* rand, logger.debug(ak, AK_LEN, "AK:"); logger.debug(sqn, SQN_LEN, "SQN:"); logger.debug("mcc=%d, mnc=%d", mcc, mnc); - security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme); + security_generate_k_asme(ck, ik, sqn, mcc, mnc, k_asme); logger.info(k_asme, KEY_LEN, "K_ASME:"); ret = AUTH_OK; diff --git a/srsue/src/stack/upper/usim.cc b/srsue/src/stack/upper/usim.cc index a0996b3d5..048524271 100644 --- a/srsue/src/stack/upper/usim.cc +++ b/srsue/src/stack/upper/usim.cc @@ -159,8 +159,12 @@ auth_result_t usim::gen_auth_res_milenage(uint8_t* rand, } } + uint8_t ak_xor_sqn[6]; + for (i = 0; i < 6; i++) { + ak_xor_sqn[i] = sqn[i] ^ ak[i]; + } // Generate K_asme - security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme); + security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme); return result; } @@ -225,8 +229,14 @@ auth_result_t usim::gen_auth_res_xor(uint8_t* rand, logger.debug(sqn, 6, "sqn:"); logger.debug(amf, 2, "amf:"); logger.debug(mac, 8, "mac:"); + + uint8_t ak_xor_sqn[6]; + for (uint32_t i = 0; i < 6; i++) { + ak_xor_sqn[i] = sqn[i] ^ ak[i]; + } + // Generate K_asme - security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme_); + security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme_); return result; }