From 7eef2c1c4b7ad4f8f709771455b3e1ebf0cbdf29 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Thu, 15 Nov 2018 23:02:30 +0100 Subject: [PATCH 01/12] start with decryption function --- srsepc/hdr/mme/s1ap_nas_transport.h | 3 + srsepc/src/mme/s1ap_nas_transport.cc | 98 ++++++++++++++++++++++++++-- 2 files changed, 94 insertions(+), 7 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index 3a11302c5..a62fc69e7 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -128,6 +128,9 @@ private: void log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req); void log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req); void log_unhandled_initial_ue_message_ies(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *init_ue); + + void cipher_decrypt(eps_sec_ctx_t *sec_ctxt, srslte::byte_buffer_t *pdu); + void cipher_encrypt(eps_sec_ctx_t *sec_ctxt, srslte::byte_buffer_t *pdu); }; } //namespace srsepc #endif // SRSEPC_S1AP_NAS_TRANSPORT_H diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 1bb871fb1..ca47e897b 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -264,18 +264,25 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA } else if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) { + + mac_valid = integrity_check(emm_ctx, nas_msg); + if (mac_valid == false){ + m_s1ap_log->warning("Invalid MAC message.\n" ); + return false; + } + + if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) { + cipher_decrypt(&emm_ctx->security_ctxt, nas_msg); + liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + } + switch (msg_type) { case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: m_s1ap_log->info("Uplink NAS: Received Security Mode Complete\n"); m_s1ap_log->console("Uplink NAS: Received Security Mode Complete\n"); emm_ctx->security_ctxt.ul_nas_count = 0; emm_ctx->security_ctxt.dl_nas_count = 0; - mac_valid = integrity_check(emm_ctx,nas_msg); - if(mac_valid){ - handle_nas_security_mode_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); - } else { - m_s1ap_log->warning("Invalid MAC in Security Mode Command Complete message.\n" ); - } + handle_nas_security_mode_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); break; default: m_s1ap_log->warning("Unhandled NAS message with new EPS security context 0x%x\n", msg_type ); @@ -287,11 +294,17 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA //Integrity protected NAS message, possibly ciphered. emm_ctx->security_ctxt.ul_nas_count++; mac_valid = integrity_check(emm_ctx,nas_msg); - if(!mac_valid){ + if(mac_valid == false){ m_s1ap_log->warning("Invalid MAC in NAS message type 0x%x.\n", msg_type); m_pool->deallocate(nas_msg); return false; } + + if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED){ + cipher_decrypt(&emm_ctx->security_ctxt, nas_msg); + liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + } + switch (msg_type) { case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: m_s1ap_log->info("Integrity Protected UL NAS: Received Attach Complete\n"); @@ -2136,6 +2149,77 @@ s1ap_nas_transport::log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQ return; } + +void s1ap_nas_transport::cipher_decrypt(eps_sec_ctx_t * sec_ctxt, srslte::byte_buffer_t *pdu) +{ + srslte::byte_buffer_t tmp_pdu; + switch(sec_ctxt->cipher_algo) + { + case srslte::CIPHERING_ALGORITHM_ID_EEA0: + break; + case srslte::CIPHERING_ALGORITHM_ID_128_EEA1: + srslte::security_128_eea1(&sec_ctxt->k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes-6, + &tmp_pdu.msg[6]); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6); + m_s1ap_log->debug_hex(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); + break; + case srslte::CIPHERING_ALGORITHM_ID_128_EEA2: + srslte::security_128_eea2(&sec_ctxt->k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes-6, + &tmp_pdu.msg[6]); + m_s1ap_log->debug_hex(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6); + break; + default: + m_s1ap_log->error("Ciphering algorithms not known\n"); + break; + } +} + +void s1ap_nas_transport::cipher_encrypt(eps_sec_ctx_t * sec_ctxt, srslte::byte_buffer_t *pdu) +{ + srslte::byte_buffer_t pdu_tmp; + switch(sec_ctxt->cipher_algo) + { + case srslte::CIPHERING_ALGORITHM_ID_EEA0: + break; + case srslte::CIPHERING_ALGORITHM_ID_128_EEA1: + srslte::security_128_eea1(&sec_ctxt->k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes-6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes-6); + m_s1ap_log->debug_hex(pdu_tmp.msg, pdu->N_bytes, "Encrypted"); + break; + case srslte::CIPHERING_ALGORITHM_ID_128_EEA2: + srslte::security_128_eea2(&sec_ctxt->k_nas_enc[16], + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes-6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes-6); + m_s1ap_log->debug_hex(pdu_tmp.msg, pdu->N_bytes, "Encrypted"); + break; + default: + m_s1ap_log->error("Ciphering algorithm not known\n"); + break; + } +} + void s1ap_nas_transport::log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req) { From e547883a8f71ca30d59296d4f42f7c2b4834a130 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Sun, 18 Nov 2018 20:30:22 +0100 Subject: [PATCH 02/12] Wrapper functions for integrity generate --- srsepc/hdr/mme/s1ap_nas_transport.h | 8 +- srsepc/src/mme/s1ap_nas_transport.cc | 185 ++++++++++++++++----------- 2 files changed, 117 insertions(+), 76 deletions(-) diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index a62fc69e7..45ac2737b 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -110,8 +110,8 @@ private: bool handle_authentication_failure(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); bool handle_nas_detach_request(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); - bool integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t *pdu); - bool short_integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t *pdu); + bool integrity_check(eps_sec_ctx_t * sec_ctxt, srslte::byte_buffer_t *pdu); + bool short_integrity_check(eps_sec_ctx_t * sec_ctxt, srslte::byte_buffer_t *pdu); bool pack_authentication_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t next_mme_ue_s1ap_id, uint8_t eksi, uint8_t *autn, uint8_t *rand); bool pack_authentication_reject(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id); @@ -131,6 +131,10 @@ private: void cipher_decrypt(eps_sec_ctx_t *sec_ctxt, srslte::byte_buffer_t *pdu); void cipher_encrypt(eps_sec_ctx_t *sec_ctxt, srslte::byte_buffer_t *pdu); + + void integrity_generate(eps_sec_ctx_t *sec_ctxt, + srslte::byte_buffer_t *pdu, + uint8_t *mac); }; } //namespace srsepc #endif // SRSEPC_S1AP_NAS_TRANSPORT_H diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index ca47e897b..5f34432f3 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -265,7 +265,7 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA else if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) { - mac_valid = integrity_check(emm_ctx, nas_msg); + mac_valid = integrity_check(&emm_ctx->security_ctxt, nas_msg); if (mac_valid == false){ m_s1ap_log->warning("Invalid MAC message.\n" ); return false; @@ -293,7 +293,7 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA { //Integrity protected NAS message, possibly ciphered. emm_ctx->security_ctxt.ul_nas_count++; - mac_valid = integrity_check(emm_ctx,nas_msg); + mac_valid = integrity_check(&emm_ctx->security_ctxt, nas_msg); if(mac_valid == false){ m_s1ap_log->warning("Invalid MAC in NAS message type 0x%x.\n", msg_type); m_pool->deallocate(nas_msg); @@ -659,7 +659,7 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id, //Check NAS integrity bool msg_valid = false; emm_ctx->security_ctxt.ul_nas_count++; - msg_valid = integrity_check(emm_ctx,nas_msg); + msg_valid = integrity_check(&emm_ctx->security_ctxt, nas_msg); if(msg_valid == true && emm_ctx->state == EMM_STATE_DEREGISTERED) { m_s1ap_log->console("GUTI Attach Integrity valid. UL count %d, DL count %d\n",emm_ctx->security_ctxt.ul_nas_count, emm_ctx->security_ctxt.dl_nas_count); @@ -860,7 +860,7 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi, ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; emm_ctx->security_ctxt.ul_nas_count++; - mac_valid = short_integrity_check(emm_ctx,nas_msg); + mac_valid = short_integrity_check(&emm_ctx->security_ctxt, nas_msg); if(mac_valid) { m_s1ap_log->console("Service Request -- Short MAC valid\n"); @@ -1334,67 +1334,98 @@ s1ap_nas_transport::handle_tracking_area_update_request(srslte::byte_buffer_t *n } bool -s1ap_nas_transport::short_integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t *pdu) +s1ap_nas_transport::short_integrity_check(eps_sec_ctx_t * sec_ctxt, srslte::byte_buffer_t *pdu) { - uint8_t exp_mac[4]; + uint8_t exp_mac[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t *mac = &pdu->msg[2]; int i; - srslte::security_128_eia1(&emm_ctx->security_ctxt.k_nas_int[16], - emm_ctx->security_ctxt.ul_nas_count, - 0, - SECURITY_DIRECTION_UPLINK, - &pdu->msg[0], - 2, - &exp_mac[0]); - + switch (sec_ctxt->integ_algo) + { + case srslte::INTEGRITY_ALGORITHM_ID_EIA0: + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1: + srslte::security_128_eia1(&sec_ctxt->k_nas_int[16], + sec_ctxt->ul_nas_count, + 0, + SECURITY_DIRECTION_UPLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + &exp_mac[0]); + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: + srslte::security_128_eia2(&sec_ctxt->k_nas_int[16], + sec_ctxt->ul_nas_count, + 0, + SECURITY_DIRECTION_UPLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + &exp_mac[0]); + break; + default: + break; + } // Check if expected mac equals the sent mac for(i=0; i<2; i++){ if(exp_mac[i+2] != mac[i]){ m_s1ap_log->warning("Short integrity check failure. Local: count=%d, [%02x %02x %02x %02x], " "Received: count=%d, [%02x %02x]\n", - emm_ctx->security_ctxt.ul_nas_count, exp_mac[0], exp_mac[1], exp_mac[2], exp_mac[3], + sec_ctxt->ul_nas_count, exp_mac[0], exp_mac[1], exp_mac[2], exp_mac[3], pdu->msg[1] & 0x1F, mac[0], mac[1]); return false; } } m_s1ap_log->info("Integrity check ok. Local: count=%d, Received: count=%d\n", - emm_ctx->security_ctxt.ul_nas_count, pdu->msg[1] & 0x1F); + sec_ctxt->ul_nas_count, pdu->msg[1] & 0x1F); return true; } - -bool -s1ap_nas_transport::integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t *pdu) +bool s1ap_nas_transport::integrity_check(eps_sec_ctx_t *sec_ctxt, srslte::byte_buffer_t *pdu) { - uint8_t exp_mac[4]; + uint8_t exp_mac[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t *mac = &pdu->msg[1]; int i; - srslte::security_128_eia1(&emm_ctx->security_ctxt.k_nas_int[16], - emm_ctx->security_ctxt.ul_nas_count, - 0, - SECURITY_DIRECTION_UPLINK, - &pdu->msg[5], - pdu->N_bytes-5, - &exp_mac[0]); - + switch (sec_ctxt->integ_algo) + { + case srslte::INTEGRITY_ALGORITHM_ID_EIA0: + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1: + srslte::security_128_eia1(&sec_ctxt->k_nas_int[16], + sec_ctxt->ul_nas_count, + 0, + SECURITY_DIRECTION_UPLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + &exp_mac[0]); + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: + srslte::security_128_eia2(&sec_ctxt->k_nas_int[16], + sec_ctxt->ul_nas_count, + 0, + SECURITY_DIRECTION_UPLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + &exp_mac[0]); + break; + default: + break; + } // Check if expected mac equals the sent mac - for(i=0; i<4; i++){ - if(exp_mac[i] != mac[i]){ + for (i = 0; i < 4; i++) { + if (exp_mac[i] != mac[i]) { m_s1ap_log->warning("Integrity check failure. UL Local: count=%d, [%02x %02x %02x %02x], " - "Received: UL count=%d, [%02x %02x %02x %02x]\n", - emm_ctx->security_ctxt.ul_nas_count, exp_mac[0], exp_mac[1], exp_mac[2], exp_mac[3], - pdu->msg[5], mac[0], mac[1], mac[2], mac[3]); + "Received: UL count=%d, [%02x %02x %02x %02x]\n", + sec_ctxt->ul_nas_count, exp_mac[0], exp_mac[1], exp_mac[2], exp_mac[3], + pdu->msg[5], mac[0], mac[1], mac[2], mac[3]); return false; } } m_s1ap_log->info("Integrity check ok. Local: count=%d, Received: count=%d\n", - emm_ctx->security_ctxt.ul_nas_count, pdu->msg[5]); - return true; + sec_ctxt->ul_nas_count, pdu->msg[5]); + return true; } - bool s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) { @@ -1620,7 +1651,12 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, //Pack NAS PDU LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sm_cmd; - + + // FIXME Selection based on UE caps and network preferences + + ue_emm_ctx->security_ctxt.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0; + ue_emm_ctx->security_ctxt.integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA1; + sm_cmd.selected_nas_sec_algs.type_of_eea = LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_EEA0; sm_cmd.selected_nas_sec_algs.type_of_eia = LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_128_EIA1; @@ -1645,15 +1681,15 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg(&sm_cmd,sec_hdr_type, ue_emm_ctx->security_ctxt.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) { - m_s1ap_log->console("Error packing Authentication Request\n"); + m_s1ap_log->console("Error packing Security Mode Command\n"); return false; } //Generate EPS security context uint8_t mac[4]; srslte::security_generate_k_nas( ue_emm_ctx->security_ctxt.k_asme, - srslte::CIPHERING_ALGORITHM_ID_EEA0, - srslte::INTEGRITY_ALGORITHM_ID_128_EIA1, + ue_emm_ctx->security_ctxt.cipher_algo, + ue_emm_ctx->security_ctxt.integ_algo, ue_emm_ctx->security_ctxt.k_nas_enc, ue_emm_ctx->security_ctxt.k_nas_int ); @@ -1666,16 +1702,9 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, m_s1ap_log->info("Generating KeNB with UL NAS COUNT: %d\n", ue_emm_ctx->security_ctxt.ul_nas_count); m_s1ap_log->console("Generating KeNB with UL NAS COUNT: %d\n", ue_emm_ctx->security_ctxt.ul_nas_count); m_s1ap_log->info_hex(ue_emm_ctx->security_ctxt.k_enb, 32, "Key eNodeB (k_enb)\n"); + //Generate MAC for integrity protection - //FIXME Write wrapper to support EIA1, EIA2, etc. - srslte::security_128_eia1 (&ue_emm_ctx->security_ctxt.k_nas_int[16], - ue_emm_ctx->security_ctxt.dl_nas_count, - 0, - SECURITY_DIRECTION_DOWNLINK, - &nas_buffer->msg[5], - nas_buffer->N_bytes - 5, - mac - ); + integrity_generate(&ue_emm_ctx->security_ctxt, nas_buffer, mac); memcpy(&nas_buffer->msg[1],mac,4); //Copy NAS PDU to Downlink NAS Trasport message buffer @@ -1686,7 +1715,7 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); if(err != LIBLTE_SUCCESS) { - m_s1ap_log->console("Error packing Authentication Request\n"); + m_s1ap_log->console("Error packing S1AP PDU transport message\n"); return false; } m_s1ap_log->debug_hex(reply_msg->msg, reply_msg->N_bytes, "Security Mode Command: "); @@ -1734,14 +1763,7 @@ s1ap_nas_transport::pack_esm_information_request(srslte::byte_buffer_t *reply_ms } uint8_t mac[4]; - srslte::security_128_eia1 (&ue_emm_ctx->security_ctxt.k_nas_int[16], - ue_emm_ctx->security_ctxt.dl_nas_count, - 0, - SECURITY_DIRECTION_DOWNLINK, - &nas_buffer->msg[5], - nas_buffer->N_bytes - 5, - mac - ); + integrity_generate(&ue_emm_ctx->security_ctxt, nas_buffer, mac); memcpy(&nas_buffer->msg[1],mac,4); @@ -1886,14 +1908,7 @@ s1ap_nas_transport::pack_attach_accept(ue_emm_ctx_t *ue_emm_ctx, ue_ecm_ctx_t *u liblte_mme_pack_attach_accept_msg(&attach_accept, sec_hdr_type, ue_emm_ctx->security_ctxt.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); //Integrity protect NAS message uint8_t mac[4]; - srslte::security_128_eia1 (&ue_emm_ctx->security_ctxt.k_nas_int[16], - ue_emm_ctx->security_ctxt.dl_nas_count, - 0, - SECURITY_DIRECTION_DOWNLINK, - &nas_buffer->msg[5], - nas_buffer->N_bytes - 5, - mac - ); + integrity_generate(&ue_emm_ctx->security_ctxt, nas_buffer, mac); memcpy(&nas_buffer->msg[1],mac,4); m_s1ap_log->info("Packed Attach Complete\n"); @@ -2006,14 +2021,7 @@ s1ap_nas_transport::pack_emm_information( ue_ctx_t *ue_ctx, srslte::byte_buffer_ } uint8_t mac[4]; - srslte::security_128_eia1 (&emm_ctx->security_ctxt.k_nas_int[16], - emm_ctx->security_ctxt.dl_nas_count, - 0, - SECURITY_DIRECTION_DOWNLINK, - &nas_buffer->msg[5], - nas_buffer->N_bytes - 5, - mac - ); + integrity_generate(&emm_ctx->security_ctxt, nas_buffer, mac); memcpy(&nas_buffer->msg[1],mac,4); //Copy NAS PDU to Downlink NAS Trasport message buffer @@ -2220,6 +2228,35 @@ void s1ap_nas_transport::cipher_encrypt(eps_sec_ctx_t * sec_ctxt, srslte::byte_b } } +void s1ap_nas_transport::integrity_generate(eps_sec_ctx_t *sec_ctxt, + srslte::byte_buffer_t *pdu, + uint8_t *mac) { + switch (sec_ctxt->integ_algo) { + case srslte::INTEGRITY_ALGORITHM_ID_EIA0: + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1: + srslte::security_128_eia1(&sec_ctxt->k_nas_int[16], + sec_ctxt->dl_nas_count, + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + mac); + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: + srslte::security_128_eia2(&sec_ctxt->k_nas_int[16], + sec_ctxt->dl_nas_count, + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + mac); + break; + default: + break; + } +} + void s1ap_nas_transport::log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req) { From e5e091b0c9a50f515fe1efd4246155ea99aef81f Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Sun, 18 Nov 2018 21:18:17 +0100 Subject: [PATCH 03/12] Minor fixes and code clean up --- srsepc/src/mme/s1ap_nas_transport.cc | 41 ++++++++++------------------ 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 5f34432f3..b0ef573ce 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -547,22 +547,6 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id, bool* reply_flag, struct sctp_sndrcvinfo *enb_sri) { - //Parse the message security header - uint8 pd = 0; - uint8 sec_hdr_type = 0; - liblte_mme_parse_msg_sec_header((LIBLTE_BYTE_MSG_STRUCT*)nas_msg, &pd, &sec_hdr_type); - - bool integrity_valid = false; - if(sec_hdr_type != LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) - { - m_s1ap_log->info("Attach request -- GUTI-stlye attach request is not integrity protected\n"); - m_s1ap_log->console("Attach request -- GUTI-stlye attach request is not integrity protected\n"); - } - else{ - m_s1ap_log->info("Attach request -- GUTI-stlye attach request is integrity protected\n"); - m_s1ap_log->console("Attach request -- GUTI-stlye attach request is integrity protected\n"); - } - //GUTI style attach uint32_t m_tmsi = attach_req.eps_mobile_id.guti.m_tmsi; @@ -657,6 +641,7 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id, ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; m_s1ap_log->console("Found UE context. IMSI: %015lu, old eNB UE S1ap Id %d, old MME UE S1AP Id %d\n",emm_ctx->imsi, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id); //Check NAS integrity + // Initial GUTI attach request should be always unencrypted and therefore no problem bool msg_valid = false; emm_ctx->security_ctxt.ul_nas_count++; msg_valid = integrity_check(&emm_ctx->security_ctxt, nas_msg); @@ -1224,7 +1209,7 @@ s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ m_s1ap_log->console("ID Response -- IMSI: %015lu\n", imsi); //Set UE's context IMSI - emm_ctx->imsi=imsi; + emm_ctx->imsi = imsi; ecm_ctx->imsi = imsi; //Get Authentication Vectors from HSS @@ -1677,8 +1662,8 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, sm_cmd.nonce_ue_present=false; sm_cmd.nonce_mme_present=false; - uint8_t sec_hdr_type=3; - LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg(&sm_cmd,sec_hdr_type, ue_emm_ctx->security_ctxt.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + uint8_t sec_hdr_type = LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT; + LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg(&sm_cmd, sec_hdr_type, ue_emm_ctx->security_ctxt.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) { m_s1ap_log->console("Error packing Security Mode Command\n"); @@ -1686,7 +1671,7 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, } //Generate EPS security context - uint8_t mac[4]; + srslte::security_generate_k_nas( ue_emm_ctx->security_ctxt.k_asme, ue_emm_ctx->security_ctxt.cipher_algo, ue_emm_ctx->security_ctxt.integ_algo, @@ -1704,9 +1689,10 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, m_s1ap_log->info_hex(ue_emm_ctx->security_ctxt.k_enb, 32, "Key eNodeB (k_enb)\n"); //Generate MAC for integrity protection + uint8_t mac[4]; integrity_generate(&ue_emm_ctx->security_ctxt, nas_buffer, mac); - memcpy(&nas_buffer->msg[1],mac,4); + //Copy NAS PDU to Downlink NAS Trasport message buffer memcpy(dw_nas->NAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); dw_nas->NAS_PDU.n_octets = nas_buffer->N_bytes; @@ -1902,16 +1888,19 @@ s1ap_nas_transport::pack_attach_accept(ue_emm_ctx_t *ue_emm_ctx, ue_ecm_ctx_t *u act_def_eps_bearer_context_req.esm_cause_present = false; act_def_eps_bearer_context_req.connectivity_type_present = false; - uint8_t sec_hdr_type =2; + uint8_t sec_hdr_type = LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED; ue_emm_ctx->security_ctxt.dl_nas_count++; liblte_mme_pack_activate_default_eps_bearer_context_request_msg(&act_def_eps_bearer_context_req, &attach_accept.esm_msg); liblte_mme_pack_attach_accept_msg(&attach_accept, sec_hdr_type, ue_emm_ctx->security_ctxt.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); - //Integrity protect NAS message + + // Encrypt NAS message + cipher_encrypt(&ue_emm_ctx->security_ctxt, nas_buffer); + + // Integrity protect NAS message uint8_t mac[4]; integrity_generate(&ue_emm_ctx->security_ctxt, nas_buffer, mac); - memcpy(&nas_buffer->msg[1],mac,4); - m_s1ap_log->info("Packed Attach Complete\n"); + m_s1ap_log->info("Packed Attach Accept\n"); //Add nas message to context setup request erab_ctxt->nAS_PDU_present = true; @@ -2010,7 +1999,7 @@ s1ap_nas_transport::pack_emm_information( ue_ctx_t *ue_ctx, srslte::byte_buffer_ emm_info.utc_and_local_time_zone_present = false; emm_info.net_dst_present = false; - uint8_t sec_hdr_type =2; + uint8_t sec_hdr_type = LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED; emm_ctx->security_ctxt.dl_nas_count++; LIBLTE_ERROR_ENUM err = liblte_mme_pack_emm_information_msg(&emm_info, sec_hdr_type, emm_ctx->security_ctxt.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) From 0dfa6426dd8b9c68acdcd73919d7383dc133f1c9 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Sun, 18 Nov 2018 21:35:55 +0100 Subject: [PATCH 04/12] restructure handle_initial_ue_message --- srsepc/src/mme/s1ap_nas_transport.cc | 116 ++++++++++++++------------- 1 file changed, 59 insertions(+), 57 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index b0ef573ce..e1b63c11a 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -97,81 +97,83 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA srslte::byte_buffer_t *nas_msg = m_pool->allocate(); memcpy(nas_msg->msg, &init_ue->NAS_PDU.buffer, init_ue->NAS_PDU.n_octets); nas_msg->N_bytes = init_ue->NAS_PDU.n_octets; + uint32_t *m_tmsi; + + bool rtn = true; liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); - if(msg_type == LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST) - { - m_s1ap_log->info("Received Attach Request \n"); - m_s1ap_log->console("Received Attach Request \n"); - handle_nas_attach_request(enb_ue_s1ap_id, nas_msg, reply_buffer,reply_flag, enb_sri); - } - else if(msg_type == LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST) - { - m_s1ap_log->info("Received Service Request \n"); - m_s1ap_log->console("Received Service Request \n"); - if(!init_ue->S_TMSI_present) - { - m_s1ap_log->error("Service request -- S-TMSI not present\n"); - m_s1ap_log->console("Service request -- S-TMSI not present\n" ); - return false; - } - uint32_t *m_tmsi = (uint32_t*) &init_ue->S_TMSI.m_TMSI.buffer; - uint32_t enb_ue_s1ap_id = init_ue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; - m_s1ap_log->info("Service request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); - m_s1ap_log->console("Service request -- S-TMSI 0x%x\n", ntohl(*m_tmsi) ); - m_s1ap_log->info("Service request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); - m_s1ap_log->console("Service request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); - handle_nas_service_request(ntohl(*m_tmsi), enb_ue_s1ap_id, nas_msg, reply_buffer,reply_flag, enb_sri); - return true; - } - else if(msg_type == LIBLTE_MME_MSG_TYPE_DETACH_REQUEST) - { - m_s1ap_log->console("Received Initial UE message -- Detach Request\n"); - m_s1ap_log->info("Received Initial UE message -- Detach Request\n"); - if(!init_ue->S_TMSI_present) - { - m_s1ap_log->error("Detach request -- S-TMSI not present\n"); - m_s1ap_log->console("Detach request -- S-TMSI not present\n" ); - return false; - } - uint32_t *m_tmsi = (uint32_t*) &init_ue->S_TMSI.m_TMSI.buffer; - uint32_t enb_ue_s1ap_id = init_ue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; - m_s1ap_log->info("Detach Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); - m_s1ap_log->console("Detach Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi) ); - m_s1ap_log->info("Detach Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); - m_s1ap_log->console("Detach Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); - - handle_nas_detach_request(ntohl(*m_tmsi), enb_ue_s1ap_id, nas_msg, reply_buffer,reply_flag, enb_sri); - return true; - } - else if(msg_type == LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST) + switch(msg_type) { + case LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST: + m_s1ap_log->info("Received Attach Request \n"); + m_s1ap_log->console("Received Attach Request \n"); + handle_nas_attach_request(enb_ue_s1ap_id, nas_msg, reply_buffer,reply_flag, enb_sri); + break; + case LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST: + m_s1ap_log->info("Received Service Request \n"); + m_s1ap_log->console("Received Service Request \n"); + if(!init_ue->S_TMSI_present) + { + m_s1ap_log->error("Service request -- S-TMSI not present\n"); + m_s1ap_log->console("Service request -- S-TMSI not present\n" ); + rtn = false; + break; + } + m_tmsi = (uint32_t*) &init_ue->S_TMSI.m_TMSI.buffer; + m_s1ap_log->info("Service request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); + m_s1ap_log->console("Service request -- S-TMSI 0x%x\n", ntohl(*m_tmsi) ); + m_s1ap_log->info("Service request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); + m_s1ap_log->console("Service request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); + handle_nas_service_request(ntohl(*m_tmsi), enb_ue_s1ap_id, nas_msg, reply_buffer,reply_flag, enb_sri); + rtn = true; + break; + case LIBLTE_MME_MSG_TYPE_DETACH_REQUEST: + m_s1ap_log->console("Received Initial UE message -- Detach Request\n"); + m_s1ap_log->info("Received Initial UE message -- Detach Request\n"); + if(!init_ue->S_TMSI_present) + { + m_s1ap_log->error("Detach request -- S-TMSI not present\n"); + m_s1ap_log->console("Detach request -- S-TMSI not present\n" ); + rtn = false; + break; + } + m_tmsi = (uint32_t*) &init_ue->S_TMSI.m_TMSI.buffer; + m_s1ap_log->info("Detach Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); + m_s1ap_log->console("Detach Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi) ); + m_s1ap_log->info("Detach Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); + m_s1ap_log->console("Detach Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); + + handle_nas_detach_request(ntohl(*m_tmsi), enb_ue_s1ap_id, nas_msg, reply_buffer,reply_flag, enb_sri); + rtn = true; + break; + case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST: m_s1ap_log->console("Received Initial UE message -- Tracking Area Update Request\n"); m_s1ap_log->info("Received Initial UE message -- Tracking Area Update Request\n"); if(!init_ue->S_TMSI_present) { m_s1ap_log->error("Tracking Area Update Request -- S-TMSI not present\n"); m_s1ap_log->console("Tracking Area Update Request -- S-TMSI not present\n" ); - return false; + rtn = false; + break; } - uint32_t *m_tmsi = (uint32_t*) &init_ue->S_TMSI.m_TMSI.buffer; - uint32_t enb_ue_s1ap_id = init_ue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; + m_tmsi = (uint32_t*) &init_ue->S_TMSI.m_TMSI.buffer; m_s1ap_log->info("Tracking Area Update Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); m_s1ap_log->console("Tracking Area Update Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi) ); m_s1ap_log->info("Tracking Area Update Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); m_s1ap_log->console("Tracking Area Update Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); handle_nas_tracking_area_update_request(ntohl(*m_tmsi), enb_ue_s1ap_id, nas_msg, reply_buffer,reply_flag, enb_sri); - return true; - } - else - { - m_s1ap_log->info("Unhandled Initial UE Message 0x%x\n",msg_type); - m_s1ap_log->console("Unhandled Initial UE Message 0x%x \n", msg_type); + rtn = true; + break; + + default: + m_s1ap_log->info("Unhandled Initial UE Message 0x%x\n",msg_type); + m_s1ap_log->console("Unhandled Initial UE Message 0x%x \n", msg_type); + break; } - m_pool->deallocate(nas_msg); - return true; + m_pool->deallocate(nas_msg); + return rtn; } bool From 894471e32650ca8464dbb8943e2fba350cb2cc6d Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Sun, 18 Nov 2018 21:36:36 +0100 Subject: [PATCH 05/12] restructure handle_initial_ue_message --- srsepc/src/mme/s1ap_nas_transport.cc | 129 +++++++++++++-------------- 1 file changed, 64 insertions(+), 65 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index e1b63c11a..8744ff238 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -101,75 +101,74 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA bool rtn = true; - liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); - switch(msg_type) + liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *)nas_msg, &pd, &msg_type); + switch (msg_type) { - case LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST: - m_s1ap_log->info("Received Attach Request \n"); - m_s1ap_log->console("Received Attach Request \n"); - handle_nas_attach_request(enb_ue_s1ap_id, nas_msg, reply_buffer,reply_flag, enb_sri); - break; - case LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST: - m_s1ap_log->info("Received Service Request \n"); - m_s1ap_log->console("Received Service Request \n"); - if(!init_ue->S_TMSI_present) - { - m_s1ap_log->error("Service request -- S-TMSI not present\n"); - m_s1ap_log->console("Service request -- S-TMSI not present\n" ); - rtn = false; - break; - } - m_tmsi = (uint32_t*) &init_ue->S_TMSI.m_TMSI.buffer; - m_s1ap_log->info("Service request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); - m_s1ap_log->console("Service request -- S-TMSI 0x%x\n", ntohl(*m_tmsi) ); - m_s1ap_log->info("Service request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); - m_s1ap_log->console("Service request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); - handle_nas_service_request(ntohl(*m_tmsi), enb_ue_s1ap_id, nas_msg, reply_buffer,reply_flag, enb_sri); - rtn = true; - break; - case LIBLTE_MME_MSG_TYPE_DETACH_REQUEST: - m_s1ap_log->console("Received Initial UE message -- Detach Request\n"); - m_s1ap_log->info("Received Initial UE message -- Detach Request\n"); - if(!init_ue->S_TMSI_present) - { - m_s1ap_log->error("Detach request -- S-TMSI not present\n"); - m_s1ap_log->console("Detach request -- S-TMSI not present\n" ); - rtn = false; - break; - } - m_tmsi = (uint32_t*) &init_ue->S_TMSI.m_TMSI.buffer; - m_s1ap_log->info("Detach Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); - m_s1ap_log->console("Detach Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi) ); - m_s1ap_log->info("Detach Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); - m_s1ap_log->console("Detach Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); - - handle_nas_detach_request(ntohl(*m_tmsi), enb_ue_s1ap_id, nas_msg, reply_buffer,reply_flag, enb_sri); - rtn = true; + case LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST: + m_s1ap_log->info("Received Attach Request \n"); + m_s1ap_log->console("Received Attach Request \n"); + handle_nas_attach_request(enb_ue_s1ap_id, nas_msg, reply_buffer, reply_flag, enb_sri); + break; + case LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST: + m_s1ap_log->info("Received Service Request \n"); + m_s1ap_log->console("Received Service Request \n"); + if (!init_ue->S_TMSI_present) + { + m_s1ap_log->error("Service request -- S-TMSI not present\n"); + m_s1ap_log->console("Service request -- S-TMSI not present\n"); + rtn = false; break; - case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST: - m_s1ap_log->console("Received Initial UE message -- Tracking Area Update Request\n"); - m_s1ap_log->info("Received Initial UE message -- Tracking Area Update Request\n"); - if(!init_ue->S_TMSI_present) - { - m_s1ap_log->error("Tracking Area Update Request -- S-TMSI not present\n"); - m_s1ap_log->console("Tracking Area Update Request -- S-TMSI not present\n" ); - rtn = false; - break; - } - m_tmsi = (uint32_t*) &init_ue->S_TMSI.m_TMSI.buffer; - m_s1ap_log->info("Tracking Area Update Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); - m_s1ap_log->console("Tracking Area Update Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi) ); - m_s1ap_log->info("Tracking Area Update Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); - m_s1ap_log->console("Tracking Area Update Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); - - handle_nas_tracking_area_update_request(ntohl(*m_tmsi), enb_ue_s1ap_id, nas_msg, reply_buffer,reply_flag, enb_sri); - rtn = true; + } + m_tmsi = (uint32_t *)&init_ue->S_TMSI.m_TMSI.buffer; + m_s1ap_log->info("Service request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); + m_s1ap_log->console("Service request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); + m_s1ap_log->info("Service request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); + m_s1ap_log->console("Service request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); + handle_nas_service_request(ntohl(*m_tmsi), enb_ue_s1ap_id, nas_msg, reply_buffer, reply_flag, enb_sri); + rtn = true; + break; + case LIBLTE_MME_MSG_TYPE_DETACH_REQUEST: + m_s1ap_log->console("Received Initial UE message -- Detach Request\n"); + m_s1ap_log->info("Received Initial UE message -- Detach Request\n"); + if (!init_ue->S_TMSI_present) + { + m_s1ap_log->error("Detach request -- S-TMSI not present\n"); + m_s1ap_log->console("Detach request -- S-TMSI not present\n"); + rtn = false; break; - - default: - m_s1ap_log->info("Unhandled Initial UE Message 0x%x\n",msg_type); - m_s1ap_log->console("Unhandled Initial UE Message 0x%x \n", msg_type); + } + m_tmsi = (uint32_t *)&init_ue->S_TMSI.m_TMSI.buffer; + m_s1ap_log->info("Detach Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); + m_s1ap_log->console("Detach Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); + m_s1ap_log->info("Detach Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); + m_s1ap_log->console("Detach Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); + + handle_nas_detach_request(ntohl(*m_tmsi), enb_ue_s1ap_id, nas_msg, reply_buffer, reply_flag, enb_sri); + rtn = true; + break; + case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST: + m_s1ap_log->console("Received Initial UE message -- Tracking Area Update Request\n"); + m_s1ap_log->info("Received Initial UE message -- Tracking Area Update Request\n"); + if (!init_ue->S_TMSI_present) + { + m_s1ap_log->error("Tracking Area Update Request -- S-TMSI not present\n"); + m_s1ap_log->console("Tracking Area Update Request -- S-TMSI not present\n"); + rtn = false; break; + } + m_tmsi = (uint32_t *)&init_ue->S_TMSI.m_TMSI.buffer; + m_s1ap_log->info("Tracking Area Update Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); + m_s1ap_log->console("Tracking Area Update Request -- S-TMSI 0x%x\n", ntohl(*m_tmsi)); + m_s1ap_log->info("Tracking Area Update Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); + m_s1ap_log->console("Tracking Area Update Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); + + handle_nas_tracking_area_update_request(ntohl(*m_tmsi), enb_ue_s1ap_id, nas_msg, reply_buffer, reply_flag, enb_sri); + rtn = true; + break; + default: + m_s1ap_log->info("Unhandled Initial UE Message 0x%x\n", msg_type); + m_s1ap_log->console("Unhandled Initial UE Message 0x%x \n", msg_type); + break; } m_pool->deallocate(nas_msg); From 718262eaaf8336b53f903d9f55c1719fba5ec5c3 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Sun, 18 Nov 2018 22:29:32 +0100 Subject: [PATCH 06/12] restucture NAS uplink message: todo security of message --- srsepc/src/mme/s1ap_nas_transport.cc | 171 ++++++++++++++++++--------- 1 file changed, 113 insertions(+), 58 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 8744ff238..4e35467cc 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -199,10 +199,117 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA srslte::byte_buffer_t *nas_msg = m_pool->allocate(); memcpy(nas_msg->msg, &ul_xport->NAS_PDU.buffer, ul_xport->NAS_PDU.n_octets); nas_msg->N_bytes = ul_xport->NAS_PDU.n_octets; - liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + bool msg_encrypted = false; // Parse the message security header liblte_mme_parse_msg_sec_header((LIBLTE_BYTE_MSG_STRUCT*)nas_msg, &pd, &sec_hdr_type); + + // Invalid Security Header Type simply return function + if (!(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS || + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED || + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT || + sec_hdr_type ==LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT)) + { + m_s1ap_log->error("Unhandled security header type in Uplink NAS Transport: %d\n", sec_hdr_type); + m_pool->deallocate(nas_msg); + return false; + } + + //Find UE EMM context if message is security protected. + if(sec_hdr_type != LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS) + { + //Make sure EMM context is set-up, to do integrity check/de-chiphering + if(emm_ctx->imsi == 0) + { + //No EMM context found. + //Perhaps a temporary context is being created? + //This can happen with integrity protected identity reponse messages + if( !(msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) + { + m_s1ap_log->warning("Uplink NAS: could not find security context for integrity protected message. MME-UE S1AP id: %d\n",mme_ue_s1ap_id); + m_pool->deallocate(nas_msg); + return false; + } + } + } + + // Check MAC if message is integrity protected + if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED || + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT || + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) + { + mac_valid = integrity_check(&emm_ctx->security_ctxt, nas_msg); + if (mac_valid == false){ + m_s1ap_log->warning("Invalid MAC message. Even if security header indicates integrity protection\n" ); + } + } + + // Decrypt message if indicated + if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED || + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) + { + cipher_decrypt(&emm_ctx->security_ctxt, nas_msg); + msg_encrypted = true; + } + + // Now parse message header and handle message + liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + + // Handle message and check if security requirements for messages + switch (msg_type) + { + case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE: + m_s1ap_log->info("UL NAS: Received Identity Response (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); + m_s1ap_log->console("UL NAS: Received Identity Response\n"); + handle_identity_response(nas_msg, ue_ctx, reply_buffer, reply_flag); + break; + case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: + m_s1ap_log->info("UL NAS: Received Authentication Response\n"); + m_s1ap_log->console("UL NAS: Received Authentication Response\n"); + handle_nas_authentication_response(nas_msg, ue_ctx, reply_buffer, reply_flag); + break; + // Authentication failure with the option sync failure can be sent not integrity protected + case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE: + m_s1ap_log->info("UL NAS: Authentication Failure\n"); + m_s1ap_log->console("UL NAS: Authentication Failure\n"); + handle_authentication_failure(nas_msg, ue_ctx, reply_buffer, reply_flag); + break; + // Detach request can be sent not integrity protected when "power off" option is used + case LIBLTE_MME_MSG_TYPE_DETACH_REQUEST: + m_s1ap_log->info("UL NAS: Detach Request\n"); + m_s1ap_log->console("UL NAS: Detach Request\n"); + handle_nas_detach_request(nas_msg, ue_ctx, reply_buffer, reply_flag); + break; + case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: + m_s1ap_log->info("UL NAS: Received Security Mode Complete\n"); + m_s1ap_log->console("UL NAS: Received Security Mode Complete\n"); + emm_ctx->security_ctxt.ul_nas_count = 0; + emm_ctx->security_ctxt.dl_nas_count = 0; + handle_nas_security_mode_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); + break; + case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: + m_s1ap_log->info("UL NAS: Received Attach Complete\n"); + m_s1ap_log->console("UL NAS: Received Attach Complete\n"); + handle_nas_attach_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); + break; + case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: + m_s1ap_log->info("UL NAS: Received ESM Information Response\n"); + m_s1ap_log->console("UL NAS: Received ESM Information Response\n"); + handle_esm_information_response(nas_msg, ue_ctx, reply_buffer, reply_flag); + break; + case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST: + m_s1ap_log->info("UL NAS: Tracking Area Update Request\n"); + m_s1ap_log->console("UL NAS: Tracking Area Update Request\n"); + handle_tracking_area_update_request(nas_msg, ue_ctx, reply_buffer, reply_flag); + break; + default: + m_s1ap_log->warning("Unhandled NAS message 0x%x\n", msg_type); + m_s1ap_log->console("Unhandled NAS message 0x%x\n", msg_type); + m_pool->deallocate(nas_msg); + return false; + } //Find UE EMM context if message is security protected. if(sec_hdr_type != LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS) @@ -266,25 +373,12 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA else if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) { - mac_valid = integrity_check(&emm_ctx->security_ctxt, nas_msg); - if (mac_valid == false){ - m_s1ap_log->warning("Invalid MAC message.\n" ); - return false; - } - if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) { - cipher_decrypt(&emm_ctx->security_ctxt, nas_msg); - liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + } switch (msg_type) { - case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: - m_s1ap_log->info("Uplink NAS: Received Security Mode Complete\n"); - m_s1ap_log->console("Uplink NAS: Received Security Mode Complete\n"); - emm_ctx->security_ctxt.ul_nas_count = 0; - emm_ctx->security_ctxt.dl_nas_count = 0; - handle_nas_security_mode_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); - break; + default: m_s1ap_log->warning("Unhandled NAS message with new EPS security context 0x%x\n", msg_type ); m_s1ap_log->warning("Unhandled NAS message with new EPS security context 0x%x\n", msg_type ); @@ -292,46 +386,8 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA } else if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED) { - //Integrity protected NAS message, possibly ciphered. - emm_ctx->security_ctxt.ul_nas_count++; - mac_valid = integrity_check(&emm_ctx->security_ctxt, nas_msg); - if(mac_valid == false){ - m_s1ap_log->warning("Invalid MAC in NAS message type 0x%x.\n", msg_type); - m_pool->deallocate(nas_msg); - return false; - } - - if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED){ - cipher_decrypt(&emm_ctx->security_ctxt, nas_msg); - liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); - } - switch (msg_type) { - case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: - m_s1ap_log->info("Integrity Protected UL NAS: Received Attach Complete\n"); - m_s1ap_log->console("Integrity Protected UL NAS: Received Attach Complete\n"); - handle_nas_attach_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); - break; - case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: - m_s1ap_log->info("Integrity Protected UL NAS: Received ESM Information Response\n"); - m_s1ap_log->console("Integrity Protected UL NAS: Received ESM Information Response\n"); - handle_esm_information_response(nas_msg, ue_ctx, reply_buffer, reply_flag); - break; - case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST: - m_s1ap_log->info("Integrity Protected UL NAS: Tracking Area Update Request\n"); - m_s1ap_log->console("Integrity Protected UL NAS: Tracking Area Update Request\n"); - handle_tracking_area_update_request(nas_msg, ue_ctx, reply_buffer, reply_flag); - break; - case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE: - m_s1ap_log->info("Integrity Protected UL NAS: Authentication Failure\n"); - m_s1ap_log->console("Integrity Protected UL NAS: Authentication Failure\n"); - handle_authentication_failure(nas_msg, ue_ctx, reply_buffer, reply_flag); - break; - case LIBLTE_MME_MSG_TYPE_DETACH_REQUEST: - m_s1ap_log->info("Integrity Protected UL NAS: Detach Request\n"); - m_s1ap_log->console("Integrity Protected UL NAS: Detach Request\n"); - handle_nas_detach_request(nas_msg, ue_ctx, reply_buffer, reply_flag); - break; + default: m_s1ap_log->warning("Unhandled NAS integrity protected message 0x%x\n", msg_type ); m_s1ap_log->console("Unhandled NAS integrity protected message 0x%x\n", msg_type ); @@ -341,9 +397,7 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA } else { - m_s1ap_log->error("Unhandled security header type in Uplink NAS Transport: %d\n", sec_hdr_type); - m_pool->deallocate(nas_msg); - return false; + } @@ -646,6 +700,7 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id, bool msg_valid = false; emm_ctx->security_ctxt.ul_nas_count++; msg_valid = integrity_check(&emm_ctx->security_ctxt, nas_msg); + if(msg_valid == true && emm_ctx->state == EMM_STATE_DEREGISTERED) { m_s1ap_log->console("GUTI Attach Integrity valid. UL count %d, DL count %d\n",emm_ctx->security_ctxt.ul_nas_count, emm_ctx->security_ctxt.dl_nas_count); From 2543a84aa423541677b643fda86b87edf1e0d9d0 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Mon, 19 Nov 2018 13:39:30 +0100 Subject: [PATCH 07/12] Minor changes in nas uplink transport and increase uplink count --- srsepc/src/mme/s1ap_nas_transport.cc | 164 ++++++++------------------- 1 file changed, 46 insertions(+), 118 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 4e35467cc..fd40f6da4 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -102,6 +102,7 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA bool rtn = true; liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *)nas_msg, &pd, &msg_type); + switch (msg_type) { case LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST: @@ -182,6 +183,7 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA uint32_t enb_ue_s1ap_id = ul_xport->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; uint32_t mme_ue_s1ap_id = ul_xport->MME_UE_S1AP_ID.MME_UE_S1AP_ID; bool mac_valid = false; + bool increase_ul_nas_cnt = true; //Get UE ECM context ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); @@ -216,24 +218,6 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA return false; } - //Find UE EMM context if message is security protected. - if(sec_hdr_type != LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS) - { - //Make sure EMM context is set-up, to do integrity check/de-chiphering - if(emm_ctx->imsi == 0) - { - //No EMM context found. - //Perhaps a temporary context is being created? - //This can happen with integrity protected identity reponse messages - if( !(msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) - { - m_s1ap_log->warning("Uplink NAS: could not find security context for integrity protected message. MME-UE S1AP id: %d\n",mme_ue_s1ap_id); - m_pool->deallocate(nas_msg); - return false; - } - } - } - // Check MAC if message is integrity protected if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED || @@ -257,6 +241,25 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA // Now parse message header and handle message liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + + //Find UE EMM context if message is security protected. + if(sec_hdr_type != LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS) + { + //Make sure EMM context is set-up, to do integrity check/de-chiphering + if(emm_ctx->imsi == 0) + { + //No EMM context found. + //Perhaps a temporary context is being created? + //This can happen with integrity protected identity reponse messages + if( !(msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) + { + m_s1ap_log->warning("Uplink NAS: could not find security context for integrity protected message. MME-UE S1AP id: %d\n",mme_ue_s1ap_id); + m_pool->deallocate(nas_msg); + return false; + } + } + } + // Handle message and check if security requirements for messages switch (msg_type) { @@ -269,11 +272,15 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA m_s1ap_log->info("UL NAS: Received Authentication Response\n"); m_s1ap_log->console("UL NAS: Received Authentication Response\n"); handle_nas_authentication_response(nas_msg, ue_ctx, reply_buffer, reply_flag); + // Incase of a successful authentication response, security mode command follows. Reset counter for incoming security mode complete + emm_ctx->security_ctxt.ul_nas_count = 0; + emm_ctx->security_ctxt.dl_nas_count = 0; + increase_ul_nas_cnt = false; break; // Authentication failure with the option sync failure can be sent not integrity protected case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE: - m_s1ap_log->info("UL NAS: Authentication Failure\n"); - m_s1ap_log->console("UL NAS: Authentication Failure\n"); + m_s1ap_log->info("Plain UL NAS: Authentication Failure\n"); + m_s1ap_log->console("Plain UL NAS: Authentication Failure\n"); handle_authentication_failure(nas_msg, ue_ctx, reply_buffer, reply_flag); break; // Detach request can be sent not integrity protected when "power off" option is used @@ -285,8 +292,6 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: m_s1ap_log->info("UL NAS: Received Security Mode Complete\n"); m_s1ap_log->console("UL NAS: Received Security Mode Complete\n"); - emm_ctx->security_ctxt.ul_nas_count = 0; - emm_ctx->security_ctxt.dl_nas_count = 0; handle_nas_security_mode_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); break; case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: @@ -311,95 +316,11 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA return false; } - //Find UE EMM context if message is security protected. - if(sec_hdr_type != LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS) + //Increment UL NAS count. if counter not resetted in function, e.g., DL Security mode command after Authentication response + if(increase_ul_nas_cnt == true) { - //Make sure EMM context is set-up, to do integrity check/de-chiphering - if(emm_ctx->imsi == 0) - { - //No EMM context found. - //Perhaps a temporary context is being created? - //This can happen with integrity protected identity reponse messages - if( !(msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) - { - m_s1ap_log->warning("Uplink NAS: could not find security context for integrity protected message. MME-UE S1AP id: %d\n",mme_ue_s1ap_id); - m_pool->deallocate(nas_msg); - return false; - } - } - } - - if( sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS || - (msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) || - (msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) || - (msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) - { - //Only identity response and authentication response are valid as plain NAS. - //Sometimes authentication response/failure and identity response are sent as integrity protected, - //but these messages are sent when the securty context is not setup yet, so we cannot integrity check it. - switch(msg_type) - { - case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE: - m_s1ap_log->info("Uplink NAS: Received Identity Response\n"); - m_s1ap_log->console("Uplink NAS: Received Identity Response\n"); - handle_identity_response(nas_msg, ue_ctx, reply_buffer, reply_flag); - break; - case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: - m_s1ap_log->info("Uplink NAS: Received Authentication Response\n"); - m_s1ap_log->console("Uplink NAS: Received Authentication Response\n"); - handle_nas_authentication_response(nas_msg, ue_ctx, reply_buffer, reply_flag); - break; - // Authentication failure with the option sync failure can be sent not integrity protected - case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE: - m_s1ap_log->info("Plain UL NAS: Authentication Failure\n"); - m_s1ap_log->console("Plain UL NAS: Authentication Failure\n"); - handle_authentication_failure(nas_msg, ue_ctx, reply_buffer, reply_flag); - break; - // Detach request can be sent not integrity protected when "power off" option is used - case LIBLTE_MME_MSG_TYPE_DETACH_REQUEST: - m_s1ap_log->info("Plain Protected UL NAS: Detach Request\n"); - m_s1ap_log->console("Plain Protected UL NAS: Detach Request\n"); - handle_nas_detach_request(nas_msg, ue_ctx, reply_buffer, reply_flag); - break; - default: - m_s1ap_log->warning("Unhandled Plain NAS message 0x%x\n", msg_type ); - m_s1ap_log->console("Unhandled Plain NAS message 0x%x\n", msg_type ); - m_pool->deallocate(nas_msg); - return false; - } - //Increment UL NAS count. emm_ctx->security_ctxt.ul_nas_count++; } - else if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) - { - - if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) { - - } - - switch (msg_type) { - - default: - m_s1ap_log->warning("Unhandled NAS message with new EPS security context 0x%x\n", msg_type ); - m_s1ap_log->warning("Unhandled NAS message with new EPS security context 0x%x\n", msg_type ); - } - } - else if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED) - { - switch (msg_type) { - - default: - m_s1ap_log->warning("Unhandled NAS integrity protected message 0x%x\n", msg_type ); - m_s1ap_log->console("Unhandled NAS integrity protected message 0x%x\n", msg_type ); - m_pool->deallocate(nas_msg); - return false; - } - } - else - { - - } - if(*reply_flag == true) { @@ -698,7 +619,6 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id, //Check NAS integrity // Initial GUTI attach request should be always unencrypted and therefore no problem bool msg_valid = false; - emm_ctx->security_ctxt.ul_nas_count++; msg_valid = integrity_check(&emm_ctx->security_ctxt, nas_msg); if(msg_valid == true && emm_ctx->state == EMM_STATE_DEREGISTERED) @@ -751,7 +671,8 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id, m_s1ap_log->console("PDN Connectivity Request -- EPS Bearer Identity requested: %d\n", pdn_con_req.eps_bearer_id); m_s1ap_log->console("PDN Connectivity Request -- Procedure Transaction Id: %d\n", pdn_con_req.proc_transaction_id); m_s1ap_log->console("PDN Connectivity Request -- ESM Information Transfer requested: %s\n", pdn_con_req.esm_info_transfer_flag_present ? "true" : "false"); - + // Now increase the ul nas count, after enb key generation + emm_ctx->security_ctxt.ul_nas_count++; //Create session request m_s1ap_log->console("GUTI Attach -- NAS Integrity OK.\n"); if(ecm_ctx->eit) @@ -900,7 +821,6 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi, ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx; ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; - emm_ctx->security_ctxt.ul_nas_count++; mac_valid = short_integrity_check(&emm_ctx->security_ctxt, nas_msg); if(mac_valid) { @@ -935,10 +855,10 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi, //Get UE IP, and uplink F-TEID if(emm_ctx->ue_ip.s_addr == 0 ) { - m_s1ap_log->error("UE has no valid IP assigned upon reception of service request"); + m_s1ap_log->error("UE has no valid IP assigned upon reception of service request\n"); } - m_s1ap_log->console("UE previously assigned IP: %s",inet_ntoa(emm_ctx->ue_ip)); + m_s1ap_log->console("UE previously assigned IP: %s\n",inet_ntoa(emm_ctx->ue_ip)); //Re-generate K_eNB srslte::security_generate_k_enb(emm_ctx->security_ctxt.k_asme, emm_ctx->security_ctxt.ul_nas_count, emm_ctx->security_ctxt.k_enb); @@ -947,6 +867,8 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi, m_s1ap_log->info_hex(emm_ctx->security_ctxt.k_enb, 32, "Key eNodeB (k_enb)\n"); m_s1ap_log->console("UE Ctr TEID %d\n", emm_ctx->sgw_ctrl_fteid.teid); + // Now increase UL count + emm_ctx->security_ctxt.ul_nas_count++; //Save UE ctx to MME UE S1AP id m_s1ap->add_ue_ctx_to_mme_ue_s1ap_id_map(ue_ctx); m_s1ap->m_s1ap_ctx_mngmt_proc->send_initial_context_setup_request(emm_ctx, ecm_ctx,&ecm_ctx->erabs_ctx[5]); @@ -990,6 +912,7 @@ s1ap_nas_transport::handle_nas_detach_request(uint32_t m_tmsi, m_mme_gtpc->send_delete_session_request(emm_ctx->imsi); emm_ctx->state = EMM_STATE_DEREGISTERED; + // Move increasment to inital and nas uplink message emm_ctx->security_ctxt.ul_nas_count++; m_s1ap_log->console("Received. M-TMSI 0x%x\n", m_tmsi); @@ -1048,7 +971,7 @@ s1ap_nas_transport::handle_nas_tracking_area_update_request(uint32_t m_tmsi, ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx; ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; - emm_ctx->security_ctxt.ul_nas_count++;//Increment the NAS count, not to break the security ctx + // emm_ctx->security_ctxt.ul_nas_count++;//Increment the NAS count, not to break the security ctx return true; } bool @@ -1380,6 +1303,11 @@ s1ap_nas_transport::short_integrity_check(eps_sec_ctx_t * sec_ctxt, srslte::byte uint8_t exp_mac[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t *mac = &pdu->msg[2]; int i; + + if(pdu->N_bytes < 4){ + m_s1ap_log->warning("NAS message to short for short integrity check (pdu len: %d)", pdu->N_bytes); + return false; + } switch (sec_ctxt->integ_algo) { @@ -1390,8 +1318,8 @@ s1ap_nas_transport::short_integrity_check(eps_sec_ctx_t * sec_ctxt, srslte::byte sec_ctxt->ul_nas_count, 0, SECURITY_DIRECTION_UPLINK, - &pdu->msg[5], - pdu->N_bytes - 5, + &pdu->msg[0], + 2, &exp_mac[0]); break; case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: @@ -1399,8 +1327,8 @@ s1ap_nas_transport::short_integrity_check(eps_sec_ctx_t * sec_ctxt, srslte::byte sec_ctxt->ul_nas_count, 0, SECURITY_DIRECTION_UPLINK, - &pdu->msg[5], - pdu->N_bytes - 5, + &pdu->msg[0], + 2, &exp_mac[0]); break; default: From 4a2c563f85bbb36a96ac5b9ac28fde02fca575af Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Mon, 19 Nov 2018 13:40:16 +0100 Subject: [PATCH 08/12] increase uplink ul nas count --- srsepc/src/mme/s1ap_ctx_mngmt_proc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc index 6f9da6b0d..bc2bbc3d7 100644 --- a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc @@ -360,8 +360,8 @@ s1ap_ctx_mngmt_proc::handle_ue_context_release_complete(LIBLTE_S1AP_MESSAGE_UECO //Delete user plane context at the SPGW (but keep GTP-C connection). if (ecm_ctx->state == ECM_STATE_CONNECTED) { //There are active E-RABs, send release access mearers request - m_s1ap_log->console("There are active E-RABs, send release access mearers request"); - m_s1ap_log->info("There are active E-RABs, send release access mearers request"); + m_s1ap_log->console("There are active E-RABs, send release access mearers request\n"); + m_s1ap_log->info("There are active E-RABs, send release access mearers request\n"); m_mme_gtpc->send_release_access_bearers_request(ecm_ctx->imsi); //The handle_releease_access_bearers_response function will make sure to mark E-RABS DEACTIVATED //It will release the UEs downstream S1-u and keep the upstream S1-U connection active. From 82f69d66dc3e0de247b0ca19fffe52fbc2e69db9 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Mon, 19 Nov 2018 13:40:54 +0100 Subject: [PATCH 09/12] ul_nas_count increment tau request --- srsepc/src/mme/s1ap_nas_transport.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index fd40f6da4..641f8147f 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -971,7 +971,7 @@ s1ap_nas_transport::handle_nas_tracking_area_update_request(uint32_t m_tmsi, ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx; ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; - // emm_ctx->security_ctxt.ul_nas_count++;//Increment the NAS count, not to break the security ctx + emm_ctx->security_ctxt.ul_nas_count++; //Increment the NAS count, not to break the security ctx return true; } bool @@ -1303,7 +1303,7 @@ s1ap_nas_transport::short_integrity_check(eps_sec_ctx_t * sec_ctxt, srslte::byte uint8_t exp_mac[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t *mac = &pdu->msg[2]; int i; - + if(pdu->N_bytes < 4){ m_s1ap_log->warning("NAS message to short for short integrity check (pdu len: %d)", pdu->N_bytes); return false; From 1442606ee1378370c04a5186c0a806faeaeec31f Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Mon, 19 Nov 2018 14:11:33 +0100 Subject: [PATCH 10/12] Encryption for ESM request --- srsepc/src/mme/s1ap_nas_transport.cc | 37 +++++++++++++++++++--------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 641f8147f..9954577c9 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -217,6 +217,7 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA m_pool->deallocate(nas_msg); return false; } + // Todo: Check on count mismatch of uplink count // Check MAC if message is integrity protected if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || @@ -261,6 +262,17 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA } // Handle message and check if security requirements for messages + // 4.4.4.3 Integrity checking of NAS signalling messages in the MME + // Except the messages listed below, no NAS signalling messages shall be processed... + // - ATTACH REQUEST; + // - IDENTITY RESPONSE (if requested identification parameter is IMSI); + // - AUTHENTICATION RESPONSE; + // - AUTHENTICATION FAILURE; + // - SECURITY MODE REJECT; + // - DETACH REQUEST; + // - DETACH ACCEPT; + // - TRACKING AREA UPDATE REQUEST. + switch (msg_type) { case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE: @@ -269,48 +281,48 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA handle_identity_response(nas_msg, ue_ctx, reply_buffer, reply_flag); break; case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: - m_s1ap_log->info("UL NAS: Received Authentication Response\n"); + m_s1ap_log->info("UL NAS: Received Authentication Response (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); m_s1ap_log->console("UL NAS: Received Authentication Response\n"); handle_nas_authentication_response(nas_msg, ue_ctx, reply_buffer, reply_flag); - // Incase of a successful authentication response, security mode command follows. Reset counter for incoming security mode complete + // In case of a successful authentication response, security mode command follows. Reset counter for incoming security mode complete emm_ctx->security_ctxt.ul_nas_count = 0; emm_ctx->security_ctxt.dl_nas_count = 0; increase_ul_nas_cnt = false; break; // Authentication failure with the option sync failure can be sent not integrity protected case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE: - m_s1ap_log->info("Plain UL NAS: Authentication Failure\n"); - m_s1ap_log->console("Plain UL NAS: Authentication Failure\n"); + m_s1ap_log->info("UL NAS: Authentication Failure (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); + m_s1ap_log->console("UL NAS: Authentication Failure\n"); handle_authentication_failure(nas_msg, ue_ctx, reply_buffer, reply_flag); break; // Detach request can be sent not integrity protected when "power off" option is used case LIBLTE_MME_MSG_TYPE_DETACH_REQUEST: - m_s1ap_log->info("UL NAS: Detach Request\n"); + m_s1ap_log->info("UL NAS: Detach Request (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); m_s1ap_log->console("UL NAS: Detach Request\n"); handle_nas_detach_request(nas_msg, ue_ctx, reply_buffer, reply_flag); break; case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: - m_s1ap_log->info("UL NAS: Received Security Mode Complete\n"); + m_s1ap_log->info("UL NAS: Received Security Mode Complete (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); m_s1ap_log->console("UL NAS: Received Security Mode Complete\n"); handle_nas_security_mode_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); break; case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: - m_s1ap_log->info("UL NAS: Received Attach Complete\n"); + m_s1ap_log->info("UL NAS: Received Attach Complete (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); m_s1ap_log->console("UL NAS: Received Attach Complete\n"); handle_nas_attach_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); break; case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: - m_s1ap_log->info("UL NAS: Received ESM Information Response\n"); + m_s1ap_log->info("UL NAS: Received ESM Information Response (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); m_s1ap_log->console("UL NAS: Received ESM Information Response\n"); handle_esm_information_response(nas_msg, ue_ctx, reply_buffer, reply_flag); break; case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST: - m_s1ap_log->info("UL NAS: Tracking Area Update Request\n"); + m_s1ap_log->info("UL NAS: Tracking Area Update Request (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); m_s1ap_log->console("UL NAS: Tracking Area Update Request\n"); handle_tracking_area_update_request(nas_msg, ue_ctx, reply_buffer, reply_flag); break; default: - m_s1ap_log->warning("Unhandled NAS message 0x%x\n", msg_type); + m_s1ap_log->warning("Unhandled NAS message 0x%x (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", msg_type, sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); m_s1ap_log->console("Unhandled NAS message 0x%x\n", msg_type); m_pool->deallocate(nas_msg); return false; @@ -1732,10 +1744,11 @@ s1ap_nas_transport::pack_esm_information_request(srslte::byte_buffer_t *reply_ms return false; } + cipher_encrypt(&ue_emm_ctx->security_ctxt, nas_buffer); + uint8_t mac[4]; integrity_generate(&ue_emm_ctx->security_ctxt, nas_buffer, mac); - - memcpy(&nas_buffer->msg[1],mac,4); + memcpy(&nas_buffer->msg[1], mac, 4); //Copy NAS PDU to Downlink NAS Trasport message buffer memcpy(dw_nas->NAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); From 3b7eeb59095e7f1c3c894763d78c4da04d6356aa Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Mon, 19 Nov 2018 14:38:44 +0100 Subject: [PATCH 11/12] Do security (integrity checks in case of NAS UL message --- srsepc/src/mme/s1ap_nas_transport.cc | 32 +++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 9954577c9..320eee347 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -217,7 +217,7 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA m_pool->deallocate(nas_msg); return false; } - // Todo: Check on count mismatch of uplink count + // Todo: Check on count mismatch of uplink count and do resync nas counter... // Check MAC if message is integrity protected if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || @@ -227,7 +227,7 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA { mac_valid = integrity_check(&emm_ctx->security_ctxt, nas_msg); if (mac_valid == false){ - m_s1ap_log->warning("Invalid MAC message. Even if security header indicates integrity protection\n" ); + m_s1ap_log->warning("Invalid MAC message. Even if security header indicates integrity protection (Maybe: Identity Response or Authenticatio Response)\n" ); } } @@ -299,22 +299,44 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA case LIBLTE_MME_MSG_TYPE_DETACH_REQUEST: m_s1ap_log->info("UL NAS: Detach Request (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); m_s1ap_log->console("UL NAS: Detach Request\n"); + // FIXME: check integrity protection in detach request handle_nas_detach_request(nas_msg, ue_ctx, reply_buffer, reply_flag); break; case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: m_s1ap_log->info("UL NAS: Received Security Mode Complete (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); m_s1ap_log->console("UL NAS: Received Security Mode Complete\n"); - handle_nas_security_mode_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); + if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT && mac_valid == true){ + handle_nas_security_mode_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); + } else { + // Security Mode Complete was not integrity protected + m_s1ap_log->console("Security Mode Complete not integrity protected. Discard message.\n"); + m_s1ap_log->warning("Security Mode Complete not integrity protected. Discard message.\n"); + // FIXME: Should we not increase uplink count? increase_ul_nas_cnt = false? + } break; case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: m_s1ap_log->info("UL NAS: Received Attach Complete (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); m_s1ap_log->console("UL NAS: Received Attach Complete\n"); - handle_nas_attach_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); + if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED && mac_valid == true){ + handle_nas_attach_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); + } else { + // Attach Complete was not integrity protected + m_s1ap_log->console("Attach Complete not integrity protected. Discard message.\n"); + m_s1ap_log->warning("Attach Complete not integrity protected. Discard message.\n"); + // FIXME: Should we not increase uplink count? increase_ul_nas_cnt = false? + } break; case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: m_s1ap_log->info("UL NAS: Received ESM Information Response (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); m_s1ap_log->console("UL NAS: Received ESM Information Response\n"); - handle_esm_information_response(nas_msg, ue_ctx, reply_buffer, reply_flag); + if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED && mac_valid == true){ + handle_esm_information_response(nas_msg, ue_ctx, reply_buffer, reply_flag); + } else { + // Attach Complete was not integrity protected + m_s1ap_log->console("ESM Information Response not integrity protected. Discard message.\n"); + m_s1ap_log->warning("ESM Information Response not integrity protected. Discard message.\n"); + // FIXME: Should we not increase uplink count? increase_ul_nas_cnt = false? + } break; case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST: m_s1ap_log->info("UL NAS: Tracking Area Update Request (sec_hdr_type: 0x%x, mac_vaild: %s, msg_encrypted: %s) \n", sec_hdr_type, mac_valid == true ? "yes": "no", msg_encrypted == true ? "yes": "no"); From c480e577214aa6aa5d97fd88a9d8c54bd246a7e7 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Mon, 19 Nov 2018 15:34:57 +0100 Subject: [PATCH 12/12] Config based security algorithm selection --- srsepc/epc.conf.example | 6 ++++++ srsepc/hdr/mme/s1ap_common.h | 2 ++ srsepc/src/main.cc | 29 ++++++++++++++++++++++++++++ srsepc/src/mme/s1ap_nas_transport.cc | 13 +++++++------ 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 12562f1f0..55004d5c2 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -13,6 +13,10 @@ # apn: Set Access Point Name (APN) # mme_bind_addr: IP bind addr to listen for eNB S1-MME connnections # dns_addr: DNS server address for the UEs +# encryption_algo: Preferred encryption algorithm for NAS layer +# (default: EEA0, support: EEA1, EEA2) +# integrity_algo: Preferred integrity protection algorithm for NAS +# (default: EIA1, support: EIA1, EIA2 (EIA0 not support) # ##################################################################### [mme] @@ -24,6 +28,8 @@ mnc = 01 mme_bind_addr = 127.0.1.100 apn = srsapn dns_addr = 8.8.8.8 +encryption_algo = EEA0 +integrity_algo = EIA1 ##################################################################### # HSS configuration diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index e5c198748..200c172e1 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -95,6 +95,8 @@ typedef struct{ std::string mme_apn; bool pcap_enable; std::string pcap_filename; + srslte::CIPHERING_ALGORITHM_ID_ENUM encryption_algo; + srslte::INTEGRITY_ALGORITHM_ID_ENUM integrity_algo; } s1ap_args_t; typedef struct{ diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index b34114363..32c3be05a 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -85,6 +85,8 @@ parse_args(all_args_t *args, int argc, char* argv[]) { string mnc; string mme_bind_addr; string mme_apn; + string encryption_algo; + string integrity_algo; string spgw_bind_addr; string sgi_if_addr; string sgi_if_name; @@ -113,6 +115,8 @@ parse_args(all_args_t *args, int argc, char* argv[]) { ("mme.mme_bind_addr", bpo::value(&mme_bind_addr)->default_value("127.0.0.1"), "IP address of MME for S1 connnection") ("mme.dns_addr", bpo::value(&dns_addr)->default_value("8.8.8.8"), "IP address of the DNS server for the UEs") ("mme.apn", bpo::value(&mme_apn)->default_value(""), "Set Access Point Name (APN) for data services") + ("mme.encryption_algo", bpo::value(&encryption_algo)->default_value("EEA0"), "Set preferred encryption algorithm for NAS layer ") + ("mme.integrity_algo", bpo::value(&integrity_algo)->default_value("EIA1"), "Set preferred integrity protection algorithm for NAS") ("hss.db_file", bpo::value(&hss_db_file)->default_value("ue_db.csv"), ".csv file that stores UE's keys") ("hss.auth_algo", bpo::value(&hss_auth_algo)->default_value("milenage"), "HSS uthentication algorithm.") ("spgw.gtpu_bind_addr", bpo::value(&spgw_bind_addr)->default_value("127.0.0.1"), "IP address of SP-GW for the S1-U connection") @@ -215,6 +219,31 @@ parse_args(all_args_t *args, int argc, char* argv[]) { cout << "Error parsing mme.mnc:" << mnc << " - must be a 2 or 3-digit string." << endl; } + if(boost::iequals(encryption_algo, "eea0")){ + args->mme_args.s1ap_args.encryption_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0; + } else if (boost::iequals(encryption_algo, "eea1")){ + args->mme_args.s1ap_args.encryption_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA1; + } else if (boost::iequals(encryption_algo, "eea2")){ + args->mme_args.s1ap_args.encryption_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA2; + } else{ + args->mme_args.s1ap_args.encryption_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0; + cout << "Error parsing mme.encryption_algo:" << encryption_algo << " - must be EEA0, EEA1, or EEA2." << endl; + cout << "Using default mme.encryption_algo: EEA0" << endl; + } + + if (boost::iequals(integrity_algo, "eia0")){ + args->mme_args.s1ap_args.integrity_algo = srslte::INTEGRITY_ALGORITHM_ID_EIA0; + cout << "Warning parsing mme.integrity_algo:" << encryption_algo << " - EIA0 will not supported by UEs use EIA1 or EIA2" << endl; + } else if (boost::iequals(integrity_algo, "eia1")) { + args->mme_args.s1ap_args.integrity_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA1; + } else if (boost::iequals(integrity_algo, "eia2")) { + args->mme_args.s1ap_args.integrity_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA2; + } else { + args->mme_args.s1ap_args.integrity_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA1; + cout << "Error parsing mme.integrity_algo:" << encryption_algo << " - must be EIA0, EIA1, or EIA2." << endl; + cout << "Using default mme.integrity_algo: EIA1" << endl; + } + args->mme_args.s1ap_args.mme_bind_addr = mme_bind_addr; args->mme_args.s1ap_args.mme_name = mme_name; args->mme_args.s1ap_args.dns_addr = dns_addr; diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 320eee347..98db74143 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -1655,13 +1655,14 @@ s1ap_nas_transport::pack_security_mode_command(srslte::byte_buffer_t *reply_msg, //Pack NAS PDU LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sm_cmd; - // FIXME Selection based on UE caps and network preferences - - ue_emm_ctx->security_ctxt.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0; - ue_emm_ctx->security_ctxt.integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA1; + // FIXME: Selection based on UE caps and network preferences + ue_emm_ctx->security_ctxt.cipher_algo = m_s1ap->m_s1ap_args.encryption_algo; + ue_emm_ctx->security_ctxt.integ_algo = m_s1ap->m_s1ap_args.integrity_algo; + + sm_cmd.selected_nas_sec_algs.type_of_eea = (LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM) ue_emm_ctx->security_ctxt.cipher_algo; + sm_cmd.selected_nas_sec_algs.type_of_eia = (LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM) ue_emm_ctx->security_ctxt.integ_algo; - sm_cmd.selected_nas_sec_algs.type_of_eea = LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_EEA0; - sm_cmd.selected_nas_sec_algs.type_of_eia = LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_128_EIA1; + m_s1ap_log->info("Using security algorithms: EEA%d, EIA%d \n", (int) ue_emm_ctx->security_ctxt.cipher_algo, (int) ue_emm_ctx->security_ctxt.integ_algo); sm_cmd.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; sm_cmd.nas_ksi.nas_ksi=ue_emm_ctx->security_ctxt.eksi;