Split NAS security ctxt

master
David Rupprecht 3 years ago committed by David Rupprecht
parent 4e49508d8f
commit 5910d8847a

@ -222,8 +222,8 @@ private:
void enter_emm_deregistered_initiated(); void enter_emm_deregistered_initiated();
// security context persistence file // security context persistence file
bool read_ctxt_file(nas_sec_ctxt* ctxt); bool read_ctxt_file(nas_sec_ctxt* ctxt_, nas_sec_base_ctxt* ctxt_base_);
bool write_ctxt_file(nas_sec_ctxt ctxt_); bool write_ctxt_file(nas_sec_ctxt ctxt_, nas_sec_base_ctxt ctxt_base_);
// ctxt file helpers // ctxt file helpers
std::string hex_to_string(uint8_t* hex, int size); std::string hex_to_string(uint8_t* hex, int size);

@ -38,28 +38,33 @@ protected:
srsran::nas_pcap* pcap = nullptr; srsran::nas_pcap* pcap = nullptr;
// Security context // Security context
// Base context applies for LTE and 5G
struct nas_sec_base_ctxt {
uint8_t k_nas_enc[32] = {};
uint8_t k_nas_int[32] = {};
srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo;
srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo;
uint32_t tx_count;
uint32_t rx_count;
};
// Only applies for LTE
struct nas_sec_ctxt { struct nas_sec_ctxt {
uint8_t ksi; uint8_t ksi;
uint8_t k_asme[32]; uint8_t k_asme[32];
uint32_t tx_count;
uint32_t rx_count;
uint32_t k_enb_count; uint32_t k_enb_count;
srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo;
srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo;
LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti;
}; };
// Only applies for 5G
struct nas_5g_sec_ctxt { struct nas_5g_sec_ctxt {
uint8_t ksi; uint8_t ksi;
uint8_t k_amf[32]; uint8_t k_amf[32];
uint32_t tx_count;
uint32_t rx_count;
}; };
nas_sec_ctxt ctxt = {}; nas_sec_base_ctxt ctxt_base = {};
nas_5g_sec_ctxt ctxt_5g = {}; nas_sec_ctxt ctxt = {};
uint8_t k_nas_enc[32] = {}; nas_5g_sec_ctxt ctxt_5g = {};
uint8_t k_nas_int[32] = {};
int parse_security_algorithm_list(std::string algorithm_string, bool* algorithm_caps); int parse_security_algorithm_list(std::string algorithm_string, bool* algorithm_caps);

