/** * Copyright 2013-2022 Software Radio Systems Limited * * This file is part of srsRAN. * * srsRAN 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. * * srsRAN 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 "srsran/common/security.h" #include "mbedtls/md5.h" #include "srsran/common/liblte_security.h" #include "srsran/common/s3g.h" #include "srsran/common/ssl.h" #include "srsran/config.h" #include #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_K_GNB_STAR_DERIVATION 0x70 #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(const uint8_t* ck, const uint8_t* ik, const uint8_t* ak_xor_sqn_, const uint16_t mcc, const uint16_t mnc, uint8_t* 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_ausf(const uint8_t* ck, const uint8_t* ik, const uint8_t* ak_xor_sqn_, const char* serving_network_name, uint8_t* k_ausf) { 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_KAUSF_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_seaf(const uint8_t* k_ausf, const char* serving_network_name, uint8_t* k_seaf) { if (k_ausf == NULL || serving_network_name == NULL || k_seaf == NULL) { log_error("Invalid inputs"); return SRSRAN_ERROR; } std::array key; memcpy(key.data(), k_ausf, 32); // Serving Network Name std::vector ssn; ssn.resize(strlen(serving_network_name)); memcpy(ssn.data(), serving_network_name, ssn.size()); if (kdf_common(FC_5G_KSEAF_DERIVATION, key, ssn, k_seaf) != SRSRAN_SUCCESS) { log_error("Failed to run kdf_common"); return SRSRAN_ERROR; } return SRSRAN_SUCCESS; } uint8_t security_generate_k_amf(const uint8_t* k_seaf, const char* supi_, const uint8_t* abba_, const uint32_t abba_len, uint8_t* k_amf) { if (k_seaf == NULL || supi_ == NULL || abba_ == NULL || k_amf == NULL) { log_error("Invalid inputs"); return SRSRAN_ERROR; } std::array key; memcpy(key.data(), k_seaf, 32); // SUPI std::vector supi; supi.resize(strlen(supi_)); memcpy(supi.data(), supi_, supi.size()); // ABBA std::vector abba; abba.resize(abba_len); memcpy(abba.data(), abba_, abba.size()); if (kdf_common(FC_5G_KAMF_DERIVATION, key, supi, abba, k_amf) != SRSRAN_SUCCESS) { log_error("Failed to run kdf_common"); return SRSRAN_ERROR; } return SRSRAN_SUCCESS; } uint8_t security_generate_k_gnb(const as_key_t& k_amf, const uint32_t nas_count_, as_key_t& k_gnb) { if (k_amf.empty()) { log_error("Invalid inputs"); return SRSRAN_ERROR; } // 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; // Access Type Distinguisher 3GPP access = 0x01 (TS 33501 Annex A.9) std::vector access_type_distinguisher = {1}; if (kdf_common(FC_5G_KGNB_KN3IWF_DERIVATION, k_amf, nas_count, access_type_distinguisher, k_gnb.data()) != SRSRAN_SUCCESS) { log_error("Failed to run kdf_common"); return SRSRAN_ERROR; } return SRSRAN_SUCCESS; } uint8_t security_generate_k_enb(const uint8_t* k_asme, const uint32_t nas_count_, uint8_t* k_enb) { 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; } // Generate k_enb* according to TS 33.401 Appendix A.5 uint8_t security_generate_k_enb_star(const uint8_t* k_enb, const uint32_t pci_, const uint32_t earfcn_, uint8_t* k_enb_star) { return security_generate_k_nb_star_common(FC_EPS_K_ENB_STAR_DERIVATION, k_enb, pci_, earfcn_, k_enb_star); } // Generate k_gnb* according to TS 33.501 Appendix A.11 uint8_t security_generate_k_gnb_star(const uint8_t* k_gnb, const uint32_t pci_, const uint32_t dl_arfcn_, uint8_t* k_gnb_star) { return security_generate_k_nb_star_common(FC_5G_K_GNB_STAR_DERIVATION, k_gnb, pci_, dl_arfcn_, k_gnb_star); } uint8_t security_generate_k_nb_star_common(uint8_t fc, const uint8_t* k_enb, const uint32_t pci_, const uint32_t earfcn_, uint8_t* k_enb_star) { 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; // ARFCN, can be two or three bytes std::vector earfcn; if (earfcn_ < pow(2, 16)) { earfcn.resize(2); earfcn[0] = (earfcn_ >> 8) & 0xFF; earfcn[1] = earfcn_ & 0xFF; } else if (earfcn_ < pow(2, 24)) { earfcn.resize(3); earfcn[0] = (earfcn_ >> 16) & 0xFF; earfcn[1] = (earfcn_ >> 8) & 0xFF; earfcn[2] = earfcn_ & 0xFF; } if (kdf_common(fc, 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(const uint8_t* k_asme, const 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(const uint8_t* k_asme, const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, uint8_t* k_nas_enc, uint8_t* 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_nas_5g(const uint8_t* k_amf, const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, uint8_t* k_nas_enc, uint8_t* k_nas_int) { if (k_amf == NULL || k_nas_enc == NULL || k_nas_int == NULL) { log_error("Invalid inputs"); return SRSRAN_ERROR; } std::array key; memcpy(key.data(), k_amf, 32); // Derive NAS ENC // algorithm type distinguisher std::vector algo_distinguisher; algo_distinguisher.resize(1); algo_distinguisher[0] = ALGO_5G_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_5G_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_5G_DISTINGUISHER_NAS_INT_ALG; // algorithm type distinguisher algorithm_identity.resize(1); algorithm_identity[0] = int_alg_id; // Derive NAS int if (kdf_common(FC_5G_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(const uint8_t* k_enb, const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, uint8_t* k_rrc_enc, uint8_t* 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(const uint8_t* k_enb, const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, uint8_t* k_up_enc, uint8_t* 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(const uint8_t* k_enb, const uint16_t scg_count_, uint8_t* sk_gnb) { 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(const uint8_t* k_gnb, const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, uint8_t* k_rrc_enc, uint8_t* 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(const uint8_t* k_gnb, const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, uint8_t* k_up_enc, uint8_t* 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_res_star(const uint8_t* ck, const uint8_t* ik, const char* serving_network_name, const uint8_t* rand_, const uint8_t* res_, const size_t res_len_, uint8_t* res_star) { 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 *****************************************************************************/ uint8_t security_128_eia1(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_eia1(key, count, bearer, direction, msg, msg_len, mac); } uint8_t security_128_eia2(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_eia2(key, count, bearer, direction, msg, msg_len, 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); } uint8_t security_md5(const uint8_t* input, size_t len, uint8_t* output) { memset(output, 0x00, 16); mbedtls_md5(input, len, output); return SRSRAN_SUCCESS; } /****************************************************************************** * Encryption / Decryption *****************************************************************************/ uint8_t security_128_eea1(uint8_t* key, uint32_t count, uint8_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* msg_out) { return liblte_security_encryption_eea1(key, count, bearer, direction, msg, msg_len * 8, msg_out); } uint8_t security_128_eea2(uint8_t* key, uint32_t count, uint8_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* msg_out) { return liblte_security_encryption_eea2(key, count, bearer, direction, msg, msg_len * 8, msg_out); } uint8_t security_128_eea3(uint8_t* key, uint32_t count, uint8_t bearer, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* msg_out) { return liblte_security_encryption_eea3(key, count, bearer, direction, msg, msg_len * 8, msg_out); } /****************************************************************************** * Authentication *****************************************************************************/ uint8_t compute_opc(uint8_t* k, uint8_t* op, uint8_t* opc) { return liblte_compute_opc(k, op, opc); } uint8_t security_milenage_f1(uint8_t* k, uint8_t* op, uint8_t* rand, uint8_t* sqn, uint8_t* amf, uint8_t* mac_a) { return liblte_security_milenage_f1(k, op, rand, sqn, amf, mac_a); } uint8_t security_milenage_f1_star(uint8_t* k, uint8_t* op, uint8_t* rand, uint8_t* sqn, uint8_t* amf, uint8_t* mac_s) { return liblte_security_milenage_f1_star(k, op, rand, sqn, amf, mac_s); } uint8_t security_milenage_f2345(uint8_t* k, uint8_t* op, uint8_t* rand, uint8_t* res, uint8_t* ck, uint8_t* ik, uint8_t* ak) { return liblte_security_milenage_f2345(k, op, rand, res, ck, ik, ak); } uint8_t security_milenage_f5_star(uint8_t* k, uint8_t* op, uint8_t* rand, uint8_t* ak) { return liblte_security_milenage_f5_star(k, op, rand, ak); } int security_xor_f2345(uint8_t* k, uint8_t* rand, uint8_t* res, uint8_t* ck, uint8_t* ik, uint8_t* ak) { uint8_t xdout[16]; uint8_t cdout[8]; // Use RAND and K to compute RES, CK, IK and AK for (uint32_t i = 0; i < 16; i++) { xdout[i] = k[i] ^ rand[i]; } for (uint32_t i = 0; i < 16; i++) { res[i] = xdout[i]; ck[i] = xdout[(i + 1) % 16]; ik[i] = xdout[(i + 2) % 16]; } for (uint32_t i = 0; i < 6; i++) { ak[i] = xdout[i + 3]; } return SRSRAN_SUCCESS; } int security_xor_f1(uint8_t* k, uint8_t* rand, uint8_t* sqn, uint8_t* amf, uint8_t* mac_a) { uint8_t xdout[16]; uint8_t cdout[8]; // Use RAND and K to compute RES, CK, IK and AK for (uint32_t i = 0; i < 16; i++) { xdout[i] = k[i] ^ rand[i]; } // Generate cdout for (uint32_t i = 0; i < 6; i++) { cdout[i] = sqn[i]; } for (uint32_t i = 0; i < 2; i++) { cdout[6 + i] = amf[i]; } // Generate MAC for (uint32_t i = 0; i < 8; i++) { mac_a[i] = xdout[i] ^ cdout[i]; } return SRSRAN_SUCCESS; } } // namespace srsran