simplify NAS security handling and fix missing call in act test mode complete

add extra method to apply NAS security config, if configured,
that can be used by each NAS message sender
This commit is contained in:
Andre Puschmann 2020-03-06 12:52:28 +01:00
parent 73feeaeba9
commit 5b8b718482
2 changed files with 83 additions and 70 deletions

View File

@ -159,6 +159,8 @@ private:
bool integrity_check(srslte::byte_buffer_t* pdu);
void cipher_encrypt(srslte::byte_buffer_t* pdu);
void cipher_decrypt(srslte::byte_buffer_t* pdu);
int apply_security_config(srslte::unique_byte_buffer_t& pdu);
void set_k_enb_count(uint32_t count);
bool check_cap_replay(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT* caps);
@ -183,8 +185,8 @@ private:
void parse_modify_eps_bearer_context_request(srslte::unique_byte_buffer_t pdu);
// Packet generators
void gen_attach_request(srslte::byte_buffer_t* msg);
void gen_service_request(srslte::byte_buffer_t* msg);
void gen_attach_request(srslte::unique_byte_buffer_t& msg);
void gen_service_request(srslte::unique_byte_buffer_t& msg);
// Senders
void send_attach_complete(const uint8_t& transaction_id, const uint8_t& eps_bearer_id);

View File

