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
#
# algo: Authentication algorithm (xor/milenage)
# db_file: Location of .csv file that stores UEs information.
#
#####################################################################
[hss]
auth_algo = xor
db_file = user_db.csv
#####################################################################

View File

@ -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;
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 };
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
{
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*/

View File

@ -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<std::string> 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<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
<< "# 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;
}

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.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.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.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")
@ -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")) {

View File

@ -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