|
|
@ -153,7 +153,7 @@ hss::read_db_file(std::string db_filename)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(line[0] != '#')
|
|
|
|
if(line[0] != '#')
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint column_size = 7;
|
|
|
|
uint column_size = 8;
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -192,7 +192,8 @@ 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());
|
|
|
|
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -225,7 +226,7 @@ bool hss::write_db_file(std::string db_filename)
|
|
|
|
//Write comment info
|
|
|
|
//Write comment info
|
|
|
|
m_db_file << "# " << std::endl
|
|
|
|
m_db_file << "# " << std::endl
|
|
|
|
<< "# .csv to store UE's information in HSS " << 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
|
|
|
|
<< "# Kept in the following format: \"Name,IMSI,Key,OP_Type,OP,AMF,SQN,QCI\" " << std::endl
|
|
|
|
<< "# " << 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
|
|
|
@ -234,6 +235,7 @@ bool hss::write_db_file(std::string db_filename)
|
|
|
|
<< "# OP/OPc: Operator Code/Cyphered Operator Code, stored in hexadecimal " << std::endl
|
|
|
|
<< "# OP/OPc: Operator Code/Cyphered Operator Code, stored in hexadecimal " << std::endl
|
|
|
|
<< "# AMF: Authentication management field, 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
|
|
|
|
<< "# SQN: UE's Sequence number for freshness of the authentication " << std::endl
|
|
|
|
|
|
|
|
<< "# QCI: QoS Class Identifier for the UE's default bearer. " << std::endl
|
|
|
|
<< "# " << std::endl
|
|
|
|
<< "# " << std::endl
|
|
|
|
<< "# Note: Lines starting by '#' are ignored and will be overwritten " << std::endl;
|
|
|
|
<< "# Note: Lines starting by '#' are ignored and will be overwritten " << std::endl;
|
|
|
|
|
|
|
|
|
|
|
@ -258,10 +260,11 @@ bool hss::write_db_file(std::string db_filename)
|
|
|
|
m_db_file << hex_string(it->second->amf, 2);
|
|
|
|
m_db_file << hex_string(it->second->amf, 2);
|
|
|
|
m_db_file << ",";
|
|
|
|
m_db_file << ",";
|
|
|
|
m_db_file << hex_string(it->second->sqn, 6);
|
|
|
|
m_db_file << hex_string(it->second->sqn, 6);
|
|
|
|
|
|
|
|
m_db_file << ",";
|
|
|
|
|
|
|
|
m_db_file << it->second->qci;
|
|
|
|
m_db_file << std::endl;
|
|
|
|
m_db_file << std::endl;
|
|
|
|
it++;
|
|
|
|
it++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(m_db_file.is_open())
|
|
|
|
if(m_db_file.is_open())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_db_file.close();
|
|
|
|
m_db_file.close();
|
|
|
@ -287,90 +290,8 @@ hss::gen_auth_info_answer(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
|
|
|
hss::resync_sqn(uint64_t imsi, uint8_t *auts)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
switch (m_auth_algo)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case HSS_ALGO_XOR:
|
|
|
|
|
|
|
|
ret = resync_sqn_xor(imsi, auts);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HSS_ALGO_MILENAGE:
|
|
|
|
|
|
|
|
ret = resync_sqn_milenage(imsi, auts);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
increment_ue_sqn(imsi);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
|
|
|
hss::resync_sqn_xor(uint64_t imsi, uint8_t *auts)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_hss_log->error("XOR SQN synchronization not supported yet\n");
|
|
|
|
|
|
|
|
m_hss_log->console("XOR SQNs synchronization not supported yet\n");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
|
|
|
hss::resync_sqn_milenage(uint64_t imsi, uint8_t *auts)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
uint8_t last_rand[16];
|
|
|
|
|
|
|
|
uint8_t ak[6];
|
|
|
|
|
|
|
|
uint8_t mac_s[8];
|
|
|
|
|
|
|
|
uint8_t sqn_ms_xor_ak[6];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t k[16];
|
|
|
|
|
|
|
|
uint8_t amf[2];
|
|
|
|
|
|
|
|
uint8_t opc[16];
|
|
|
|
|
|
|
|
uint8_t sqn[6];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_last_rand(imsi, last_rand);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(int i=0; i<6; i++){
|
|
|
|
|
|
|
|
sqn_ms_xor_ak[i] = auts[i];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(int i=0; i<8; i++){
|
|
|
|
|
|
|
|
mac_s[i] = auts[i+6];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_hss_log->debug_hex(k, 16, "User Key : ");
|
|
|
|
|
|
|
|
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, opc, last_rand, ak);
|
|
|
|
|
|
|
|
m_hss_log->debug_hex(ak, 6, "Resynch AK : ");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t sqn_ms[6];
|
|
|
|
|
|
|
|
for(int i=0; i<6; i++){
|
|
|
|
|
|
|
|
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, opc, last_rand, sqn_ms, amf, mac_s_tmp);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_hss_log->debug_hex(mac_s_tmp, 8, "MAC calc : ");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set_sqn(imsi, sqn_ms);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
bool
|
|
|
|
hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres)
|
|
|
|
hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -559,6 +480,23 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
|
|
|
hss::gen_update_loc_answer(uint64_t imsi, uint8_t* qci)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::map<uint64_t,hss_ue_ctx_t*>::iterator ue_ctx_it = m_imsi_to_ue_ctx.find(imsi);
|
|
|
|
|
|
|
|
if(ue_ctx_it == m_imsi_to_ue_ctx.end())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_hss_log->info("User not found. IMSI: %015lu\n",imsi);
|
|
|
|
|
|
|
|
m_hss_log->console("User not found. IMSI: %015lu\n",imsi);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
hss_ue_ctx_t *ue_ctx = ue_ctx_it->second;
|
|
|
|
|
|
|
|
m_hss_log->info("Found User %015lu\n",imsi);
|
|
|
|
|
|
|
|
*qci = ue_ctx->qci;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
bool
|
|
|
|
hss::get_k_amf_opc_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *opc, uint8_t *sqn)
|
|
|
|
hss::get_k_amf_opc_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *opc, uint8_t *sqn)
|
|
|
@ -581,6 +519,90 @@ hss::get_k_amf_opc_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *opc, ui
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
|
|
|
hss::resync_sqn(uint64_t imsi, uint8_t *auts)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
switch (m_auth_algo)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case HSS_ALGO_XOR:
|
|
|
|
|
|
|
|
ret = resync_sqn_xor(imsi, auts);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HSS_ALGO_MILENAGE:
|
|
|
|
|
|
|
|
ret = resync_sqn_milenage(imsi, auts);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
increment_ue_sqn(imsi);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
|
|
|
hss::resync_sqn_xor(uint64_t imsi, uint8_t *auts)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_hss_log->error("XOR SQN synchronization not supported yet\n");
|
|
|
|
|
|
|
|
m_hss_log->console("XOR SQNs synchronization not supported yet\n");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
|
|
|
hss::resync_sqn_milenage(uint64_t imsi, uint8_t *auts)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
uint8_t last_rand[16];
|
|
|
|
|
|
|
|
uint8_t ak[6];
|
|
|
|
|
|
|
|
uint8_t mac_s[8];
|
|
|
|
|
|
|
|
uint8_t sqn_ms_xor_ak[6];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t k[16];
|
|
|
|
|
|
|
|
uint8_t amf[2];
|
|
|
|
|
|
|
|
uint8_t opc[16];
|
|
|
|
|
|
|
|
uint8_t sqn[6];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_last_rand(imsi, last_rand);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(int i=0; i<6; i++){
|
|
|
|
|
|
|
|
sqn_ms_xor_ak[i] = auts[i];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(int i=0; i<8; i++){
|
|
|
|
|
|
|
|
mac_s[i] = auts[i+6];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_hss_log->debug_hex(k, 16, "User Key : ");
|
|
|
|
|
|
|
|
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, opc, last_rand, ak);
|
|
|
|
|
|
|
|
m_hss_log->debug_hex(ak, 6, "Resynch AK : ");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t sqn_ms[6];
|
|
|
|
|
|
|
|
for(int i=0; i<6; i++){
|
|
|
|
|
|
|
|
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, opc, last_rand, sqn_ms, amf, mac_s_tmp);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_hss_log->debug_hex(mac_s_tmp, 8, "MAC calc : ");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set_sqn(imsi, sqn_ms);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
hss::increment_ue_sqn(uint64_t imsi)
|
|
|
|
hss::increment_ue_sqn(uint64_t imsi)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -613,6 +635,7 @@ hss::increment_sqn(uint8_t *sqn, uint8_t *next_sqn)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
hss::set_sqn(uint64_t imsi, uint8_t *sqn)
|
|
|
|
hss::set_sqn(uint64_t imsi, uint8_t *sqn)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -713,15 +736,4 @@ hss::hex_string(uint8_t *hex, int size)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ss.str();
|
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
|
|
|
|
string_to_imsi()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
uint64_t imsi = 0;
|
|
|
|
|
|
|
|
for(int i=0;i<=14;i++){
|
|
|
|
|
|
|
|
imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return imsi;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
} //namespace srsepc
|
|
|
|
} //namespace srsepc
|
|
|
|