From 9a0b883296d7ecdef394c548d2e310e4db174e69 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 15 Dec 2017 18:20:57 +0000 Subject: [PATCH] Added XOR support the the HSS. --- srsepc/epc.conf.example | 3 +- srsepc/hdr/hss/hss.h | 12 ++- srsepc/src/hss/hss.cc | 154 ++++++++++++++++++++++++++- srsepc/src/main.cc | 5 +- srsepc/src/mme/s1ap.cc | 4 +- srsepc/src/mme/s1ap_nas_transport.cc | 60 +++++------ srsepc/user_db.csv | 2 +- 7 files changed, 200 insertions(+), 40 deletions(-) diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 544e153d1..34df1eb74 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -14,7 +14,7 @@ # ##################################################################### [mme] -mme_code = 0x19 +mme_code = 0x1a mme_group = 0x0001 tac = 0x0001 mcc = 001 @@ -28,6 +28,7 @@ mme_bind_addr = 127.0.0.0/24 # ##################################################################### [hss] +auth_algo = xor db_file = user_db.csv diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index 06ca26842..5278c99bc 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -39,10 +39,12 @@ #include "srslte/common/log_filter.h" #include "srslte/common/buffer_pool.h" #include +#include namespace srsepc{ typedef struct{ + std::string auth_algo; std::string db_file; }hss_args_t; @@ -54,7 +56,10 @@ typedef struct{ uint8_t amf[2]; }hss_ue_ctx_t; - +enum hss_auth_algo { + HSS_ALGO_XOR, + HSS_ALGO_MILENAGE +}; class hss { @@ -62,12 +67,15 @@ public: static hss* get_instance(void); static void cleanup(void); int init(hss_args_t *hss_args, srslte::log_filter* hss_log); + bool set_auth_algo(std::string auth_algo); bool read_db_file(std::string db_file); void get_sqn(uint8_t sqn[6]); void gen_rand(uint8_t rand_[16]); bool get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op); + bool gen_auth_info_answer(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres); 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); 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); @@ -84,6 +92,8 @@ private: std::map m_imsi_to_ue_ctx; + enum hss_auth_algo m_auth_algo; + /*Logs*/ srslte::log_filter *m_hss_log; diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 32bc1d54d..e8cbf52ae 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -39,7 +39,8 @@ hss* hss::m_instance = NULL; boost::mutex hss_instance_mutex; hss::hss() - :m_sqn(0x112233445566) +// :m_sqn(0x112233445566) + :m_sqn(0) { m_pool = srslte::byte_buffer_pool::get_instance(); return; @@ -80,14 +81,42 @@ hss::init(hss_args_t *hss_args, srslte::log_filter *hss_log) srand(time(NULL)); /*Init loggers*/ m_hss_log = hss_log; - m_hss_log->info("HSS Initialized\n"); - m_hss_log->console("HSS Initialized\n"); + /*Set authentication algorithm*/ + if(set_auth_algo(hss_args->auth_algo) == false) + { + return -1; + } /*Read user information from DB*/ - read_db_file(hss_args->db_file); + if(read_db_file(hss_args->db_file) == false) + { + return -1; + } + + m_hss_log->info("HSS Initialized. DB file %s, authentication algorithm %s\n", hss_args->db_file.c_str(),hss_args->auth_algo.c_str()); + m_hss_log->console("HSS Initialized\n"); return 0; } +bool +hss::set_auth_algo(std::string auth_algo) +{ + if(auth_algo != "xor" && auth_algo != "milenage" ) + { + m_hss_log->error("Unrecognized authentication algorithm. auth_algo = %s\n", auth_algo.c_str()); + return false; + } + if(auth_algo == "xor") + { + m_auth_algo = HSS_ALGO_XOR; + } + else + { + m_auth_algo = HSS_ALGO_MILENAGE; + } + return true; +} + bool hss::read_db_file(std::string db_filename) { @@ -128,6 +157,23 @@ hss::read_db_file(std::string db_filename) return true; } +bool +hss::gen_auth_info_answer(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) +{ + bool ret = false; + switch (m_auth_algo) + { + case HSS_ALGO_XOR: + ret = gen_auth_info_answer_xor(imsi, k_asme, autn, rand, xres); + break; + case HSS_ALGO_MILENAGE: + ret = gen_auth_info_answer_milenage(imsi, k_asme, autn, rand, xres); + break; + } + return ret; + +} + bool hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) { @@ -196,6 +242,106 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn return true; } +bool +hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) +{ + uint8_t k[16]; + uint8_t amf[2]; + uint8_t op[16]; + uint8_t sqn[6]; + + uint8_t xdout[16]; + uint8_t cdout[8]; + + uint8_t ck[16]; + uint8_t ik[16]; + uint8_t ak[6]; + uint8_t mac[8]; + + uint16_t mcc=61441; //001 + uint16_t mnc=65281; //01 + + int i = 0; + + if(!get_k_amf_op(imsi,k,amf,op)) + { + return false; + } + gen_rand(rand); + get_sqn(sqn); + + // Use RAND and K to compute RES, CK, IK and AK + for(i=0; i<16; i++) { + xdout[i] = k[i]^rand[i]; + } + + for(i=0; i<16; i++) { + xres[i] = xdout[i]; + ck[i] = xdout[(i+1)%16]; + ik[i] = xdout[(i+2)%16]; + } + for(i=0; i<6; i++) { + ak[i] = xdout[i+3]; + } + + // Generate cdout + for(i=0; i<6; i++) { + cdout[i] = sqn[i]; + } + for(i=0; i<2; i++) { + cdout[6+i] = amf[i]; + } + + // Generate MAC + for(i=0;i<8;i++) { + mac[i] = xdout[i] ^ cdout[i]; + } + + //Generate AUTN (autn = sqn ^ ak |+| amf |+| mac) + for(int i=0;i<6;i++ ) + { + autn[i] = sqn[i]^ak[i]; + } + for(int i=0;i<2;i++) + { + autn[6+i]=amf[i]; + } + for(int i=0;i<8;i++) + { + autn[8+i]=mac[i]; + } + + // Generate K_asme + security_generate_k_asme( ck, + ik, + ak, + sqn, + mcc, + mnc, + k_asme); + + //Generate AUTN (autn = sqn ^ ak |+| amf |+| mac) + for(int i=0;i<6;i++ ) + { + autn[i] = sqn[i]^ak[i]; + } + for(int i=0;i<2;i++) + { + autn[6+i]=amf[i]; + } + for(int i=0;i<8;i++) + { + autn[8+i]=mac[i]; + } + + m_hss_log->debug_hex(sqn, 6, "User SQN : "); + m_hss_log->debug_hex(autn, 8, "User AUTN: "); + m_hss_log->debug_hex(xres, 8, "User XRES: "); + + return true; +} + + bool hss::get_k_amf_op(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op ) { diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 5db3235fa..b579464cb 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -74,6 +74,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { string spgw_bind_addr; string sgi_if_addr; string hss_db_file; + string hss_auth_algo; // Command line only options bpo::options_description general("General options"); @@ -94,6 +95,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { ("mme.mnc", bpo::value(&mnc)->default_value("01"), "Mobile Network Code") ("mme.mme_bind_addr", bpo::value(&mme_bind_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection") ("hss.db_file", bpo::value(&hss_db_file)->default_value("ue_db.csv"),".csv file that stores UE's keys") + ("hss.auth_algo", bpo::value(&hss_auth_algo)->default_value("milenage"),"HSS uthentication algorithm.") ("spgw.gtpu_bind_addr", bpo::value(&spgw_bind_addr)->default_value("127.0.0.1"),"IP address of SP-GW for the S1-U connection") ("spgw.sgi_if_addr", bpo::value(&sgi_if_addr)->default_value("176.16.0.1"),"IP address of TUN interface for the SGi connection") ; @@ -166,11 +168,12 @@ parse_args(all_args_t *args, int argc, char* argv[]) { if(!srslte::string_to_mnc(mnc, &args->mme_args.s1ap_args.mnc)) { cout << "Error parsing enb.mnc:" << mnc << " - must be a 2 or 3-digit string." << endl; } - + args->mme_args.s1ap_args.mme_bind_addr = mme_bind_addr; args->spgw_args.gtpu_bind_addr = spgw_bind_addr; args->spgw_args.sgi_if_addr = sgi_if_addr; args->hss_args.db_file = hss_db_file; + args->hss_args.auth_algo = hss_auth_algo; return; } diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index a995da889..0b3bc3e8d 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -378,7 +378,7 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini memcpy(&ue_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); //Get Authentication Vectors from HSS - if(!m_hss->gen_auth_info_answer_milenage(imsi, ue_ctx.security_ctxt.k_asme, autn, rand, ue_ctx.security_ctxt.xres)) + if(!m_hss->gen_auth_info_answer(imsi, ue_ctx.security_ctxt.k_asme, autn, rand, ue_ctx.security_ctxt.xres)) { m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); @@ -468,7 +468,7 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT return true; //no need for reply. FIXME this should be better structured... break; default: - m_s1ap_log->info("Unhandled NAS message"); + m_s1ap_log->info("Unhandled NAS message 0x%x\n", msg_type ); return false; //FIXME (nas_msg deallocate needs to be called) } diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 490fc46c4..75265691e 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -82,7 +82,7 @@ s1ap_nas_transport::unpack_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA return false; } - if(pdn_con_req->pdn_type != LIBLTE_MME_PDN_TYPE_IPV4) + if(pdn_con_req->pdn_type == LIBLTE_MME_PDN_TYPE_IPV6) { m_s1ap_log->error("PDN Connectivity Request: Only IPv4 connectivity supported.\n"); return false; @@ -331,59 +331,59 @@ s1ap_nas_transport::log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQ { if(attach_req->old_p_tmsi_signature_present) { - m_s1ap_log->warning("NAS attach request: Old P-TMSI signature present, but not handled."); + m_s1ap_log->warning("NAS attach request: Old P-TMSI signature present, but not handled.\n"); } if(attach_req->additional_guti_present) { - m_s1ap_log->warning("NAS attach request: Aditional GUTI present, but not handled."); + m_s1ap_log->warning("NAS attach request: Aditional GUTI present, but not handled.\n"); } if(attach_req->last_visited_registered_tai_present) { - m_s1ap_log->warning("NAS attach request: Last visited registered TAI present, but not handled."); + m_s1ap_log->warning("NAS attach request: Last visited registered TAI present, but not handled.\n"); } if(attach_req->drx_param_present) { - m_s1ap_log->warning("NAS attach request: DRX Param present, but not handled."); + m_s1ap_log->warning("NAS attach request: DRX Param present, but not handled.\n"); } if(attach_req->ms_network_cap_present) { - m_s1ap_log->warning("NAS attach request: MS network cap present, but not handled."); + m_s1ap_log->warning("NAS attach request: MS network cap present, but not handled.\n"); } if(attach_req->old_lai_present) { - m_s1ap_log->warning("NAS attach request: Old LAI present, but not handled."); + m_s1ap_log->warning("NAS attach request: Old LAI present, but not handled.\n"); } if(attach_req->tmsi_status_present) { - m_s1ap_log->warning("NAS attach request: TSMI status present, but not handled."); + m_s1ap_log->warning("NAS attach request: TSMI status present, but not handled.\n"); } if(attach_req->ms_cm2_present) { - m_s1ap_log->warning("NAS attach request: MS CM2 present, but not handled."); + m_s1ap_log->warning("NAS attach request: MS CM2 present, but not handled.\n"); } if(attach_req->ms_cm3_present) { - m_s1ap_log->warning("NAS attach request: MS CM3 present, but not handled."); + m_s1ap_log->warning("NAS attach request: MS CM3 present, but not handled.\n"); } if(attach_req->supported_codecs_present) { - m_s1ap_log->warning("NAS attach request: Supported CODECs present, but not handled."); + m_s1ap_log->warning("NAS attach request: Supported CODECs present, but not handled.\n"); } if(attach_req->additional_update_type_present) { - m_s1ap_log->warning("NAS attach request: Additional Update Type present, but not handled."); + m_s1ap_log->warning("NAS attach request: Additional Update Type present, but not handled.\n"); } if(attach_req->voice_domain_pref_and_ue_usage_setting_present) { - m_s1ap_log->warning("NAS attach request: Voice domain preference and UE usage setting present, but not handled."); + m_s1ap_log->warning("NAS attach request: Voice domain preference and UE usage setting present, but not handled.\n"); } if(attach_req->device_properties_present) { - m_s1ap_log->warning("NAS attach request: Device properties present, but not handled."); + m_s1ap_log->warning("NAS attach request: Device properties present, but not handled.\n"); } if(attach_req->old_guti_type_present) { - m_s1ap_log->warning("NAS attach request: Old GUTI type present, but not handled."); + m_s1ap_log->warning("NAS attach request: Old GUTI type present, but not handled.\n"); } return; } @@ -394,19 +394,19 @@ s1ap_nas_transport::log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNE //Handle the optional flags if(pdn_con_req->esm_info_transfer_flag_present) { - m_s1ap_log->warning("PDN Connectivity request: ESM info transfer flag properties present, but not handled."); + m_s1ap_log->warning("PDN Connectivity request: ESM info transfer flag properties present, but not handled.\n"); } if(pdn_con_req->apn_present) { - m_s1ap_log->warning("PDN Connectivity request: APN present, but not handled."); + m_s1ap_log->warning("PDN Connectivity request: APN present, but not handled.\n"); } if(pdn_con_req->protocol_cnfg_opts_present) { - m_s1ap_log->warning("PDN Connectivity request: Protocol Cnfg options present, but not handled."); + m_s1ap_log->warning("PDN Connectivity request: Protocol Cnfg options present, but not handled.\n"); } if(pdn_con_req->device_properties_present) { - m_s1ap_log->warning("PDN Connectivity request: Device properties present, but not handled."); + m_s1ap_log->warning("PDN Connectivity request: Device properties present, but not handled.\n"); } } @@ -415,37 +415,37 @@ void s1ap_nas_transport::log_unhandled_initial_ue_message_ies(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue) { if(init_ue->S_TMSI_present){ - m_s1ap_log->warning("S-TMSI present, but not handled."); + m_s1ap_log->warning("S-TMSI present, but not handled.\n"); } if(init_ue->CSG_Id_present){ - m_s1ap_log->warning("S-TMSI present, but not handled."); + m_s1ap_log->warning("S-TMSI present, but not handled.\n"); } if(init_ue->GUMMEI_ID_present){ - m_s1ap_log->warning("GUMMEI ID present, but not handled."); + m_s1ap_log->warning("GUMMEI ID present, but not handled.\n"); } if(init_ue->CellAccessMode_present){ - m_s1ap_log->warning("Cell Access Mode present, but not handled."); + m_s1ap_log->warning("Cell Access Mode present, but not handled.\n"); } if(init_ue->GW_TransportLayerAddress_present){ - m_s1ap_log->warning("GW Transport Layer present, but not handled."); + m_s1ap_log->warning("GW Transport Layer present, but not handled.\n"); } if(init_ue->GW_TransportLayerAddress_present){ - m_s1ap_log->warning("GW Transport Layer present, but not handled."); + m_s1ap_log->warning("GW Transport Layer present, but not handled.\n"); } if(init_ue->RelayNode_Indicator_present){ - m_s1ap_log->warning("Relay Node Indicator present, but not handled."); + m_s1ap_log->warning("Relay Node Indicator present, but not handled.\n"); } if(init_ue->GUMMEIType_present){ - m_s1ap_log->warning("GUMMEI Type present, but not handled."); + m_s1ap_log->warning("GUMMEI Type present, but not handled.\n"); } if(init_ue->Tunnel_Information_for_BBF_present){ - m_s1ap_log->warning("Tunnel Information for BBF present, but not handled."); + m_s1ap_log->warning("Tunnel Information for BBF present, but not handled.\n"); } if(init_ue->SIPTO_L_GW_TransportLayerAddress_present){ - m_s1ap_log->warning("SIPTO GW Transport Layer Address present, but not handled."); + m_s1ap_log->warning("SIPTO GW Transport Layer Address present, but not handled.\n"); } if(init_ue->LHN_ID_present){ - m_s1ap_log->warning("LHN Id present, but not handled."); + m_s1ap_log->warning("LHN Id present, but not handled.\n"); } return; } diff --git a/srsepc/user_db.csv b/srsepc/user_db.csv index f306adaa3..89d0dedf1 100644 --- a/srsepc/user_db.csv +++ b/srsepc/user_db.csv @@ -9,5 +9,5 @@ # AMF: Authentication management feild, stored in hexadecimal # # Note: Lines starting by '#' are ignored -ue1,001010123456789,00112233445566778899aabbccddeeff,63BFA50EE6523365FF14C1F45F88737D,8000 +ue1,001010123456789,00112233445566778899aabbccddeeff,63BFA50EE6523365FF14C1F45F88737D,9001 ue2,001010123456780,00112233445566778899aabbccddeeaa,63BFA50EE6523365FF14C1F45F88737D,2000