@ -81,10 +81,11 @@ int nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_n
cfg = cfg_; cfg = cfg_;
if ((read_ctxt_file(&ctxt))) { if ((read_ctxt_file(&ctxt, &ctxt_base))) {
usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, ctxt.cipher_algo, ctxt.integ_algo); usim->generate_nas_keys(
logger.debug(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); ctxt.k_asme, ctxt_base.k_nas_enc, ctxt_base.k_nas_int, ctxt_base.cipher_algo, ctxt_base.integ_algo);
logger.debug(k_nas_int, 32, "NAS integrity key - k_nas_int"); logger.debug(ctxt_base.k_nas_enc, 32, "NAS encryption key - k_nas_enc");
logger.debug(ctxt_base.k_nas_int, 32, "NAS integrity key - k_nas_int");
} }
// Configure timers // Configure timers
@ -108,7 +109,7 @@ nas::~nas() {}
void nas::stop() void nas::stop()
{ {
running = false; running = false;
write_ctxt_file(ctxt); write_ctxt_file(ctxt, ctxt_base);
} }
void nas::get_metrics(nas_metrics_t* m) void nas::get_metrics(nas_metrics_t* m)
@ -715,8 +716,12 @@ int nas::apply_security_config(srsran::unique_byte_buffer_t& pdu, uint8_t sec_hd
cipher_encrypt(pdu.get()); cipher_encrypt(pdu.get());
} }
if (sec_hdr_type >= LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) { if (sec_hdr_type >= LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) {
integrity_generate( integrity_generate(&ctxt_base.k_nas_int[16],
&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]); ctxt_base.tx_count,
SECURITY_DIRECTION_UPLINK,
&pdu->msg[5],
pdu->N_bytes - 5,
&pdu->msg[1]);
} }
} else { } else {
logger.error("Invalid PDU size %d", pdu->N_bytes); logger.error("Invalid PDU size %d", pdu->N_bytes);
@ -1010,7 +1015,7 @@ void nas::parse_attach_accept(uint32_t lcid, unique_byte_buffer_t pdu)
enter_emm_deregistered(emm_state_t::deregistered_substate_t::plmn_search); enter_emm_deregistered(emm_state_t::deregistered_substate_t::plmn_search);
} }
ctxt.rx_count++; ctxt_base.rx_count++;
} }
void nas::parse_attach_reject(uint32_t lcid, unique_byte_buffer_t pdu) void nas::parse_attach_reject(uint32_t lcid, unique_byte_buffer_t pdu)
@ -1065,7 +1070,7 @@ void nas::parse_authentication_request(uint32_t lcid, unique_byte_buffer_t pdu,
logger.info("Received Authentication Request"); logger.info("Received Authentication Request");
liblte_mme_unpack_authentication_request_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), &auth_req); liblte_mme_unpack_authentication_request_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), &auth_req);
ctxt.rx_count++; ctxt_base.rx_count++;
// Generate authentication response using RAND, AUTN & KSI-ASME // Generate authentication response using RAND, AUTN & KSI-ASME
uint16 mcc, mnc; uint16 mcc, mnc;
@ -1121,7 +1126,7 @@ void nas::parse_identity_request(unique_byte_buffer_t pdu, const uint8_t sec_hdr
liblte_mme_unpack_identity_request_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), &id_req); liblte_mme_unpack_identity_request_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), &id_req);
logger.info("Received Identity Request. ID type: %d", id_req.id_type); logger.info("Received Identity Request. ID type: %d", id_req.id_type);
ctxt.rx_count++; ctxt_base.rx_count++;
// do not respond if request is not protected (TS 24.301 Sec. 4.4.4.2) // do not respond if request is not protected (TS 24.301 Sec. 4.4.4.2)
if (sec_hdr_type >= LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || if (sec_hdr_type >= LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY ||
@ -1178,27 +1183,31 @@ void nas::parse_security_mode_command(uint32_t lcid, unique_byte_buffer_t pdu)
// Reset counters (as per 24.301 5.4.3.2), only needed for initial security mode command // Reset counters (as per 24.301 5.4.3.2), only needed for initial security mode command
if (auth_request) { if (auth_request) {
ctxt.rx_count = 0; ctxt_base.rx_count = 0;
ctxt.tx_count = 0; ctxt_base.tx_count = 0;
auth_request = false; auth_request = false;
} }
ctxt.cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM)sec_mode_cmd.selected_nas_sec_algs.type_of_eea; ctxt_base.cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM)sec_mode_cmd.selected_nas_sec_algs.type_of_eea;
ctxt.integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM)sec_mode_cmd.selected_nas_sec_algs.type_of_eia; ctxt_base.integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM)sec_mode_cmd.selected_nas_sec_algs.type_of_eia;
// Check capabilities // Check capabilities
if (!eea_caps[ctxt.cipher_algo] || !eia_caps[ctxt.integ_algo]) { if (!eea_caps[ctxt_base.cipher_algo] || !eia_caps[ctxt_base.integ_algo]) {
logger.warning("Sending Security Mode Reject due to security capabilities mismatch"); logger.warning("Sending Security Mode Reject due to security capabilities mismatch");
send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH); send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH);
return; return;
} }
// Generate NAS keys // Generate NAS keys
usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, ctxt.cipher_algo, ctxt.integ_algo); usim->generate_nas_keys(
logger.info(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); ctxt.k_asme, ctxt_base.k_nas_enc, ctxt_base.k_nas_int, ctxt_base.cipher_algo, ctxt_base.integ_algo);
logger.info(k_nas_int, 32, "NAS integrity key - k_nas_int"); logger.info(ctxt_base.k_nas_enc, 32, "NAS encryption key - k_nas_enc");
logger.info(ctxt_base.k_nas_int, 32, "NAS integrity key - k_nas_int");
logger.debug("Generating integrity check. integ_algo:%d, count_dl:%d, lcid:%d", ctxt.integ_algo, ctxt.rx_count, lcid); logger.debug("Generating integrity check. integ_algo:%d, count_dl:%d, lcid:%d",
ctxt_base.integ_algo,
ctxt_base.rx_count,
lcid);
if (not integrity_check(pdu.get())) { if (not integrity_check(pdu.get())) {
logger.warning("Sending Security Mode Reject due to integrity check failure"); logger.warning("Sending Security Mode Reject due to integrity check failure");
@ -1206,7 +1215,7 @@ void nas::parse_security_mode_command(uint32_t lcid, unique_byte_buffer_t pdu)
return; return;
} }
ctxt.rx_count++; ctxt_base.rx_count++;
LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sec_mode_comp = {}; LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sec_mode_comp = {};
if (sec_mode_cmd.imeisv_req_present && LIBLTE_MME_IMEISV_REQUESTED == sec_mode_cmd.imeisv_req) { if (sec_mode_cmd.imeisv_req_present && LIBLTE_MME_IMEISV_REQUESTED == sec_mode_cmd.imeisv_req) {
@ -1226,7 +1235,7 @@ void nas::parse_security_mode_command(uint32_t lcid, unique_byte_buffer_t pdu)
// Pack and send response // Pack and send response
pdu->clear(); pdu->clear();
liblte_mme_pack_security_mode_complete_msg( liblte_mme_pack_security_mode_complete_msg(
&sec_mode_comp, current_sec_hdr, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()); &sec_mode_comp, current_sec_hdr, ctxt_base.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get());
if (pcap != nullptr) { if (pcap != nullptr) {
pcap->write_nas(pdu->msg, pdu->N_bytes); pcap->write_nas(pdu->msg, pdu->N_bytes);
} }
@ -1237,9 +1246,9 @@ void nas::parse_security_mode_command(uint32_t lcid, unique_byte_buffer_t pdu)
} }
logger.info( logger.info(
"Sending Security Mode Complete nas_current_ctxt.tx_count=%d, RB=%s", ctxt.tx_count, rrc->get_rb_name(lcid)); "Sending Security Mode Complete ctxt_base.tx_count=%d, RB=%s", ctxt_base.tx_count, rrc->get_rb_name(lcid));
rrc->write_sdu(std::move(pdu)); rrc->write_sdu(std::move(pdu));
ctxt.tx_count++; ctxt_base.tx_count++;
// switch security header for all following messages // switch security header for all following messages
current_sec_hdr = LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED; current_sec_hdr = LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED;
@ -1278,7 +1287,7 @@ void nas::parse_esm_information_request(uint32_t lcid, unique_byte_buffer_t pdu)
logger.info("ESM information request received for beaser=%d, transaction_id=%d", logger.info("ESM information request received for beaser=%d, transaction_id=%d",
esm_info_req.eps_bearer_id, esm_info_req.eps_bearer_id,
esm_info_req.proc_transaction_id); esm_info_req.proc_transaction_id);
ctxt.rx_count++; ctxt_base.rx_count++;
// send response // send response
send_esm_information_response(esm_info_req.proc_transaction_id); send_esm_information_response(esm_info_req.proc_transaction_id);
@ -1291,14 +1300,14 @@ void nas::parse_emm_information(uint32_t lcid, unique_byte_buffer_t pdu)
std::string str = emm_info_str(&emm_info); std::string str = emm_info_str(&emm_info);
logger.info("Received EMM Information: %s", str.c_str()); logger.info("Received EMM Information: %s", str.c_str());
srsran::console("%s\n", str.c_str()); srsran::console("%s\n", str.c_str());
ctxt.rx_count++; ctxt_base.rx_count++;
} }
void nas::parse_detach_request(uint32_t lcid, unique_byte_buffer_t pdu) void nas::parse_detach_request(uint32_t lcid, unique_byte_buffer_t pdu)
{ {
LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT detach_request; LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT detach_request;
liblte_mme_unpack_detach_request_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), &detach_request); liblte_mme_unpack_detach_request_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), &detach_request);
ctxt.rx_count++; ctxt_base.rx_count++;
logger.info("Received detach request (type=%d). NAS State: %s", logger.info("Received detach request (type=%d). NAS State: %s",
detach_request.detach_type.type_of_detach, detach_request.detach_type.type_of_detach,
@ -1339,7 +1348,7 @@ void nas::parse_activate_dedicated_eps_bearer_context_request(uint32_t lcid, uni
request.linked_eps_bearer_id, request.linked_eps_bearer_id,
request.proc_transaction_id); request.proc_transaction_id);
ctxt.rx_count++; ctxt_base.rx_count++;
LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft = &request.tft; LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft = &request.tft;
logger.info("Traffic Flow Template: TFT OP code 0x%x, Filter list size %d, Parameter list size %d", logger.info("Traffic Flow Template: TFT OP code 0x%x, Filter list size %d, Parameter list size %d",
tft->tft_op_code, tft->tft_op_code,
@ -1390,7 +1399,7 @@ void nas::parse_deactivate_eps_bearer_context_request(unique_byte_buffer_t pdu)
request.proc_transaction_id, request.proc_transaction_id,
request.esm_cause); request.esm_cause);
ctxt.rx_count++; ctxt_base.rx_count++;
// check if bearer exists // check if bearer exists
if (eps_bearer.find(request.eps_bearer_id) == eps_bearer.end()) { if (eps_bearer.find(request.eps_bearer_id) == eps_bearer.end()) {
@ -1421,7 +1430,7 @@ void nas::parse_modify_eps_bearer_context_request(srsran::unique_byte_buffer_t p
request.eps_bearer_id, request.eps_bearer_id,
request.proc_transaction_id); request.proc_transaction_id);
ctxt.rx_count++; ctxt_base.rx_count++;
// check if bearer exists // check if bearer exists
const auto it = eps_bearer.find(request.eps_bearer_id); const auto it = eps_bearer.find(request.eps_bearer_id);
@ -1452,7 +1461,7 @@ void nas::parse_activate_test_mode(uint32_t lcid, unique_byte_buffer_t pdu)
{ {
logger.info("Received Activate test mode"); logger.info("Received Activate test mode");
ctxt.rx_count++; ctxt_base.rx_count++;
send_activate_test_mode_complete(); send_activate_test_mode_complete();
} }
@ -1475,7 +1484,7 @@ void nas::parse_close_ue_test_loop(uint32_t lcid, unique_byte_buffer_t pdu)
break; break;
} }
ctxt.rx_count++; ctxt_base.rx_count++;
send_close_ue_test_loop_complete(); send_close_ue_test_loop_complete();
} }
@ -1484,7 +1493,7 @@ void nas::parse_emm_status(uint32_t lcid, unique_byte_buffer_t pdu)
{ {
LIBLTE_MME_EMM_STATUS_MSG_STRUCT emm_status; LIBLTE_MME_EMM_STATUS_MSG_STRUCT emm_status;
liblte_mme_unpack_emm_status_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), &emm_status); liblte_mme_unpack_emm_status_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), &emm_status);
ctxt.rx_count++; ctxt_base.rx_count++;
switch (emm_status.emm_cause) { switch (emm_status.emm_cause) {
case LIBLTE_MME_ESM_CAUSE_INVALID_EPS_BEARER_IDENTITY: case LIBLTE_MME_ESM_CAUSE_INVALID_EPS_BEARER_IDENTITY:
@ -1578,7 +1587,7 @@ void nas::gen_attach_request(srsran::unique_byte_buffer_t& msg)
// According to Sec 4.4.5, the attach request is always unciphered, even if a context exists // According to Sec 4.4.5, the attach request is always unciphered, even if a context exists
liblte_mme_pack_attach_request_msg( liblte_mme_pack_attach_request_msg(
&attach_req, LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)msg.get()); &attach_req, LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY, ctxt_base.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)msg.get());
if (apply_security_config(msg, LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) { if (apply_security_config(msg, LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) {
logger.error("Error applying NAS security."); logger.error("Error applying NAS security.");
@ -1598,8 +1607,8 @@ void nas::gen_attach_request(srsran::unique_byte_buffer_t& msg)
} }
if (have_ctxt) { if (have_ctxt) {
set_k_enb_count(ctxt.tx_count); set_k_enb_count(ctxt_base.tx_count);
ctxt.tx_count++; ctxt_base.tx_count++;
} }
// stop T3411 and T3402 // stop T3411 and T3402
@ -1631,11 +1640,11 @@ void nas::gen_service_request(srsran::unique_byte_buffer_t& msg)
msg->msg[0] = (LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST << 4u) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); msg->msg[0] = (LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST << 4u) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
msg->N_bytes++; msg->N_bytes++;
msg->msg[1] = (ctxt.ksi & 0x07u) << 5u; msg->msg[1] = (ctxt.ksi & 0x07u) << 5u;
msg->msg[1] |= ctxt.tx_count & 0x1Fu; msg->msg[1] |= ctxt_base.tx_count & 0x1Fu;
msg->N_bytes++; msg->N_bytes++;
uint8_t mac[4]; uint8_t mac[4];
integrity_generate(&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &msg->msg[0], 2, &mac[0]); integrity_generate(&ctxt_base.k_nas_int[16], ctxt_base.tx_count, SECURITY_DIRECTION_UPLINK, &msg->msg[0], 2, &mac[0]);
// Set the short MAC // Set the short MAC
msg->msg[2] = mac[2]; msg->msg[2] = mac[2];
msg->N_bytes++; msg->N_bytes++;
@ -1645,8 +1654,8 @@ void nas::gen_service_request(srsran::unique_byte_buffer_t& msg)
if (pcap != nullptr) { if (pcap != nullptr) {
pcap->write_nas(msg->msg, msg->N_bytes); pcap->write_nas(msg->msg, msg->N_bytes);
} }
set_k_enb_count(ctxt.tx_count); set_k_enb_count(ctxt_base.tx_count);
ctxt.tx_count++; ctxt_base.tx_count++;
} }
void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT* msg) void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT* msg)
@ -1750,8 +1759,10 @@ void nas::send_detach_request(bool switch_off)
detach_request.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; detach_request.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE;
detach_request.nas_ksi.nas_ksi = ctxt.ksi; detach_request.nas_ksi.nas_ksi = ctxt.ksi;
logger.info("Sending detach request with GUTI"); // If sent as an Initial UE message, it cannot be ciphered logger.info("Sending detach request with GUTI"); // If sent as an Initial UE message, it cannot be ciphered
liblte_mme_pack_detach_request_msg( liblte_mme_pack_detach_request_msg(&detach_request,
&detach_request, LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()); LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY,
ctxt_base.tx_count,
(LIBLTE_BYTE_MSG_STRUCT*)pdu.get());
if (pcap != nullptr) { if (pcap != nullptr) {
pcap->write_nas(pdu->msg, pdu->N_bytes); pcap->write_nas(pdu->msg, pdu->N_bytes);
@ -1768,7 +1779,7 @@ void nas::send_detach_request(bool switch_off)
usim->get_imsi_vec(detach_request.eps_mobile_id.imsi, 15); usim->get_imsi_vec(detach_request.eps_mobile_id.imsi, 15);
logger.info("Sending detach request with IMSI"); logger.info("Sending detach request with IMSI");
liblte_mme_pack_detach_request_msg( liblte_mme_pack_detach_request_msg(
&detach_request, current_sec_hdr, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()); &detach_request, current_sec_hdr, ctxt_base.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get());
if (pcap != nullptr) { if (pcap != nullptr) {
pcap->write_nas(pdu->msg, pdu->N_bytes); pcap->write_nas(pdu->msg, pdu->N_bytes);
@ -1794,7 +1805,7 @@ void nas::send_detach_request(bool switch_off)
} }
} }
ctxt.tx_count++; ctxt_base.tx_count++;
} }
void nas::send_attach_complete(const uint8_t& transaction_id_, const uint8_t& eps_bearer_id) void nas::send_attach_complete(const uint8_t& transaction_id_, const uint8_t& eps_bearer_id)
@ -1815,7 +1826,7 @@ void nas::send_attach_complete(const uint8_t& transaction_id_, const uint8_t& ep
return; return;
} }
liblte_mme_pack_attach_complete_msg( liblte_mme_pack_attach_complete_msg(
&attach_complete, current_sec_hdr, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()); &attach_complete, current_sec_hdr, ctxt_base.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get());
// Write NAS pcap // Write NAS pcap
if (pcap != nullptr) { if (pcap != nullptr) {
pcap->write_nas(pdu->msg, pdu->N_bytes); pcap->write_nas(pdu->msg, pdu->N_bytes);
@ -1831,7 +1842,7 @@ void nas::send_attach_complete(const uint8_t& transaction_id_, const uint8_t& ep
logger.info("Sending Attach Complete"); logger.info("Sending Attach Complete");
rrc->write_sdu(std::move(pdu)); rrc->write_sdu(std::move(pdu));
ctxt.tx_count++; ctxt_base.tx_count++;
} }
void nas::send_detach_accept() void nas::send_detach_accept()
@ -1844,7 +1855,8 @@ void nas::send_detach_accept()
LIBLTE_MME_DETACH_ACCEPT_MSG_STRUCT detach_accept; LIBLTE_MME_DETACH_ACCEPT_MSG_STRUCT detach_accept;
bzero(&detach_accept, sizeof(detach_accept)); bzero(&detach_accept, sizeof(detach_accept));
liblte_mme_pack_detach_accept_msg(&detach_accept, current_sec_hdr, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()); liblte_mme_pack_detach_accept_msg(
&detach_accept, current_sec_hdr, ctxt_base.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get());
if (pcap != nullptr) { if (pcap != nullptr) {
pcap->write_nas(pdu->msg, pdu->N_bytes); pcap->write_nas(pdu->msg, pdu->N_bytes);
@ -1874,7 +1886,7 @@ void nas::send_authentication_response(const uint8_t* res, const size_t res_len)
} }
auth_res.res_len = res_len; auth_res.res_len = res_len;
liblte_mme_pack_authentication_response_msg( liblte_mme_pack_authentication_response_msg(
&auth_res, current_sec_hdr, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()); &auth_res, current_sec_hdr, ctxt_base.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get());
if (pcap != nullptr) { if (pcap != nullptr) {
pcap->write_nas(pdu->msg, pdu->N_bytes); pcap->write_nas(pdu->msg, pdu->N_bytes);
@ -1887,7 +1899,7 @@ void nas::send_authentication_response(const uint8_t* res, const size_t res_len)
logger.info("Sending Authentication Response"); logger.info("Sending Authentication Response");
rrc->write_sdu(std::move(pdu)); rrc->write_sdu(std::move(pdu));
ctxt.tx_count++; ctxt_base.tx_count++;
} }
void nas::send_authentication_failure(const uint8_t cause, const uint8_t* auth_fail_param) void nas::send_authentication_failure(const uint8_t cause, const uint8_t* auth_fail_param)
@ -1946,7 +1958,8 @@ void nas::send_identity_response(const uint8 id_type)
return; return;
} }
liblte_mme_pack_identity_response_msg(&id_resp, current_sec_hdr, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()); liblte_mme_pack_identity_response_msg(
&id_resp, current_sec_hdr, ctxt_base.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get());
// add security if needed // add security if needed
if (apply_security_config(pdu, current_sec_hdr)) { if (apply_security_config(pdu, current_sec_hdr)) {
@ -1959,7 +1972,7 @@ void nas::send_identity_response(const uint8 id_type)
} }
rrc->write_sdu(std::move(pdu)); rrc->write_sdu(std::move(pdu));
ctxt.tx_count++; ctxt_base.tx_count++;
} }
void nas::send_service_request() void nas::send_service_request()
@ -1974,11 +1987,11 @@ void nas::send_service_request()
msg->msg[0] = (LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST << 4u) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT); msg->msg[0] = (LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST << 4u) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
msg->N_bytes++; msg->N_bytes++;
msg->msg[1] = (ctxt.ksi & 0x07u) << 5u; msg->msg[1] = (ctxt.ksi & 0x07u) << 5u;
msg->msg[1] |= ctxt.tx_count & 0x1Fu; msg->msg[1] |= ctxt_base.tx_count & 0x1Fu;
msg->N_bytes++; msg->N_bytes++;
uint8_t mac[4]; uint8_t mac[4];
integrity_generate(&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &msg->msg[0], 2, &mac[0]); integrity_generate(&ctxt_base.k_nas_int[16], ctxt_base.tx_count, SECURITY_DIRECTION_UPLINK, &msg->msg[0], 2, &mac[0]);
// Set the short MAC // Set the short MAC
msg->msg[2] = mac[2]; msg->msg[2] = mac[2];
msg->N_bytes++; msg->N_bytes++;
@ -1991,7 +2004,7 @@ void nas::send_service_request()
logger.info("Sending service request"); logger.info("Sending service request");
rrc->write_sdu(std::move(msg)); rrc->write_sdu(std::move(msg));
ctxt.tx_count++; ctxt_base.tx_count++;
} }
void nas::send_esm_information_response(const uint8 proc_transaction_id) void nas::send_esm_information_response(const uint8 proc_transaction_id)
@ -2091,7 +2104,7 @@ void nas::send_esm_information_response(const uint8 proc_transaction_id)
} }
if (liblte_mme_pack_esm_information_response_msg( if (liblte_mme_pack_esm_information_response_msg(
&esm_info_resp, current_sec_hdr, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()) != LIBLTE_SUCCESS) { &esm_info_resp, current_sec_hdr, ctxt_base.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()) != LIBLTE_SUCCESS) {
logger.error("Error packing ESM information response."); logger.error("Error packing ESM information response.");
return; return;
} }
@ -2108,7 +2121,7 @@ void nas::send_esm_information_response(const uint8 proc_transaction_id)
logger.info(pdu->msg, pdu->N_bytes, "Sending ESM information response"); logger.info(pdu->msg, pdu->N_bytes, "Sending ESM information response");
rrc->write_sdu(std::move(pdu)); rrc->write_sdu(std::move(pdu));
ctxt.tx_count++; ctxt_base.tx_count++;
chap_id++; chap_id++;
} }
@ -2127,7 +2140,7 @@ void nas::send_activate_dedicated_eps_bearer_context_accept(const uint8_t& proc_
accept.proc_transaction_id = proc_transaction_id; accept.proc_transaction_id = proc_transaction_id;
if (liblte_mme_pack_activate_dedicated_eps_bearer_context_accept_msg( if (liblte_mme_pack_activate_dedicated_eps_bearer_context_accept_msg(
&accept, current_sec_hdr, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()) != LIBLTE_SUCCESS) { &accept, current_sec_hdr, ctxt_base.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()) != LIBLTE_SUCCESS) {
logger.error("Error packing Activate Dedicated EPS Bearer context accept."); logger.error("Error packing Activate Dedicated EPS Bearer context accept.");
return; return;
} }
@ -2148,7 +2161,7 @@ void nas::send_activate_dedicated_eps_bearer_context_accept(const uint8_t& proc_
accept.proc_transaction_id); accept.proc_transaction_id);
rrc->write_sdu(std::move(pdu)); rrc->write_sdu(std::move(pdu));
ctxt.tx_count++; ctxt_base.tx_count++;
} }
void nas::send_deactivate_eps_bearer_context_accept(const uint8_t& proc_transaction_id, const uint8_t& eps_bearer_id) void nas::send_deactivate_eps_bearer_context_accept(const uint8_t& proc_transaction_id, const uint8_t& eps_bearer_id)
@ -2165,7 +2178,7 @@ void nas::send_deactivate_eps_bearer_context_accept(const uint8_t& proc_transact
accept.proc_transaction_id = proc_transaction_id; accept.proc_transaction_id = proc_transaction_id;
if (liblte_mme_pack_deactivate_eps_bearer_context_accept_msg( if (liblte_mme_pack_deactivate_eps_bearer_context_accept_msg(
&accept, current_sec_hdr, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()) != LIBLTE_SUCCESS) { &accept, current_sec_hdr, ctxt_base.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()) != LIBLTE_SUCCESS) {
logger.error("Error packing Activate EPS Bearer context accept."); logger.error("Error packing Activate EPS Bearer context accept.");
return; return;
} }
@ -2186,7 +2199,7 @@ void nas::send_deactivate_eps_bearer_context_accept(const uint8_t& proc_transact
accept.proc_transaction_id); accept.proc_transaction_id);
rrc->write_sdu(std::move(pdu)); rrc->write_sdu(std::move(pdu));
ctxt.tx_count++; ctxt_base.tx_count++;
} }
void nas::send_modify_eps_bearer_context_accept(const uint8_t& proc_transaction_id, const uint8_t& eps_bearer_id) void nas::send_modify_eps_bearer_context_accept(const uint8_t& proc_transaction_id, const uint8_t& eps_bearer_id)
@ -2203,7 +2216,7 @@ void nas::send_modify_eps_bearer_context_accept(const uint8_t& proc_transaction_
accept.proc_transaction_id = proc_transaction_id; accept.proc_transaction_id = proc_transaction_id;
if (liblte_mme_pack_modify_eps_bearer_context_accept_msg( if (liblte_mme_pack_modify_eps_bearer_context_accept_msg(
&accept, current_sec_hdr, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()) != LIBLTE_SUCCESS) { &accept, current_sec_hdr, ctxt_base.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()) != LIBLTE_SUCCESS) {
logger.error("Error packing Modify EPS Bearer context accept."); logger.error("Error packing Modify EPS Bearer context accept.");
return; return;
} }
@ -2224,7 +2237,7 @@ void nas::send_modify_eps_bearer_context_accept(const uint8_t& proc_transaction_
accept.proc_transaction_id); accept.proc_transaction_id);
rrc->write_sdu(std::move(pdu)); rrc->write_sdu(std::move(pdu));
ctxt.tx_count++; ctxt_base.tx_count++;
} }
void nas::send_activate_test_mode_complete() void nas::send_activate_test_mode_complete()
@ -2236,7 +2249,7 @@ void nas::send_activate_test_mode_complete()
} }
if (liblte_mme_pack_activate_test_mode_complete_msg( if (liblte_mme_pack_activate_test_mode_complete_msg(
(LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), current_sec_hdr, ctxt.tx_count)) { (LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), current_sec_hdr, ctxt_base.tx_count)) {
logger.error("Error packing activate test mode complete."); logger.error("Error packing activate test mode complete.");
return; return;
} }
@ -2253,7 +2266,7 @@ void nas::send_activate_test_mode_complete()
logger.info(pdu->msg, pdu->N_bytes, "Sending Activate test mode complete"); logger.info(pdu->msg, pdu->N_bytes, "Sending Activate test mode complete");
rrc->write_sdu(std::move(pdu)); rrc->write_sdu(std::move(pdu));
ctxt.tx_count++; ctxt_base.tx_count++;
} }
void nas::send_close_ue_test_loop_complete() void nas::send_close_ue_test_loop_complete()
@ -2265,7 +2278,7 @@ void nas::send_close_ue_test_loop_complete()
} }
if (liblte_mme_pack_close_ue_test_loop_complete_msg( if (liblte_mme_pack_close_ue_test_loop_complete_msg(
(LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), current_sec_hdr, ctxt.tx_count)) { (LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), current_sec_hdr, ctxt_base.tx_count)) {
logger.error("Error packing close UE test loop complete."); logger.error("Error packing close UE test loop complete.");
return; return;
} }
@ -2282,17 +2295,17 @@ void nas::send_close_ue_test_loop_complete()
logger.info(pdu->msg, pdu->N_bytes, "Sending Close UE test loop complete"); logger.info(pdu->msg, pdu->N_bytes, "Sending Close UE test loop complete");
rrc->write_sdu(std::move(pdu)); rrc->write_sdu(std::move(pdu));
ctxt.tx_count++; ctxt_base.tx_count++;
} }
/******************************************************************************* /*******************************************************************************
* Security context persistence file * Security context persistence file
******************************************************************************/ ******************************************************************************/
bool nas::read_ctxt_file(nas_sec_ctxt* ctxt_) bool nas::read_ctxt_file(nas_sec_ctxt* ctxt_, nas_sec_base_ctxt* ctxt_base_)
{ {
std::ifstream file; std::ifstream file;
if (ctxt_ == nullptr) { if (ctxt_ == nullptr || ctxt_base_ == nullptr) {
return false; return false;
} }
@ -2318,16 +2331,16 @@ bool nas::read_ctxt_file(nas_sec_ctxt* ctxt_)
if (!readvar(file, "mme_code=", &ctxt_->guti.mme_code)) { if (!readvar(file, "mme_code=", &ctxt_->guti.mme_code)) {
return false; return false;
} }
if (!readvar(file, "tx_count=", &ctxt_->tx_count)) { if (!readvar(file, "tx_count=", &ctxt_base_->tx_count)) {
return false; return false;
} }
if (!readvar(file, "rx_count=", &ctxt_->rx_count)) { if (!readvar(file, "rx_count=", &ctxt_base_->rx_count)) {
return false; return false;
} }
if (!readvar(file, "int_alg=", &ctxt_->integ_algo)) { if (!readvar(file, "int_alg=", &ctxt_base_->integ_algo)) {
return false; return false;
} }
if (!readvar(file, "enc_alg=", &ctxt_->cipher_algo)) { if (!readvar(file, "enc_alg=", &ctxt_base_->cipher_algo)) {
return false; return false;
} }
if (!readvar(file, "ksi=", &ctxt_->ksi)) { if (!readvar(file, "ksi=", &ctxt_->ksi)) {
@ -2350,10 +2363,10 @@ bool nas::read_ctxt_file(nas_sec_ctxt* ctxt_)
"ksi: %x, k_asme: %s, tx_count: %x, rx_count: %x, int_alg: %d, enc_alg: %d", "ksi: %x, k_asme: %s, tx_count: %x, rx_count: %x, int_alg: %d, enc_alg: %d",
ctxt_->ksi, ctxt_->ksi,
hex_to_string(ctxt_->k_asme, 32).c_str(), hex_to_string(ctxt_->k_asme, 32).c_str(),
ctxt_->tx_count, ctxt_base_->tx_count,
ctxt_->rx_count, ctxt_base_->rx_count,
ctxt_->integ_algo, ctxt_base_->integ_algo,
ctxt_->cipher_algo); ctxt_base_->cipher_algo);
have_guti = true; have_guti = true;
have_ctxt = true; have_ctxt = true;
@ -2369,7 +2382,7 @@ bool nas::read_ctxt_file(nas_sec_ctxt* ctxt_)
return false; return false;
} }
bool nas::write_ctxt_file(nas_sec_ctxt ctxt_) bool nas::write_ctxt_file(nas_sec_ctxt ctxt_, nas_sec_base_ctxt ctxt_base_)
{ {
if (!have_guti || !have_ctxt) { if (!have_guti || !have_ctxt) {
return false; return false;
@ -2382,10 +2395,10 @@ bool nas::write_ctxt_file(nas_sec_ctxt ctxt_)
file << "mnc=" << (int)ctxt_.guti.mnc << std::endl; file << "mnc=" << (int)ctxt_.guti.mnc << std::endl;
file << "mme_group_id=" << (int)ctxt_.guti.mme_group_id << std::endl; file << "mme_group_id=" << (int)ctxt_.guti.mme_group_id << std::endl;
file << "mme_code=" << (int)ctxt_.guti.mme_code << std::endl; file << "mme_code=" << (int)ctxt_.guti.mme_code << std::endl;
file << "tx_count=" << (int)ctxt_.tx_count << std::endl; file << "tx_count=" << (int)ctxt_base_.tx_count << std::endl;
file << "rx_count=" << (int)ctxt_.rx_count << std::endl; file << "rx_count=" << (int)ctxt_base_.rx_count << std::endl;
file << "int_alg=" << (int)ctxt_.integ_algo << std::endl; file << "int_alg=" << (int)ctxt_base_.integ_algo << std::endl;
file << "enc_alg=" << (int)ctxt_.cipher_algo << std::endl; file << "enc_alg=" << (int)ctxt_base_.cipher_algo << std::endl;
file << "ksi=" << (int)ctxt_.ksi << std::endl; file << "ksi=" << (int)ctxt_.ksi << std::endl;
file << "k_asme=" << hex_to_string(ctxt_.k_asme, 32) << std::endl; file << "k_asme=" << hex_to_string(ctxt_.k_asme, 32) << std::endl;
@ -2401,10 +2414,10 @@ bool nas::write_ctxt_file(nas_sec_ctxt ctxt_)
"ksi: %x, k_asme: %s, tx_count: %x, rx_count: %x, int_alg: %d, enc_alg: %d", "ksi: %x, k_asme: %s, tx_count: %x, rx_count: %x, int_alg: %d, enc_alg: %d",
ctxt_.ksi, ctxt_.ksi,
hex_to_string(ctxt_.k_asme, 32).c_str(), hex_to_string(ctxt_.k_asme, 32).c_str(),
ctxt_.tx_count, ctxt_base_.tx_count,
ctxt_.rx_count, ctxt_base_.rx_count,
ctxt_.integ_algo, ctxt_base_.integ_algo,
ctxt_.cipher_algo); ctxt_base_.cipher_algo);
file.close(); file.close();
return true; return true;
} }

