Split NAS security ctxt

This commit is contained in:
David Rupprecht 2021-09-17 17:28:35 +02:00 committed by David Rupprecht
parent 4e49508d8f
commit 5910d8847a
5 changed files with 155 additions and 135 deletions

View File

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

View File

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

View File

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

View File

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

View File

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