@ -149,9 +149,9 @@ proc_outcome_t nas::rrc_connect_proc::init(srslte::establishment_cause_t cause_,
}
if (nas_ptr->state == EMM_STATE_REGISTERED) {
nas_ptr->gen_service_request(pdu.get());
nas_ptr->gen_service_request(pdu);
} else {
nas_ptr->gen_attach_request(pdu.get());
nas_ptr->gen_attach_request(pdu);
}
}
@ -856,6 +856,33 @@ bool nas::check_cap_replay(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT* caps)
return true;
}
/**
* Applies the current security config on a packed NAS PDU
*
* The PDU is ciphered and integrity protected if NAS security is configured
* and the current security context is valid. The function also performs
* a length check.
*
* @param pdu The NAS PDU already packed inside a byte_buffer
* @return True if successfull, false otherwise
*/
int nas::apply_security_config(srslte::unique_byte_buffer_t& pdu)
{
if (have_ctxt) {
if (pdu->N_bytes > 5) {
cipher_encrypt(pdu.get());
integrity_generate(
&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]);
} else {
nas_log->error("Invalid PDU size %d\n", pdu->N_bytes);
return SRSLTE_ERROR;
}
} else {
nas_log->debug("Not applying security for PDU. No context configured.\n");
}
return SRSLTE_SUCCESS;
}
/*******************************************************************************
* Parsers
******************************************************************************/
@ -1311,9 +1338,12 @@ void nas::parse_security_mode_command(uint32_t lcid, unique_byte_buffer_t pdu)
if (pcap != nullptr) {
pcap->write_nas(pdu->msg, pdu->N_bytes);
}
cipher_encrypt(pdu.get());
integrity_generate(
&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]);
if (apply_security_config(pdu)) {
nas_log->error("Error applying NAS security.\n");
return;
}
nas_log->info("Sending Security Mode Complete nas_current_ctxt.tx_count=%d, RB=%s\n",
ctxt.tx_count,
rrc->get_rb_name(lcid).c_str());
@ -1346,7 +1376,7 @@ void nas::parse_service_reject(uint32_t lcid, unique_byte_buffer_t pdu)
// Send attach request after receiving service reject
pdu->clear();
gen_attach_request(pdu.get());
gen_attach_request(pdu);
rrc->write_sdu(std::move(pdu));
}
@ -1548,7 +1578,7 @@ void nas::parse_emm_status(uint32_t lcid, unique_byte_buffer_t pdu)
* Senders
******************************************************************************/
void nas::gen_attach_request(byte_buffer_t* msg)
void nas::gen_attach_request(srslte::unique_byte_buffer_t& msg)
{
if (msg == nullptr) {
nas_log->error("Fatal Error: Couldn't allocate PDU in gen_attach_request().\n");
@ -1609,14 +1639,11 @@ void nas::gen_attach_request(byte_buffer_t* msg)
ctxt.guti.mme_group_id,
ctxt.guti.mme_code);
liblte_mme_pack_attach_request_msg(
&attach_req, LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)msg);
&attach_req, LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)msg.get());
// Add MAC
if (msg->N_bytes > 5) {
integrity_generate(
&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &msg->msg[5], msg->N_bytes - 5, &msg->msg[1]);
} else {
nas_log->error("Invalid PDU size %d\n", msg->N_bytes);
if (apply_security_config(msg)) {
nas_log->error("Error applying NAS security.\n");
return;
}
} else {
attach_req.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI;
@ -1624,7 +1651,7 @@ void nas::gen_attach_request(byte_buffer_t* msg)
attach_req.nas_ksi.nas_ksi = 0;
usim->get_imsi_vec(attach_req.eps_mobile_id.imsi, 15);
nas_log->info("Requesting IMSI attach (IMSI=%s)\n", usim->get_imsi_str().c_str());
liblte_mme_pack_attach_request_msg(&attach_req, (LIBLTE_BYTE_MSG_STRUCT*)msg);
liblte_mme_pack_attach_request_msg(&attach_req, (LIBLTE_BYTE_MSG_STRUCT*)msg.get());
}
if (pcap != nullptr) {
@ -1643,7 +1670,7 @@ void nas::gen_attach_request(byte_buffer_t* msg)
}
}
void nas::gen_service_request(byte_buffer_t* msg)
void nas::gen_service_request(srslte::unique_byte_buffer_t& msg)
{
if (msg == nullptr) {
nas_log->error("Fatal Error: Couldn't allocate PDU in gen_service_request().\n");
@ -1772,16 +1799,9 @@ void nas::send_detach_request(bool switch_off)
pcap->write_nas(pdu->msg, pdu->N_bytes);
}
// Add MAC
if (pdu->N_bytes > 5) {
if (rrc->is_connected()) {
cipher_encrypt(pdu.get());
}
integrity_generate(
&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]);
ctxt.tx_count++;
} else {
nas_log->error("Invalid PDU size %d\n", pdu->N_bytes);
if (apply_security_config(pdu)) {
nas_log->error("Error applying NAS security.\n");
return;
}
} else {
detach_request.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI;
@ -1812,6 +1832,8 @@ void nas::send_detach_request(bool switch_off)
}
callbacks.add_proc(rrc_connector);
}
ctxt.tx_count++;
}
void nas::send_attach_complete(const uint8_t& transaction_id, const uint8_t& eps_bearer_id)
@ -1836,9 +1858,10 @@ void nas::send_attach_complete(const uint8_t& transaction_id, const uint8_t& eps
pcap->write_nas(pdu->msg, pdu->N_bytes);
}
cipher_encrypt(pdu.get());
integrity_generate(
&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]);
if (apply_security_config(pdu)) {
nas_log->error("Error applying NAS security.\n");
return;
}
// Instruct RRC to enable capabilities
rrc->enable_capabilities();
@ -1867,13 +1890,9 @@ void nas::send_detach_accept()
pcap->write_nas(pdu->msg, pdu->N_bytes);
}
// Encrypt and add MAC
if (pdu->N_bytes > 5) {
cipher_encrypt(pdu.get());
integrity_generate(
&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]);
} else {
nas_log->error("Invalid PDU size %d\n", pdu->N_bytes);
if (apply_security_config(pdu)) {
nas_log->error("Error applying NAS security.\n");
return;
}
nas_log->info("Sending detach accept\n");
@ -1902,14 +1921,16 @@ void nas::send_authentication_response(const uint8_t* res, const size_t res_len,
pcap->write_nas(pdu->msg, pdu->N_bytes);
}
if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED && pdu->N_bytes > 5) {
cipher_encrypt(pdu.get());
integrity_generate(
&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]);
if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED) {
if (apply_security_config(pdu)) {
nas_log->error("Error applying NAS security.\n");
return;
}
}
nas_log->info("Sending Authentication Response\n");
rrc->write_sdu(std::move(pdu));
ctxt.tx_count++;
}
void nas::send_authentication_failure(const uint8_t cause, const uint8_t* auth_fail_param)
@ -1971,10 +1992,11 @@ void nas::send_identity_response(const uint8 id_type, const uint8_t sec_hdr_type
liblte_mme_pack_identity_response_msg(&id_resp, sec_hdr_type, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT*)pdu.get());
// add security if needed
if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED && pdu->N_bytes > 5) {
cipher_encrypt(pdu.get());
integrity_generate(
&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]);
if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED) {
if (apply_security_config(pdu)) {
nas_log->error("Error applying NAS security.\n");
return;
}
}
if (pcap != nullptr) {
@ -2126,12 +2148,8 @@ void nas::send_esm_information_response(const uint8 proc_transaction_id)
pcap->write_nas(pdu->msg, pdu->N_bytes);
}
cipher_encrypt(pdu.get());
if (pdu->N_bytes > 5) {
integrity_generate(
&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]);
} else {
nas_log->error("Invalid PDU size %d\n", pdu->N_bytes);
if (apply_security_config(pdu)) {
nas_log->error("Error applying NAS security.\n");
return;
}
@ -2165,12 +2183,8 @@ void nas::send_activate_dedicated_eps_bearer_context_accept(const uint8_t& proc_
pcap->write_nas(pdu->msg, pdu->N_bytes);
}
cipher_encrypt(pdu.get());
if (pdu->N_bytes > 5) {
integrity_generate(
&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]);
} else {
nas_log->error("Invalid PDU size %d\n", pdu->N_bytes);
if (apply_security_config(pdu)) {
nas_log->error("Error applying NAS security.\n");
return;
}
@ -2205,12 +2219,8 @@ void nas::send_deactivate_eps_bearer_context_accept(const uint8_t& proc_transact
pcap->write_nas(pdu->msg, pdu->N_bytes);
}
cipher_encrypt(pdu.get());
if (pdu->N_bytes > 5) {
integrity_generate(
&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]);
} else {
nas_log->error("Invalid PDU size %d\n", pdu->N_bytes);
if (apply_security_config(pdu)) {
nas_log->error("Error applying NAS security.\n");
return;
}
@ -2245,12 +2255,8 @@ void nas::send_modify_eps_bearer_context_accept(const uint8_t& proc_transaction_
pcap->write_nas(pdu->msg, pdu->N_bytes);
}
cipher_encrypt(pdu.get());
if (pdu->N_bytes > 5) {
integrity_generate(
&k_nas_int[16], ctxt.tx_count, SECURITY_DIRECTION_UPLINK, &pdu->msg[5], pdu->N_bytes - 5, &pdu->msg[1]);
} else {
nas_log->error("Invalid PDU size %d\n", pdu->N_bytes);
if (apply_security_config(pdu)) {
nas_log->error("Error applying NAS security.\n");
return;
}
@ -2278,6 +2284,11 @@ void nas::send_activate_test_mode_complete(const uint8_t sec_hdr_type)
pcap->write_nas(pdu->msg, pdu->N_bytes);
}
if (apply_security_config(pdu)) {
nas_log->error("Error applying NAS security.\n");
return;
}
nas_log->info_hex(pdu->msg, pdu->N_bytes, "Sending Activate test mode complete\n");
rrc->write_sdu(std::move(pdu));