mirror of https://github.com/PentHertz/srsLTE.git
commit
1cba6b18ee
|
@ -52,6 +52,17 @@
|
|||
DECLARATIONS
|
||||
*******************************************************************************/
|
||||
|
||||
/*********************************************************************
|
||||
Name: compute_OPc
|
||||
|
||||
Description: Computes OPc from OP and K.
|
||||
|
||||
Document Reference: 35.206 v10.0.0 Annex 3
|
||||
*********************************************************************/
|
||||
LIBLTE_ERROR_ENUM liblte_compute_opc(uint8 *k,
|
||||
uint8 *op,
|
||||
uint8 *op_c);
|
||||
|
||||
/*********************************************************************
|
||||
Name: liblte_security_generate_k_asme
|
||||
|
||||
|
|
|
@ -151,6 +151,9 @@ uint8_t security_128_eea2(uint8_t *key,
|
|||
/******************************************************************************
|
||||
* Authentication
|
||||
*****************************************************************************/
|
||||
uint8_t compute_opc( uint8_t *k,
|
||||
uint8_t *op,
|
||||
uint8_t *opc);
|
||||
|
||||
uint8_t security_milenage_f1( uint8_t *k,
|
||||
uint8_t *op,
|
||||
|
|
|
@ -1099,7 +1099,7 @@ LIBLTE_ERROR_ENUM liblte_security_decryption_eea2(uint8 *key,
|
|||
Document Reference: 35.206 v10.0.0 Annex 3
|
||||
*********************************************************************/
|
||||
LIBLTE_ERROR_ENUM liblte_security_milenage_f1(uint8 *k,
|
||||
uint8 *op,
|
||||
uint8 *op_c,
|
||||
uint8 *rand,
|
||||
uint8 *sqn,
|
||||
uint8 *amf,
|
||||
|
@ -1108,13 +1108,13 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1(uint8 *k,
|
|||
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
||||
ROUND_KEY_STRUCT round_keys;
|
||||
uint32 i;
|
||||
uint8 op_c[16];
|
||||
uint8 temp[16];
|
||||
uint8 in1[16];
|
||||
uint8 out1[16];
|
||||
uint8 rijndael_input[16];
|
||||
|
||||
if(k != NULL &&
|
||||
op_c != NULL &&
|
||||
rand != NULL &&
|
||||
sqn != NULL &&
|
||||
amf != NULL &&
|
||||
|
@ -1123,9 +1123,6 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1(uint8 *k,
|
|||
// Initialize the round keys
|
||||
rijndael_key_schedule(k, &round_keys);
|
||||
|
||||
// Compute OPc
|
||||
compute_OPc(&round_keys, op, op_c);
|
||||
|
||||
// Compute temp
|
||||
for(i=0; i<16; i++)
|
||||
{
|
||||
|
@ -1183,7 +1180,7 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1(uint8 *k,
|
|||
Document Reference: 35.206 v10.0.0 Annex 3
|
||||
*********************************************************************/
|
||||
LIBLTE_ERROR_ENUM liblte_security_milenage_f1_star(uint8 *k,
|
||||
uint8 *op,
|
||||
uint8 *op_c,
|
||||
uint8 *rand,
|
||||
uint8 *sqn,
|
||||
uint8 *amf,
|
||||
|
@ -1192,13 +1189,13 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1_star(uint8 *k,
|
|||
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
||||
ROUND_KEY_STRUCT round_keys;
|
||||
uint32 i;
|
||||
uint8 op_c[16];
|
||||
uint8 temp[16];
|
||||
uint8 in1[16];
|
||||
uint8 out1[16];
|
||||
uint8 rijndael_input[16];
|
||||
|
||||
if(k != NULL &&
|
||||
op_c != NULL &&
|
||||
rand != NULL &&
|
||||
sqn != NULL &&
|
||||
amf != NULL &&
|
||||
|
@ -1207,9 +1204,6 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1_star(uint8 *k,
|
|||
// Initialize the round keys
|
||||
rijndael_key_schedule(k, &round_keys);
|
||||
|
||||
// Compute OPc
|
||||
compute_OPc(&round_keys, op, op_c);
|
||||
|
||||
// Compute temp
|
||||
for(i=0; i<16; i++)
|
||||
{
|
||||
|
@ -1267,7 +1261,7 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f1_star(uint8 *k,
|
|||
Document Reference: 35.206 v10.0.0 Annex 3
|
||||
*********************************************************************/
|
||||
LIBLTE_ERROR_ENUM liblte_security_milenage_f2345(uint8 *k,
|
||||
uint8 *op,
|
||||
uint8 *op_c,
|
||||
uint8 *rand,
|
||||
uint8 *res,
|
||||
uint8 *ck,
|
||||
|
@ -1277,12 +1271,12 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f2345(uint8 *k,
|
|||
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
||||
ROUND_KEY_STRUCT round_keys;
|
||||
uint32 i;
|
||||
uint8 op_c[16];
|
||||
uint8 temp[16];
|
||||
uint8 out[16];
|
||||
uint8 rijndael_input[16];
|
||||
|
||||
if(k != NULL &&
|
||||
op_c != NULL &&
|
||||
rand != NULL &&
|
||||
res != NULL &&
|
||||
ck != NULL &&
|
||||
|
@ -1292,9 +1286,6 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f2345(uint8 *k,
|
|||
// Initialize the round keys
|
||||
rijndael_key_schedule(k, &round_keys);
|
||||
|
||||
// Compute OPc
|
||||
compute_OPc(&round_keys, op, op_c);
|
||||
|
||||
// Compute temp
|
||||
for(i=0; i<16; i++)
|
||||
{
|
||||
|
@ -1378,28 +1369,25 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f2345(uint8 *k,
|
|||
Document Reference: 35.206 v10.0.0 Annex 3
|
||||
*********************************************************************/
|
||||
LIBLTE_ERROR_ENUM liblte_security_milenage_f5_star(uint8 *k,
|
||||
uint8 *op,
|
||||
uint8 *op_c,
|
||||
uint8 *rand,
|
||||
uint8 *ak)
|
||||
{
|
||||
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
||||
ROUND_KEY_STRUCT round_keys;
|
||||
uint32 i;
|
||||
uint8 op_c[16];
|
||||
uint8 temp[16];
|
||||
uint8 out[16];
|
||||
uint8 rijndael_input[16];
|
||||
|
||||
if(k != NULL &&
|
||||
op_c != NULL &&
|
||||
rand != NULL &&
|
||||
ak != NULL)
|
||||
{
|
||||
// Initialize the round keys
|
||||
rijndael_key_schedule(k, &round_keys);
|
||||
|
||||
// Compute OPc
|
||||
compute_OPc(&round_keys, op, op_c);
|
||||
|
||||
// Compute temp
|
||||
for(i=0; i<16; i++)
|
||||
{
|
||||
|
@ -1424,36 +1412,47 @@ LIBLTE_ERROR_ENUM liblte_security_milenage_f5_star(uint8 *k,
|
|||
{
|
||||
ak[i] = out[i];
|
||||
}
|
||||
|
||||
err = LIBLTE_SUCCESS;
|
||||
}
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Name: liblte_compute_opc
|
||||
|
||||
Description: Computes OPc from OP and K.
|
||||
|
||||
Document Reference: 35.206 v10.0.0 Annex 3
|
||||
*********************************************************************/
|
||||
|
||||
LIBLTE_ERROR_ENUM liblte_compute_opc(uint8 *k,
|
||||
uint8 *op,
|
||||
uint8 *op_c)
|
||||
{
|
||||
uint32 i;
|
||||
ROUND_KEY_STRUCT round_keys;
|
||||
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
||||
|
||||
if(k != NULL &&
|
||||
op != NULL &&
|
||||
op_c != NULL)
|
||||
{
|
||||
|
||||
rijndael_key_schedule(k, &round_keys);
|
||||
rijndael_encrypt(op, &round_keys, op_c);
|
||||
for(i=0; i<16; i++)
|
||||
{
|
||||
op_c[i] ^= op[i];
|
||||
}
|
||||
err = LIBLTE_SUCCESS;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
LOCAL FUNCTIONS
|
||||
*******************************************************************************/
|
||||
|
||||
/*********************************************************************
|
||||
Name: compute_OPc
|
||||
|
||||
Description: Computes OPc from OP and K.
|
||||
|
||||
Document Reference: 35.206 v10.0.0 Annex 3
|
||||
*********************************************************************/
|
||||
void compute_OPc(ROUND_KEY_STRUCT *rk,
|
||||
uint8 *op,
|
||||
uint8 *op_c)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
rijndael_encrypt(op, rk, op_c);
|
||||
for(i=0; i<16; i++)
|
||||
{
|
||||
op_c[i] ^= op[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Name: rijndael_key_schedule
|
||||
|
|
|
@ -229,6 +229,14 @@ uint8_t security_128_eea2(uint8_t *key,
|
|||
/******************************************************************************
|
||||
* Authentication
|
||||
*****************************************************************************/
|
||||
uint8_t compute_opc( uint8_t *k,
|
||||
uint8_t *op,
|
||||
uint8_t *opc)
|
||||
{
|
||||
return liblte_compute_opc(k,
|
||||
op,
|
||||
opc);
|
||||
}
|
||||
|
||||
uint8_t security_milenage_f1( uint8_t *k,
|
||||
uint8_t *op,
|
||||
|
|
|
@ -63,9 +63,19 @@ void test_set_2()
|
|||
uint8_t op[] = {0xcd, 0xc2, 0x02, 0xd5, 0x12, 0x3e, 0x20, 0xf6, 0x2b, 0x6d, 0x67, 0x6a, 0xc7, 0x2c, 0xb3, 0x18};
|
||||
// f1
|
||||
|
||||
uint8_t mac_o[8];
|
||||
uint8_t opc_o[16];
|
||||
err_lte = liblte_compute_opc(k,op,opc_o);
|
||||
assert(err_lte == LIBLTE_SUCCESS);
|
||||
|
||||
arrprint(opc_o, sizeof(opc_o));
|
||||
|
||||
uint8_t opc_a[] = {0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e, 0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf};
|
||||
err_cmp = arrcmp(opc_o,opc_a,sizeof(opc_o));
|
||||
assert(err_cmp == 0);
|
||||
|
||||
uint8_t mac_o[8];
|
||||
err_lte = liblte_security_milenage_f1(k,
|
||||
op,
|
||||
opc_o,
|
||||
rand,
|
||||
sqn,
|
||||
amf,
|
||||
|
@ -84,7 +94,7 @@ void test_set_2()
|
|||
|
||||
uint8_t mac_so[8];
|
||||
err_lte = liblte_security_milenage_f1_star(k,
|
||||
op,
|
||||
opc_o,
|
||||
rand,
|
||||
sqn,
|
||||
amf,
|
||||
|
@ -93,9 +103,9 @@ void test_set_2()
|
|||
assert(err_lte == LIBLTE_SUCCESS);
|
||||
|
||||
uint8_t mac_s[] = {0x01, 0xcf, 0xaf, 0x9e, 0xc4, 0xe8, 0x71, 0xe9};
|
||||
|
||||
|
||||
arrprint(mac_so, sizeof(mac_so));
|
||||
|
||||
|
||||
err_cmp = arrcmp(mac_so, mac_s, sizeof(mac_s));
|
||||
assert(err_cmp == 0);
|
||||
|
||||
|
@ -106,7 +116,7 @@ void test_set_2()
|
|||
uint8_t ak_o[6];
|
||||
|
||||
err_lte = liblte_security_milenage_f2345(k,
|
||||
op,
|
||||
opc_o,
|
||||
rand,
|
||||
res_o,
|
||||
ck_o,
|
||||
|
@ -126,7 +136,7 @@ void test_set_2()
|
|||
err_cmp = arrcmp(res_o, res, sizeof(res));
|
||||
assert(err_cmp == 0);
|
||||
|
||||
// CK
|
||||
// CK
|
||||
arrprint(ck_o, sizeof(ck_o));
|
||||
|
||||
err_cmp = arrcmp(ck_o, ck, sizeof(ck));
|
||||
|
@ -142,10 +152,10 @@ void test_set_2()
|
|||
err_cmp = arrcmp(ak_o, ak, sizeof(ak));
|
||||
assert(err_cmp == 0);
|
||||
|
||||
// f star
|
||||
// f star
|
||||
uint8_t ak_star_o[6];
|
||||
|
||||
err_lte = liblte_security_milenage_f5_star(k, op, rand, ak_star_o);
|
||||
|
||||
err_lte = liblte_security_milenage_f5_star(k, opc_o, rand, ak_star_o);
|
||||
assert(err_lte == LIBLTE_SUCCESS);
|
||||
|
||||
arrprint(ak_star_o, sizeof(ak_star_o));
|
||||
|
@ -160,8 +170,9 @@ void test_set_2()
|
|||
*/
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
/*
|
||||
|
||||
test_set_2();
|
||||
/*
|
||||
test_set_3();
|
||||
test_set_4();
|
||||
test_set_5();
|
||||
|
|
|
@ -54,11 +54,13 @@ typedef struct{
|
|||
typedef struct{
|
||||
std::string name;
|
||||
uint64_t imsi;
|
||||
uint8_t key[16];
|
||||
uint8_t op[16];
|
||||
uint8_t amf[2];
|
||||
uint8_t sqn[6];
|
||||
uint8_t last_rand[16];
|
||||
uint8_t key[16];
|
||||
bool op_configured;
|
||||
uint8_t op[16];
|
||||
uint8_t opc[16];
|
||||
uint8_t amf[2];
|
||||
uint8_t sqn[6];
|
||||
uint8_t last_rand[16];
|
||||
}hss_ue_ctx_t;
|
||||
|
||||
enum hss_auth_algo {
|
||||
|
@ -89,7 +91,7 @@ private:
|
|||
|
||||
|
||||
void gen_rand(uint8_t rand_[16]);
|
||||
bool get_k_amf_op_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op, uint8_t *sqn);
|
||||
bool get_k_amf_opc_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *opc, uint8_t *sqn);
|
||||
|
||||
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);
|
||||
|
@ -100,7 +102,8 @@ private:
|
|||
std::vector<std::string> 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);
|
||||
|
||||
void increment_sqn(uint64_t imsi);
|
||||
void increment_ue_sqn(uint64_t imsi);
|
||||
void increment_sqn(uint8_t *sqn, uint8_t *next_sqn);
|
||||
void set_sqn(uint64_t imsi, uint8_t *sqn);
|
||||
|
||||
void set_last_rand(uint64_t imsi, uint8_t *rand);
|
||||
|
|
|
@ -110,6 +110,7 @@ typedef struct{
|
|||
} enb_ctx_t;
|
||||
|
||||
typedef struct{
|
||||
uint8_t eksi;
|
||||
uint8_t k_asme[32];
|
||||
uint8_t xres[16]; //minimum 6, maximum 16
|
||||
uint32_t dl_nas_count;
|
||||
|
|
|
@ -113,7 +113,7 @@ private:
|
|||
bool integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t *pdu);
|
||||
bool short_integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t *pdu);
|
||||
|
||||
bool pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t *autn,uint8_t *rand);
|
||||
bool pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t eksi, uint8_t *autn, uint8_t *rand);
|
||||
bool pack_authentication_reject(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id);
|
||||
bool unpack_authentication_response(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT *ul_xport, LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT *auth_resp);
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ hss::~hss()
|
|||
|
||||
hss*
|
||||
hss::get_instance(void)
|
||||
{
|
||||
{
|
||||
pthread_mutex_lock(&hss_instance_mutex);
|
||||
if(NULL == m_instance) {
|
||||
m_instance = new hss();
|
||||
|
@ -93,7 +93,7 @@ hss::init(hss_args_t *hss_args, srslte::log_filter *hss_log)
|
|||
|
||||
mcc = hss_args->mcc;
|
||||
mnc = hss_args->mnc;
|
||||
|
||||
|
||||
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);
|
||||
|
@ -140,7 +140,7 @@ bool
|
|||
hss::read_db_file(std::string db_filename)
|
||||
{
|
||||
std::ifstream m_db_file;
|
||||
|
||||
|
||||
m_db_file.open(db_filename.c_str(), std::ifstream::in);
|
||||
if(!m_db_file.is_open())
|
||||
{
|
||||
|
@ -153,23 +153,43 @@ hss::read_db_file(std::string db_filename)
|
|||
{
|
||||
if(line[0] != '#')
|
||||
{
|
||||
std::vector<std::string> split = split_string(line,',');
|
||||
if(split.size()!=6)
|
||||
uint column_size = 7;
|
||||
std::vector<std::string> split = split_string(line,',');
|
||||
if(split.size() != column_size)
|
||||
{
|
||||
m_hss_log->error("Error parsing UE database\n");
|
||||
m_hss_log->error("Error parsing UE database. Wrong number of columns in .csv\n");
|
||||
m_hss_log->error("Columns: %lu, Expected %d.\n",split.size(),column_size);
|
||||
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);
|
||||
get_uint_vec_from_hex_str(split[3],ue_ctx->op,16);
|
||||
get_uint_vec_from_hex_str(split[4],ue_ctx->amf,2);
|
||||
get_uint_vec_from_hex_str(split[5],ue_ctx->sqn,6);
|
||||
if(split[3] == std::string("op"))
|
||||
{
|
||||
ue_ctx->op_configured = true;
|
||||
get_uint_vec_from_hex_str(split[4],ue_ctx->op,16);
|
||||
compute_opc(ue_ctx->key,ue_ctx->op,ue_ctx->opc);
|
||||
}
|
||||
else if (split[3] == std::string("opc"))
|
||||
{
|
||||
ue_ctx->op_configured =false;
|
||||
get_uint_vec_from_hex_str(split[4],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);
|
||||
|
||||
m_hss_log->debug("Added user from DB, IMSI: %015lu\n", ue_ctx->imsi);
|
||||
m_hss_log->debug_hex(ue_ctx->key, 16, "User Key : ");
|
||||
m_hss_log->debug_hex(ue_ctx->op, 16, "User OP : ");
|
||||
if(ue_ctx->op_configured){
|
||||
m_hss_log->debug_hex(ue_ctx->op, 16, "User OP : ");
|
||||
}
|
||||
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 : ");
|
||||
|
||||
|
@ -194,7 +214,7 @@ bool hss::write_db_file(std::string db_filename)
|
|||
uint8_t sqn[6];
|
||||
|
||||
std::ofstream m_db_file;
|
||||
|
||||
|
||||
m_db_file.open(db_filename.c_str(), std::ofstream::out);
|
||||
if(!m_db_file.is_open())
|
||||
{
|
||||
|
@ -202,6 +222,21 @@ bool hss::write_db_file(std::string db_filename)
|
|||
}
|
||||
m_hss_log->info("Opened DB file: %s\n", db_filename.c_str() );
|
||||
|
||||
//Write comment info
|
||||
m_db_file << "# " << 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
|
||||
<< "# " << std::endl
|
||||
<< "# Name: Human readable name to help distinguish UE's. Ignored by the HSS " << std::endl
|
||||
<< "# IMSI: UE's IMSI value " << 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
|
||||
<< "# AMF: Authentication management field, stored in hexadecimal " << std::endl
|
||||
<< "# SQN: UE's Sequence number for freshness of the authentication " << std::endl
|
||||
<< "# " << std::endl
|
||||
<< "# Note: Lines starting by '#' are ignored and will be overwritten " << std::endl;
|
||||
|
||||
std::map<uint64_t,hss_ue_ctx_t*>::iterator it = m_imsi_to_ue_ctx.begin();
|
||||
while(it!=m_imsi_to_ue_ctx.end())
|
||||
{
|
||||
|
@ -211,7 +246,14 @@ bool hss::write_db_file(std::string db_filename)
|
|||
m_db_file << ",";
|
||||
m_db_file << hex_string(it->second->key, 16);
|
||||
m_db_file << ",";
|
||||
m_db_file << hex_string(it->second->op, 16);
|
||||
if(it->second->op_configured){
|
||||
m_db_file << "op,";
|
||||
m_db_file << hex_string(it->second->op, 16);
|
||||
}
|
||||
else{
|
||||
m_db_file << "opc,";
|
||||
m_db_file << hex_string(it->second->opc, 16);
|
||||
}
|
||||
m_db_file << ",";
|
||||
m_db_file << hex_string(it->second->amf, 2);
|
||||
m_db_file << ",";
|
||||
|
@ -240,7 +282,7 @@ hss::gen_auth_info_answer(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t
|
|||
ret = gen_auth_info_answer_milenage(imsi, k_asme, autn, rand, xres);
|
||||
break;
|
||||
}
|
||||
increment_sqn(imsi);
|
||||
increment_ue_sqn(imsi);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
@ -258,7 +300,7 @@ hss::resync_sqn(uint64_t imsi, uint8_t *auts)
|
|||
ret = resync_sqn_milenage(imsi, auts);
|
||||
break;
|
||||
}
|
||||
increment_sqn(imsi);
|
||||
increment_ue_sqn(imsi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -281,10 +323,10 @@ hss::resync_sqn_milenage(uint64_t imsi, uint8_t *auts)
|
|||
|
||||
uint8_t k[16];
|
||||
uint8_t amf[2];
|
||||
uint8_t op[16];
|
||||
uint8_t opc[16];
|
||||
uint8_t sqn[6];
|
||||
|
||||
if(!get_k_amf_op_sqn(imsi, k, amf, op, sqn))
|
||||
if(!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -300,13 +342,13 @@ hss::resync_sqn_milenage(uint64_t imsi, uint8_t *auts)
|
|||
}
|
||||
|
||||
m_hss_log->debug_hex(k, 16, "User Key : ");
|
||||
m_hss_log->debug_hex(op, 16, "User OP : ");
|
||||
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, op, last_rand, ak);
|
||||
security_milenage_f5_star(k, opc, last_rand, ak);
|
||||
m_hss_log->debug_hex(ak, 6, "Resynch AK : ");
|
||||
|
||||
uint8_t sqn_ms[6];
|
||||
|
@ -314,22 +356,16 @@ hss::resync_sqn_milenage(uint64_t imsi, uint8_t *auts)
|
|||
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, op, last_rand, sqn_ms, amf, mac_s_tmp);
|
||||
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 : ");
|
||||
/*
|
||||
for(int i=0; i<8; i++){
|
||||
if(!(mac_s_tmp[i] == mac_s[i])){
|
||||
m_hss_log->error("Calculated MAC does not match sent MAC\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
set_sqn(imsi, sqn_ms);
|
||||
|
||||
return true;
|
||||
|
@ -340,7 +376,7 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn
|
|||
{
|
||||
uint8_t k[16];
|
||||
uint8_t amf[2];
|
||||
uint8_t op[16];
|
||||
uint8_t opc[16];
|
||||
uint8_t sqn[6];
|
||||
|
||||
uint8_t ck[16];
|
||||
|
@ -349,14 +385,14 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn
|
|||
uint8_t mac[8];
|
||||
|
||||
|
||||
if(!get_k_amf_op_sqn(imsi, k, amf, op, sqn))
|
||||
if(!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
gen_rand(rand);
|
||||
|
||||
security_milenage_f2345( k,
|
||||
op,
|
||||
opc,
|
||||
rand,
|
||||
xres,
|
||||
ck,
|
||||
|
@ -364,7 +400,7 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn
|
|||
ak);
|
||||
|
||||
m_hss_log->debug_hex(k, 16, "User Key : ");
|
||||
m_hss_log->debug_hex(op, 16, "User OP : ");
|
||||
m_hss_log->debug_hex(opc, 16, "User OPc : ");
|
||||
m_hss_log->debug_hex(rand, 16, "User Rand : ");
|
||||
m_hss_log->debug_hex(xres, 8, "User XRES: ");
|
||||
m_hss_log->debug_hex(ck, 16, "User CK: ");
|
||||
|
@ -372,7 +408,7 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn
|
|||
m_hss_log->debug_hex(ak, 6, "User AK: ");
|
||||
|
||||
security_milenage_f1( k,
|
||||
op,
|
||||
opc,
|
||||
rand,
|
||||
sqn,
|
||||
amf,
|
||||
|
@ -419,7 +455,7 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin
|
|||
{
|
||||
uint8_t k[16];
|
||||
uint8_t amf[2];
|
||||
uint8_t op[16];
|
||||
uint8_t opc[16];
|
||||
uint8_t sqn[6];
|
||||
|
||||
uint8_t xdout[16];
|
||||
|
@ -432,7 +468,7 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin
|
|||
|
||||
int i = 0;
|
||||
|
||||
if(!get_k_amf_op_sqn(imsi, k, amf, op, sqn))
|
||||
if(!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -453,7 +489,7 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin
|
|||
}
|
||||
|
||||
m_hss_log->debug_hex(k, 16, "User Key : ");
|
||||
m_hss_log->debug_hex(op, 16, "User OP : ");
|
||||
m_hss_log->debug_hex(opc, 16, "User OPc : ");
|
||||
m_hss_log->debug_hex(rand, 16, "User Rand : ");
|
||||
m_hss_log->debug_hex(xres, 8, "User XRES: ");
|
||||
m_hss_log->debug_hex(ck, 16, "User CK: ");
|
||||
|
@ -525,7 +561,7 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin
|
|||
|
||||
|
||||
bool
|
||||
hss::get_k_amf_op_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op, uint8_t *sqn)
|
||||
hss::get_k_amf_opc_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *opc, uint8_t *sqn)
|
||||
{
|
||||
|
||||
std::map<uint64_t,hss_ue_ctx_t*>::iterator ue_ctx_it = m_imsi_to_ue_ctx.find(imsi);
|
||||
|
@ -539,14 +575,14 @@ hss::get_k_amf_op_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *op, uint
|
|||
m_hss_log->info("Found User %015lu\n",imsi);
|
||||
memcpy(k, ue_ctx->key, 16);
|
||||
memcpy(amf, ue_ctx->amf, 2);
|
||||
memcpy(op, ue_ctx->op, 16);
|
||||
memcpy(opc, ue_ctx->opc, 16);
|
||||
memcpy(sqn, ue_ctx->sqn, 6);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
hss::increment_sqn(uint64_t imsi)
|
||||
void
|
||||
hss::increment_ue_sqn(uint64_t imsi)
|
||||
{
|
||||
hss_ue_ctx_t *ue_ctx = NULL;
|
||||
bool ret = get_ue_ctx(imsi, &ue_ctx);
|
||||
|
@ -555,23 +591,28 @@ hss::increment_sqn(uint64_t imsi)
|
|||
return;
|
||||
}
|
||||
|
||||
// Awkward 48 bit sqn and doing arithmetic
|
||||
uint64_t sqn = 0;
|
||||
uint8_t *p = (uint8_t *)&sqn;
|
||||
|
||||
for(int i = 0; i < 6; i++) {
|
||||
p[5-i] = (uint8_t) ((ue_ctx->sqn[i]));
|
||||
}
|
||||
|
||||
sqn++;
|
||||
|
||||
m_hss_log->debug("Incremented SQN (IMSI: %" PRIu64 ") SQN: %" PRIu64 "\n", imsi, sqn);
|
||||
|
||||
for(int i = 0; i < 6; i++){
|
||||
ue_ctx->sqn[i] = p[5-i];
|
||||
}
|
||||
increment_sqn(ue_ctx->sqn,ue_ctx->sqn);
|
||||
m_hss_log->debug("Incremented SQN (IMSI: %" PRIu64 ")" PRIu64 "\n", imsi);
|
||||
m_hss_log->debug_hex(ue_ctx->sqn, 6, "SQN: ");
|
||||
}
|
||||
|
||||
void
|
||||
hss::increment_sqn(uint8_t *sqn, uint8_t *next_sqn)
|
||||
{
|
||||
// Awkward 48 bit sqn and doing arithmetic
|
||||
uint64_t tmp_sqn = 0;
|
||||
uint8_t *p = (uint8_t *)&tmp_sqn;
|
||||
|
||||
for(int i = 0; i < 6; i++) {
|
||||
p[5-i] = sqn[i];
|
||||
}
|
||||
|
||||
tmp_sqn++;
|
||||
for(int i = 0; i < 6; i++){
|
||||
next_sqn[i] = p[5-i];
|
||||
}
|
||||
return;
|
||||
}
|
||||
void
|
||||
hss::set_sqn(uint64_t imsi, uint8_t *sqn)
|
||||
{
|
||||
|
|
|
@ -223,7 +223,8 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
|
|||
|
||||
if( sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS ||
|
||||
(msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) ||
|
||||
(msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY))
|
||||
(msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) ||
|
||||
(msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY))
|
||||
{
|
||||
//Only identity response and authentication response are valid as plain NAS.
|
||||
//Sometimes authentication response and identity are sent as integrity protected,
|
||||
|
@ -504,6 +505,9 @@ s1ap_nas_transport::handle_nas_imsi_attach_request(uint32_t enb_ue_s1ap_id,
|
|||
m_s1ap_log->info("User not found. IMSI %015lu\n",emm_ctx->imsi);
|
||||
return false;
|
||||
}
|
||||
//Allocate eKSI for this authentication vector
|
||||
//Here we assume a new security context thus a new eKSI
|
||||
emm_ctx->security_ctxt.eksi=0;
|
||||
|
||||
//Save the UE context
|
||||
ue_ctx_t *new_ctx = new ue_ctx_t;
|
||||
|
@ -513,7 +517,7 @@ s1ap_nas_transport::handle_nas_imsi_attach_request(uint32_t enb_ue_s1ap_id,
|
|||
m_s1ap->add_ue_to_enb_set(enb_sri->sinfo_assoc_id,ecm_ctx->mme_ue_s1ap_id);
|
||||
|
||||
//Pack NAS Authentication Request in Downlink NAS Transport msg
|
||||
pack_authentication_request(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand);
|
||||
pack_authentication_request(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, emm_ctx->security_ctxt.eksi, autn, rand);
|
||||
|
||||
//Send reply to eNB
|
||||
*reply_flag = true;
|
||||
|
@ -593,7 +597,7 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id,
|
|||
|
||||
//Save whether ESM information transfer is necessary
|
||||
ecm_ctx->eit = pdn_con_req.esm_info_transfer_flag_present;
|
||||
//m_s1ap_log->console("EPS Bearer id: %d\n", eps_bearer_id);
|
||||
|
||||
//Add eNB info to UE ctxt
|
||||
memcpy(&ecm_ctx->enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo));
|
||||
//Initialize E-RABs
|
||||
|
@ -618,7 +622,6 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id,
|
|||
|
||||
m_s1ap_log->console("Could not find M-TMSI=0x%x. Sending ID request\n",m_tmsi);
|
||||
m_s1ap_log->info("Could not find M-TMSI=0x%x. Sending Id Request\n", m_tmsi);
|
||||
//m_s1ap->add_new_ue_ecm_ctx(ue_ecm_ctx);
|
||||
|
||||
//Store temporary ue context
|
||||
ue_ctx_t *new_ctx = new ue_ctx_t;
|
||||
|
@ -763,12 +766,12 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id,
|
|||
}
|
||||
//Store context based on MME UE S1AP id
|
||||
m_s1ap->add_ue_ctx_to_mme_ue_s1ap_id_map(ue_ctx);
|
||||
|
||||
|
||||
//NAS integrity failed. Re-start authentication process.
|
||||
m_s1ap_log->console("GUTI Attach request NAS integrity failed.\n");
|
||||
m_s1ap_log->console("RE-starting authentication procedure.\n");
|
||||
uint8_t autn[16];
|
||||
uint8_t rand[16];
|
||||
uint8_t autn[16];
|
||||
uint8_t rand[16];
|
||||
//Get Authentication Vectors from HSS
|
||||
if(!m_hss->gen_auth_info_answer(emm_ctx->imsi, emm_ctx->security_ctxt.k_asme, autn, rand, emm_ctx->security_ctxt.xres))
|
||||
{
|
||||
|
@ -776,7 +779,9 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id,
|
|||
m_s1ap_log->info("User not found. IMSI %015lu\n",emm_ctx->imsi);
|
||||
return false;
|
||||
}
|
||||
pack_authentication_request(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand);
|
||||
//Restarting security context. Reseting eKSI to 0.
|
||||
emm_ctx->security_ctxt.eksi=0;
|
||||
pack_authentication_request(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, emm_ctx->security_ctxt.eksi, autn, rand);
|
||||
|
||||
//Send reply to eNB
|
||||
*reply_flag = true;
|
||||
|
@ -1034,6 +1039,7 @@ s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *na
|
|||
{
|
||||
m_s1ap_log->console("UE Authentication Accepted.\n");
|
||||
m_s1ap_log->info("UE Authentication Accepted.\n");
|
||||
|
||||
//Send Security Mode Command
|
||||
emm_ctx->security_ctxt.ul_nas_count = 0; // Reset the NAS uplink counter for the right key k_enb derivation
|
||||
pack_security_mode_command(reply_buffer, emm_ctx, ecm_ctx);
|
||||
|
@ -1199,12 +1205,14 @@ s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_
|
|||
m_s1ap_log->info("User not found. IMSI %015lu\n",imsi);
|
||||
return false;
|
||||
}
|
||||
//Identity reponse from unknown GUTI atach. Assigning new eKSI.
|
||||
emm_ctx->security_ctxt.eksi=0;
|
||||
|
||||
//Store UE context im IMSI map
|
||||
m_s1ap->add_ue_ctx_to_imsi_map(ue_ctx);
|
||||
|
||||
//Pack NAS Authentication Request in Downlink NAS Transport msg
|
||||
pack_authentication_request(reply_msg, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand);
|
||||
pack_authentication_request(reply_msg, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, emm_ctx->security_ctxt.eksi, autn, rand);
|
||||
|
||||
//Send reply to eNB
|
||||
*reply_flag = true;
|
||||
|
@ -1385,8 +1393,8 @@ s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg
|
|||
m_s1ap_log->info("Non-EPS authentication unacceptable\n");
|
||||
break;
|
||||
case 21:
|
||||
m_s1ap_log->console("Sequence number synch failure\n");
|
||||
m_s1ap_log->info("Sequence number synch failure\n");
|
||||
m_s1ap_log->console("Authentication Failure -- Synchronization Failure\n");
|
||||
m_s1ap_log->info("Authentication Failure -- Synchronization Failure\n");
|
||||
if(auth_fail.auth_fail_param_present == false){
|
||||
m_s1ap_log->error("Missing fail parameter\n");
|
||||
return false;
|
||||
|
@ -1404,8 +1412,11 @@ s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg
|
|||
m_s1ap_log->info("User not found. IMSI %015lu\n", emm_ctx->imsi);
|
||||
return false;
|
||||
}
|
||||
//Making sure eKSI is different from previous eKSI.
|
||||
emm_ctx->security_ctxt.eksi = (emm_ctx->security_ctxt.eksi+1)%6;
|
||||
|
||||
//Pack NAS Authentication Request in Downlink NAS Transport msg
|
||||
pack_authentication_request(reply_msg, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand);
|
||||
pack_authentication_request(reply_msg, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, emm_ctx->security_ctxt.eksi, autn, rand);
|
||||
|
||||
//Send reply to eNB
|
||||
*reply_flag = true;
|
||||
|
@ -1417,15 +1428,10 @@ s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg
|
|||
}
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
bool
|
||||
s1ap_nas_transport::handle_detach_request(nas_msg, ue_ctx, reply_buffer, reply_flag)
|
||||
{
|
||||
return true;
|
||||
}*/
|
||||
|
||||
/*Packing/Unpacking helper functions*/
|
||||
bool
|
||||
s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t *autn, uint8_t *rand)
|
||||
s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t eksi, uint8_t *autn, uint8_t *rand)
|
||||
{
|
||||
srslte::byte_buffer_t *nas_buffer = m_pool->allocate();
|
||||
|
||||
|
@ -1453,7 +1459,7 @@ s1ap_nas_transport::pack_authentication_request(srslte::byte_buffer_t *reply_msg
|
|||
memcpy(auth_req.autn , autn, 16);
|
||||
memcpy(auth_req.rand, rand, 16);
|
||||
auth_req.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE;
|
||||
auth_req.nas_ksi.nas_ksi=0;
|
||||
auth_req.nas_ksi.nas_ksi = eksi;
|
||||
|
||||
LIBLTE_ERROR_ENUM err = liblte_mme_pack_authentication_request_msg(&auth_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer);
|
||||
if(err != LIBLTE_SUCCESS)
|
||||
|
@ -1590,7 +1596,7 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg,
|
|||
sm_cmd.selected_nas_sec_algs.type_of_eia = LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_128_EIA1;
|
||||
|
||||
sm_cmd.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE;
|
||||
sm_cmd.nas_ksi.nas_ksi=0;
|
||||
sm_cmd.nas_ksi.nas_ksi=ue_emm_ctx->security_ctxt.eksi;
|
||||
|
||||
//Replay UE security cap
|
||||
memcpy(sm_cmd.ue_security_cap.eea,ue_emm_ctx->security_ctxt.ue_network_cap.eea,8*sizeof(bool));
|
||||
|
@ -1607,8 +1613,6 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg,
|
|||
sm_cmd.nonce_mme_present=false;
|
||||
|
||||
uint8_t sec_hdr_type=3;
|
||||
|
||||
// ue_emm_ctx->security_ctxt.dl_nas_count = 0;
|
||||
LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg(&sm_cmd,sec_hdr_type, ue_emm_ctx->security_ctxt.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer);
|
||||
if(err != LIBLTE_SUCCESS)
|
||||
{
|
||||
|
@ -1690,9 +1694,8 @@ s1ap_nas_transport::pack_esm_information_request(srslte::byte_buffer_t *reply_ms
|
|||
esm_info_req.proc_transaction_id = ue_emm_ctx->procedure_transaction_id;
|
||||
|
||||
uint8_t sec_hdr_type = LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED;
|
||||
|
||||
|
||||
ue_emm_ctx->security_ctxt.dl_nas_count++;
|
||||
|
||||
LIBLTE_ERROR_ENUM err = srslte_mme_pack_esm_information_request_msg(&esm_info_req, sec_hdr_type,ue_emm_ctx->security_ctxt.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer);
|
||||
if(err != LIBLTE_SUCCESS)
|
||||
{
|
||||
|
@ -1893,7 +1896,7 @@ s1ap_nas_transport::pack_identity_request(srslte::byte_buffer_t *reply_msg, uint
|
|||
//Setup Dw NAS structure
|
||||
LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport;
|
||||
dw_nas->ext=false;
|
||||
dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = mme_ue_s1ap_id;//FIXME Change name
|
||||
dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = mme_ue_s1ap_id;
|
||||
dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id;
|
||||
dw_nas->HandoverRestrictionList_present=false;
|
||||
dw_nas->SubscriberProfileIDforRFP_present=false;
|
||||
|
@ -1919,7 +1922,7 @@ s1ap_nas_transport::pack_identity_request(srslte::byte_buffer_t *reply_msg, uint
|
|||
m_s1ap_log->error("Error packing Dw NAS Transport: Authentication Reject\n");
|
||||
m_s1ap_log->console("Error packing Downlink NAS Transport: Authentication Reject\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_pool->deallocate(nas_buffer);
|
||||
return true;
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
#
|
||||
# .csv to store UE's information in HSS
|
||||
# Kept in the following format: "Name,IMSI,Key,OP,AMF"
|
||||
#
|
||||
# Name: Human readable name to help distinguish UE's. Largely ignored by the HSS
|
||||
# IMSI: UE's IMSI value
|
||||
# Key: UE's key, where other keys are derived from. Stored in hexadecimal
|
||||
# OP: Operator's code, sotred in hexadecimal
|
||||
# AMF: Authentication management field, stored in hexadecimal
|
||||
# SQN: UE's Sequence number for freshness of the authentication
|
||||
# Kept in the following format: "Name,IMSI,Key,OP_Type,OP,AMF,SQN"
|
||||
#
|
||||
# Note: Lines starting by '#' are ignored
|
||||
ue1,001010123456789,00112233445566778899aabbccddeeff,63BFA50EE6523365FF14C1F45F88737D,9001,000000001234
|
||||
ue2,001010123456780,00112233445566778899aabbccddeeaa,63BFA50EE6523365FF14C1F45F88737D,8000,000000001235
|
||||
# Name: Human readable name to help distinguish UE's. Ignored by the HSS
|
||||
# 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
|
||||
# OP/OPc: Operator Code/Cyphered Operator Code, stored in hexadecimal
|
||||
# AMF: Authentication management field, stored in hexadecimal
|
||||
# SQN: UE's Sequence number for freshness of the authentication
|
||||
#
|
||||
# Note: Lines starting by '#' are ignored and will be overwritten
|
||||
ue1,001010123456789,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,9001,000000001234
|
||||
ue2,001010123456780,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,8000,000000001234
|
||||
|
|
|
@ -110,6 +110,7 @@ private:
|
|||
auth_algo_t auth_algo;
|
||||
uint8_t amf[2]; // 3GPP 33.102 v10.0.0 Annex H
|
||||
uint8_t op[16];
|
||||
uint8_t opc[16];
|
||||
uint64_t imsi;
|
||||
uint64_t imei;
|
||||
uint8_t k[16];
|
||||
|
|
|
@ -43,7 +43,9 @@ typedef enum{
|
|||
typedef struct{
|
||||
std::string mode;
|
||||
std::string algo;
|
||||
bool using_op;
|
||||
std::string op;
|
||||
std::string opc;
|
||||
std::string imsi;
|
||||
std::string imei;
|
||||
std::string k;
|
||||
|
|
|
@ -131,7 +131,8 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
|
|||
|
||||
("usim.mode", bpo::value<string>(&args->usim.mode)->default_value("soft"), "USIM mode (soft or pcsc)")
|
||||
("usim.algo", bpo::value<string>(&args->usim.algo), "USIM authentication algorithm")
|
||||
("usim.op", bpo::value<string>(&args->usim.op), "USIM operator variant")
|
||||
("usim.op", bpo::value<string>(&args->usim.op), "USIM operator code")
|
||||
("usim.opc", bpo::value<string>(&args->usim.opc), "USIM operator code (ciphered variant)")
|
||||
("usim.imsi", bpo::value<string>(&args->usim.imsi), "USIM IMSI")
|
||||
("usim.imei", bpo::value<string>(&args->usim.imei), "USIM IMEI")
|
||||
("usim.k", bpo::value<string>(&args->usim.k), "USIM K")
|
||||
|
@ -142,11 +143,11 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
|
|||
("expert.ip_netmask",
|
||||
bpo::value<string>(&args->expert.ip_netmask)->default_value("255.255.255.0"),
|
||||
"Netmask of the tun_srsue device")
|
||||
|
||||
|
||||
("expert.mbms_service",
|
||||
bpo::value<int>(&args->expert.mbms_service)->default_value(-1),
|
||||
"automatically starts an mbms service of the number given")
|
||||
|
||||
|
||||
("expert.phy.worker_cpu_mask",
|
||||
bpo::value<int>(&args->expert.phy.worker_cpu_mask)->default_value(-1),
|
||||
"cpu bit mask (eg 255 = 1111 1111)")
|
||||
|
@ -361,9 +362,27 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
|
|||
cout << "Failed to read configuration file " << config_file << " - exiting" << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bpo::store(bpo::parse_config_file(conf, common), vm);
|
||||
bpo::notify(vm);
|
||||
|
||||
//Check conflicting OP/OPc options and which is being used
|
||||
if (vm.count("usim.op") && !vm["usim.op"].defaulted() &&
|
||||
vm.count("usim.opc") && !vm["usim.opc"].defaulted())
|
||||
{
|
||||
cout << "Conflicting options OP and OPc. Please configure either one or the other." << endl;
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(vm["usim.op"].defaulted()){
|
||||
args->usim.using_op = true;
|
||||
}
|
||||
else{
|
||||
args->usim.using_op = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply all_level to any unset layers
|
||||
if (vm.count("log.all_level")) {
|
||||
if (!vm.count("log.phy_level")) {
|
||||
|
|
|
@ -46,11 +46,30 @@ int usim::init(usim_args_t *args, srslte::log *usim_log_)
|
|||
const char *imei_c = args->imei.c_str();
|
||||
uint32_t i;
|
||||
|
||||
if(32 == args->op.length()) {
|
||||
str_to_hex(args->op, op);
|
||||
if(32 == args->k.length()) {
|
||||
str_to_hex(args->k, k);
|
||||
} else {
|
||||
usim_log->error("Invalid length for OP: %zu should be %d\n", args->op.length(), 32);
|
||||
usim_log->console("Invalid length for OP: %zu should be %d\n", args->op.length(), 32);
|
||||
usim_log->error("Invalid length for K: %zu should be %d\n", args->k.length(), 32);
|
||||
usim_log->console("Invalid length for K: %zu should be %d\n", args->k.length(), 32);
|
||||
}
|
||||
|
||||
if(args->using_op)
|
||||
{
|
||||
if(32 == args->op.length()) {
|
||||
str_to_hex(args->op, op);
|
||||
compute_opc(k,op,opc);
|
||||
} else {
|
||||
usim_log->error("Invalid length for OP: %zu should be %d\n", args->op.length(), 32);
|
||||
usim_log->console("Invalid length for OP: %zu should be %d\n", args->op.length(), 32);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(32 == args->opc.length()) {
|
||||
str_to_hex(args->opc, opc);
|
||||
} else {
|
||||
usim_log->error("Invalid length for OPc: %zu should be %d\n", args->opc.length(), 32);
|
||||
usim_log->console("Invalid length for OPc: %zu should be %d\n", args->opc.length(), 32);
|
||||
}
|
||||
}
|
||||
|
||||
if(15 == args->imsi.length()) {
|
||||
|
@ -77,13 +96,6 @@ int usim::init(usim_args_t *args, srslte::log *usim_log_)
|
|||
usim_log->console("Invalid length for IMEI: %zu should be %d\n", args->imei.length(), 15);
|
||||
}
|
||||
|
||||
if(32 == args->k.length()) {
|
||||
str_to_hex(args->k, k);
|
||||
} else {
|
||||
usim_log->error("Invalid length for K: %zu should be %d\n", args->k.length(), 32);
|
||||
usim_log->console("Invalid length for K: %zu should be %d\n", args->k.length(), 32);
|
||||
}
|
||||
|
||||
auth_algo = auth_algo_milenage;
|
||||
if("xor" == args->algo) {
|
||||
auth_algo = auth_algo_xor;
|
||||
|
@ -341,7 +353,7 @@ auth_result_t usim::gen_auth_res_milenage(uint8_t *rand,
|
|||
|
||||
// Use RAND and K to compute RES, CK, IK and AK
|
||||
security_milenage_f2345( k,
|
||||
op,
|
||||
opc,
|
||||
rand,
|
||||
res,
|
||||
ck,
|
||||
|
@ -363,7 +375,7 @@ auth_result_t usim::gen_auth_res_milenage(uint8_t *rand,
|
|||
|
||||
// Generate MAC
|
||||
security_milenage_f1( k,
|
||||
op,
|
||||
opc,
|
||||
rand,
|
||||
sqn,
|
||||
amf,
|
||||
|
|
|
@ -78,10 +78,11 @@ int main(int argc, char **argv)
|
|||
args.imei = "356092040793011";
|
||||
args.imsi = "208930000000001";
|
||||
args.k = "8BAF473F2F8FD09487CCCBD7097C6862";
|
||||
args.using_op = true;
|
||||
args.op = "11111111111111111111111111111111";
|
||||
|
||||
srsue::usim usim;
|
||||
usim.init(&args, &usim_log);
|
||||
|
||||
//assert(usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, res, &res_len, k_asme) == AUTH_OK);
|
||||
assert(usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, res, &res_len, k_asme) == AUTH_OK);
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ file_max_size = -1
|
|||
[usim]
|
||||
mode = soft
|
||||
algo = xor
|
||||
op = 63BFA50EE6523365FF14C1F45F88737D
|
||||
opc = 63BFA50EE6523365FF14C1F45F88737D
|
||||
k = 00112233445566778899aabbccddeeff
|
||||
imsi = 001010123456789
|
||||
imei = 353490069873319
|
||||
|
|
Loading…
Reference in New Issue