mirror of https://github.com/PentHertz/srsLTE.git
Split NAS security ctxt
This commit is contained in:
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…
Reference in New Issue