From 3ad19f21b680675cb582525a44cc84b03b8f75b4 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 4 Apr 2019 17:13:57 +0100 Subject: [PATCH] Adding per UE authentication algorithm choice to the HSS and users_db.csv. --- srsepc/epc.conf.example | 2 - srsepc/hdr/hss/hss.h | 27 ++++++------ srsepc/src/hss/hss.cc | 86 +++++++++++++++++++++++--------------- srsepc/src/main.cc | 2 - srsepc/user_db.csv.example | 7 ++-- 5 files changed, 69 insertions(+), 55 deletions(-) diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 6ad12ead3..32a6dafc0 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -36,12 +36,10 @@ paging_timer = 2 ##################################################################### # HSS configuration # -# algo: Authentication algorithm (xor/milenage) # db_file: Location of .csv file that stores UEs information. # ##################################################################### [hss] -auth_algo = xor db_file = user_db.csv ##################################################################### diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index d7ec9cedd..19f25769b 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -50,27 +50,27 @@ namespace srsepc { typedef struct { - std::string auth_algo; std::string db_file; uint16_t mcc; uint16_t mnc; } hss_args_t; +enum hss_auth_algo { HSS_ALGO_XOR, HSS_ALGO_MILENAGE }; + typedef struct { - std::string name; - uint64_t imsi; - uint8_t key[16]; - bool op_configured; - uint8_t op[16]; - uint8_t opc[16]; - uint8_t amf[2]; - uint8_t sqn[6]; - uint16_t qci; - uint8_t last_rand[16]; + std::string name; + uint64_t imsi; + enum hss_auth_algo algo; + uint8_t key[16]; + bool op_configured; + uint8_t op[16]; + uint8_t opc[16]; + uint8_t amf[2]; + uint8_t sqn[6]; + uint16_t qci; + uint8_t last_rand[16]; } hss_ue_ctx_t; -enum hss_auth_algo { HSS_ALGO_XOR, HSS_ALGO_MILENAGE }; - class hss : public hss_interface_nas { public: @@ -118,7 +118,6 @@ private: std::string hex_string(uint8_t* hex, int size); - enum hss_auth_algo m_auth_algo; std::string db_file; /*Logs*/ diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 571c49d11..db6124fd6 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -73,10 +73,6 @@ int hss::init(hss_args_t* hss_args, srslte::log_filter* hss_log) /*Init loggers*/ m_hss_log = hss_log; - /*Set authentication algorithm*/ - if (set_auth_algo(hss_args->auth_algo) == false) { - return -1; - } /*Read user information from DB*/ if (read_db_file(hss_args->db_file) == false) { m_hss_log->console("Error reading user database file %s\n", hss_args->db_file.c_str()); @@ -88,8 +84,8 @@ int hss::init(hss_args_t* hss_args, srslte::log_filter* hss_log) 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); + m_hss_log->info("HSS Initialized. DB file %s, MCC: %d, MNC: %d\n", + hss_args->db_file.c_str(), mcc, mnc); m_hss_log->console("HSS Initialized.\n"); return 0; } @@ -107,20 +103,6 @@ void hss::stop() return; } -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) { std::ifstream m_db_file; @@ -134,30 +116,45 @@ bool hss::read_db_file(std::string db_filename) std::string line; while (std::getline(m_db_file, line)) { if (line[0] != '#') { - uint column_size = 8; + uint column_size = 9; std::vector split = split_string(line, ','); if (split.size() != column_size) { m_hss_log->error("Error parsing UE database. Wrong number of columns in .csv\n"); m_hss_log->error("Columns: %zd, Expected %d.\n", split.size(), column_size); + if (split.size() == 8) { + m_hss_log->console("\nError parsing UE database. Wrong number of columns in user database CSV.\n"); + m_hss_log->console("Perhaps you are using an old user_db.csv?\n"); + m_hss_log->console("In the new 19.03 version of srsLTE you are required to specify the authentication " + "algorithim in the CSV file.\n"); + m_hss_log->console("See 'srsepc/user_db.csv.example' for an example.\n\n"); + } 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); - if (split[3] == std::string("op")) { + if (split[1] == std::string("xor")) { + ue_ctx->algo = HSS_ALGO_XOR; + } else if (split[1] == std::string("mil")) { + ue_ctx->algo = HSS_ALGO_MILENAGE; + } else { + m_hss_log->error("Neither XOR nor MILENAGE configured.\n"); + return false; + } + ue_ctx->imsi = atoll(split[2].c_str()); + get_uint_vec_from_hex_str(split[3], ue_ctx->key, 16); + if (split[4] == std::string("op")) { ue_ctx->op_configured = true; - get_uint_vec_from_hex_str(split[4], ue_ctx->op, 16); + get_uint_vec_from_hex_str(split[5], ue_ctx->op, 16); srslte::compute_opc(ue_ctx->key, ue_ctx->op, ue_ctx->opc); - } else if (split[3] == std::string("opc")) { + } else if (split[4] == std::string("opc")) { ue_ctx->op_configured = false; - get_uint_vec_from_hex_str(split[4], ue_ctx->opc, 16); + get_uint_vec_from_hex_str(split[5], 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); + get_uint_vec_from_hex_str(split[6], ue_ctx->amf, 2); + get_uint_vec_from_hex_str(split[7], ue_ctx->sqn, 6); m_hss_log->debug("Added user from DB, IMSI: %015" PRIu64 "\n", ue_ctx->imsi); m_hss_log->debug_hex(ue_ctx->key, 16, "User Key : "); @@ -167,7 +164,7 @@ bool hss::read_db_file(std::string db_filename) 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 : "); - ue_ctx->qci = atoi(split[7].c_str()); + ue_ctx->qci = atoi(split[8].c_str()); m_hss_log->debug("Default Bearer QCI: %d\n", ue_ctx->qci); m_imsi_to_ue_ctx.insert(std::pair(ue_ctx->imsi, ue_ctx)); } @@ -203,6 +200,8 @@ bool hss::write_db_file(std::string db_filename) << "# " << std::endl << "# Name: Human readable name to help distinguish UE's. Ignored by the HSS " << std::endl << "# IMSI: UE's IMSI value " << std::endl + << "# Auth: Authentication algorithm used by the UE. Valid algorithms are XOR " + "(xor) and MILENAGE (mil)" << 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 @@ -216,6 +215,8 @@ bool hss::write_db_file(std::string db_filename) while (it != m_imsi_to_ue_ctx.end()) { m_db_file << it->second->name; m_db_file << ","; + m_db_file << (it->second->algo == HSS_ALGO_XOR ? "xor" : "mil"); + m_db_file << ","; m_db_file << std::setfill('0') << std::setw(15) << it->second->imsi; m_db_file << ","; m_db_file << hex_string(it->second->key, 16); @@ -244,8 +245,16 @@ bool hss::write_db_file(std::string db_filename) 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) { + hss_ue_ctx_t* ue_ctx = NULL; + + bool ret = get_ue_ctx(imsi, &ue_ctx); + if (ret == false) { + m_hss_log->console("User not found at HSS. IMSI: %015" PRIu64 "\n", imsi); + m_hss_log->error("User not found at HSS. IMSI: %015" PRIu64 "\n", imsi); + return false; + } + + switch (ue_ctx->algo) { case HSS_ALGO_XOR: ret = gen_auth_info_answer_xor(imsi, k_asme, autn, rand, xres); break; @@ -439,8 +448,16 @@ bool hss::get_k_amf_opc_sqn(uint64_t imsi, uint8_t* k, uint8_t* amf, uint8_t* op bool hss::resync_sqn(uint64_t imsi, uint8_t* auts) { - bool ret = false; - switch (m_auth_algo) { + hss_ue_ctx_t* ue_ctx = NULL; + + bool ret = get_ue_ctx(imsi, &ue_ctx); + if (ret == false) { + m_hss_log->console("User not found at HSS. IMSI: %015" PRIu64 "\n", imsi); + m_hss_log->error("User not found at HSS. IMSI: %015" PRIu64 "\n", imsi); + return false; + } + + switch (ue_ctx->algo) { case HSS_ALGO_XOR: ret = resync_sqn_xor(imsi, auts); break; @@ -448,6 +465,7 @@ bool hss::resync_sqn(uint64_t imsi, uint8_t* auts) ret = resync_sqn_milenage(imsi, auts); break; } + increment_seq_after_resync(imsi); return ret; } diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index f8bde129c..b7e607c63 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -124,7 +124,6 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("mme.integrity_algo", bpo::value(&integrity_algo)->default_value("EIA1"), "Set preferred integrity protection algorithm for NAS") ("mme.paging_timer", bpo::value(&paging_timer)->default_value(2), "Set paging timer value in seconds (T3413)") ("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") ("spgw.sgi_if_name", bpo::value(&sgi_if_name)->default_value("srs_spgw_sgi"), "Name of TUN interface for the SGi connection") @@ -272,7 +271,6 @@ void parse_args(all_args_t* args, int argc, char* argv[]) args->spgw_args.sgi_if_name = sgi_if_name; args->spgw_args.max_paging_queue = max_paging_queue; args->hss_args.db_file = hss_db_file; - args->hss_args.auth_algo = hss_auth_algo; // Apply all_level to any unset layers if (vm.count("log.all_level")) { diff --git a/srsepc/user_db.csv.example b/srsepc/user_db.csv.example index 54d61eb30..2c0c03e18 100644 --- a/srsepc/user_db.csv.example +++ b/srsepc/user_db.csv.example @@ -1,8 +1,9 @@ # # .csv to store UE's information in HSS -# Kept in the following format: "Name,IMSI,Key,OP_Type,OP,AMF,SQN,QCI" +# Kept in the following format: "Name,Auth,IMSI,Key,OP_Type,OP,AMF,SQN,QCI" # # Name: Human readable name to help distinguish UE's. Ignored by the HSS +# Auth: Authentication algorithm used by the UE. Valid algorithms are XOR (xor) and MILENAGE (mil) # 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 @@ -12,5 +13,5 @@ # QCI: QoS Class Identifier for the UE's default bearer. # # Note: Lines starting by '#' are ignored and will be overwritten -ue1,001010123456789,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,9001,000000001234,7 -ue2,001010123456780,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,8000,000000001234,7 +ue1,xor,001010123456789,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,9001,000000001234,7 +ue2,mil,001010123456780,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,8000,000000001234,7