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_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

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)
{
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)
{