diff --git a/srsue/hdr/stack/upper/nas.h b/srsue/hdr/stack/upper/nas.h index 010e5978f..3832c0259 100644 --- a/srsue/hdr/stack/upper/nas.h +++ b/srsue/hdr/stack/upper/nas.h @@ -222,8 +222,8 @@ private: void enter_emm_deregistered_initiated(); // security context persistence file - bool read_ctxt_file(nas_sec_ctxt* ctxt); - bool write_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_, nas_sec_base_ctxt ctxt_base_); // ctxt file helpers std::string hex_to_string(uint8_t* hex, int size); diff --git a/srsue/hdr/stack/upper/nas_base.h b/srsue/hdr/stack/upper/nas_base.h index 00b719548..5bcc61c03 100644 --- a/srsue/hdr/stack/upper/nas_base.h +++ b/srsue/hdr/stack/upper/nas_base.h @@ -38,28 +38,33 @@ protected: srsran::nas_pcap* pcap = nullptr; // 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 { uint8_t ksi; uint8_t k_asme[32]; - uint32_t tx_count; - uint32_t rx_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; }; + // Only applies for 5G struct nas_5g_sec_ctxt { uint8_t ksi; uint8_t k_amf[32]; - uint32_t tx_count; - uint32_t rx_count; }; - nas_sec_ctxt ctxt = {}; - nas_5g_sec_ctxt ctxt_5g = {}; - uint8_t k_nas_enc[32] = {}; - uint8_t k_nas_int[32] = {}; + nas_sec_base_ctxt ctxt_base = {}; + nas_sec_ctxt ctxt = {}; + nas_5g_sec_ctxt ctxt_5g = {}; int parse_security_algorithm_list(std::string algorithm_string, bool* algorithm_caps); diff --git a/srsue/src/stack/upper/nas.cc b/srsue/src/stack/upper/nas.cc index 934da0441..7f6bb8983 100644 --- a/srsue/src/stack/upper/nas.cc +++ b/srsue/src/stack/upper/nas.cc @@ -81,10 +81,11 @@ int nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_n cfg = cfg_; - if ((read_ctxt_file(&ctxt))) { - usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, ctxt.cipher_algo, ctxt.integ_algo); - logger.debug(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); - logger.debug(k_nas_int, 32, "NAS integrity key - k_nas_int"); + if ((read_ctxt_file(&ctxt, &ctxt_base))) { + usim->generate_nas_keys( + ctxt.k_asme, ctxt_base.k_nas_enc, ctxt_base.k_nas_int, ctxt_base.cipher_algo, ctxt_base.integ_algo); + 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 @@ -108,7 +109,7 @@ nas::~nas() {} void nas::stop() { running = false; - write_ctxt_file(ctxt); + write_ctxt_file(ctxt, ctxt_base); } 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()); } if (sec_hdr_type >= LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) { - integrity_generate( - &k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]); + integrity_generate(&ctxt_base.k_nas_int[16], + ctxt_base.tx_count, + SECURITY_DIRECTION_UPLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + &pdu->msg[1]); } } else { 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); } - ctxt.rx_count++; + ctxt_base.rx_count++; } 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"); 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 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); 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) 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 if (auth_request) { - ctxt.rx_count = 0; - ctxt.tx_count = 0; + ctxt_base.rx_count = 0; + ctxt_base.tx_count = 0; auth_request = false; } - ctxt.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.cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM)sec_mode_cmd.selected_nas_sec_algs.type_of_eea; + ctxt_base.integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM)sec_mode_cmd.selected_nas_sec_algs.type_of_eia; // 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"); send_security_mode_reject(LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH); return; } // Generate NAS keys - usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, ctxt.cipher_algo, ctxt.integ_algo); - logger.info(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); - logger.info(k_nas_int, 32, "NAS integrity key - k_nas_int"); + usim->generate_nas_keys( + ctxt.k_asme, ctxt_base.k_nas_enc, ctxt_base.k_nas_int, ctxt_base.cipher_algo, ctxt_base.integ_algo); + 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())) { 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; } - ctxt.rx_count++; + ctxt_base.rx_count++; 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) { @@ -1226,7 +1235,7 @@ void nas::parse_security_mode_command(uint32_t lcid, unique_byte_buffer_t pdu) // Pack and send response pdu->clear(); 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) { 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( - "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)); - ctxt.tx_count++; + ctxt_base.tx_count++; // switch security header for all following messages 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", esm_info_req.eps_bearer_id, esm_info_req.proc_transaction_id); - ctxt.rx_count++; + ctxt_base.rx_count++; // send response 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); logger.info("Received EMM Information: %s", 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) { LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT 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", 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.proc_transaction_id); - ctxt.rx_count++; + ctxt_base.rx_count++; 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", 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.esm_cause); - ctxt.rx_count++; + ctxt_base.rx_count++; // check if bearer exists 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.proc_transaction_id); - ctxt.rx_count++; + ctxt_base.rx_count++; // check if bearer exists 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"); - ctxt.rx_count++; + ctxt_base.rx_count++; 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; } - ctxt.rx_count++; + ctxt_base.rx_count++; 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_unpack_emm_status_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu.get(), &emm_status); - ctxt.rx_count++; + ctxt_base.rx_count++; switch (emm_status.emm_cause) { 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 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)) { logger.error("Error applying NAS security."); @@ -1598,8 +1607,8 @@ void nas::gen_attach_request(srsran::unique_byte_buffer_t& msg) } if (have_ctxt) { - set_k_enb_count(ctxt.tx_count); - ctxt.tx_count++; + set_k_enb_count(ctxt_base.tx_count); + ctxt_base.tx_count++; } // 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->N_bytes++; 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++; 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 msg->msg[2] = mac[2]; msg->N_bytes++; @@ -1645,8 +1654,8 @@ void nas::gen_service_request(srsran::unique_byte_buffer_t& msg) if (pcap != nullptr) { pcap->write_nas(msg->msg, msg->N_bytes); } - set_k_enb_count(ctxt.tx_count); - ctxt.tx_count++; + set_k_enb_count(ctxt_base.tx_count); + ctxt_base.tx_count++; } 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.nas_ksi = ctxt.ksi; logger.info("Sending detach request with GUTI"); // If sent as an Initial UE message, it cannot be ciphered - liblte_mme_pack_detach_request_msg( - &detach_request, LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()); + liblte_mme_pack_detach_request_msg(&detach_request, + LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY, + ctxt_base.tx_count, + (LIBLTE_BYTE_MSG_STRUCT*)pdu.get()); if (pcap != nullptr) { 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); logger.info("Sending detach request with IMSI"); 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) { 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) @@ -1815,7 +1826,7 @@ void nas::send_attach_complete(const uint8_t& transaction_id_, const uint8_t& ep return; } 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 if (pcap != nullptr) { 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"); rrc->write_sdu(std::move(pdu)); - ctxt.tx_count++; + ctxt_base.tx_count++; } void nas::send_detach_accept() @@ -1844,7 +1855,8 @@ void nas::send_detach_accept() LIBLTE_MME_DETACH_ACCEPT_MSG_STRUCT 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) { 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; 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) { 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"); 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) @@ -1946,7 +1958,8 @@ void nas::send_identity_response(const uint8 id_type) 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 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)); - ctxt.tx_count++; + ctxt_base.tx_count++; } 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->N_bytes++; 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++; 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 msg->msg[2] = mac[2]; msg->N_bytes++; @@ -1991,7 +2004,7 @@ void nas::send_service_request() logger.info("Sending service request"); rrc->write_sdu(std::move(msg)); - ctxt.tx_count++; + ctxt_base.tx_count++; } 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( - &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."); 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"); rrc->write_sdu(std::move(pdu)); - ctxt.tx_count++; + ctxt_base.tx_count++; 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; 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."); return; } @@ -2148,7 +2161,7 @@ void nas::send_activate_dedicated_eps_bearer_context_accept(const uint8_t& proc_ accept.proc_transaction_id); 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) @@ -2165,7 +2178,7 @@ void nas::send_deactivate_eps_bearer_context_accept(const uint8_t& proc_transact accept.proc_transaction_id = proc_transaction_id; 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."); return; } @@ -2186,7 +2199,7 @@ void nas::send_deactivate_eps_bearer_context_accept(const uint8_t& proc_transact accept.proc_transaction_id); 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) @@ -2203,7 +2216,7 @@ void nas::send_modify_eps_bearer_context_accept(const uint8_t& proc_transaction_ accept.proc_transaction_id = proc_transaction_id; 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."); return; } @@ -2224,7 +2237,7 @@ void nas::send_modify_eps_bearer_context_accept(const uint8_t& proc_transaction_ accept.proc_transaction_id); rrc->write_sdu(std::move(pdu)); - ctxt.tx_count++; + ctxt_base.tx_count++; } 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( - (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."); return; } @@ -2253,7 +2266,7 @@ void nas::send_activate_test_mode_complete() logger.info(pdu->msg, pdu->N_bytes, "Sending Activate test mode complete"); rrc->write_sdu(std::move(pdu)); - ctxt.tx_count++; + ctxt_base.tx_count++; } 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( - (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."); 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"); rrc->write_sdu(std::move(pdu)); - ctxt.tx_count++; + ctxt_base.tx_count++; } /******************************************************************************* * 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; - if (ctxt_ == nullptr) { + if (ctxt_ == nullptr || ctxt_base_ == nullptr) { return false; } @@ -2318,16 +2331,16 @@ bool nas::read_ctxt_file(nas_sec_ctxt* ctxt_) if (!readvar(file, "mme_code=", &ctxt_->guti.mme_code)) { return false; } - if (!readvar(file, "tx_count=", &ctxt_->tx_count)) { + if (!readvar(file, "tx_count=", &ctxt_base_->tx_count)) { return false; } - if (!readvar(file, "rx_count=", &ctxt_->rx_count)) { + if (!readvar(file, "rx_count=", &ctxt_base_->rx_count)) { return false; } - if (!readvar(file, "int_alg=", &ctxt_->integ_algo)) { + if (!readvar(file, "int_alg=", &ctxt_base_->integ_algo)) { return false; } - if (!readvar(file, "enc_alg=", &ctxt_->cipher_algo)) { + if (!readvar(file, "enc_alg=", &ctxt_base_->cipher_algo)) { return false; } 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", ctxt_->ksi, hex_to_string(ctxt_->k_asme, 32).c_str(), - ctxt_->tx_count, - ctxt_->rx_count, - ctxt_->integ_algo, - ctxt_->cipher_algo); + ctxt_base_->tx_count, + ctxt_base_->rx_count, + ctxt_base_->integ_algo, + ctxt_base_->cipher_algo); have_guti = true; have_ctxt = true; @@ -2369,7 +2382,7 @@ bool nas::read_ctxt_file(nas_sec_ctxt* ctxt_) 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) { return false; @@ -2382,10 +2395,10 @@ bool nas::write_ctxt_file(nas_sec_ctxt ctxt_) file << "mnc=" << (int)ctxt_.guti.mnc << 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 << "tx_count=" << (int)ctxt_.tx_count << std::endl; - file << "rx_count=" << (int)ctxt_.rx_count << std::endl; - file << "int_alg=" << (int)ctxt_.integ_algo << std::endl; - file << "enc_alg=" << (int)ctxt_.cipher_algo << std::endl; + file << "tx_count=" << (int)ctxt_base_.tx_count << std::endl; + file << "rx_count=" << (int)ctxt_base_.rx_count << std::endl; + file << "int_alg=" << (int)ctxt_base_.integ_algo << std::endl; + file << "enc_alg=" << (int)ctxt_base_.cipher_algo << std::endl; file << "ksi=" << (int)ctxt_.ksi << 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", ctxt_.ksi, hex_to_string(ctxt_.k_asme, 32).c_str(), - ctxt_.tx_count, - ctxt_.rx_count, - ctxt_.integ_algo, - ctxt_.cipher_algo); + ctxt_base_.tx_count, + ctxt_base_.rx_count, + ctxt_base_.integ_algo, + ctxt_base_.cipher_algo); file.close(); return true; } diff --git a/srsue/src/stack/upper/nas_5g.cc b/srsue/src/stack/upper/nas_5g.cc index 4e226b2b8..29a59266e 100644 --- a/srsue/src/stack/upper/nas_5g.cc +++ b/srsue/src/stack/upper/nas_5g.cc @@ -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_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) { 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()); - integrity_generate(&k_nas_int[16], - ctxt.tx_count, + integrity_generate(&ctxt_base.k_nas_int[16], + ctxt_base.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[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"); rrc_nr->write_sdu(std::move(pdu)); - ctxt.tx_count++; + ctxt_base.tx_count++; 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; // 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_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()); - integrity_generate(&k_nas_int[16], - ctxt.tx_count, + integrity_generate(&ctxt_base.k_nas_int[16], + ctxt_base.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[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) { 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; - ctxt.integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) - security_mode_command.selected_nas_security_algorithms.integrity_protection_algorithm.value; + ctxt_base.integ_algo = + (INTEGRITY_ALGORITHM_ID_ENUM) + security_mode_command.selected_nas_security_algorithms.integrity_protection_algorithm.value; // Check 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 if (initial_sec_command) { - ctxt.rx_count = 0; - ctxt.tx_count = 0; + ctxt_base.rx_count = 0; + ctxt_base.tx_count = 0; initial_sec_command = false; } // Generate NAS keys 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); - logger.info(k_nas_enc, 32, "NAS encryption key - k_nas_enc"); - logger.info(k_nas_int, 32, "NAS integrity key - k_nas_int"); + usim->generate_nas_keys_5g( + ctxt_5g.k_amf, ctxt_base.k_nas_enc, ctxt_base.k_nas_int, ctxt_base.cipher_algo, ctxt_base.integ_algo); + 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())) { 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); - ctxt.rx_count++; + ctxt_base.rx_count++; return SRSRAN_SUCCESS; } diff --git a/srsue/src/stack/upper/nas_base.cc b/srsue/src/stack/upper/nas_base.cc index dc18463c3..4fc180b6d 100644 --- a/srsue/src/stack/upper/nas_base.cc +++ b/srsue/src/stack/upper/nas_base.cc @@ -49,7 +49,7 @@ void nas_base::integrity_generate(uint8_t* key_128, uint32_t msg_len, uint8_t* mac) { - switch (ctxt.integ_algo) { + switch (ctxt_base.integ_algo) { case INTEGRITY_ALGORITHM_ID_EIA0: break; 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]; // generate expected MAC - uint32_t count_est = (ctxt.rx_count & 0x00FFFF00u) | pdu->msg[seq_offset]; - integrity_generate(&k_nas_int[16], + uint32_t count_est = (ctxt_base.rx_count & 0x00FFFF00u) | pdu->msg[seq_offset]; + integrity_generate(&ctxt_base.k_nas_int[16], count_est, SECURITY_DIRECTION_DOWNLINK, &pdu->msg[seq_offset], @@ -115,9 +115,9 @@ bool nas_base::integrity_check(byte_buffer_t* pdu) mac[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); - ctxt.rx_count = count_est; + ctxt_base.rx_count = count_est; } return true; } else { @@ -130,16 +130,16 @@ void nas_base::cipher_encrypt(byte_buffer_t* pdu) { byte_buffer_t pdu_tmp; - if (ctxt.cipher_algo != CIPHERING_ALGORITHM_ID_EEA0) { - logger.debug("Encrypting PDU. count=%d", ctxt.tx_count); + if (ctxt_base.cipher_algo != CIPHERING_ALGORITHM_ID_EEA0) { + logger.debug("Encrypting PDU. count=%d", ctxt_base.tx_count); } - switch (ctxt.cipher_algo) { + switch (ctxt_base.cipher_algo) { case CIPHERING_ALGORITHM_ID_EEA0: break; case CIPHERING_ALGORITHM_ID_128_EEA1: - security_128_eea1(&k_nas_enc[16], - ctxt.tx_count, + security_128_eea1(&ctxt_base.k_nas_enc[16], + ctxt_base.tx_count, bearer_id, SECURITY_DIRECTION_UPLINK, &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); break; case CIPHERING_ALGORITHM_ID_128_EEA2: - security_128_eea2(&k_nas_enc[16], - ctxt.tx_count, + security_128_eea2(&ctxt_base.k_nas_enc[16], + ctxt_base.tx_count, bearer_id, SECURITY_DIRECTION_UPLINK, &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); break; case CIPHERING_ALGORITHM_ID_128_EEA3: - security_128_eea3(&k_nas_enc[16], - ctxt.tx_count, + security_128_eea3(&ctxt_base.k_nas_enc[16], + ctxt_base.tx_count, bearer_id, SECURITY_DIRECTION_UPLINK, &pdu->msg[seq_offset + 1], @@ -177,16 +177,16 @@ void nas_base::cipher_decrypt(byte_buffer_t* pdu) { byte_buffer_t tmp_pdu; - uint32_t count_est = (ctxt.rx_count & 0x00FFFF00u) | pdu->msg[5]; - if (ctxt.cipher_algo != CIPHERING_ALGORITHM_ID_EEA0) { - logger.debug("Decrypting PDU. Local: count=%d, Received: count=%d", ctxt.rx_count, count_est); + uint32_t count_est = (ctxt_base.rx_count & 0x00FFFF00u) | pdu->msg[5]; + if (ctxt_base.cipher_algo != CIPHERING_ALGORITHM_ID_EEA0) { + 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: break; case CIPHERING_ALGORITHM_ID_128_EEA1: - security_128_eea1(&k_nas_enc[16], + security_128_eea1(&ctxt_base.k_nas_enc[16], count_est, bearer_id, 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); break; case CIPHERING_ALGORITHM_ID_128_EEA2: - security_128_eea2(&k_nas_enc[16], + security_128_eea2(&ctxt_base.k_nas_enc[16], count_est, bearer_id, 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); break; case CIPHERING_ALGORITHM_ID_128_EEA3: - security_128_eea3(&k_nas_enc[16], + security_128_eea3(&ctxt_base.k_nas_enc[16], count_est, bearer_id, SECURITY_DIRECTION_DOWNLINK,