Adding per UE authentication algorithm choice to the HSS and users_db.csv.

This commit is contained in:
Pedro Alvarez 2019-04-04 17:13:57 +01:00 committed by Andre Puschmann
parent ca603810ce
commit 3ad19f21b6
5 changed files with 70 additions and 56 deletions

View File

@ -36,12 +36,10 @@ paging_timer = 2
##################################################################### #####################################################################
# HSS configuration # HSS configuration
# #
# algo: Authentication algorithm (xor/milenage)
# db_file: Location of .csv file that stores UEs information. # db_file: Location of .csv file that stores UEs information.
# #
##################################################################### #####################################################################
[hss] [hss]
auth_algo = xor
db_file = user_db.csv db_file = user_db.csv
##################################################################### #####################################################################

View File

@ -50,27 +50,27 @@
namespace srsepc { namespace srsepc {
typedef struct { typedef struct {
std::string auth_algo;
std::string db_file; std::string db_file;
uint16_t mcc; uint16_t mcc;
uint16_t mnc; uint16_t mnc;
} hss_args_t; } hss_args_t;
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];
} hss_ue_ctx_t;
enum hss_auth_algo { HSS_ALGO_XOR, HSS_ALGO_MILENAGE }; enum hss_auth_algo { HSS_ALGO_XOR, HSS_ALGO_MILENAGE };
typedef struct {
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;
class hss : public hss_interface_nas class hss : public hss_interface_nas
{ {
public: public:
@ -118,7 +118,6 @@ private:
std::string hex_string(uint8_t* hex, int size); std::string hex_string(uint8_t* hex, int size);
enum hss_auth_algo m_auth_algo;
std::string db_file; std::string db_file;
/*Logs*/ /*Logs*/

View File

@ -73,10 +73,6 @@ int hss::init(hss_args_t* hss_args, srslte::log_filter* hss_log)
/*Init loggers*/ /*Init loggers*/
m_hss_log = hss_log; m_hss_log = hss_log;
/*Set authentication algorithm*/
if (set_auth_algo(hss_args->auth_algo) == false) {
return -1;
}
/*Read user information from DB*/ /*Read user information from DB*/
if (read_db_file(hss_args->db_file) == false) { 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()); 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; db_file = hss_args->db_file;
m_hss_log->info("HSS Initialized. DB file %s, authentication algorithm %s, MCC: %d, MNC: %d\n", m_hss_log->info("HSS Initialized. DB file %s, MCC: %d, MNC: %d\n",
hss_args->db_file.c_str(), hss_args->auth_algo.c_str(), mcc, mnc); hss_args->db_file.c_str(), mcc, mnc);
m_hss_log->console("HSS Initialized.\n"); m_hss_log->console("HSS Initialized.\n");
return 0; return 0;
} }
@ -107,20 +103,6 @@ void hss::stop()
return; 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) bool hss::read_db_file(std::string db_filename)
{ {
std::ifstream m_db_file; std::ifstream m_db_file;
@ -134,30 +116,45 @@ bool hss::read_db_file(std::string db_filename)
std::string line; std::string line;
while (std::getline(m_db_file, line)) { while (std::getline(m_db_file, line)) {
if (line[0] != '#') { if (line[0] != '#') {
uint column_size = 8; uint column_size = 9;
std::vector<std::string> split = split_string(line, ','); std::vector<std::string> split = split_string(line, ',');
if (split.size() != column_size) { if (split.size() != column_size) {
m_hss_log->error("Error parsing UE database. Wrong number of columns in .csv\n"); 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); 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; return false;
} }
hss_ue_ctx_t* ue_ctx = new hss_ue_ctx_t; hss_ue_ctx_t* ue_ctx = new hss_ue_ctx_t;
ue_ctx->name = split[0]; ue_ctx->name = split[0];
ue_ctx->imsi = atoll(split[1].c_str()); if (split[1] == std::string("xor")) {
get_uint_vec_from_hex_str(split[2], ue_ctx->key, 16); ue_ctx->algo = HSS_ALGO_XOR;
if (split[3] == std::string("op")) { } 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; 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); 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; 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 { } else {
m_hss_log->error("Neither OP nor OPc configured.\n"); m_hss_log->error("Neither OP nor OPc configured.\n");
return false; return false;
} }
get_uint_vec_from_hex_str(split[5], ue_ctx->amf, 2); get_uint_vec_from_hex_str(split[6], ue_ctx->amf, 2);
get_uint_vec_from_hex_str(split[6], ue_ctx->sqn, 6); 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("Added user from DB, IMSI: %015" PRIu64 "\n", ue_ctx->imsi);
m_hss_log->debug_hex(ue_ctx->key, 16, "User Key : "); 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->opc, 16, "User OPc : ");
m_hss_log->debug_hex(ue_ctx->amf, 2, "AMF : "); m_hss_log->debug_hex(ue_ctx->amf, 2, "AMF : ");
m_hss_log->debug_hex(ue_ctx->sqn, 6, "SQN : "); 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_hss_log->debug("Default Bearer QCI: %d\n", ue_ctx->qci);
m_imsi_to_ue_ctx.insert(std::pair<uint64_t, hss_ue_ctx_t*>(ue_ctx->imsi, ue_ctx)); m_imsi_to_ue_ctx.insert(std::pair<uint64_t, hss_ue_ctx_t*>(ue_ctx->imsi, ue_ctx));
} }
@ -203,6 +200,8 @@ bool hss::write_db_file(std::string db_filename)
<< "# " << std::endl << "# " << std::endl
<< "# Name: Human readable name to help distinguish UE's. Ignored by the HSS " << std::endl << "# Name: Human readable name to help distinguish UE's. Ignored by the HSS " << std::endl
<< "# IMSI: UE's IMSI value " << 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 << "# 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_Type: Operator's code type, either OP or OPc " << std::endl
<< "# OP/OPc: Operator Code/Cyphered Operator Code, stored in hexadecimal " << 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()) { while (it != m_imsi_to_ue_ctx.end()) {
m_db_file << it->second->name; m_db_file << it->second->name;
m_db_file << ","; 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 << std::setfill('0') << std::setw(15) << it->second->imsi;
m_db_file << ","; m_db_file << ",";
m_db_file << hex_string(it->second->key, 16); 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 hss::gen_auth_info_answer(uint64_t imsi, uint8_t* k_asme, uint8_t* autn, uint8_t* rand, uint8_t* xres)
{ {
bool ret = false; hss_ue_ctx_t* ue_ctx = NULL;
switch (m_auth_algo) {
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: case HSS_ALGO_XOR:
ret = gen_auth_info_answer_xor(imsi, k_asme, autn, rand, xres); ret = gen_auth_info_answer_xor(imsi, k_asme, autn, rand, xres);
break; 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 hss::resync_sqn(uint64_t imsi, uint8_t* auts)
{ {
bool ret = false; hss_ue_ctx_t* ue_ctx = NULL;
switch (m_auth_algo) {
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: case HSS_ALGO_XOR:
ret = resync_sqn_xor(imsi, auts); ret = resync_sqn_xor(imsi, auts);
break; break;
@ -448,6 +465,7 @@ bool hss::resync_sqn(uint64_t imsi, uint8_t* auts)
ret = resync_sqn_milenage(imsi, auts); ret = resync_sqn_milenage(imsi, auts);
break; break;
} }
increment_seq_after_resync(imsi); increment_seq_after_resync(imsi);
return ret; return ret;
} }

View File

@ -124,7 +124,6 @@ void parse_args(all_args_t* args, int argc, char* argv[])
("mme.integrity_algo", bpo::value<string>(&integrity_algo)->default_value("EIA1"), "Set preferred integrity protection algorithm for NAS") ("mme.integrity_algo", bpo::value<string>(&integrity_algo)->default_value("EIA1"), "Set preferred integrity protection algorithm for NAS")
("mme.paging_timer", bpo::value<uint16_t>(&paging_timer)->default_value(2), "Set paging timer value in seconds (T3413)") ("mme.paging_timer", bpo::value<uint16_t>(&paging_timer)->default_value(2), "Set paging timer value in seconds (T3413)")
("hss.db_file", bpo::value<string>(&hss_db_file)->default_value("ue_db.csv"), ".csv file that stores UE's keys") ("hss.db_file", bpo::value<string>(&hss_db_file)->default_value("ue_db.csv"), ".csv file that stores UE's keys")
("hss.auth_algo", bpo::value<string>(&hss_auth_algo)->default_value("milenage"), "HSS uthentication algorithm.")
("spgw.gtpu_bind_addr", bpo::value<string>(&spgw_bind_addr)->default_value("127.0.0.1"), "IP address of SP-GW for the S1-U connection") ("spgw.gtpu_bind_addr", bpo::value<string>(&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<string>(&sgi_if_addr)->default_value("176.16.0.1"), "IP address of TUN interface for the SGi connection") ("spgw.sgi_if_addr", bpo::value<string>(&sgi_if_addr)->default_value("176.16.0.1"), "IP address of TUN interface for the SGi connection")
("spgw.sgi_if_name", bpo::value<string>(&sgi_if_name)->default_value("srs_spgw_sgi"), "Name of TUN interface for the SGi connection") ("spgw.sgi_if_name", bpo::value<string>(&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.sgi_if_name = sgi_if_name;
args->spgw_args.max_paging_queue = max_paging_queue; args->spgw_args.max_paging_queue = max_paging_queue;
args->hss_args.db_file = hss_db_file; args->hss_args.db_file = hss_db_file;
args->hss_args.auth_algo = hss_auth_algo;
// Apply all_level to any unset layers // Apply all_level to any unset layers
if (vm.count("log.all_level")) { if (vm.count("log.all_level")) {

View File

@ -1,8 +1,9 @@
# #
# .csv to store UE's information in HSS # .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 # 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 # IMSI: UE's IMSI value
# Key: UE's key, where other keys are derived from. Stored in hexadecimal # Key: UE's key, where other keys are derived from. Stored in hexadecimal
# OP_Type: Operator's code type, either OP or OPc # OP_Type: Operator's code type, either OP or OPc
@ -12,5 +13,5 @@
# QCI: QoS Class Identifier for the UE's default bearer. # QCI: QoS Class Identifier for the UE's default bearer.
# #
# Note: Lines starting by '#' are ignored and will be overwritten # Note: Lines starting by '#' are ignored and will be overwritten
ue1,001010123456789,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,9001,000000001234,7 ue1,xor,001010123456789,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,9001,000000001234,7
ue2,001010123456780,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,8000,000000001234,7 ue2,mil,001010123456780,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,8000,000000001234,7