diff --git a/lib/include/srslte/common/liblte_security.h b/lib/include/srslte/common/liblte_security.h index 8dc31f341..b82168696 100644 --- a/lib/include/srslte/common/liblte_security.h +++ b/lib/include/srslte/common/liblte_security.h @@ -52,6 +52,17 @@ DECLARATIONS *******************************************************************************/ +/********************************************************************* + Name: compute_OPc + + Description: Computes OPc from OP and K. + + Document Reference: 35.206 v10.0.0 Annex 3 +*********************************************************************/ +LIBLTE_ERROR_ENUM liblte_compute_opc(uint8 *k, + uint8 *op, + uint8 *op_c); + /********************************************************************* Name: liblte_security_generate_k_asme diff --git a/lib/include/srslte/common/security.h b/lib/include/srslte/common/security.h index 5dc8a6305..29bd6000c 100644 --- a/lib/include/srslte/common/security.h +++ b/lib/include/srslte/common/security.h @@ -151,6 +151,9 @@ uint8_t security_128_eea2(uint8_t *key, /****************************************************************************** * Authentication *****************************************************************************/ +uint8_t compute_opc( uint8_t *k, + uint8_t *op, + uint8_t *opc); uint8_t security_milenage_f1( uint8_t *k, uint8_t *op, diff --git a/lib/src/common/liblte_security.cc b/lib/src/common/liblte_security.cc index 1cf83e5b3..09e79fb5a 100644 --- a/lib/src/common/liblte_security.cc +++ b/lib/src/common/liblte_security.cc @@ -1099,7 +1099,7 @@ LIBLTE_ERROR_ENUM liblte_security_decryption_eea2(uint8 *key, Document Reference: 35.206 v10.0.0 Annex 3 *********************************************************************/ LIBLTE_ERROR_ENUM liblte_security_milenage_f1(uint8 *k, - uint8 *op, + uint8 *op_c, uint8 *rand, uint8 *sqn, uint8 *amf, @@ -1108,13 +1108,13 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1(uint8 *k, LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; ROUND_KEY_STRUCT round_keys; uint32 i; - uint8 op_c[16]; uint8 temp[16]; uint8 in1[16]; uint8 out1[16]; uint8 rijndael_input[16]; if(k != NULL && + op_c != NULL && rand != NULL && sqn != NULL && amf != NULL && @@ -1123,9 +1123,6 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1(uint8 *k, // Initialize the round keys rijndael_key_schedule(k, &round_keys); - // Compute OPc - compute_OPc(&round_keys, op, op_c); - // Compute temp for(i=0; i<16; i++) { @@ -1183,7 +1180,7 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1(uint8 *k, Document Reference: 35.206 v10.0.0 Annex 3 *********************************************************************/ LIBLTE_ERROR_ENUM liblte_security_milenage_f1_star(uint8 *k, - uint8 *op, + uint8 *op_c, uint8 *rand, uint8 *sqn, uint8 *amf, @@ -1192,13 +1189,13 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1_star(uint8 *k, LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; ROUND_KEY_STRUCT round_keys; uint32 i; - uint8 op_c[16]; uint8 temp[16]; uint8 in1[16]; uint8 out1[16]; uint8 rijndael_input[16]; if(k != NULL && + op_c != NULL && rand != NULL && sqn != NULL && amf != NULL && @@ -1207,9 +1204,6 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1_star(uint8 *k, // Initialize the round keys rijndael_key_schedule(k, &round_keys); - // Compute OPc - compute_OPc(&round_keys, op, op_c); - // Compute temp for(i=0; i<16; i++) { @@ -1267,7 +1261,7 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1_star(uint8 *k, Document Reference: 35.206 v10.0.0 Annex 3 *********************************************************************/ LIBLTE_ERROR_ENUM liblte_security_milenage_f2345(uint8 *k, - uint8 *op, + uint8 *op_c, uint8 *rand, uint8 *res, uint8 *ck, @@ -1277,12 +1271,12 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f2345(uint8 *k, LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; ROUND_KEY_STRUCT round_keys; uint32 i; - uint8 op_c[16]; uint8 temp[16]; uint8 out[16]; uint8 rijndael_input[16]; if(k != NULL && + op_c != NULL && rand != NULL && res != NULL && ck != NULL && @@ -1292,9 +1286,6 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f2345(uint8 *k, // Initialize the round keys rijndael_key_schedule(k, &round_keys); - // Compute OPc - compute_OPc(&round_keys, op, op_c); - // Compute temp for(i=0; i<16; i++) { @@ -1378,28 +1369,25 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f2345(uint8 *k, Document Reference: 35.206 v10.0.0 Annex 3 *********************************************************************/ LIBLTE_ERROR_ENUM liblte_security_milenage_f5_star(uint8 *k, - uint8 *op, + uint8 *op_c, uint8 *rand, uint8 *ak) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; ROUND_KEY_STRUCT round_keys; uint32 i; - uint8 op_c[16]; uint8 temp[16]; uint8 out[16]; uint8 rijndael_input[16]; if(k != NULL && + op_c != NULL && rand != NULL && ak != NULL) { // Initialize the round keys rijndael_key_schedule(k, &round_keys); - // Compute OPc - compute_OPc(&round_keys, op, op_c); - // Compute temp for(i=0; i<16; i++) { @@ -1424,37 +1412,48 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f5_star(uint8 *k, { ak[i] = out[i]; } - err = LIBLTE_SUCCESS; } - return(err); } -/******************************************************************************* - LOCAL FUNCTIONS -*******************************************************************************/ - /********************************************************************* - Name: compute_OPc + Name: liblte_compute_opc Description: Computes OPc from OP and K. Document Reference: 35.206 v10.0.0 Annex 3 *********************************************************************/ -void compute_OPc(ROUND_KEY_STRUCT *rk, - uint8 *op, - uint8 *op_c) + +LIBLTE_ERROR_ENUM liblte_compute_opc(uint8 *k, + uint8 *op, + uint8 *op_c) { - uint32 i; + uint32 i; + ROUND_KEY_STRUCT round_keys; + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(k != NULL && + op != NULL && + op_c != NULL) + { - rijndael_encrypt(op, rk, op_c); + rijndael_key_schedule(k, &round_keys); + rijndael_encrypt(op, &round_keys, op_c); for(i=0; i<16; i++) { - op_c[i] ^= op[i]; + op_c[i] ^= op[i]; } + err = LIBLTE_SUCCESS; + } + return err; } +/******************************************************************************* + LOCAL FUNCTIONS +*******************************************************************************/ + + /********************************************************************* Name: rijndael_key_schedule diff --git a/lib/src/common/security.cc b/lib/src/common/security.cc index 63cd478c0..65ef5e0c4 100644 --- a/lib/src/common/security.cc +++ b/lib/src/common/security.cc @@ -229,6 +229,14 @@ uint8_t security_128_eea2(uint8_t *key, /****************************************************************************** * 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, diff --git a/lib/test/common/test_f12345.cc b/lib/test/common/test_f12345.cc index 1c5375c43..e75d80bd7 100644 --- a/lib/test/common/test_f12345.cc +++ b/lib/test/common/test_f12345.cc @@ -63,9 +63,19 @@ void test_set_2() uint8_t op[] = {0xcd, 0xc2, 0x02, 0xd5, 0x12, 0x3e, 0x20, 0xf6, 0x2b, 0x6d, 0x67, 0x6a, 0xc7, 0x2c, 0xb3, 0x18}; // f1 - uint8_t mac_o[8]; + uint8_t opc_o[16]; + err_lte = liblte_compute_opc(k,op,opc_o); + assert(err_lte == LIBLTE_SUCCESS); + + arrprint(opc_o, sizeof(opc_o)); + + uint8_t opc_a[] = {0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e, 0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf}; + err_cmp = arrcmp(opc_o,opc_a,sizeof(opc_o)); + assert(err_cmp == 0); + + uint8_t mac_o[8]; err_lte = liblte_security_milenage_f1(k, - op, + opc_o, rand, sqn, amf, @@ -84,7 +94,7 @@ void test_set_2() uint8_t mac_so[8]; err_lte = liblte_security_milenage_f1_star(k, - op, + opc_o, rand, sqn, amf, @@ -93,9 +103,9 @@ void test_set_2() assert(err_lte == LIBLTE_SUCCESS); uint8_t mac_s[] = {0x01, 0xcf, 0xaf, 0x9e, 0xc4, 0xe8, 0x71, 0xe9}; - + arrprint(mac_so, sizeof(mac_so)); - + err_cmp = arrcmp(mac_so, mac_s, sizeof(mac_s)); assert(err_cmp == 0); @@ -106,7 +116,7 @@ void test_set_2() uint8_t ak_o[6]; err_lte = liblte_security_milenage_f2345(k, - op, + opc_o, rand, res_o, ck_o, @@ -126,7 +136,7 @@ void test_set_2() err_cmp = arrcmp(res_o, res, sizeof(res)); assert(err_cmp == 0); - // CK + // CK arrprint(ck_o, sizeof(ck_o)); err_cmp = arrcmp(ck_o, ck, sizeof(ck)); @@ -142,10 +152,10 @@ void test_set_2() err_cmp = arrcmp(ak_o, ak, sizeof(ak)); assert(err_cmp == 0); - // f star + // f star uint8_t ak_star_o[6]; - - err_lte = liblte_security_milenage_f5_star(k, op, rand, ak_star_o); + + err_lte = liblte_security_milenage_f5_star(k, opc_o, rand, ak_star_o); assert(err_lte == LIBLTE_SUCCESS); arrprint(ak_star_o, sizeof(ak_star_o)); @@ -160,8 +170,9 @@ void test_set_2() */ int main(int argc, char * argv[]) { - /* + test_set_2(); + /* test_set_3(); test_set_4(); test_set_5(); diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index 97e2d45c1..4df632d83 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -54,11 +54,13 @@ typedef struct{ typedef struct{ std::string name; uint64_t imsi; - uint8_t key[16]; - uint8_t op[16]; - uint8_t amf[2]; - uint8_t sqn[6]; - uint8_t last_rand[16]; + uint8_t key[16]; + bool op_configured; + uint8_t op[16]; + uint8_t opc[16]; + uint8_t amf[2]; + uint8_t sqn[6]; + uint8_t last_rand[16]; }hss_ue_ctx_t; enum hss_auth_algo { @@ -89,7 +91,7 @@ private: void gen_rand(uint8_t rand_[16]); - bool get_k_amf_op_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op, uint8_t *sqn); + bool get_k_amf_opc_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *opc, uint8_t *sqn); bool gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres); bool gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres); @@ -100,7 +102,8 @@ private: std::vector split_string(const std::string &str, char delimiter); void get_uint_vec_from_hex_str(const std::string &key_str, uint8_t *key, uint len); - void increment_sqn(uint64_t imsi); + void increment_ue_sqn(uint64_t imsi); + void increment_sqn(uint8_t *sqn, uint8_t *next_sqn); void set_sqn(uint64_t imsi, uint8_t *sqn); void set_last_rand(uint64_t imsi, uint8_t *rand); diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index a71daada8..7465f9696 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -110,6 +110,7 @@ typedef struct{ } enb_ctx_t; typedef struct{ + uint8_t eksi; uint8_t k_asme[32]; uint8_t xres[16]; //minimum 6, maximum 16 uint32_t dl_nas_count; diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index e0b7d93fa..3a11302c5 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -113,7 +113,7 @@ private: bool integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t *pdu); bool short_integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t *pdu); - bool pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t *autn,uint8_t *rand); + bool pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t eksi, uint8_t *autn, uint8_t *rand); bool pack_authentication_reject(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id); bool unpack_authentication_response(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp); diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 9a8db0e3a..cd48f23c1 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -52,7 +52,7 @@ hss::~hss() hss* hss::get_instance(void) -{ +{ pthread_mutex_lock(&hss_instance_mutex); if(NULL == m_instance) { m_instance = new hss(); @@ -93,7 +93,7 @@ hss::init(hss_args_t *hss_args, srslte::log_filter *hss_log) mcc = hss_args->mcc; mnc = hss_args->mnc; - + db_file = hss_args->db_file; m_hss_log->info("HSS Initialized. DB file %s, authentication algorithm %s, MCC: %d, MNC: %d\n", hss_args->db_file.c_str(),hss_args->auth_algo.c_str(), mcc, mnc); @@ -140,7 +140,7 @@ bool hss::read_db_file(std::string db_filename) { std::ifstream m_db_file; - + m_db_file.open(db_filename.c_str(), std::ifstream::in); if(!m_db_file.is_open()) { @@ -153,23 +153,43 @@ hss::read_db_file(std::string db_filename) { if(line[0] != '#') { - std::vector split = split_string(line,','); - if(split.size()!=6) + uint column_size = 7; + std::vector split = split_string(line,','); + if(split.size() != column_size) { - m_hss_log->error("Error parsing UE database\n"); + m_hss_log->error("Error parsing UE database. Wrong number of columns in .csv\n"); + m_hss_log->error("Columns: %lu, Expected %d.\n",split.size(),column_size); return false; } hss_ue_ctx_t *ue_ctx = new hss_ue_ctx_t; ue_ctx->name = split[0]; ue_ctx->imsi = atoll(split[1].c_str()); get_uint_vec_from_hex_str(split[2],ue_ctx->key,16); - get_uint_vec_from_hex_str(split[3],ue_ctx->op,16); - get_uint_vec_from_hex_str(split[4],ue_ctx->amf,2); - get_uint_vec_from_hex_str(split[5],ue_ctx->sqn,6); + if(split[3] == std::string("op")) + { + ue_ctx->op_configured = true; + get_uint_vec_from_hex_str(split[4],ue_ctx->op,16); + compute_opc(ue_ctx->key,ue_ctx->op,ue_ctx->opc); + } + else if (split[3] == std::string("opc")) + { + ue_ctx->op_configured =false; + get_uint_vec_from_hex_str(split[4],ue_ctx->opc,16); + } + else + { + m_hss_log->error("Neither OP nor OPc configured.\n"); + return false; + } + get_uint_vec_from_hex_str(split[5],ue_ctx->amf,2); + get_uint_vec_from_hex_str(split[6],ue_ctx->sqn,6); m_hss_log->debug("Added user from DB, IMSI: %015lu\n", ue_ctx->imsi); m_hss_log->debug_hex(ue_ctx->key, 16, "User Key : "); - m_hss_log->debug_hex(ue_ctx->op, 16, "User OP : "); + if(ue_ctx->op_configured){ + m_hss_log->debug_hex(ue_ctx->op, 16, "User OP : "); + } + m_hss_log->debug_hex(ue_ctx->opc, 16, "User OPc : "); m_hss_log->debug_hex(ue_ctx->amf, 2, "AMF : "); m_hss_log->debug_hex(ue_ctx->sqn, 6, "SQN : "); @@ -194,7 +214,7 @@ bool hss::write_db_file(std::string db_filename) uint8_t sqn[6]; std::ofstream m_db_file; - + m_db_file.open(db_filename.c_str(), std::ofstream::out); if(!m_db_file.is_open()) { @@ -202,6 +222,21 @@ bool hss::write_db_file(std::string db_filename) } m_hss_log->info("Opened DB file: %s\n", db_filename.c_str() ); + //Write comment info + m_db_file << "# " << std::endl + << "# .csv to store UE's information in HSS " << std::endl + << "# Kept in the following format: \"Name,IMSI,Key,OP_Type,OP,AMF,SQN\" " << std::endl + << "# " << std::endl + << "# Name: Human readable name to help distinguish UE's. Ignored by the HSS " << std::endl + << "# IMSI: UE's IMSI value " << std::endl + << "# Key: UE's key, where other keys are derived from. Stored in hexadecimal" << std::endl + << "# OP_Type: Operator's code type, either OP or OPc " << std::endl + << "# OP/OPc: Operator Code/Cyphered Operator Code, stored in hexadecimal " << std::endl + << "# AMF: Authentication management field, stored in hexadecimal " << std::endl + << "# SQN: UE's Sequence number for freshness of the authentication " << std::endl + << "# " << std::endl + << "# Note: Lines starting by '#' are ignored and will be overwritten " << std::endl; + std::map::iterator it = m_imsi_to_ue_ctx.begin(); while(it!=m_imsi_to_ue_ctx.end()) { @@ -211,7 +246,14 @@ bool hss::write_db_file(std::string db_filename) m_db_file << ","; m_db_file << hex_string(it->second->key, 16); m_db_file << ","; - m_db_file << hex_string(it->second->op, 16); + if(it->second->op_configured){ + m_db_file << "op,"; + m_db_file << hex_string(it->second->op, 16); + } + else{ + m_db_file << "opc,"; + m_db_file << hex_string(it->second->opc, 16); + } m_db_file << ","; m_db_file << hex_string(it->second->amf, 2); m_db_file << ","; @@ -240,7 +282,7 @@ hss::gen_auth_info_answer(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t ret = gen_auth_info_answer_milenage(imsi, k_asme, autn, rand, xres); break; } - increment_sqn(imsi); + increment_ue_sqn(imsi); return ret; } @@ -258,7 +300,7 @@ hss::resync_sqn(uint64_t imsi, uint8_t *auts) ret = resync_sqn_milenage(imsi, auts); break; } - increment_sqn(imsi); + increment_ue_sqn(imsi); return ret; } @@ -281,10 +323,10 @@ hss::resync_sqn_milenage(uint64_t imsi, uint8_t *auts) uint8_t k[16]; uint8_t amf[2]; - uint8_t op[16]; + uint8_t opc[16]; uint8_t sqn[6]; - if(!get_k_amf_op_sqn(imsi, k, amf, op, sqn)) + if(!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn)) { return false; } @@ -300,13 +342,13 @@ hss::resync_sqn_milenage(uint64_t imsi, uint8_t *auts) } m_hss_log->debug_hex(k, 16, "User Key : "); - m_hss_log->debug_hex(op, 16, "User OP : "); + m_hss_log->debug_hex(opc, 16, "User OPc : "); m_hss_log->debug_hex(last_rand, 16, "User Last Rand : "); m_hss_log->debug_hex(auts, 16, "AUTS : "); m_hss_log->debug_hex(sqn_ms_xor_ak, 6, "SQN xor AK : "); m_hss_log->debug_hex(mac_s, 8, "MAC : "); - security_milenage_f5_star(k, op, last_rand, ak); + security_milenage_f5_star(k, opc, last_rand, ak); m_hss_log->debug_hex(ak, 6, "Resynch AK : "); uint8_t sqn_ms[6]; @@ -314,22 +356,16 @@ hss::resync_sqn_milenage(uint64_t imsi, uint8_t *auts) sqn_ms[i] = sqn_ms_xor_ak[i] ^ ak[i]; } m_hss_log->debug_hex(sqn_ms, 6, "SQN MS : "); + m_hss_log->debug_hex(sqn , 6, "SQN HE : "); m_hss_log->debug_hex(amf, 2, "AMF : "); uint8_t mac_s_tmp[8]; - security_milenage_f1_star(k, op, last_rand, sqn_ms, amf, mac_s_tmp); + security_milenage_f1_star(k, opc, last_rand, sqn_ms, amf, mac_s_tmp); m_hss_log->debug_hex(mac_s_tmp, 8, "MAC calc : "); - /* - for(int i=0; i<8; i++){ - if(!(mac_s_tmp[i] == mac_s[i])){ - m_hss_log->error("Calculated MAC does not match sent MAC\n"); - return false; - } - } - */ + set_sqn(imsi, sqn_ms); return true; @@ -340,7 +376,7 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn { uint8_t k[16]; uint8_t amf[2]; - uint8_t op[16]; + uint8_t opc[16]; uint8_t sqn[6]; uint8_t ck[16]; @@ -349,14 +385,14 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn uint8_t mac[8]; - if(!get_k_amf_op_sqn(imsi, k, amf, op, sqn)) + if(!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn)) { return false; } gen_rand(rand); security_milenage_f2345( k, - op, + opc, rand, xres, ck, @@ -364,7 +400,7 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn ak); m_hss_log->debug_hex(k, 16, "User Key : "); - m_hss_log->debug_hex(op, 16, "User OP : "); + m_hss_log->debug_hex(opc, 16, "User OPc : "); m_hss_log->debug_hex(rand, 16, "User Rand : "); m_hss_log->debug_hex(xres, 8, "User XRES: "); m_hss_log->debug_hex(ck, 16, "User CK: "); @@ -372,7 +408,7 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn m_hss_log->debug_hex(ak, 6, "User AK: "); security_milenage_f1( k, - op, + opc, rand, sqn, amf, @@ -419,7 +455,7 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin { uint8_t k[16]; uint8_t amf[2]; - uint8_t op[16]; + uint8_t opc[16]; uint8_t sqn[6]; uint8_t xdout[16]; @@ -432,7 +468,7 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin int i = 0; - if(!get_k_amf_op_sqn(imsi, k, amf, op, sqn)) + if(!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn)) { return false; } @@ -453,7 +489,7 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin } m_hss_log->debug_hex(k, 16, "User Key : "); - m_hss_log->debug_hex(op, 16, "User OP : "); + m_hss_log->debug_hex(opc, 16, "User OPc : "); m_hss_log->debug_hex(rand, 16, "User Rand : "); m_hss_log->debug_hex(xres, 8, "User XRES: "); m_hss_log->debug_hex(ck, 16, "User CK: "); @@ -525,7 +561,7 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin bool -hss::get_k_amf_op_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op, uint8_t *sqn) +hss::get_k_amf_opc_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *opc, uint8_t *sqn) { std::map::iterator ue_ctx_it = m_imsi_to_ue_ctx.find(imsi); @@ -539,14 +575,14 @@ hss::get_k_amf_op_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op, uint m_hss_log->info("Found User %015lu\n",imsi); memcpy(k, ue_ctx->key, 16); memcpy(amf, ue_ctx->amf, 2); - memcpy(op, ue_ctx->op, 16); + memcpy(opc, ue_ctx->opc, 16); memcpy(sqn, ue_ctx->sqn, 6); return true; } -void -hss::increment_sqn(uint64_t imsi) +void +hss::increment_ue_sqn(uint64_t imsi) { hss_ue_ctx_t *ue_ctx = NULL; bool ret = get_ue_ctx(imsi, &ue_ctx); @@ -555,23 +591,28 @@ hss::increment_sqn(uint64_t imsi) return; } + increment_sqn(ue_ctx->sqn,ue_ctx->sqn); + m_hss_log->debug("Incremented SQN (IMSI: %" PRIu64 ")" PRIu64 "\n", imsi); + m_hss_log->debug_hex(ue_ctx->sqn, 6, "SQN: "); +} + +void +hss::increment_sqn(uint8_t *sqn, uint8_t *next_sqn) +{ // Awkward 48 bit sqn and doing arithmetic - uint64_t sqn = 0; - uint8_t *p = (uint8_t *)&sqn; + uint64_t tmp_sqn = 0; + uint8_t *p = (uint8_t *)&tmp_sqn; for(int i = 0; i < 6; i++) { - p[5-i] = (uint8_t) ((ue_ctx->sqn[i])); + p[5-i] = sqn[i]; } - - sqn++; - - m_hss_log->debug("Incremented SQN (IMSI: %" PRIu64 ") SQN: %" PRIu64 "\n", imsi, sqn); + tmp_sqn++; for(int i = 0; i < 6; i++){ - ue_ctx->sqn[i] = p[5-i]; + next_sqn[i] = p[5-i]; } + return; } - void hss::set_sqn(uint64_t imsi, uint8_t *sqn) { diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index e8ee25a1d..821ccf1bf 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -223,7 +223,8 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA if( sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS || (msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) || - (msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) + (msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) || + (msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) { //Only identity response and authentication response are valid as plain NAS. //Sometimes authentication response and identity are sent as integrity protected, @@ -504,6 +505,9 @@ s1ap_nas_transport::handle_nas_imsi_attach_request(uint32_t enb_ue_s1ap_id, m_s1ap_log->info("User not found. IMSI %015lu\n",emm_ctx->imsi); return false; } + //Allocate eKSI for this authentication vector + //Here we assume a new security context thus a new eKSI + emm_ctx->security_ctxt.eksi=0; //Save the UE context ue_ctx_t *new_ctx = new ue_ctx_t; @@ -513,7 +517,7 @@ s1ap_nas_transport::handle_nas_imsi_attach_request(uint32_t enb_ue_s1ap_id, m_s1ap->add_ue_to_enb_set(enb_sri->sinfo_assoc_id,ecm_ctx->mme_ue_s1ap_id); //Pack NAS Authentication Request in Downlink NAS Transport msg - pack_authentication_request(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand); + pack_authentication_request(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, emm_ctx->security_ctxt.eksi, autn, rand); //Send reply to eNB *reply_flag = true; @@ -593,7 +597,7 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id, //Save whether ESM information transfer is necessary ecm_ctx->eit = pdn_con_req.esm_info_transfer_flag_present; - //m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id); + //Add eNB info to UE ctxt memcpy(&ecm_ctx->enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); //Initialize E-RABs @@ -618,7 +622,6 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id, m_s1ap_log->console("Could not find M-TMSI=0x%x. Sending ID request\n",m_tmsi); m_s1ap_log->info("Could not find M-TMSI=0x%x. Sending Id Request\n", m_tmsi); - //m_s1ap->add_new_ue_ecm_ctx(ue_ecm_ctx); //Store temporary ue context ue_ctx_t *new_ctx = new ue_ctx_t; @@ -763,12 +766,12 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id, } //Store context based on MME UE S1AP id m_s1ap->add_ue_ctx_to_mme_ue_s1ap_id_map(ue_ctx); - + //NAS integrity failed. Re-start authentication process. m_s1ap_log->console("GUTI Attach request NAS integrity failed.\n"); m_s1ap_log->console("RE-starting authentication procedure.\n"); - uint8_t autn[16]; - uint8_t rand[16]; + uint8_t autn[16]; + uint8_t rand[16]; //Get Authentication Vectors from HSS if(!m_hss->gen_auth_info_answer(emm_ctx->imsi, emm_ctx->security_ctxt.k_asme, autn, rand, emm_ctx->security_ctxt.xres)) { @@ -776,7 +779,9 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id, m_s1ap_log->info("User not found. IMSI %015lu\n",emm_ctx->imsi); return false; } - pack_authentication_request(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand); + //Restarting security context. Reseting eKSI to 0. + emm_ctx->security_ctxt.eksi=0; + pack_authentication_request(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, emm_ctx->security_ctxt.eksi, autn, rand); //Send reply to eNB *reply_flag = true; @@ -1034,6 +1039,7 @@ s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *na { m_s1ap_log->console("UE Authentication Accepted.\n"); m_s1ap_log->info("UE Authentication Accepted.\n"); + //Send Security Mode Command emm_ctx->security_ctxt.ul_nas_count = 0; // Reset the NAS uplink counter for the right key k_enb derivation pack_security_mode_command(reply_buffer, emm_ctx, ecm_ctx); @@ -1199,12 +1205,14 @@ s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); return false; } + //Identity reponse from unknown GUTI atach. Assigning new eKSI. + emm_ctx->security_ctxt.eksi=0; //Store UE context im IMSI map m_s1ap->add_ue_ctx_to_imsi_map(ue_ctx); //Pack NAS Authentication Request in Downlink NAS Transport msg - pack_authentication_request(reply_msg, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand); + pack_authentication_request(reply_msg, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, emm_ctx->security_ctxt.eksi, autn, rand); //Send reply to eNB *reply_flag = true; @@ -1385,8 +1393,8 @@ s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg m_s1ap_log->info("Non-EPS authentication unacceptable\n"); break; case 21: - m_s1ap_log->console("Sequence number synch failure\n"); - m_s1ap_log->info("Sequence number synch failure\n"); + m_s1ap_log->console("Authentication Failure -- Synchronization Failure\n"); + m_s1ap_log->info("Authentication Failure -- Synchronization Failure\n"); if(auth_fail.auth_fail_param_present == false){ m_s1ap_log->error("Missing fail parameter\n"); return false; @@ -1404,8 +1412,11 @@ s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg m_s1ap_log->info("User not found. IMSI %015lu\n", emm_ctx->imsi); return false; } + //Making sure eKSI is different from previous eKSI. + emm_ctx->security_ctxt.eksi = (emm_ctx->security_ctxt.eksi+1)%6; + //Pack NAS Authentication Request in Downlink NAS Transport msg - pack_authentication_request(reply_msg, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand); + pack_authentication_request(reply_msg, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, emm_ctx->security_ctxt.eksi, autn, rand); //Send reply to eNB *reply_flag = true; @@ -1417,15 +1428,10 @@ s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg } return true; } - /* -bool -s1ap_nas_transport::handle_detach_request(nas_msg, ue_ctx, reply_buffer, reply_flag) -{ - return true; - }*/ + /*Packing/Unpacking helper functions*/ bool -s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t *autn, uint8_t *rand) +s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t eksi, uint8_t *autn, uint8_t *rand) { srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); @@ -1453,7 +1459,7 @@ s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg memcpy(auth_req.autn , autn, 16); memcpy(auth_req.rand, rand, 16); auth_req.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; - auth_req.nas_ksi.nas_ksi=0; + auth_req.nas_ksi.nas_ksi = eksi; LIBLTE_ERROR_ENUM err = liblte_mme_pack_authentication_request_msg(&auth_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) @@ -1590,7 +1596,7 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, sm_cmd.selected_nas_sec_algs.type_of_eia = LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_128_EIA1; sm_cmd.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; - sm_cmd.nas_ksi.nas_ksi=0; + sm_cmd.nas_ksi.nas_ksi=ue_emm_ctx->security_ctxt.eksi; //Replay UE security cap memcpy(sm_cmd.ue_security_cap.eea,ue_emm_ctx->security_ctxt.ue_network_cap.eea,8*sizeof(bool)); @@ -1607,8 +1613,6 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, sm_cmd.nonce_mme_present=false; uint8_t sec_hdr_type=3; - - // ue_emm_ctx->security_ctxt.dl_nas_count = 0; LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg(&sm_cmd,sec_hdr_type, ue_emm_ctx->security_ctxt.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) { @@ -1690,9 +1694,8 @@ s1ap_nas_transport::pack_esm_information_request(srslte::byte_buffer_t *reply_ms esm_info_req.proc_transaction_id = ue_emm_ctx->procedure_transaction_id; uint8_t sec_hdr_type = LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED; - + ue_emm_ctx->security_ctxt.dl_nas_count++; - LIBLTE_ERROR_ENUM err = srslte_mme_pack_esm_information_request_msg(&esm_info_req, sec_hdr_type,ue_emm_ctx->security_ctxt.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) { @@ -1893,7 +1896,7 @@ s1ap_nas_transport::pack_identity_request(srslte::byte_buffer_t *reply_msg, uint //Setup Dw NAS structure LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; dw_nas->ext=false; - dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = mme_ue_s1ap_id;//FIXME Change name + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = mme_ue_s1ap_id; dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id; dw_nas->HandoverRestrictionList_present=false; dw_nas->SubscriberProfileIDforRFP_present=false; @@ -1919,7 +1922,7 @@ s1ap_nas_transport::pack_identity_request(srslte::byte_buffer_t *reply_msg, uint m_s1ap_log->error("Error packing Dw NAS Transport: Authentication Reject\n"); m_s1ap_log->console("Error packing Downlink NAS Transport: Authentication Reject\n"); return false; - } + } m_pool->deallocate(nas_buffer); return true; diff --git a/srsepc/user_db.csv.example b/srsepc/user_db.csv.example index 7551c50f8..55db2e44c 100644 --- a/srsepc/user_db.csv.example +++ b/srsepc/user_db.csv.example @@ -1,14 +1,15 @@ # # .csv to store UE's information in HSS -# Kept in the following format: "Name,IMSI,Key,OP,AMF" -# -# Name: Human readable name to help distinguish UE's. Largely ignored by the HSS -# IMSI: UE's IMSI value -# Key: UE's key, where other keys are derived from. Stored in hexadecimal -# OP: Operator's code, sotred in hexadecimal -# AMF: Authentication management field, stored in hexadecimal -# SQN: UE's Sequence number for freshness of the authentication +# Kept in the following format: "Name,IMSI,Key,OP_Type,OP,AMF,SQN" # -# Note: Lines starting by '#' are ignored -ue1,001010123456789,00112233445566778899aabbccddeeff,63BFA50EE6523365FF14C1F45F88737D,9001,000000001234 -ue2,001010123456780,00112233445566778899aabbccddeeaa,63BFA50EE6523365FF14C1F45F88737D,8000,000000001235 +# Name: Human readable name to help distinguish UE's. Ignored by the HSS +# IMSI: UE's IMSI value +# Key: UE's key, where other keys are derived from. Stored in hexadecimal +# OP_Type: Operator's code type, either OP or OPc +# OP/OPc: Operator Code/Cyphered Operator Code, stored in hexadecimal +# AMF: Authentication management field, stored in hexadecimal +# SQN: UE's Sequence number for freshness of the authentication +# +# Note: Lines starting by '#' are ignored and will be overwritten +ue1,001010123456789,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,9001,000000001234 +ue2,001010123456780,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,8000,000000001234 diff --git a/srsue/hdr/upper/usim.h b/srsue/hdr/upper/usim.h index f36ae545f..ce42e3022 100644 --- a/srsue/hdr/upper/usim.h +++ b/srsue/hdr/upper/usim.h @@ -110,6 +110,7 @@ private: auth_algo_t auth_algo; uint8_t amf[2]; // 3GPP 33.102 v10.0.0 Annex H uint8_t op[16]; + uint8_t opc[16]; uint64_t imsi; uint64_t imei; uint8_t k[16]; diff --git a/srsue/hdr/upper/usim_base.h b/srsue/hdr/upper/usim_base.h index 9af01b8b6..b9a6ee44c 100644 --- a/srsue/hdr/upper/usim_base.h +++ b/srsue/hdr/upper/usim_base.h @@ -43,7 +43,9 @@ typedef enum{ typedef struct{ std::string mode; std::string algo; + bool using_op; std::string op; + std::string opc; std::string imsi; std::string imei; std::string k; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index fd754a4b3..f1026f6b7 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -131,7 +131,8 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { ("usim.mode", bpo::value(&args->usim.mode)->default_value("soft"), "USIM mode (soft or pcsc)") ("usim.algo", bpo::value(&args->usim.algo), "USIM authentication algorithm") - ("usim.op", bpo::value(&args->usim.op), "USIM operator variant") + ("usim.op", bpo::value(&args->usim.op), "USIM operator code") + ("usim.opc", bpo::value(&args->usim.opc), "USIM operator code (ciphered variant)") ("usim.imsi", bpo::value(&args->usim.imsi), "USIM IMSI") ("usim.imei", bpo::value(&args->usim.imei), "USIM IMEI") ("usim.k", bpo::value(&args->usim.k), "USIM K") @@ -142,11 +143,11 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { ("expert.ip_netmask", bpo::value(&args->expert.ip_netmask)->default_value("255.255.255.0"), "Netmask of the tun_srsue device") - + ("expert.mbms_service", bpo::value(&args->expert.mbms_service)->default_value(-1), "automatically starts an mbms service of the number given") - + ("expert.phy.worker_cpu_mask", bpo::value(&args->expert.phy.worker_cpu_mask)->default_value(-1), "cpu bit mask (eg 255 = 1111 1111)") @@ -361,9 +362,27 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { cout << "Failed to read configuration file " << config_file << " - exiting" << endl; exit(1); } + bpo::store(bpo::parse_config_file(conf, common), vm); bpo::notify(vm); + //Check conflicting OP/OPc options and which is being used + if (vm.count("usim.op") && !vm["usim.op"].defaulted() && + vm.count("usim.opc") && !vm["usim.opc"].defaulted()) + { + cout << "Conflicting options OP and OPc. Please configure either one or the other." << endl; + exit(1); + } + else + { + if(vm["usim.op"].defaulted()){ + args->usim.using_op = true; + } + else{ + args->usim.using_op = false; + } + } + // Apply all_level to any unset layers if (vm.count("log.all_level")) { if (!vm.count("log.phy_level")) { diff --git a/srsue/src/upper/usim.cc b/srsue/src/upper/usim.cc index af3cb3fbb..dedbc8794 100644 --- a/srsue/src/upper/usim.cc +++ b/srsue/src/upper/usim.cc @@ -46,11 +46,30 @@ int usim::init(usim_args_t *args, srslte::log *usim_log_) const char *imei_c = args->imei.c_str(); uint32_t i; - if(32 == args->op.length()) { - str_to_hex(args->op, op); + if(32 == args->k.length()) { + str_to_hex(args->k, k); } else { - usim_log->error("Invalid length for OP: %zu should be %d\n", args->op.length(), 32); - usim_log->console("Invalid length for OP: %zu should be %d\n", args->op.length(), 32); + usim_log->error("Invalid length for K: %zu should be %d\n", args->k.length(), 32); + usim_log->console("Invalid length for K: %zu should be %d\n", args->k.length(), 32); + } + + if(args->using_op) + { + if(32 == args->op.length()) { + str_to_hex(args->op, op); + compute_opc(k,op,opc); + } else { + usim_log->error("Invalid length for OP: %zu should be %d\n", args->op.length(), 32); + usim_log->console("Invalid length for OP: %zu should be %d\n", args->op.length(), 32); + } + } + else{ + if(32 == args->opc.length()) { + str_to_hex(args->opc, opc); + } else { + usim_log->error("Invalid length for OPc: %zu should be %d\n", args->opc.length(), 32); + usim_log->console("Invalid length for OPc: %zu should be %d\n", args->opc.length(), 32); + } } if(15 == args->imsi.length()) { @@ -77,13 +96,6 @@ int usim::init(usim_args_t *args, srslte::log *usim_log_) usim_log->console("Invalid length for IMEI: %zu should be %d\n", args->imei.length(), 15); } - if(32 == args->k.length()) { - str_to_hex(args->k, k); - } else { - usim_log->error("Invalid length for K: %zu should be %d\n", args->k.length(), 32); - usim_log->console("Invalid length for K: %zu should be %d\n", args->k.length(), 32); - } - auth_algo = auth_algo_milenage; if("xor" == args->algo) { auth_algo = auth_algo_xor; @@ -341,7 +353,7 @@ auth_result_t usim::gen_auth_res_milenage(uint8_t *rand, // Use RAND and K to compute RES, CK, IK and AK security_milenage_f2345( k, - op, + opc, rand, res, ck, @@ -363,7 +375,7 @@ auth_result_t usim::gen_auth_res_milenage(uint8_t *rand, // Generate MAC security_milenage_f1( k, - op, + opc, rand, sqn, amf, diff --git a/srsue/test/upper/usim_test.cc b/srsue/test/upper/usim_test.cc index 9e49dc173..35688a23f 100644 --- a/srsue/test/upper/usim_test.cc +++ b/srsue/test/upper/usim_test.cc @@ -78,10 +78,11 @@ int main(int argc, char **argv) args.imei = "356092040793011"; args.imsi = "208930000000001"; args.k = "8BAF473F2F8FD09487CCCBD7097C6862"; + args.using_op = true; args.op = "11111111111111111111111111111111"; srsue::usim usim; usim.init(&args, &usim_log); - //assert(usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, res, &res_len, k_asme) == AUTH_OK); + assert(usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, res, &res_len, k_asme) == AUTH_OK); } diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index cbeca8541..eeef5531b 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -98,7 +98,7 @@ file_max_size = -1 [usim] mode = soft algo = xor -op = 63BFA50EE6523365FF14C1F45F88737D +opc = 63BFA50EE6523365FF14C1F45F88737D k = 00112233445566778899aabbccddeeff imsi = 001010123456789 imei = 353490069873319