@ -428,7 +428,7 @@ int nas_5g::send_security_mode_complete(const srsran::nas_5g::security_mode_comm
nas_msg.hdr.security_header_type = nas_msg.hdr.security_header_type =
nas_5gs_hdr::security_header_type_opts::integrity_protected_and_ciphered_with_new_5G_nas_context; nas_5gs_hdr::security_header_type_opts::integrity_protected_and_ciphered_with_new_5G_nas_context;
nas_msg.hdr.sequence_number = ctxt.tx_count; nas_msg.hdr.sequence_number = ctxt_base.tx_count;
if (nas_msg.pack(pdu) != SRSASN_SUCCESS) { if (nas_msg.pack(pdu) != SRSASN_SUCCESS) {
logger.error("Failed to pack security mode complete"); logger.error("Failed to pack security mode complete");
@ -436,8 +436,8 @@ int nas_5g::send_security_mode_complete(const srsran::nas_5g::security_mode_comm
} }
cipher_encrypt(pdu.get()); cipher_encrypt(pdu.get());
integrity_generate(&k_nas_int[16], integrity_generate(&ctxt_base.k_nas_int[16],
ctxt.tx_count, ctxt_base.tx_count,
SECURITY_DIRECTION_UPLINK, SECURITY_DIRECTION_UPLINK,
&pdu->msg[SEQ_5G_OFFSET], &pdu->msg[SEQ_5G_OFFSET],
pdu->N_bytes - SEQ_5G_OFFSET, pdu->N_bytes - SEQ_5G_OFFSET,
@ -449,7 +449,7 @@ int nas_5g::send_security_mode_complete(const srsran::nas_5g::security_mode_comm
logger.info("Sending Security Mode Complete"); logger.info("Sending Security Mode Complete");
rrc_nr->write_sdu(std::move(pdu)); rrc_nr->write_sdu(std::move(pdu));
ctxt.tx_count++; ctxt_base.tx_count++;
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }
@ -545,7 +545,7 @@ int nas_5g::send_pdu_session_establishment_request(uint32_t tran
env_nas_msg.hdr.security_header_type = nas_5gs_hdr::security_header_type_opts::integrity_protected_and_ciphered; env_nas_msg.hdr.security_header_type = nas_5gs_hdr::security_header_type_opts::integrity_protected_and_ciphered;
// TODO move that seq number setting to the security part // TODO move that seq number setting to the security part
env_nas_msg.hdr.sequence_number = ctxt.tx_count; env_nas_msg.hdr.sequence_number = ctxt_base.tx_count;
ul_nas_transport_t& ul_nas_msg = env_nas_msg.set_ul_nas_transport(); ul_nas_transport_t& ul_nas_msg = env_nas_msg.set_ul_nas_transport();
ul_nas_msg.payload_container_type.payload_container_type.value = ul_nas_msg.payload_container_type.payload_container_type.value =
@ -583,8 +583,8 @@ int nas_5g::send_pdu_session_establishment_request(uint32_t tran
} }
cipher_encrypt(pdu.get()); cipher_encrypt(pdu.get());
integrity_generate(&k_nas_int[16], integrity_generate(&ctxt_base.k_nas_int[16],
ctxt.tx_count, ctxt_base.tx_count,
SECURITY_DIRECTION_UPLINK, SECURITY_DIRECTION_UPLINK,
&pdu->msg[SEQ_5G_OFFSET], &pdu->msg[SEQ_5G_OFFSET],
pdu->N_bytes - SEQ_5G_OFFSET, pdu->N_bytes - SEQ_5G_OFFSET,
@ -853,10 +853,11 @@ int nas_5g::handle_security_mode_command(security_mode_command_t& security_m
srsran::unique_byte_buffer_t pdu) srsran::unique_byte_buffer_t pdu)
{ {
logger.info("Handling Security Mode Command"); logger.info("Handling Security Mode Command");
ctxt.cipher_algo = ctxt_base.cipher_algo =
(CIPHERING_ALGORITHM_ID_ENUM)security_mode_command.selected_nas_security_algorithms.ciphering_algorithm.value; (CIPHERING_ALGORITHM_ID_ENUM)security_mode_command.selected_nas_security_algorithms.ciphering_algorithm.value;
ctxt.integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) ctxt_base.integ_algo =
security_mode_command.selected_nas_security_algorithms.integrity_protection_algorithm.value; (INTEGRITY_ALGORITHM_ID_ENUM)
security_mode_command.selected_nas_security_algorithms.integrity_protection_algorithm.value;
// Check replayed ue security capabilities // Check replayed ue security capabilities
if (!check_replayed_ue_security_capabilities(security_mode_command.replayed_ue_security_capabilities)) { if (!check_replayed_ue_security_capabilities(security_mode_command.replayed_ue_security_capabilities)) {
@ -868,20 +869,21 @@ int nas_5g::handle_security_mode_command(security_mode_command_t& security_m
initial_sec_command = false; // TODO initial_sec_command = false; // TODO
if (initial_sec_command) { if (initial_sec_command) {
ctxt.rx_count = 0; ctxt_base.rx_count = 0;
ctxt.tx_count = 0; ctxt_base.tx_count = 0;
initial_sec_command = false; initial_sec_command = false;
} }
// Generate NAS keys // Generate NAS keys
logger.debug(ctxt_5g.k_amf, 32, "K AMF"); logger.debug(ctxt_5g.k_amf, 32, "K AMF");
logger.debug("cipher_algo %d, integ_algo %d", ctxt.cipher_algo, ctxt.integ_algo); logger.debug("cipher_algo %d, integ_algo %d", ctxt_base.cipher_algo, ctxt_base.integ_algo);
usim->generate_nas_keys_5g(ctxt_5g.k_amf, k_nas_enc, k_nas_int, ctxt.cipher_algo, ctxt.integ_algo); usim->generate_nas_keys_5g(
logger.info(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); ctxt_5g.k_amf, ctxt_base.k_nas_enc, ctxt_base.k_nas_int, ctxt_base.cipher_algo, ctxt_base.integ_algo);
logger.info(k_nas_int, 32, "NAS integrity key - k_nas_int"); logger.info(ctxt_base.k_nas_enc, 32, "NAS encryption key - k_nas_enc");
logger.info(ctxt_base.k_nas_int, 32, "NAS integrity key - k_nas_int");
logger.debug("Generating integrity check. integ_algo:%d, count_dl:%d", ctxt.integ_algo, ctxt.rx_count); logger.debug("Generating integrity check. integ_algo:%d, count_dl:%d", ctxt_base.integ_algo, ctxt_base.rx_count);
if (not integrity_check(pdu.get())) { if (not integrity_check(pdu.get())) {
logger.warning("Sending Security Mode Reject due to integrity check failure"); logger.warning("Sending Security Mode Reject due to integrity check failure");
@ -890,7 +892,7 @@ int nas_5g::handle_security_mode_command(security_mode_command_t& security_m
} }
send_security_mode_complete(security_mode_command); send_security_mode_complete(security_mode_command);
ctxt.rx_count++; ctxt_base.rx_count++;
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }

@ -49,7 +49,7 @@ void nas_base::integrity_generate(uint8_t* key_128,
uint32_t msg_len, uint32_t msg_len,
uint8_t* mac) uint8_t* mac)
{ {
switch (ctxt.integ_algo) { switch (ctxt_base.integ_algo) {
case INTEGRITY_ALGORITHM_ID_EIA0: case INTEGRITY_ALGORITHM_ID_EIA0:
break; break;
case INTEGRITY_ALGORITHM_ID_128_EIA1: case INTEGRITY_ALGORITHM_ID_128_EIA1:
@ -80,8 +80,8 @@ bool nas_base::integrity_check(byte_buffer_t* pdu)
uint8_t* mac = &pdu->msg[mac_offset]; uint8_t* mac = &pdu->msg[mac_offset];
// generate expected MAC // generate expected MAC
uint32_t count_est = (ctxt.rx_count & 0x00FFFF00u) | pdu->msg[seq_offset]; uint32_t count_est = (ctxt_base.rx_count & 0x00FFFF00u) | pdu->msg[seq_offset];
integrity_generate(&k_nas_int[16], integrity_generate(&ctxt_base.k_nas_int[16],
count_est, count_est,
SECURITY_DIRECTION_DOWNLINK, SECURITY_DIRECTION_DOWNLINK,
&pdu->msg[seq_offset], &pdu->msg[seq_offset],
@ -115,9 +115,9 @@ bool nas_base::integrity_check(byte_buffer_t* pdu)
mac[3]); mac[3]);
// Updated local count (according to TS 24.301 Sec. 4.4.3.3) // Updated local count (according to TS 24.301 Sec. 4.4.3.3)
if (count_est != ctxt.rx_count) { if (count_est != ctxt_base.rx_count) {
logger.info("Update local count to estimated count %d", count_est); logger.info("Update local count to estimated count %d", count_est);
ctxt.rx_count = count_est; ctxt_base.rx_count = count_est;
} }
return true; return true;
} else { } else {
@ -130,16 +130,16 @@ void nas_base::cipher_encrypt(byte_buffer_t* pdu)
{ {
byte_buffer_t pdu_tmp; byte_buffer_t pdu_tmp;
if (ctxt.cipher_algo != CIPHERING_ALGORITHM_ID_EEA0) { if (ctxt_base.cipher_algo != CIPHERING_ALGORITHM_ID_EEA0) {
logger.debug("Encrypting PDU. count=%d", ctxt.tx_count); logger.debug("Encrypting PDU. count=%d", ctxt_base.tx_count);
} }
switch (ctxt.cipher_algo) { switch (ctxt_base.cipher_algo) {
case CIPHERING_ALGORITHM_ID_EEA0: case CIPHERING_ALGORITHM_ID_EEA0:
break; break;
case CIPHERING_ALGORITHM_ID_128_EEA1: case CIPHERING_ALGORITHM_ID_128_EEA1:
security_128_eea1(&k_nas_enc[16], security_128_eea1(&ctxt_base.k_nas_enc[16],
ctxt.tx_count, ctxt_base.tx_count,
bearer_id, bearer_id,
SECURITY_DIRECTION_UPLINK, SECURITY_DIRECTION_UPLINK,
&pdu->msg[seq_offset + 1], &pdu->msg[seq_offset + 1],
@ -148,8 +148,8 @@ void nas_base::cipher_encrypt(byte_buffer_t* pdu)
memcpy(&pdu->msg[seq_offset + 1], &pdu_tmp.msg[seq_offset + 1], pdu->N_bytes - seq_offset + 1); memcpy(&pdu->msg[seq_offset + 1], &pdu_tmp.msg[seq_offset + 1], pdu->N_bytes - seq_offset + 1);
break; break;
case CIPHERING_ALGORITHM_ID_128_EEA2: case CIPHERING_ALGORITHM_ID_128_EEA2:
security_128_eea2(&k_nas_enc[16], security_128_eea2(&ctxt_base.k_nas_enc[16],
ctxt.tx_count, ctxt_base.tx_count,
bearer_id, bearer_id,
SECURITY_DIRECTION_UPLINK, SECURITY_DIRECTION_UPLINK,
&pdu->msg[seq_offset + 1], &pdu->msg[seq_offset + 1],
@ -158,8 +158,8 @@ void nas_base::cipher_encrypt(byte_buffer_t* pdu)
memcpy(&pdu->msg[seq_offset + 1], &pdu_tmp.msg[seq_offset + 1], pdu->N_bytes - seq_offset + 1); memcpy(&pdu->msg[seq_offset + 1], &pdu_tmp.msg[seq_offset + 1], pdu->N_bytes - seq_offset + 1);
break; break;
case CIPHERING_ALGORITHM_ID_128_EEA3: case CIPHERING_ALGORITHM_ID_128_EEA3:
security_128_eea3(&k_nas_enc[16], security_128_eea3(&ctxt_base.k_nas_enc[16],
ctxt.tx_count, ctxt_base.tx_count,
bearer_id, bearer_id,
SECURITY_DIRECTION_UPLINK, SECURITY_DIRECTION_UPLINK,
&pdu->msg[seq_offset + 1], &pdu->msg[seq_offset + 1],
@ -177,16 +177,16 @@ void nas_base::cipher_decrypt(byte_buffer_t* pdu)
{ {
byte_buffer_t tmp_pdu; byte_buffer_t tmp_pdu;
uint32_t count_est = (ctxt.rx_count & 0x00FFFF00u) | pdu->msg[5]; uint32_t count_est = (ctxt_base.rx_count & 0x00FFFF00u) | pdu->msg[5];
if (ctxt.cipher_algo != CIPHERING_ALGORITHM_ID_EEA0) { if (ctxt_base.cipher_algo != CIPHERING_ALGORITHM_ID_EEA0) {
logger.debug("Decrypting PDU. Local: count=%d, Received: count=%d", ctxt.rx_count, count_est); logger.debug("Decrypting PDU. Local: count=%d, Received: count=%d", ctxt_base.rx_count, count_est);
} }
switch (ctxt.cipher_algo) { switch (ctxt_base.cipher_algo) {
case CIPHERING_ALGORITHM_ID_EEA0: case CIPHERING_ALGORITHM_ID_EEA0:
break; break;
case CIPHERING_ALGORITHM_ID_128_EEA1: case CIPHERING_ALGORITHM_ID_128_EEA1:
security_128_eea1(&k_nas_enc[16], security_128_eea1(&ctxt_base.k_nas_enc[16],
count_est, count_est,
bearer_id, bearer_id,
SECURITY_DIRECTION_DOWNLINK, SECURITY_DIRECTION_DOWNLINK,
@ -196,7 +196,7 @@ void nas_base::cipher_decrypt(byte_buffer_t* pdu)
memcpy(&pdu->msg[seq_offset + 1], &tmp_pdu.msg[seq_offset + 1], pdu->N_bytes - seq_offset + 1); memcpy(&pdu->msg[seq_offset + 1], &tmp_pdu.msg[seq_offset + 1], pdu->N_bytes - seq_offset + 1);
break; break;
case CIPHERING_ALGORITHM_ID_128_EEA2: case CIPHERING_ALGORITHM_ID_128_EEA2:
security_128_eea2(&k_nas_enc[16], security_128_eea2(&ctxt_base.k_nas_enc[16],
count_est, count_est,
bearer_id, bearer_id,
SECURITY_DIRECTION_DOWNLINK, SECURITY_DIRECTION_DOWNLINK,
@ -207,7 +207,7 @@ void nas_base::cipher_decrypt(byte_buffer_t* pdu)
memcpy(&pdu->msg[seq_offset + 1], &tmp_pdu.msg[seq_offset + 1], pdu->N_bytes - seq_offset + 1); memcpy(&pdu->msg[seq_offset + 1], &tmp_pdu.msg[seq_offset + 1], pdu->N_bytes - seq_offset + 1);
break; break;
case CIPHERING_ALGORITHM_ID_128_EEA3: case CIPHERING_ALGORITHM_ID_128_EEA3:
security_128_eea3(&k_nas_enc[16], security_128_eea3(&ctxt_base.k_nas_enc[16],
count_est, count_est,
bearer_id, bearer_id,
SECURITY_DIRECTION_DOWNLINK, SECURITY_DIRECTION_DOWNLINK,

Loading…
Cancel
Save