Minor changes in nas uplink transport and increase uplink count

master
David Rupprecht 6 years ago
parent 718262eaaf
commit 2543a84aa4

@ -102,6 +102,7 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA
bool rtn = true; bool rtn = true;
liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *)nas_msg, &pd, &msg_type); liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *)nas_msg, &pd, &msg_type);
switch (msg_type) switch (msg_type)
{ {
case LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST: 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 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; uint32_t mme_ue_s1ap_id = ul_xport->MME_UE_S1AP_ID.MME_UE_S1AP_ID;
bool mac_valid = false; bool mac_valid = false;
bool increase_ul_nas_cnt = true;
//Get UE ECM context //Get UE ECM context
ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); 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; 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 // Check MAC if message is integrity protected
if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || 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_AND_CIPHERED ||
@ -257,6 +241,25 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
// Now parse message header and handle message // Now parse message header and handle message
liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); 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 // Handle message and check if security requirements for messages
switch (msg_type) 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->info("UL NAS: Received Authentication Response\n");
m_s1ap_log->console("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); 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; break;
// Authentication failure with the option sync failure can be sent not integrity protected // Authentication failure with the option sync failure can be sent not integrity protected
case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE: case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE:
m_s1ap_log->info("UL NAS: Authentication Failure\n"); m_s1ap_log->info("Plain UL NAS: Authentication Failure\n");
m_s1ap_log->console("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); handle_authentication_failure(nas_msg, ue_ctx, reply_buffer, reply_flag);
break; break;
// Detach request can be sent not integrity protected when "power off" option is used // 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: 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\n");
m_s1ap_log->console("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); handle_nas_security_mode_complete(nas_msg, ue_ctx, reply_buffer, reply_flag);
break; break;
case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE:
@ -311,95 +316,11 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
return false; return false;
} }
//Find UE EMM context if message is security protected. //Increment UL NAS count. if counter not resetted in function, e.g., DL Security mode command after Authentication response
if(sec_hdr_type != LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS) 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++; 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) 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 //Check NAS integrity
// Initial GUTI attach request should be always unencrypted and therefore no problem // Initial GUTI attach request should be always unencrypted and therefore no problem
bool msg_valid = false; bool msg_valid = false;
emm_ctx->security_ctxt.ul_nas_count++;
msg_valid = integrity_check(&emm_ctx->security_ctxt, nas_msg); msg_valid = integrity_check(&emm_ctx->security_ctxt, nas_msg);
if(msg_valid == true && emm_ctx->state == EMM_STATE_DEREGISTERED) 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 -- 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 -- 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"); 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 //Create session request
m_s1ap_log->console("GUTI Attach -- NAS Integrity OK.\n"); m_s1ap_log->console("GUTI Attach -- NAS Integrity OK.\n");
if(ecm_ctx->eit) 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_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_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); mac_valid = short_integrity_check(&emm_ctx->security_ctxt, nas_msg);
if(mac_valid) 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 //Get UE IP, and uplink F-TEID
if(emm_ctx->ue_ip.s_addr == 0 ) 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 //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); 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->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); 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 //Save UE ctx to MME UE S1AP id
m_s1ap->add_ue_ctx_to_mme_ue_s1ap_id_map(ue_ctx); 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]); 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); m_mme_gtpc->send_delete_session_request(emm_ctx->imsi);
emm_ctx->state = EMM_STATE_DEREGISTERED; emm_ctx->state = EMM_STATE_DEREGISTERED;
// Move increasment to inital and nas uplink message
emm_ctx->security_ctxt.ul_nas_count++; emm_ctx->security_ctxt.ul_nas_count++;
m_s1ap_log->console("Received. M-TMSI 0x%x\n", m_tmsi); 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_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_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; return true;
} }
bool bool
@ -1381,6 +1304,11 @@ s1ap_nas_transport::short_integrity_check(eps_sec_ctx_t * sec_ctxt, srslte::byte
uint8_t *mac = &pdu->msg[2]; uint8_t *mac = &pdu->msg[2];
int i; 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) switch (sec_ctxt->integ_algo)
{ {
case srslte::INTEGRITY_ALGORITHM_ID_EIA0: case srslte::INTEGRITY_ALGORITHM_ID_EIA0:
@ -1390,8 +1318,8 @@ s1ap_nas_transport::short_integrity_check(eps_sec_ctx_t * sec_ctxt, srslte::byte
sec_ctxt->ul_nas_count, sec_ctxt->ul_nas_count,
0, 0,
SECURITY_DIRECTION_UPLINK, SECURITY_DIRECTION_UPLINK,
&pdu->msg[5], &pdu->msg[0],
pdu->N_bytes - 5, 2,
&exp_mac[0]); &exp_mac[0]);
break; break;
case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: 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, sec_ctxt->ul_nas_count,
0, 0,
SECURITY_DIRECTION_UPLINK, SECURITY_DIRECTION_UPLINK,
&pdu->msg[5], &pdu->msg[0],
pdu->N_bytes - 5, 2,
&exp_mac[0]); &exp_mac[0]);
break; break;
default: default:

Loading…
Cancel
Save