Wrapper functions for integrity generate

This commit is contained in:
David Rupprecht 2018-11-18 20:30:22 +01:00
parent 7eef2c1c4b
commit e547883a8f
2 changed files with 117 additions and 76 deletions

View File

@ -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_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 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 integrity_check(eps_sec_ctx_t * sec_ctxt, srslte::byte_buffer_t *pdu);
bool short_integrity_check(ue_emm_ctx_t *emm_ctx, 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_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); 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_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 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 } //namespace srsepc
#endif // SRSEPC_S1AP_NAS_TRANSPORT_H #endif // SRSEPC_S1AP_NAS_TRANSPORT_H

View File

@ -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) 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){ if (mac_valid == false){
m_s1ap_log->warning("Invalid MAC message.\n" ); m_s1ap_log->warning("Invalid MAC message.\n" );
return false; return false;
@ -293,7 +293,7 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
{ {
//Integrity protected NAS message, possibly ciphered. //Integrity protected NAS message, possibly ciphered.
emm_ctx->security_ctxt.ul_nas_count++; 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){ if(mac_valid == false){
m_s1ap_log->warning("Invalid MAC in NAS message type 0x%x.\n", msg_type); m_s1ap_log->warning("Invalid MAC in NAS message type 0x%x.\n", msg_type);
m_pool->deallocate(nas_msg); 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 //Check NAS integrity
bool msg_valid = false; bool msg_valid = false;
emm_ctx->security_ctxt.ul_nas_count++; 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) 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); 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; ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
emm_ctx->security_ctxt.ul_nas_count++; 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) if(mac_valid)
{ {
m_s1ap_log->console("Service Request -- Short MAC valid\n"); 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 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]; uint8_t *mac = &pdu->msg[2];
int i; int i;
srslte::security_128_eia1(&emm_ctx->security_ctxt.k_nas_int[16], switch (sec_ctxt->integ_algo)
emm_ctx->security_ctxt.ul_nas_count, {
0, case srslte::INTEGRITY_ALGORITHM_ID_EIA0:
SECURITY_DIRECTION_UPLINK, break;
&pdu->msg[0], case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1:
2, srslte::security_128_eia1(&sec_ctxt->k_nas_int[16],
&exp_mac[0]); 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 // Check if expected mac equals the sent mac
for(i=0; i<2; i++){ for(i=0; i<2; i++){
if(exp_mac[i+2] != mac[i]){ if(exp_mac[i+2] != mac[i]){
m_s1ap_log->warning("Short integrity check failure. Local: count=%d, [%02x %02x %02x %02x], " m_s1ap_log->warning("Short integrity check failure. Local: count=%d, [%02x %02x %02x %02x], "
"Received: count=%d, [%02x %02x]\n", "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]); pdu->msg[1] & 0x1F, mac[0], mac[1]);
return false; return false;
} }
} }
m_s1ap_log->info("Integrity check ok. Local: count=%d, Received: count=%d\n", 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; return true;
} }
bool s1ap_nas_transport::integrity_check(eps_sec_ctx_t *sec_ctxt, srslte::byte_buffer_t *pdu)
bool
s1ap_nas_transport::integrity_check(ue_emm_ctx_t *emm_ctx, 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]; uint8_t *mac = &pdu->msg[1];
int i; int i;
srslte::security_128_eia1(&emm_ctx->security_ctxt.k_nas_int[16], switch (sec_ctxt->integ_algo)
emm_ctx->security_ctxt.ul_nas_count, {
0, case srslte::INTEGRITY_ALGORITHM_ID_EIA0:
SECURITY_DIRECTION_UPLINK, break;
&pdu->msg[5], case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1:
pdu->N_bytes-5, srslte::security_128_eia1(&sec_ctxt->k_nas_int[16],
&exp_mac[0]); 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 // Check if expected mac equals the sent mac
for(i=0; i<4; i++){ for (i = 0; i < 4; i++) {
if(exp_mac[i] != mac[i]){ if (exp_mac[i] != mac[i]) {
m_s1ap_log->warning("Integrity check failure. UL Local: count=%d, [%02x %02x %02x %02x], " m_s1ap_log->warning("Integrity check failure. UL Local: count=%d, [%02x %02x %02x %02x], "
"Received: UL count=%d, [%02x %02x %02x %02x]\n", "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], 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]); pdu->msg[5], mac[0], mac[1], mac[2], mac[3]);
return false; return false;
} }
} }
m_s1ap_log->info("Integrity check ok. Local: count=%d, Received: count=%d\n", m_s1ap_log->info("Integrity check ok. Local: count=%d, Received: count=%d\n",
emm_ctx->security_ctxt.ul_nas_count, pdu->msg[5]); sec_ctxt->ul_nas_count, pdu->msg[5]);
return true; return true;
} }
bool 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) 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 //Pack NAS PDU
LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sm_cmd; 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_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; 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); 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) 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; return false;
} }
//Generate EPS security context //Generate EPS security context
uint8_t mac[4]; uint8_t mac[4];
srslte::security_generate_k_nas( ue_emm_ctx->security_ctxt.k_asme, srslte::security_generate_k_nas( ue_emm_ctx->security_ctxt.k_asme,
srslte::CIPHERING_ALGORITHM_ID_EEA0, ue_emm_ctx->security_ctxt.cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_128_EIA1, ue_emm_ctx->security_ctxt.integ_algo,
ue_emm_ctx->security_ctxt.k_nas_enc, ue_emm_ctx->security_ctxt.k_nas_enc,
ue_emm_ctx->security_ctxt.k_nas_int 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->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->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"); m_s1ap_log->info_hex(ue_emm_ctx->security_ctxt.k_enb, 32, "Key eNodeB (k_enb)\n");
//Generate MAC for integrity protection //Generate MAC for integrity protection
//FIXME Write wrapper to support EIA1, EIA2, etc. integrity_generate(&ue_emm_ctx->security_ctxt, nas_buffer, mac);
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
);
memcpy(&nas_buffer->msg[1],mac,4); memcpy(&nas_buffer->msg[1],mac,4);
//Copy NAS PDU to Downlink NAS Trasport message buffer //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); err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg);
if(err != LIBLTE_SUCCESS) 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; return false;
} }
m_s1ap_log->debug_hex(reply_msg->msg, reply_msg->N_bytes, "Security Mode Command: "); 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]; uint8_t mac[4];
srslte::security_128_eia1 (&ue_emm_ctx->security_ctxt.k_nas_int[16], integrity_generate(&ue_emm_ctx->security_ctxt, nas_buffer, mac);
ue_emm_ctx->security_ctxt.dl_nas_count,
0,
SECURITY_DIRECTION_DOWNLINK,
&nas_buffer->msg[5],
nas_buffer->N_bytes - 5,
mac
);
memcpy(&nas_buffer->msg[1],mac,4); 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); 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 //Integrity protect NAS message
uint8_t mac[4]; uint8_t mac[4];
srslte::security_128_eia1 (&ue_emm_ctx->security_ctxt.k_nas_int[16], integrity_generate(&ue_emm_ctx->security_ctxt, nas_buffer, mac);
ue_emm_ctx->security_ctxt.dl_nas_count,
0,
SECURITY_DIRECTION_DOWNLINK,
&nas_buffer->msg[5],
nas_buffer->N_bytes - 5,
mac
);
memcpy(&nas_buffer->msg[1],mac,4); memcpy(&nas_buffer->msg[1],mac,4);
m_s1ap_log->info("Packed Attach Complete\n"); 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]; uint8_t mac[4];
srslte::security_128_eia1 (&emm_ctx->security_ctxt.k_nas_int[16], integrity_generate(&emm_ctx->security_ctxt, nas_buffer, mac);
emm_ctx->security_ctxt.dl_nas_count,
0,
SECURITY_DIRECTION_DOWNLINK,
&nas_buffer->msg[5],
nas_buffer->N_bytes - 5,
mac
);
memcpy(&nas_buffer->msg[1],mac,4); memcpy(&nas_buffer->msg[1],mac,4);
//Copy NAS PDU to Downlink NAS Trasport message buffer //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 void
s1ap_nas_transport::log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req) s1ap_nas_transport::log_unhandled_pdn_con_request_ies(const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT *pdn_con_req)
{ {