Commit 5345032a authored by Lionel Gauthier's avatar Lionel Gauthier

Integrity seems to work (simple scenario with EURECOM UE), encryption should...

Integrity seems to work (simple scenario with EURECOM UE), encryption should be far more easier to set up since they use the same mechanisms.

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5579 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent 65c84039
...@@ -65,6 +65,21 @@ int mme_app_request_authentication_info(const mme_app_imsi_t imsi, ...@@ -65,6 +65,21 @@ int mme_app_request_authentication_info(const mme_app_imsi_t imsi,
auth_info_req = &message_p->ittiMsg.s6a_auth_info_req; auth_info_req = &message_p->ittiMsg.s6a_auth_info_req;
MME_APP_IMSI_TO_STRING(imsi, auth_info_req->imsi); MME_APP_IMSI_TO_STRING(imsi, auth_info_req->imsi);
memcpy(&auth_info_req->visited_plmn, plmn, sizeof(plmn_t)); memcpy(&auth_info_req->visited_plmn, plmn, sizeof(plmn_t));
MME_APP_DEBUG("%s visited_plmn MCC %X%X%X MNC %X%X%X\n",
__FUNCTION__,
auth_info_req->visited_plmn.MCCdigit1,
auth_info_req->visited_plmn.MCCdigit2,
auth_info_req->visited_plmn.MCCdigit3,
auth_info_req->visited_plmn.MNCdigit1,
auth_info_req->visited_plmn.MNCdigit2,
auth_info_req->visited_plmn.MNCdigit3);
uint8_t *ptr = (uint8_t *)&auth_info_req->visited_plmn;
MME_APP_DEBUG("%s visited_plmn %X%X%X%X%X%X\n",
__FUNCTION__,
ptr[0],
ptr[1],
ptr[2]);
auth_info_req->nb_of_vectors = nb_of_vectors; auth_info_req->nb_of_vectors = nb_of_vectors;
if (auts != NULL) { if (auts != NULL) {
auth_info_req->re_synchronization = 1; auth_info_req->re_synchronization = 1;
......
...@@ -287,13 +287,15 @@ mme_app_handle_conn_est_cnf( ...@@ -287,13 +287,15 @@ mme_app_handle_conn_est_cnf(
mme_app_connection_establishment_cnf_t *establishment_cnf_p = NULL; mme_app_connection_establishment_cnf_t *establishment_cnf_p = NULL;
bearer_context_t *current_bearer_p = NULL; bearer_context_t *current_bearer_p = NULL;
ebi_t bearer_id = 0; ebi_t bearer_id = 0;
uint8_t *keNB = NULL; uint8_t keNB[32];
MME_APP_DEBUG("Received NAS_CONNECTION_ESTABLISHMENT_CNF from NAS\n"); MME_APP_DEBUG("Received NAS_CONNECTION_ESTABLISHMENT_CNF from NAS\n");
ue_context_p = mme_ue_context_exists_nas_ue_id(&mme_app_desc.mme_ue_contexts, nas_conn_est_cnf_pP->UEid); ue_context_p = mme_ue_context_exists_nas_ue_id(&mme_app_desc.mme_ue_contexts, nas_conn_est_cnf_pP->UEid);
if (ue_context_p == NULL) { if (ue_context_p == NULL) {
MME_APP_ERROR("UE context doesn't exist\n"); MME_APP_ERROR("UE context doesn't exist for UE ox%08X/dec%u\n",
nas_conn_est_cnf_pP->UEid,
nas_conn_est_cnf_pP->UEid);
return; return;
} }
...@@ -332,9 +334,8 @@ mme_app_handle_conn_est_cnf( ...@@ -332,9 +334,8 @@ mme_app_handle_conn_est_cnf(
establishment_cnf_p->ambr = ue_context_p->used_ambr; establishment_cnf_p->ambr = ue_context_p->used_ambr;
MME_APP_DEBUG("Derive keNB with UL NAS COUNT %x\n", nas_conn_est_cnf_pP->ul_nas_count); MME_APP_DEBUG("Derive keNB with UL NAS COUNT %x\n", nas_conn_est_cnf_pP->ul_nas_count);
derive_keNB(ue_context_p->vector_in_use->kasme, nas_conn_est_cnf_pP->ul_nas_count, &keNB); //156 derive_keNB(ue_context_p->vector_in_use->kasme, nas_conn_est_cnf_pP->ul_nas_count, keNB); //156
memcpy(establishment_cnf_p->keNB, keNB, 32); memcpy(establishment_cnf_p->keNB, keNB, 32);
free(keNB);
itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p); itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p);
} }
...@@ -355,8 +356,9 @@ mme_app_handle_conn_est_ind( ...@@ -355,8 +356,9 @@ mme_app_handle_conn_est_ind(
&mme_app_desc.mme_ue_contexts, &mme_app_desc.mme_ue_contexts,
conn_est_ind_pP->mme_ue_s1ap_id); conn_est_ind_pP->mme_ue_s1ap_id);
if (ue_context_p == NULL) { if (ue_context_p == NULL) {
MME_APP_DEBUG("We didn't find this mme_ue_s1ap_id in list of UE: %08x\n", MME_APP_DEBUG("We didn't find this mme_ue_s1ap_id in list of UE: 0x%08x/dec%u\n",
conn_est_ind_pP->mme_ue_s1ap_id); conn_est_ind_pP->mme_ue_s1ap_id,
conn_est_ind_pP->mme_ue_s1ap_id);
MME_APP_DEBUG("UE context doesn't exist -> create one\n"); MME_APP_DEBUG("UE context doesn't exist -> create one\n");
if ((ue_context_p = mme_create_new_ue_context()) == NULL) { if ((ue_context_p = mme_create_new_ue_context()) == NULL) {
/* Error during ue context malloc */ /* Error during ue context malloc */
...@@ -369,11 +371,15 @@ mme_app_handle_conn_est_ind( ...@@ -369,11 +371,15 @@ mme_app_handle_conn_est_ind(
ue_context_p->ue_id = conn_est_ind_pP->mme_ue_s1ap_id; ue_context_p->ue_id = conn_est_ind_pP->mme_ue_s1ap_id;
DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context_p) == 0); DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context_p) == 0);
// test // tests
ue_context_p = mme_ue_context_exists_mme_ue_s1ap_id( ue_context_p = mme_ue_context_exists_mme_ue_s1ap_id(
&mme_app_desc.mme_ue_contexts, &mme_app_desc.mme_ue_contexts,
conn_est_ind_pP->mme_ue_s1ap_id); conn_est_ind_pP->mme_ue_s1ap_id);
AssertFatal(ue_context_p != NULL, "mme_ue_context_exists_mme_ue_s1ap_id Failed"); AssertFatal(ue_context_p != NULL, "mme_ue_context_exists_mme_ue_s1ap_id Failed");
ue_context_p = mme_ue_context_exists_nas_ue_id(
&mme_app_desc.mme_ue_contexts,
conn_est_ind_pP->mme_ue_s1ap_id);
AssertFatal(ue_context_p != NULL, "mme_ue_context_exists_nas_ue_id Failed");
} }
message_p = itti_alloc_new_message(TASK_MME_APP, NAS_CONNECTION_ESTABLISHMENT_IND); message_p = itti_alloc_new_message(TASK_MME_APP, NAS_CONNECTION_ESTABLISHMENT_IND);
......
...@@ -101,11 +101,11 @@ void *mme_app_thread(void *args) ...@@ -101,11 +101,11 @@ void *mme_app_thread(void *args)
mme_app_handle_nas_pdn_connectivity_req(&received_message_p->ittiMsg.nas_pdn_connectivity_req); mme_app_handle_nas_pdn_connectivity_req(&received_message_p->ittiMsg.nas_pdn_connectivity_req);
} break; } break;
//case NAS_CONNECTION_ESTABLISHMENT_CNF: {
case NAS_CONNECTION_ESTABLISHMENT_CNF: { case NAS_CONNECTION_ESTABLISHMENT_CNF: {
mme_app_handle_conn_est_cnf(&NAS_CONNECTION_ESTABLISHMENT_CNF(received_message_p)); mme_app_handle_conn_est_cnf(&NAS_CONNECTION_ESTABLISHMENT_CNF(received_message_p));
} break; } break;
// From S1AP Initiating Message/EMM Attach Request
case MME_APP_CONNECTION_ESTABLISHMENT_IND: { case MME_APP_CONNECTION_ESTABLISHMENT_IND: {
mme_app_handle_conn_est_ind(&MME_APP_CONNECTION_ESTABLISHMENT_IND(received_message_p)); mme_app_handle_conn_est_ind(&MME_APP_CONNECTION_ESTABLISHMENT_IND(received_message_p));
} break; } break;
......
...@@ -108,6 +108,7 @@ _nas_message_encrypt( ...@@ -108,6 +108,7 @@ _nas_message_encrypt(
UInt8_t type, UInt8_t type,
UInt32_t code, UInt32_t code,
UInt8_t seq, UInt8_t seq,
int const direction,
int length, int length,
const emm_security_context_t * const emm_security_context); const emm_security_context_t * const emm_security_context);
...@@ -166,6 +167,11 @@ nas_message_encrypt( ...@@ -166,6 +167,11 @@ nas_message_encrypt(
header->security_header_type, header->security_header_type,
header->message_authentication_code, header->message_authentication_code,
header->sequence_number, header->sequence_number,
#ifdef NAS_MME
SECU_DIRECTION_DOWNLINK,
#else
SECU_DIRECTION_UPLINK,
#endif
length - size, length - size,
emm_security_context); emm_security_context);
/* Integrity protected the NAS message */ /* Integrity protected the NAS message */
...@@ -183,7 +189,7 @@ nas_message_encrypt( ...@@ -183,7 +189,7 @@ nas_message_encrypt(
#endif #endif
emm_security_context); emm_security_context);
/* Set the message authentication code of the NAS message */ /* Set the message authentication code of the NAS message */
*(UInt32_t*)(outbuf + sizeof(UInt8_t)) = mac; *(UInt32_t*)(outbuf + sizeof(UInt8_t)) = htonl(mac);
} }
} }
else { else {
...@@ -265,9 +271,22 @@ int nas_message_decrypt( ...@@ -265,9 +271,22 @@ int nas_message_decrypt(
int size = _nas_message_header_decode(inbuf, header, length); int size = _nas_message_header_decode(inbuf, header, length);
if (size < 0) { if (size < 0) {
LOG_TRACE(DEBUG, "MESSAGE TOO SHORT");
LOG_FUNC_RETURN (TLV_DECODE_BUFFER_TOO_SHORT); LOG_FUNC_RETURN (TLV_DECODE_BUFFER_TOO_SHORT);
} }
else if (size > 1) { else if (size > 1) {
#if defined(NAS_MME)
if (emm_security_context->ul_count.seq_num > header->sequence_number) {
emm_security_context->ul_count.overflow += 1;
}
emm_security_context->ul_count.seq_num = header->sequence_number;
#else
if (emm_security_context->dl_count.seq_num > header->sequence_number) {
emm_security_context->dl_count.overflow += 1;
}
emm_security_context->dl_count.seq_num = header->sequence_number;
#endif
/* Compute offset of the sequence number field */ /* Compute offset of the sequence number field */
int offset = size - sizeof(UInt8_t); int offset = size - sizeof(UInt8_t);
/* Compute the NAS message authentication code */ /* Compute the NAS message authentication code */
...@@ -281,20 +300,29 @@ int nas_message_decrypt( ...@@ -281,20 +300,29 @@ int nas_message_decrypt(
#endif #endif
emm_security_context); emm_security_context);
/* Check NAS message integrity */ /* Check NAS message integrity */
if (mac != header->message_authentication_code) { if (mac != header->message_authentication_code) {
LOG_TRACE(DEBUG,
"MAC Failure MSG:%08X(%u) <> INT ALGO:%08X(%u)",
header->message_authentication_code,
header->message_authentication_code,
mac,
mac);
#if defined(NAS_MME) #if defined(NAS_MME)
LOG_FUNC_RETURN (TLV_DECODE_MAC_MISMATCH); LOG_FUNC_RETURN (TLV_DECODE_MAC_MISMATCH);
#else #else
#warning "added test on integrity algorithm because of SECURITY_MODE_COMMAND not correctly handled in UE (check integrity)" #warning "added test on integrity algorithm because of SECURITY_MODE_COMMAND not correctly handled in UE (check integrity)"
if (emm_security_context->selected_algorithms.integrity != if (emm_security_context->selected_algorithms.integrity !=
NAS_SECURITY_ALGORITHMS_EIA0) { NAS_SECURITY_ALGORITHMS_EIA0) {
LOG_FUNC_RETURN (TLV_DECODE_MAC_MISMATCH); LOG_FUNC_RETURN (TLV_DECODE_MAC_MISMATCH);
} else { } else {
LOG_TRACE(WARNING, LOG_TRACE(WARNING,
"MAC failure but continue due to EIA0 selected"); "MAC failure but continue due to EIA0 selected");
} }
#endif #endif
} else {
LOG_TRACE(DEBUG, "Integrity: MAC Success");
} }
/* Decrypt the security protected NAS message */ /* Decrypt the security protected NAS message */
...@@ -307,6 +335,7 @@ int nas_message_decrypt( ...@@ -307,6 +335,7 @@ int nas_message_decrypt(
bytes = length - size; bytes = length - size;
} }
else { else {
LOG_TRACE(DEBUG, "Plain NAS message found");
/* The input buffer contains a plain NAS message */ /* The input buffer contains a plain NAS message */
memcpy(outbuf, inbuf, length); memcpy(outbuf, inbuf, length);
} }
...@@ -341,15 +370,6 @@ int nas_message_decode( ...@@ -341,15 +370,6 @@ int nas_message_decode(
LOG_FUNC_IN; LOG_FUNC_IN;
emm_security_context_t *emm_security_context = (emm_security_context_t*)security; emm_security_context_t *emm_security_context = (emm_security_context_t*)security;
int bytes; int bytes;
#if ((defined(EPC_BUILD) && defined(NAS_MME)) || (defined(ENABLE_NAS_UE_LOGGING) && defined(UE_BUILD) && defined(NAS_UE)))
int down_link;
# if ((defined(EPC_BUILD) && defined(NAS_MME)))
down_link = 0;
# else
down_link = 1;
# endif
#endif
/* Decode the header */ /* Decode the header */
int size = _nas_message_header_decode(buffer, &msg->header, length); int size = _nas_message_header_decode(buffer, &msg->header, length);
...@@ -358,6 +378,18 @@ int nas_message_decode( ...@@ -358,6 +378,18 @@ int nas_message_decode(
LOG_FUNC_RETURN (TLV_DECODE_BUFFER_TOO_SHORT); LOG_FUNC_RETURN (TLV_DECODE_BUFFER_TOO_SHORT);
} }
else if (size > 1) { else if (size > 1) {
#if defined(NAS_MME)
if (emm_security_context->ul_count.seq_num > msg->header.sequence_number) {
emm_security_context->ul_count.overflow += 1;
}
emm_security_context->ul_count.seq_num = msg->header.sequence_number;
#else
if (emm_security_context->dl_count.seq_num > msg->header.sequence_number) {
emm_security_context->dl_count.overflow += 1;
}
emm_security_context->dl_count.seq_num = msg->header.sequence_number;
#endif
/* Compute offset of the sequence number field */ /* Compute offset of the sequence number field */
int offset = size - sizeof(UInt8_t); int offset = size - sizeof(UInt8_t);
/* Compute the NAS message authentication code */ /* Compute the NAS message authentication code */
...@@ -431,15 +463,7 @@ int nas_message_encode( ...@@ -431,15 +463,7 @@ int nas_message_encode(
emm_security_context_t *emm_security_context = (emm_security_context_t*)security; emm_security_context_t *emm_security_context = (emm_security_context_t*)security;
int bytes; int bytes;
#if ((defined(EPC_BUILD) && defined(NAS_MME)) || (defined(ENABLE_NAS_UE_LOGGING) && defined(UE_BUILD) && defined(NAS_UE)))
int down_link;
# if ((defined(EPC_BUILD) && defined(NAS_MME)))
down_link = 1;
# else
down_link = 0;
# endif
#endif
/* Encode the header */ /* Encode the header */
int size = _nas_message_header_encode(buffer, &msg->header, length); int size = _nas_message_header_encode(buffer, &msg->header, length);
...@@ -459,9 +483,13 @@ int nas_message_encode( ...@@ -459,9 +483,13 @@ int nas_message_encode(
/* Compute offset of the sequence number field */ /* Compute offset of the sequence number field */
int offset = size - sizeof(UInt8_t); int offset = size - sizeof(UInt8_t);
/* Compute the NAS message authentication code */ /* Compute the NAS message authentication code */
LOG_TRACE(DEBUG,
"offset %d = %d - %d, hdr encode = %d, length = %d bytes = %d",
offset, size, sizeof(UInt8_t),
size, length, bytes);
UInt32_t mac = _nas_message_get_mac( UInt32_t mac = _nas_message_get_mac(
buffer + offset, buffer + offset,
length - offset, bytes + size - offset,
#ifdef NAS_MME #ifdef NAS_MME
SECU_DIRECTION_DOWNLINK, SECU_DIRECTION_DOWNLINK,
#else #else
...@@ -469,7 +497,7 @@ int nas_message_encode( ...@@ -469,7 +497,7 @@ int nas_message_encode(
#endif #endif
emm_security_context); emm_security_context);
/* Set the message authentication code of the NAS message */ /* Set the message authentication code of the NAS message */
*(UInt32_t*)(buffer + sizeof(UInt8_t)) = mac; *(UInt32_t*)(buffer + sizeof(UInt8_t)) = htonl(mac);
if (emm_security_context) { if (emm_security_context) {
#ifdef NAS_MME #ifdef NAS_MME
...@@ -832,6 +860,11 @@ static int _nas_message_protected_encode( ...@@ -832,6 +860,11 @@ static int _nas_message_protected_encode(
msg->header.security_header_type, msg->header.security_header_type,
msg->header.message_authentication_code, msg->header.message_authentication_code,
msg->header.sequence_number, msg->header.sequence_number,
#ifdef NAS_MME
SECU_DIRECTION_DOWNLINK,
#else
SECU_DIRECTION_UPLINK,
#endif
size, size,
emm_security_context); emm_security_context);
//seq, size); //seq, size);
...@@ -901,6 +934,7 @@ static int _nas_message_decrypt( ...@@ -901,6 +934,7 @@ static int _nas_message_decrypt(
** type: The security header type ** ** type: The security header type **
** code: The message authentication code ** ** code: The message authentication code **
** seq: The sequence number ** ** seq: The sequence number **
** direction: The sequence number **
** length: Maximal capacity of the output buffer ** ** length: Maximal capacity of the output buffer **
** Others: None ** ** Others: None **
** ** ** **
...@@ -917,17 +951,60 @@ static int _nas_message_encrypt( ...@@ -917,17 +951,60 @@ static int _nas_message_encrypt(
UInt8_t type, UInt8_t type,
UInt32_t code, UInt32_t code,
UInt8_t seq, UInt8_t seq,
int const direction,
int length, int length,
const emm_security_context_t * const emm_security_context) const emm_security_context_t * const emm_security_context)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int size = length; if (!emm_security_context) {
LOG_TRACE(ERROR,
"No security context set for encryption protection algorithm");
LOG_FUNC_RETURN (0);
}
switch (emm_security_context->selected_algorithms.encryption) {
/* TODO: run the cyphering algorithm */ case NAS_SECURITY_ALGORITHMS_EEA1: {
memcpy(dest, src, length); LOG_TRACE(WARNING,
"TODO NAS_SECURITY_ALGORITHMS_EEA1 dir %d ul_count.seq_num %d dl_count.seq_num %d",
direction,
emm_security_context->ul_count.seq_num,
emm_security_context->dl_count.seq_num);
memcpy(dest, src, length);
LOG_FUNC_RETURN (length);
LOG_FUNC_RETURN (size); }break;
case NAS_SECURITY_ALGORITHMS_EEA2: {
LOG_TRACE(WARNING,
"TODO NAS_SECURITY_ALGORITHMS_EEA2 dir %d ul_count.seq_num %d dl_count.seq_num %d",
direction,
emm_security_context->ul_count.seq_num,
emm_security_context->dl_count.seq_num);
memcpy(dest, src, length);
LOG_FUNC_RETURN (length);
}break;
case NAS_SECURITY_ALGORITHMS_EEA0:
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EEA0 dir %d ul_count.seq_num %d dl_count.seq_num %d",
direction,
emm_security_context->ul_count.seq_num,
emm_security_context->dl_count.seq_num);
memcpy(dest, src, length);
LOG_FUNC_RETURN (length);
break;
default:
LOG_TRACE(ERROR,
"Unknown Cyphering protection algorithm %d",
emm_security_context->selected_algorithms.encryption);
break;
}
LOG_FUNC_RETURN (length);
} }
/* /*
...@@ -938,21 +1015,22 @@ static int _nas_message_encrypt( ...@@ -938,21 +1015,22 @@ static int _nas_message_encrypt(
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: _nas_message_get_mac() ** ** Name: _nas_message_get_mac() **
** ** ** **
** Description: Run integrity algorithm onto cyphered or uncyphered NAS ** ** Description: Run integrity algorithm onto cyphered or uncyphered NAS **
** message encoded in the input buffer and return the compu- ** ** message encoded in the input buffer and return the compu- **
** ted message authentication code ** ** ted message authentication code **
** ** ** **
** Inputs buffer: Pointer to the integrity protected data ** ** Inputs buffer: Pointer to the integrity protected data **
** buffer ** ** buffer **
** count: Value of the uplink NAS counter ** ** count: Value of the uplink NAS counter **
** length: Length of the input buffer ** ** length: Length of the input buffer **
** Others: None ** ** direction **
** Others: None **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: The message authentication code ** ** Return: The message authentication code **
** Others: None ** ** Others: None **
** ** ** **
***************************************************************************/ ***************************************************************************/
static UInt32_t _nas_message_get_mac( static UInt32_t _nas_message_get_mac(
...@@ -982,11 +1060,8 @@ static UInt32_t _nas_message_get_mac( ...@@ -982,11 +1060,8 @@ static UInt32_t _nas_message_get_mac(
UInt32_t count; UInt32_t count;
UInt32_t *mac32; UInt32_t *mac32;
LOG_TRACE(DEBUG, int i,bytes = 0;
"NAS_SECURITY_ALGORITHMS_EIA1 dir %d ul_count.seq_num %d dl_count.seq_num %d",
direction,
emm_security_context->ul_count.seq_num,
emm_security_context->dl_count.seq_num);
if (direction == SECU_DIRECTION_UPLINK) { if (direction == SECU_DIRECTION_UPLINK) {
count = 0x00000000 || count = 0x00000000 ||
((emm_security_context->ul_count.overflow && 0x0000FFFF) << 8) || ((emm_security_context->ul_count.overflow && 0x0000FFFF) << 8) ||
...@@ -996,7 +1071,31 @@ static UInt32_t _nas_message_get_mac( ...@@ -996,7 +1071,31 @@ static UInt32_t _nas_message_get_mac(
((emm_security_context->dl_count.overflow && 0x0000FFFF) << 8) || ((emm_security_context->dl_count.overflow && 0x0000FFFF) << 8) ||
(emm_security_context->dl_count.seq_num & 0x000000FF); (emm_security_context->dl_count.seq_num & 0x000000FF);
} }
stream_cipher.key = emm_security_context->knas_int.value; LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EIA1 dir %s count.seq_num %u count %u",
(direction == SECU_DIRECTION_UPLINK) ? "UPLINK":"DOWNLINK",
(direction == SECU_DIRECTION_UPLINK) ? emm_security_context->ul_count.seq_num:emm_security_context->dl_count.seq_num,
count);
fprintf(stderr, "\n[NAS]\t");
for (i=0; i < length; i++)
{
fprintf(stderr, "%.2hx ", (const unsigned char) buffer[i]);
/* Add new line when the number of displayed bytes exceeds
* the line's size */
if ( ++bytes > (16 - 1) ) {
bytes = 0;
fprintf(stderr, "\n[NAS]\t");
}
}
if (bytes % 16) {
fprintf(stderr, "\n");
}
fprintf(stderr, "\n");
fflush(stderr);
stream_cipher.key = emm_security_context->knas_int.value;
stream_cipher.key_length = AUTH_KNAS_INT_SIZE; stream_cipher.key_length = AUTH_KNAS_INT_SIZE;
stream_cipher.count = count; stream_cipher.count = count;
stream_cipher.bearer = 0x00; //33.401 section 8.1.1 stream_cipher.bearer = 0x00; //33.401 section 8.1.1
...@@ -1009,10 +1108,14 @@ static UInt32_t _nas_message_get_mac( ...@@ -1009,10 +1108,14 @@ static UInt32_t _nas_message_get_mac(
&stream_cipher, &stream_cipher,
mac); mac);
LOG_TRACE(DEBUG, LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EIA1 returned MAC %x.%x.%x.%x for length %d direction %d, count %d", "NAS_SECURITY_ALGORITHMS_EIA1 returned MAC %x.%x.%x.%x(%u) for length %d direction %d, count %d",
mac[0], mac[1], mac[2],mac[3], length, direction, count); mac[0], mac[1], mac[2],mac[3],
*((UInt32_t*)&mac),
length,
direction,
count);
mac32 = (UInt32_t*)&mac; mac32 = (UInt32_t*)&mac;
LOG_FUNC_RETURN (*mac32); LOG_FUNC_RETURN (ntohl(*mac32));
}break; }break;
case NAS_SECURITY_ALGORITHMS_EIA2: { case NAS_SECURITY_ALGORITHMS_EIA2: {
...@@ -1021,11 +1124,6 @@ static UInt32_t _nas_message_get_mac( ...@@ -1021,11 +1124,6 @@ static UInt32_t _nas_message_get_mac(
UInt32_t count; UInt32_t count;
UInt32_t *mac32; UInt32_t *mac32;
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EIA2 dir %d ul_count.seq_num %d dl_count.seq_num %d",
direction,
emm_security_context->ul_count.seq_num,
emm_security_context->dl_count.seq_num);
if (direction == SECU_DIRECTION_UPLINK) { if (direction == SECU_DIRECTION_UPLINK) {
count = 0x00000000 || count = 0x00000000 ||
((emm_security_context->ul_count.overflow && 0x0000FFFF) << 8) || ((emm_security_context->ul_count.overflow && 0x0000FFFF) << 8) ||
...@@ -1035,6 +1133,12 @@ static UInt32_t _nas_message_get_mac( ...@@ -1035,6 +1133,12 @@ static UInt32_t _nas_message_get_mac(
((emm_security_context->dl_count.overflow && 0x0000FFFF) << 8) || ((emm_security_context->dl_count.overflow && 0x0000FFFF) << 8) ||
(emm_security_context->dl_count.seq_num & 0x000000FF); (emm_security_context->dl_count.seq_num & 0x000000FF);
} }
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EIA2 dir %s count.seq_num %u count %u",
(direction == SECU_DIRECTION_UPLINK) ? "UPLINK":"DOWNLINK",
(direction == SECU_DIRECTION_UPLINK) ? emm_security_context->ul_count.seq_num:emm_security_context->dl_count.seq_num,
count);
stream_cipher.key = emm_security_context->knas_int.value; stream_cipher.key = emm_security_context->knas_int.value;
stream_cipher.key_length = AUTH_KNAS_INT_SIZE; stream_cipher.key_length = AUTH_KNAS_INT_SIZE;
stream_cipher.count = count; stream_cipher.count = count;
...@@ -1048,18 +1152,23 @@ static UInt32_t _nas_message_get_mac( ...@@ -1048,18 +1152,23 @@ static UInt32_t _nas_message_get_mac(
&stream_cipher, &stream_cipher,
mac); mac);
LOG_TRACE(DEBUG, LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EIA2 returned MAC %x.%x.%x.%x for length %d direction %d, count %d", "NAS_SECURITY_ALGORITHMS_EIA2 returned MAC %x.%x.%x.%x(%u) for length %d direction %d, count %d",
mac[0], mac[1], mac[2],mac[3], length, direction, count); mac[0], mac[1], mac[2],mac[3],
*((UInt32_t*)&mac),
length,
direction,
count);
mac32 = (UInt32_t*)&mac; mac32 = (UInt32_t*)&mac;
LOG_FUNC_RETURN (*mac32); LOG_FUNC_RETURN (ntohl(*mac32));
}break; }break;
case NAS_SECURITY_ALGORITHMS_EIA0: case NAS_SECURITY_ALGORITHMS_EIA0:
LOG_TRACE(DEBUG, LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EIA0 dir %d ul_count.seq_num %d dl_count.seq_num %d", "NAS_SECURITY_ALGORITHMS_EIA0 dir %s count.seq_num %u",
direction, (direction == SECU_DIRECTION_UPLINK) ? "UPLINK":"DOWNLINK",
emm_security_context->ul_count.seq_num, (direction == SECU_DIRECTION_UPLINK) ? emm_security_context->ul_count.seq_num:emm_security_context->dl_count.seq_num
emm_security_context->dl_count.seq_num); );
#if defined(EPC_BUILD) || defined(UE_BUILD) #if defined(EPC_BUILD) || defined(UE_BUILD)
LOG_FUNC_RETURN (0); LOG_FUNC_RETURN (0);
#else #else
...@@ -1071,6 +1180,7 @@ static UInt32_t _nas_message_get_mac( ...@@ -1071,6 +1180,7 @@ static UInt32_t _nas_message_get_mac(
LOG_TRACE(ERROR, LOG_TRACE(ERROR,
"Unknown integrity protection algorithm %d", "Unknown integrity protection algorithm %d",
emm_security_context->selected_algorithms.integrity); emm_security_context->selected_algorithms.integrity);
break;
} }
LOG_FUNC_RETURN (0); LOG_FUNC_RETURN (0);
} }
......
...@@ -222,8 +222,8 @@ int usim_api_authenticate(const OctetString* rand_pP, const OctetString* autn_pP ...@@ -222,8 +222,8 @@ int usim_api_authenticate(const OctetString* rand_pP, const OctetString* autn_pP
int rc; int rc;
int i; int i;
LOG_TRACE(DEBUG, "USIM-API - rand :");dump_octet_string(rand_pP); LOG_TRACE(DEBUG, "USIM-API - rand :%s",dump_octet_string(rand_pP));
LOG_TRACE(DEBUG, "USIM-API - autn :");dump_octet_string(autn_pP); LOG_TRACE(DEBUG, "USIM-API - autn :%s",dump_octet_string(autn_pP));
/* Compute the authentication response RES = f2K (RAND) */ /* Compute the authentication response RES = f2K (RAND) */
/* Compute the cipher key CK = f3K (RAND) */ /* Compute the cipher key CK = f3K (RAND) */
...@@ -233,9 +233,9 @@ int usim_api_authenticate(const OctetString* rand_pP, const OctetString* autn_pP ...@@ -233,9 +233,9 @@ int usim_api_authenticate(const OctetString* rand_pP, const OctetString* autn_pP
u8 ak[USIM_API_AK_SIZE]; u8 ak[USIM_API_AK_SIZE];
f2345(_usim_api_k, rand_pP->value, f2345(_usim_api_k, rand_pP->value,
res_pP->value, ck_pP->value, ik_pP->value, ak); res_pP->value, ck_pP->value, ik_pP->value, ak);
LOG_TRACE(DEBUG, "USIM-API - res(f2) :");dump_octet_string(res_pP); LOG_TRACE(DEBUG, "USIM-API - res(f2) :%s",dump_octet_string(res_pP));
LOG_TRACE(DEBUG, "USIM-API - ck(f3) :");dump_octet_string(ck_pP); LOG_TRACE(DEBUG, "USIM-API - ck(f3) :%s",dump_octet_string(ck_pP));
LOG_TRACE(DEBUG, "USIM-API - ik(f4) :");dump_octet_string(ik_pP); LOG_TRACE(DEBUG, "USIM-API - ik(f4) :%s",dump_octet_string(ik_pP));
LOG_TRACE(DEBUG, "USIM-API - ak(f5) : %02X%02X%02X%02X%02X%02X", LOG_TRACE(DEBUG, "USIM-API - ak(f5) : %02X%02X%02X%02X%02X%02X",
ak[0],ak[1],ak[2],ak[3],ak[4],ak[5]); ak[0],ak[1],ak[2],ak[3],ak[4],ak[5]);
......
...@@ -1672,29 +1672,40 @@ static int _emm_attach_release(void *args) ...@@ -1672,29 +1672,40 @@ static int _emm_attach_release(void *args)
if (emm_ctx->guti) { if (emm_ctx->guti) {
free(emm_ctx->guti); free(emm_ctx->guti);
emm_ctx->guti = NULL;
} }
if (emm_ctx->imsi) { if (emm_ctx->imsi) {
free(emm_ctx->imsi); free(emm_ctx->imsi);
emm_ctx->imsi = NULL;
} }
if (emm_ctx->imei) { if (emm_ctx->imei) {
free(emm_ctx->imei); free(emm_ctx->imei);
emm_ctx->imei = NULL;
} }
if (emm_ctx->esm_msg.length > 0) { if (emm_ctx->esm_msg.length > 0) {
free(emm_ctx->esm_msg.value); free(emm_ctx->esm_msg.value);
emm_ctx->esm_msg.value = NULL;
} }
/* Release NAS security context */ /* Release NAS security context */
if (emm_ctx->security) { if (emm_ctx->security) {
emm_security_context_t *security = emm_ctx->security; emm_security_context_t *security = emm_ctx->security;
if (security->kasme.value) { if (security->kasme.value) {
free(security->kasme.value); free(security->kasme.value);
security->kasme.value = NULL;
security->kasme.length = 0;
} }
if (security->knas_enc.value) { if (security->knas_enc.value) {
free(security->knas_enc.value); free(security->knas_enc.value);
security->knas_enc.value = NULL;
security->knas_enc.length = 0;
} }
if (security->knas_int.value) { if (security->knas_int.value) {
free(security->knas_int.value); free(security->knas_int.value);
security->knas_int.value = NULL;
security->knas_int.length = 0;
} }
free(emm_ctx->security); free(emm_ctx->security);
emm_ctx->security = NULL;
} }
/* Release the EMM context */ /* Release the EMM context */
#if defined(EPC_BUILD) #if defined(EPC_BUILD)
......
...@@ -59,6 +59,7 @@ Description Defines the authentication EMM procedure executed by the ...@@ -59,6 +59,7 @@ Description Defines the authentication EMM procedure executed by the
#include <stdlib.h> // malloc, free #include <stdlib.h> // malloc, free
#include <string.h> // memcpy, memcmp, memset #include <string.h> // memcpy, memcmp, memset
#include <arpa/inet.h> // htons
#include "emm_proc.h" #include "emm_proc.h"
#include "nas_log.h" #include "nas_log.h"
...@@ -389,8 +390,7 @@ int emm_proc_authentication_request(int native_ksi, int ksi, ...@@ -389,8 +390,7 @@ int emm_proc_authentication_request(int native_ksi, int ksi,
/* Derive the Kasme from the authentication challenge using /* Derive the Kasme from the authentication challenge using
* the PLMN identity of the selected PLMN */ * the PLMN identity of the selected PLMN */
_emm_data.non_current->kasme.length = AUTH_KASME_SIZE; _emm_data.non_current->kasme.length = AUTH_KASME_SIZE;
_emm_data.non_current->kasme.value = _emm_data.non_current->kasme.value = malloc(32);
(uint8_t *)malloc(sizeof(AUTH_KASME_SIZE));
_authentication_kasme(autn, &ck, &ik, &_emm_data.splmn, _authentication_kasme(autn, &ck, &ik, &_emm_data.splmn,
&_emm_data.non_current->kasme); &_emm_data.non_current->kasme);
/* NAS integrity and cyphering keys are not yet available */ /* NAS integrity and cyphering keys are not yet available */
...@@ -1171,68 +1171,78 @@ static int _authentication_kasme(const OctetString *autn, ...@@ -1171,68 +1171,78 @@ static int _authentication_kasme(const OctetString *autn,
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
LOG_TRACE(INFO,"EMM-PROC _authentication_kasme INPUT CK %s",
dump_octet_string(ck));
LOG_TRACE(INFO,"EMM-PROC _authentication_kasme INPUT IK %s",
dump_octet_string(ik));
LOG_TRACE(INFO,"EMM-PROC _authentication_kasme INPUT AUTN %s",
dump_octet_string(autn));
LOG_TRACE(INFO,"EMM-PROC _authentication_kasme INPUT KASME LENGTH %u",
kasme->length);
/* Compute the derivation key KEY = CK || IK */ /* Compute the derivation key KEY = CK || IK */
UInt8_t key[ck->length + ik->length]; UInt8_t key[ck->length + ik->length];
memcpy(key, ck->value, ck->length); memcpy(key, ck->value, ck->length);
memcpy(key + ck->length, ik->value, ik->length); memcpy(key + ck->length, ik->value, ik->length);
/* Compute the KDF input parameter /* Compute the KDF input_s parameter
* S = FC(0x10) || SNid(MCC, MNC) || 0x00 0x03 || SQN ⊕ AK || 0x00 0x06 * S = FC(0x10) || SNid(MCC, MNC) || 0x00 0x03 || SQN ⊕ AK || 0x00 0x06
*/ */
UInt8_t input[kasme->length]; UInt8_t input_s[16]; // less than 16
UInt8_t sn_id[AUTH_SNID_SIZE]; // less than 16
UInt16_t length; UInt16_t length;
int offset = 0; int offset = 0;
int size_of_length = sizeof(length); int size_of_length = sizeof(length);
// FC // FC
input[offset] = 0x10; input_s[offset] = 0x10;
offset += 1; offset += 1;
// P0=SN id // P0=SN id
length = AUTH_SNID_SIZE; length = AUTH_SNID_SIZE;
memcpy(input + offset, plmn, length); sn_id[0] = (plmn->MCCdigit2 << 4) | plmn->MCCdigit1;
sn_id[1] = (plmn->MNCdigit3 << 4) | plmn->MCCdigit3;
sn_id[2] = (plmn->MNCdigit2 << 4) | plmn->MNCdigit1;
memcpy(input_s + offset, sn_id, length);
LOG_TRACE(INFO,"EMM-PROC _authentication_kasme P0 MCC,MNC %02X %02X %02X", LOG_TRACE(INFO,"EMM-PROC _authentication_kasme P0 MCC,MNC %02X %02X %02X",
input[offset], input_s[offset],
input[offset+1], input_s[offset+1],
input[offset+2]); input_s[offset+2]);
offset += length; offset += length;
// L0=SN id length // L0=SN id length
memcpy(input + offset, &length, size_of_length); length = htons(length);
memcpy(input_s + offset, &length, size_of_length);
offset += size_of_length; offset += size_of_length;
// P1=Authentication token // P1=Authentication token
length = AUTH_SQN_SIZE; length = AUTH_SQN_SIZE;
memcpy(input + offset, autn, length); memcpy(input_s + offset, autn->value, length);
offset += length; offset += length;
// L1 // L1
memcpy(input + offset, &length, size_of_length); length = htons(length);
memcpy(input_s + offset, &length, size_of_length);
offset += size_of_length; offset += size_of_length;
/* TODO !!! Compute the Kasme key */ LOG_TRACE(INFO,
// todo_hmac_256(key, input, kasme->value); "EMM-PROC _authentication_kasme input S to KFD (length %u)%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
kdf(input,
offset, offset,
key, input_s[0],input_s[1],input_s[2],input_s[3],
ck->length + ik->length , /*key_length*/ input_s[4],input_s[5],input_s[6],input_s[7],
&kasme->value, input_s[8],input_s[9],input_s[10],input_s[11],
kasme->length); input_s[12],input_s[13]);
/* TODO !!! Compute the Kasme key */
LOG_TRACE(INFO,"EMM-PROC CK (l=%d)", ck->length); // todo_hmac_256(key, input_s, kasme->value);
LOG_TRACE(INFO,"EMM-PROC IK (l=%d)", ik->length); kdf(key,
ck->length + ik->length , /*key_length*/
LOG_TRACE(INFO,"EMM-PROC KASME (l=%d)%02X%02X%02X%02X%02X%02X%02X%02X", input_s,
"%02X%02X%02X%02X%02X%02X%02X%02X", offset,
"%02X%02X%02X%02X%02X%02X%02X%02X", kasme->value,
"%02X%02X%02X%02X%02X%02X%02X%02X", kasme->length);
LOG_TRACE(INFO,"EMM-PROC KASME (l=%d)%s",
kasme->length, kasme->length,
kasme->value[0],kasme->value[1],kasme->value[2],kasme->value[3], dump_octet_string(kasme));
kasme->value[4],kasme->value[5],kasme->value[6],kasme->value[7],
kasme->value[8],kasme->value[9],kasme->value[10],kasme->value[11],
kasme->value[12],kasme->value[13],kasme->value[14],kasme->value[15],
kasme->value[16],kasme->value[17],kasme->value[18],kasme->value[19],
kasme->value[20],kasme->value[21],kasme->value[22],kasme->value[23],
kasme->value[24],kasme->value[25],kasme->value[26],kasme->value[27],
kasme->value[28],kasme->value[29],kasme->value[30],kasme->value[31]);
LOG_FUNC_RETURN (RETURNok); LOG_FUNC_RETURN (RETURNok);
} }
......
...@@ -483,24 +483,29 @@ void emm_as_set_security_data(emm_as_security_data_t *data, const void *args, ...@@ -483,24 +483,29 @@ void emm_as_set_security_data(emm_as_security_data_t *data, const void *args,
* into use, UE and MME shall cipher and integrity protect all * into use, UE and MME shall cipher and integrity protect all
* NAS signalling messages with the selected NAS ciphering and * NAS signalling messages with the selected NAS ciphering and
* NAS integrity algorithms */ * NAS integrity algorithms */
LOG_TRACE(WARNING, LOG_TRACE(INFO,
"EPS security context exists is new %u KSI %u SQN %u count %u knas_int %s", "EPS security context exists is new %u KSI %u SQN %u count %u",
is_new, is_new,
context->eksi, context->eksi,
context->ul_count.seq_num, context->ul_count.seq_num,
*(UInt32_t *)(&context->ul_count), *(UInt32_t *)(&context->ul_count));
context->knas_int.value LOG_TRACE(INFO,
); "knas_int %s",dump_octet_string(&context->knas_int));
LOG_TRACE(INFO,
"knas_enc %s",dump_octet_string(&context->knas_enc));
LOG_TRACE(INFO,
"kasme %s",dump_octet_string(&context->kasme));
data->is_new = is_new; data->is_new = is_new;
data->ksi = context->eksi; data->ksi = context->eksi;
#if defined (NAS_UE) #if defined (NAS_UE)
data->sqn = context->ul_count.seq_num; data->sqn = context->ul_count.seq_num;
// LG data->count = *(UInt32_t *)(&context->ul_count); // LG data->count = *(UInt32_t *)(&context->ul_count);
data->count = 0x00000000 | (context->ul_count.overflow << 8 ) | context->ul_count.seq_num; data->count = 0x00000000 | (context->ul_count.overflow << 8 ) | context->ul_count.seq_num;
#else #else
data->sqn = context->dl_count.seq_num; data->sqn = context->dl_count.seq_num;
// LG data->count = *(UInt32_t *)(&context->ul_count); // LG data->count = *(UInt32_t *)(&context->ul_count);
data->count = 0x00000000 | (context->dl_count.overflow << 8 ) | context->dl_count.seq_num; data->count = 0x00000000 | (context->dl_count.overflow << 8 ) | context->dl_count.seq_num;
#endif #endif
/* NAS integrity and cyphering keys may not be available if the /* NAS integrity and cyphering keys may not be available if the
* current security context is a partial EPS security context * current security context is a partial EPS security context
...@@ -515,9 +520,7 @@ void emm_as_set_security_data(emm_as_security_data_t *data, const void *args, ...@@ -515,9 +520,7 @@ void emm_as_set_security_data(emm_as_security_data_t *data, const void *args,
* The MME shall send the SECURITY MODE COMMAND message integrity * The MME shall send the SECURITY MODE COMMAND message integrity
* protected and unciphered */ * protected and unciphered */
LOG_TRACE(WARNING, LOG_TRACE(WARNING,
"EPS security context exists knas_enc %s", "EPS security context exists knas_enc");
context->knas_enc.value
);
data->k_enc = &context->knas_enc; data->k_enc = &context->knas_enc;
} }
} else { } else {
......
...@@ -234,12 +234,12 @@ int emm_proc_security_mode_command(int native_ksi, int ksi, ...@@ -234,12 +234,12 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
LOG_TRACE(INFO, "EMM-PROC - Update the non-current EPS security context seea=%u seia=%u", seea, seia); LOG_TRACE(INFO, "EMM-PROC - Update the non-current EPS security context seea=%u seia=%u", seea, seia);
/* Update selected cyphering and integrity algorithms */ /* Update selected cyphering and integrity algorithms */
_emm_data.non_current->capability.encryption = seea; _emm_data.non_current->capability.encryption = seea;
_emm_data.non_current->capability.integrity = seia; _emm_data.non_current->capability.integrity = seia;
/* Derive the NAS cyphering key */ /* Derive the NAS cyphering key */
if (_emm_data.non_current->knas_enc.value == NULL) { if (_emm_data.non_current->knas_enc.value == NULL) {
_emm_data.non_current->knas_enc.value = _emm_data.non_current->knas_enc.value =
(uint8_t *)malloc(AUTH_KNAS_ENC_SIZE); (uint8_t *)calloc(1,AUTH_KNAS_ENC_SIZE);
_emm_data.non_current->knas_enc.length = AUTH_KNAS_ENC_SIZE; _emm_data.non_current->knas_enc.length = AUTH_KNAS_ENC_SIZE;
} }
if (_emm_data.non_current->knas_enc.value != NULL) { if (_emm_data.non_current->knas_enc.value != NULL) {
...@@ -250,26 +250,27 @@ int emm_proc_security_mode_command(int native_ksi, int ksi, ...@@ -250,26 +250,27 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
/* Derive the NAS integrity key */ /* Derive the NAS integrity key */
if (_emm_data.non_current->knas_int.value == NULL) { if (_emm_data.non_current->knas_int.value == NULL) {
_emm_data.non_current->knas_int.value = _emm_data.non_current->knas_int.value =
(uint8_t *)malloc(AUTH_KNAS_INT_SIZE); (uint8_t *)calloc(1,AUTH_KNAS_INT_SIZE);
_emm_data.non_current->knas_int.length = AUTH_KNAS_INT_SIZE; _emm_data.non_current->knas_int.length = AUTH_KNAS_INT_SIZE;
} }
if (_emm_data.non_current->knas_int.value != NULL) { if (_emm_data.non_current->knas_int.value != NULL) {
if (rc != RETURNerror) { if (rc != RETURNerror) {
LOG_TRACE(INFO, "EMM-PROC - Update the non-current EPS security context knas_int"); LOG_TRACE(INFO, "EMM-PROC - Update the non-current EPS security context knas_int");
rc = _security_knas_int(&_emm_data.non_current->kasme, rc = _security_knas_int(&_emm_data.non_current->kasme,
&_emm_data.non_current->knas_int, seea); &_emm_data.non_current->knas_int, seia);
} }
} }
/* Derive the eNodeB key */ /* Derive the eNodeB key */
if (_security_data.kenb.value == NULL) { if (_security_data.kenb.value == NULL) {
_security_data.kenb.value = (uint8_t *)malloc(AUTH_KENB_SIZE); _security_data.kenb.value = (uint8_t *)calloc(1,AUTH_KENB_SIZE);
_security_data.kenb.length = AUTH_KENB_SIZE; _security_data.kenb.length = AUTH_KENB_SIZE;
} }
if (_security_data.kenb.value != NULL) { if (_security_data.kenb.value != NULL) {
if (rc != RETURNerror) { if (rc != RETURNerror) {
LOG_TRACE(INFO, "EMM-PROC - Update the non-current EPS security context kenb"); LOG_TRACE(INFO, "EMM-PROC - Update the non-current EPS security context kenb");
rc = _security_kenb(&_security_data.kenb, // LG COMMENT rc = _security_kenb(&_emm_data.security->kasme,
&_emm_data.security->kasme, rc = _security_kenb(&_emm_data.non_current->kasme,
&_security_data.kenb,
*(UInt32_t *)(&_emm_data.non_current->ul_count)); *(UInt32_t *)(&_emm_data.non_current->ul_count));
} }
} }
...@@ -319,6 +320,10 @@ int emm_proc_security_mode_command(int native_ksi, int ksi, ...@@ -319,6 +320,10 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
_emm_data.security->ul_count.seq_num = 0; _emm_data.security->ul_count.seq_num = 0;
} }
} }
_emm_data.security->selected_algorithms.encryption = seea;
_emm_data.security->selected_algorithms.integrity = seia;
} }
/* /*
* NAS security mode command not accepted by the UE * NAS security mode command not accepted by the UE
...@@ -446,6 +451,13 @@ int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia, ...@@ -446,6 +451,13 @@ int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
// LG: Kasme should have been received from authentication // LG: Kasme should have been received from authentication
// information request (S6A) // information request (S6A)
// Kasme is located in emm_ctx->vector.kasme // Kasme is located in emm_ctx->vector.kasme
FREE_OCTET_STRING(emm_ctx->security->kasme);
emm_ctx->security->kasme.value = malloc(32);
memcpy(emm_ctx->security->kasme.value,
emm_ctx->vector.kasme,
32);
emm_ctx->security->kasme.length = 32;
rc = _security_select_algorithms( rc = _security_select_algorithms(
eia, eia,
...@@ -474,7 +486,7 @@ int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia, ...@@ -474,7 +486,7 @@ int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
NAS_INT_ALG, NAS_INT_ALG,
emm_ctx->security->selected_algorithms.integrity, emm_ctx->security->selected_algorithms.integrity,
emm_ctx->vector.kasme, emm_ctx->vector.kasme,
&emm_ctx->security->knas_int.value); emm_ctx->security->knas_int.value);
if ( ! emm_ctx->security->knas_enc.value) { if ( ! emm_ctx->security->knas_enc.value) {
emm_ctx->security->knas_enc.value = malloc(AUTH_KNAS_ENC_SIZE); emm_ctx->security->knas_enc.value = malloc(AUTH_KNAS_ENC_SIZE);
...@@ -488,7 +500,7 @@ int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia, ...@@ -488,7 +500,7 @@ int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
NAS_ENC_ALG, NAS_ENC_ALG,
emm_ctx->security->selected_algorithms.encryption, emm_ctx->security->selected_algorithms.encryption,
emm_ctx->vector.kasme, emm_ctx->vector.kasme,
&emm_ctx->security->knas_enc.value); emm_ctx->security->knas_enc.value);
/* Set new security context indicator */ /* Set new security context indicator */
security_context_is_new = TRUE; security_context_is_new = TRUE;
...@@ -733,14 +745,20 @@ static void _security_release(emm_security_context_t *ctx) ...@@ -733,14 +745,20 @@ static void _security_release(emm_security_context_t *ctx)
/* Release Kasme security key */ /* Release Kasme security key */
if (ctx->kasme.value) { if (ctx->kasme.value) {
free(ctx->kasme.value); free(ctx->kasme.value);
ctx->kasme.value = NULL;
ctx->kasme.length = 0;
} }
/* Release NAS cyphering key */ /* Release NAS cyphering key */
if (ctx->knas_enc.value) { if (ctx->knas_enc.value) {
free(ctx->knas_enc.value); free(ctx->knas_enc.value);
ctx->knas_enc.value = NULL;
ctx->knas_enc.length = 0;
} }
/* Release NAS integrity key */ /* Release NAS integrity key */
if (ctx->knas_int.value) { if (ctx->knas_int.value) {
free(ctx->knas_int.value); free(ctx->knas_int.value);
ctx->knas_int.value = NULL;
ctx->knas_int.length = 0;
} }
/* Release the NAS security context */ /* Release the NAS security context */
free(ctx); free(ctx);
...@@ -771,6 +789,7 @@ static int _security_knas_enc(const OctetString *kasme, OctetString *knas_enc, ...@@ -771,6 +789,7 @@ static int _security_knas_enc(const OctetString *kasme, OctetString *knas_enc,
UInt8_t eea) UInt8_t eea)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
LOG_TRACE(INFO, "%s with algo dist %d algo id %d", __FUNCTION__,0x01, eea);
LOG_FUNC_RETURN (_security_kdf(kasme, knas_enc, 0x01, eea)); LOG_FUNC_RETURN (_security_kdf(kasme, knas_enc, 0x01, eea));
} }
...@@ -796,6 +815,7 @@ static int _security_knas_int(const OctetString *kasme, OctetString *knas_int, ...@@ -796,6 +815,7 @@ static int _security_knas_int(const OctetString *kasme, OctetString *knas_int,
UInt8_t eia) UInt8_t eia)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
LOG_TRACE(INFO, "%s with algo dist %d algo id %d", __FUNCTION__,0x02, eia);
LOG_FUNC_RETURN (_security_kdf(kasme, knas_int, 0x02, eia)); LOG_FUNC_RETURN (_security_kdf(kasme, knas_int, 0x02, eia));
} }
...@@ -823,18 +843,24 @@ static int _security_kenb(const OctetString *kasme, OctetString *kenb, ...@@ -823,18 +843,24 @@ static int _security_kenb(const OctetString *kasme, OctetString *kenb,
/* Compute the KDF input parameter /* Compute the KDF input parameter
* S = FC(0x11) || UL NAS Count || 0x00 0x04 * S = FC(0x11) || UL NAS Count || 0x00 0x04
*/ */
UInt8_t input[kasme->length]; UInt8_t input[32];
UInt16_t length = 4; UInt16_t length = 4;
int offset = 0; int offset = 0;
input[offset] = 0x11; LOG_TRACE(INFO, "%s with count= %d", __FUNCTION__, count);
offset += 1; memset(input, 0, 32);
input[offset] = count; input[0] = 0x11;
offset += length; // P0
input[offset] = length; input[1] = count >> 24;
input[2] = (UInt8_t)(count >> 16);
/* TODO !!! Compute the derived key */ input[3] = (UInt8_t)(count >> 8);
// todo_hmac_256(key, input, kasme->value); input[4] = (UInt8_t)count;
// L0
input[5] = 0;
input[6] = 4;
kdf(kasme->value, 32, input, 7, kenb->value, 32);
kenb->length = 32;
return (RETURNok); return (RETURNok);
} }
...@@ -865,24 +891,29 @@ static int _security_kdf(const OctetString *kasme, OctetString *key, ...@@ -865,24 +891,29 @@ static int _security_kdf(const OctetString *kasme, OctetString *key,
* S = FC(0x15) || Algorithm distinguisher || 0x00 0x01 * S = FC(0x15) || Algorithm distinguisher || 0x00 0x01
|| Algorithm identity || 0x00 0x01 || Algorithm identity || 0x00 0x01
*/ */
UInt8_t input[kasme->length]; UInt8_t input[32];
UInt16_t length = 1; UInt8_t output[32];
int offset = 0; LOG_TRACE(DEBUG, "%s:%u output key mem %p lenth %u",
int size_of_length = sizeof(length); __FUNCTION__, __LINE__,
key->value,
input[offset] = 0x15; key->length);
offset += 1; memset(input, 0, 32);
input[offset] = algo_dist; // FC
offset += length; input[0] = 0x15;
input[offset] = length; // P0 = Algorithm distinguisher
offset += size_of_length; input[1] = algo_dist;
input[offset] = algo_id; // L0 = 0x00 01
offset += length; input[2] = 0x00;
input[offset] = length; input[3] = 0x01;
// P1 = Algorithm identity
/* TODO !!! Compute the derived key */ input[4] = algo_id;
// todo_hmac_256(key, input, kasme->value); // L1 = length of Algorithm identity 0x00 0x01
input[5] = 0x00;
input[6] = 0x01;
/* Compute the derived key */
kdf(kasme->value, kasme->length, input, 7, output, 32);
memcpy(key->value, &output[31 - key->length + 1], key->length);
return (RETURNok); return (RETURNok);
} }
#endif // NAS_UE #endif // NAS_UE
......
...@@ -534,12 +534,18 @@ void emm_main_cleanup(void) ...@@ -534,12 +534,18 @@ void emm_main_cleanup(void)
emm_security_context_t *security = _emm_data.security; emm_security_context_t *security = _emm_data.security;
if (security->kasme.value) { if (security->kasme.value) {
free(security->kasme.value); free(security->kasme.value);
security->kasme.value = NULL;
security->kasme.length = 0;
} }
if (security->knas_enc.value) { if (security->knas_enc.value) {
free(security->knas_enc.value); free(security->knas_enc.value);
security->knas_enc.value = NULL;
security->knas_enc.length = 0;
} }
if (security->knas_int.value) { if (security->knas_int.value) {
free(security->knas_int.value); free(security->knas_int.value);
security->knas_int.value = NULL;
security->knas_int.length = 0;
} }
free(_emm_data.security); free(_emm_data.security);
_emm_data.security = NULL; _emm_data.security = NULL;
......
...@@ -1263,6 +1263,9 @@ static int _emm_as_send(const emm_as_t *msg) ...@@ -1263,6 +1263,9 @@ static int _emm_as_send(const emm_as_t *msg)
as_msg.msg.nas_establish_rsp.nasMsg.length); as_msg.msg.nas_establish_rsp.nasMsg.length);
LOG_FUNC_RETURN (RETURNok); LOG_FUNC_RETURN (RETURNok);
} else { } else {
LOG_TRACE(DEBUG, "EMMAS-SAP - "
"Sending nas_itti_establish_cnf to S1AP UE ID %d",
as_msg.msg.nas_establish_rsp.UEid);
/* Handle success case */ /* Handle success case */
nas_itti_establish_cnf( nas_itti_establish_cnf(
as_msg.msg.nas_establish_rsp.UEid, as_msg.msg.nas_establish_rsp.UEid,
......
...@@ -88,7 +88,7 @@ void dump_access_point_name_xml(AccessPointName *accesspointname, uint8_t iei) ...@@ -88,7 +88,7 @@ void dump_access_point_name_xml(AccessPointName *accesspointname, uint8_t iei)
if (iei > 0) if (iei > 0)
/* Don't display IEI if = 0 */ /* Don't display IEI if = 0 */
printf(" <IEI>0x%X</IEI>\n", iei); printf(" <IEI>0x%X</IEI>\n", iei);
dump_octet_string_xml(&accesspointname->accesspointnamevalue); printf("%s</Access Point Name>\n",
printf("</Access Point Name>\n"); dump_octet_string_xml(&accesspointname->accesspointnamevalue));
} }
...@@ -88,7 +88,7 @@ void dump_authentication_failure_parameter_xml(AuthenticationFailureParameter *a ...@@ -88,7 +88,7 @@ void dump_authentication_failure_parameter_xml(AuthenticationFailureParameter *a
if (iei > 0) if (iei > 0)
/* Don't display IEI if = 0 */ /* Don't display IEI if = 0 */
printf(" <IEI>0x%X</IEI>\n", iei); printf(" <IEI>0x%X</IEI>\n", iei);
dump_octet_string_xml(&authenticationfailureparameter->auts); printf("%s",dump_octet_string_xml(&authenticationfailureparameter->auts));
printf("</Authentication Failure Parameter>\n"); printf("</Authentication Failure Parameter>\n");
} }
...@@ -88,7 +88,7 @@ void dump_authentication_parameter_autn_xml(AuthenticationParameterAutn *authent ...@@ -88,7 +88,7 @@ void dump_authentication_parameter_autn_xml(AuthenticationParameterAutn *authent
if (iei > 0) if (iei > 0)
/* Don't display IEI if = 0 */ /* Don't display IEI if = 0 */
printf(" <IEI>0x%X</IEI>\n", iei); printf(" <IEI>0x%X</IEI>\n", iei);
dump_octet_string_xml(&authenticationparameterautn->autn); printf("%s", dump_octet_string_xml(&authenticationparameterautn->autn));
printf("</Authentication Parameter Autn>\n"); printf("</Authentication Parameter Autn>\n");
} }
...@@ -82,7 +82,7 @@ void dump_authentication_parameter_rand_xml(AuthenticationParameterRand *authent ...@@ -82,7 +82,7 @@ void dump_authentication_parameter_rand_xml(AuthenticationParameterRand *authent
if (iei > 0) if (iei > 0)
/* Don't display IEI if = 0 */ /* Don't display IEI if = 0 */
printf(" <IEI>0x%X</IEI>\n", iei); printf(" <IEI>0x%X</IEI>\n", iei);
dump_octet_string_xml(&authenticationparameterrand->rand); printf("%s",dump_octet_string_xml(&authenticationparameterrand->rand));
printf("</Authentication Parameter Rand>\n"); printf("</Authentication Parameter Rand>\n");
} }
...@@ -88,7 +88,7 @@ void dump_cli_xml(Cli *cli, uint8_t iei) ...@@ -88,7 +88,7 @@ void dump_cli_xml(Cli *cli, uint8_t iei)
if (iei > 0) if (iei > 0)
/* Don't display IEI if = 0 */ /* Don't display IEI if = 0 */
printf(" <IEI>0x%X</IEI>\n", iei); printf(" <IEI>0x%X</IEI>\n", iei);
dump_octet_string_xml(&cli->clivalue); printf("%s", dump_octet_string_xml(&cli->clivalue));
printf("</Cli>\n"); printf("</Cli>\n");
} }
...@@ -100,7 +100,7 @@ void dump_esm_message_container_xml(EsmMessageContainer *esmmessagecontainer, ui ...@@ -100,7 +100,7 @@ void dump_esm_message_container_xml(EsmMessageContainer *esmmessagecontainer, ui
if (iei > 0) if (iei > 0)
/* Don't display IEI if = 0 */ /* Don't display IEI if = 0 */
printf(" <IEI>0x%X</IEI>\n", iei); printf(" <IEI>0x%X</IEI>\n", iei);
dump_octet_string_xml(&esmmessagecontainer->esmmessagecontainercontents); printf("%s", dump_octet_string_xml(&esmmessagecontainer->esmmessagecontainercontents));
printf("</Esm Message Container>\n"); printf("</Esm Message Container>\n");
} }
...@@ -88,7 +88,7 @@ void dump_lcs_client_identity_xml(LcsClientIdentity *lcsclientidentity, uint8_t ...@@ -88,7 +88,7 @@ void dump_lcs_client_identity_xml(LcsClientIdentity *lcsclientidentity, uint8_t
if (iei > 0) if (iei > 0)
/* Don't display IEI if = 0 */ /* Don't display IEI if = 0 */
printf(" <IEI>0x%X</IEI>\n", iei); printf(" <IEI>0x%X</IEI>\n", iei);
dump_octet_string_xml(&lcsclientidentity->lcsclientidentityvalue); printf("%s",dump_octet_string_xml(&lcsclientidentity->lcsclientidentityvalue));
printf("</Lcs Client Identity>\n"); printf("</Lcs Client Identity>\n");
} }
...@@ -88,7 +88,7 @@ void dump_ms_network_capability_xml(MsNetworkCapability *msnetworkcapability, ui ...@@ -88,7 +88,7 @@ void dump_ms_network_capability_xml(MsNetworkCapability *msnetworkcapability, ui
if (iei > 0) if (iei > 0)
/* Don't display IEI if = 0 */ /* Don't display IEI if = 0 */
printf(" <IEI>0x%X</IEI>\n", iei); printf(" <IEI>0x%X</IEI>\n", iei);
dump_octet_string_xml(&msnetworkcapability->msnetworkcapabilityvalue); printf("%s",dump_octet_string_xml(&msnetworkcapability->msnetworkcapabilityvalue));
printf("</Ms Network Capability>\n"); printf("</Ms Network Capability>\n");
} }
...@@ -88,7 +88,7 @@ void dump_nas_message_container_xml(NasMessageContainer *nasmessagecontainer, ui ...@@ -88,7 +88,7 @@ void dump_nas_message_container_xml(NasMessageContainer *nasmessagecontainer, ui
if (iei > 0) if (iei > 0)
/* Don't display IEI if = 0 */ /* Don't display IEI if = 0 */
printf(" <IEI>0x%X</IEI>\n", iei); printf(" <IEI>0x%X</IEI>\n", iei);
dump_octet_string_xml(&nasmessagecontainer->nasmessagecontainercontents); printf("%s", dump_octet_string_xml(&nasmessagecontainer->nasmessagecontainercontents));
printf("</Nas Message Container>\n"); printf("</Nas Message Container>\n");
} }
...@@ -104,7 +104,7 @@ void dump_network_name_xml(NetworkName *networkname, uint8_t iei) ...@@ -104,7 +104,7 @@ void dump_network_name_xml(NetworkName *networkname, uint8_t iei)
printf(" <Coding scheme>%u</Coding scheme>\n", networkname->codingscheme); printf(" <Coding scheme>%u</Coding scheme>\n", networkname->codingscheme);
printf(" <Add CI>%u</Add CI>\n", networkname->addci); printf(" <Add CI>%u</Add CI>\n", networkname->addci);
printf(" <Number of spare bits in last octet>%u</Number of spare bits in last octet>\n", networkname->numberofsparebitsinlastoctet); printf(" <Number of spare bits in last octet>%u</Number of spare bits in last octet>\n", networkname->numberofsparebitsinlastoctet);
dump_octet_string_xml(&networkname->textstring); printf("%s", dump_octet_string_xml(&networkname->textstring));
printf("</Network Name>\n"); printf("</Network Name>\n");
} }
...@@ -82,7 +82,7 @@ void dump_p_tmsi_signature_xml(PTmsiSignature *ptmsisignature, uint8_t iei) ...@@ -82,7 +82,7 @@ void dump_p_tmsi_signature_xml(PTmsiSignature *ptmsisignature, uint8_t iei)
if (iei > 0) if (iei > 0)
/* Don't display IEI if = 0 */ /* Don't display IEI if = 0 */
printf(" <IEI>0x%X</IEI>\n", iei); printf(" <IEI>0x%X</IEI>\n", iei);
dump_octet_string_xml(&ptmsisignature->ptmsisignaturevalue); printf("%s",dump_octet_string_xml(&ptmsisignature->ptmsisignaturevalue));
printf("</P Tmsi Signature>\n"); printf("</P Tmsi Signature>\n");
} }
...@@ -94,7 +94,7 @@ void dump_pdn_address_xml(PdnAddress *pdnaddress, uint8_t iei) ...@@ -94,7 +94,7 @@ void dump_pdn_address_xml(PdnAddress *pdnaddress, uint8_t iei)
/* Don't display IEI if = 0 */ /* Don't display IEI if = 0 */
printf(" <IEI>0x%X</IEI>\n", iei); printf(" <IEI>0x%X</IEI>\n", iei);
printf(" <PDN type value>%u</PDN type value>\n", pdnaddress->pdntypevalue); printf(" <PDN type value>%u</PDN type value>\n", pdnaddress->pdntypevalue);
dump_octet_string_xml(&pdnaddress->pdnaddressinformation); printf("%s", dump_octet_string_xml(&pdnaddress->pdnaddressinformation));
printf("</Pdn Address>\n"); printf("</Pdn Address>\n");
} }
...@@ -117,7 +117,7 @@ void dump_protocol_configuration_options_xml(ProtocolConfigurationOptions *proto ...@@ -117,7 +117,7 @@ void dump_protocol_configuration_options_xml(ProtocolConfigurationOptions *proto
printf(" <Configuration protol>%u</Configuration protol>\n", protocolconfigurationoptions->configurationprotol); printf(" <Configuration protol>%u</Configuration protol>\n", protocolconfigurationoptions->configurationprotol);
printf(" <Protocol ID>%u</Protocol ID>\n", protocolconfigurationoptions->protocolid); printf(" <Protocol ID>%u</Protocol ID>\n", protocolconfigurationoptions->protocolid);
printf(" <Length of protocol ID>%u</Length of protocol ID>\n", protocolconfigurationoptions->lengthofprotocolid); printf(" <Length of protocol ID>%u</Length of protocol ID>\n", protocolconfigurationoptions->lengthofprotocolid);
dump_octet_string_xml(&protocolconfigurationoptions->protocolidcontents); printf("%s",dump_octet_string_xml(&protocolconfigurationoptions->protocolidcontents));
printf("</Protocol Configuration Options>\n"); printf("</Protocol Configuration Options>\n");
} }
...@@ -34,6 +34,9 @@ ...@@ -34,6 +34,9 @@
#include "TLVDecoder.h" #include "TLVDecoder.h"
#include "OctetString.h" #include "OctetString.h"
#define DUMP_OUTPUT_SIZE 1024
static char _dump_output[DUMP_OUTPUT_SIZE];
OctetString* dup_octet_string(OctetString *octetstring) OctetString* dup_octet_string(OctetString *octetstring)
{ {
OctetString *os_p = NULL; OctetString *os_p = NULL;
...@@ -78,20 +81,29 @@ int decode_octet_string(OctetString *octetstring, uint16_t pdulen, uint8_t *buff ...@@ -78,20 +81,29 @@ int decode_octet_string(OctetString *octetstring, uint16_t pdulen, uint8_t *buff
return octetstring->length; return octetstring->length;
} }
void dump_octet_string_xml(OctetString *octetstring) char* dump_octet_string_xml( const OctetString * const octetstring)
{ {
int i; int i;
printf(" <Length>%u</Length>\n <values>", octetstring->length); int remaining_size = DUMP_OUTPUT_SIZE;
for (i = 0; i < octetstring->length; i++) int size = 0;
printf("0x%x ", octetstring->value[i]); size = snprintf(_dump_output, remaining_size, "<Length>%u</Length>\n\t<values>", octetstring->length);
printf("</values>\n"); remaining_size -= size;
for (i = 0; i < octetstring->length; i++) {
size +=snprintf(&_dump_output[size], remaining_size, "0x%x ", octetstring->value[i]);
remaining_size -= size;
}
size +=snprintf(&_dump_output[size], remaining_size, "</values>\n");
return _dump_output;
} }
void dump_octet_string(OctetString *octetstring) char* dump_octet_string( const OctetString * const octetstring)
{ {
int i; int i;
printf(" <Length=%u><values>", octetstring->length); int remaining_size = DUMP_OUTPUT_SIZE;
for (i = 0; i < octetstring->length; i++) int size = 0;
printf("0x%x ", octetstring->value[i]); for (i = 0; i < octetstring->length; i++) {
printf("</values>\n"); size +=snprintf(&_dump_output[size], remaining_size, "0x%x ", octetstring->value[i]);
remaining_size -= size;
}
return _dump_output;
} }
...@@ -55,11 +55,10 @@ typedef struct OctetString_tag { ...@@ -55,11 +55,10 @@ typedef struct OctetString_tag {
} \ } \
(oCTETsTRINGcOPY).length = strlen((const char*)(oCTETsTRINGoRIG).value);\ (oCTETsTRINGcOPY).length = strlen((const char*)(oCTETsTRINGoRIG).value);\
assert((oCTETsTRINGoRIG).length == (oCTETsTRINGcOPY).length); \ assert((oCTETsTRINGoRIG).length == (oCTETsTRINGcOPY).length); \
(oCTETsTRINGcOPY).value = malloc((oCTETsTRINGoRIG).length+1); \ (oCTETsTRINGcOPY).value = malloc((oCTETsTRINGoRIG).length); \
memcpy((oCTETsTRINGcOPY).value, \ memcpy((oCTETsTRINGcOPY).value, \
(oCTETsTRINGoRIG).value, \ (oCTETsTRINGoRIG).value, \
(oCTETsTRINGoRIG).length); \ (oCTETsTRINGoRIG).length); \
(oCTETsTRINGcOPY).value[(oCTETsTRINGoRIG).length] = '\0'; \
} while (0); } while (0);
OctetString* dup_octet_string(OctetString*octetstring); OctetString* dup_octet_string(OctetString*octetstring);
...@@ -70,9 +69,9 @@ int encode_octet_string(OctetString *octetstring, uint8_t *buffer, uint32_t len) ...@@ -70,9 +69,9 @@ int encode_octet_string(OctetString *octetstring, uint8_t *buffer, uint32_t len)
int decode_octet_string(OctetString *octetstring, uint16_t pdulen, uint8_t *buffer, uint32_t buflen); int decode_octet_string(OctetString *octetstring, uint16_t pdulen, uint8_t *buffer, uint32_t buflen);
void dump_octet_string_xml(OctetString *octetstring); char* dump_octet_string_xml(const OctetString * const octetstring);
void dump_octet_string(OctetString *octetstring); char* dump_octet_string(const OctetString * const octetstring);
#endif /* OCTET_STRING_H_ */ #endif /* OCTET_STRING_H_ */
...@@ -347,12 +347,23 @@ int s6a_generate_authentication_info_req(s6a_auth_info_req_t *air_p) ...@@ -347,12 +347,23 @@ int s6a_generate_authentication_info_req(s6a_auth_info_req_t *air_p)
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_visited_plmn_id, 0, &avp)); CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_visited_plmn_id, 0, &avp));
PLMN_T_TO_TBCD(air_p->visited_plmn, plmn); PLMN_T_TO_TBCD(air_p->visited_plmn, plmn);
value.os.data = plmn; value.os.data = plmn;
value.os.len = 3; value.os.len = 3;
CHECK_FCT(fd_msg_avp_setvalue(avp, &value)); CHECK_FCT(fd_msg_avp_setvalue(avp, &value));
CHECK_FCT(fd_msg_avp_add(msg, MSG_BRW_LAST_CHILD, avp)); CHECK_FCT(fd_msg_avp_add(msg, MSG_BRW_LAST_CHILD, avp));
S6A_DEBUG("%s plmn: %02X%02X%02X\n",
__FUNCTION__,
plmn[0],
plmn[1],
plmn[2]);
S6A_DEBUG("%s visited_plmn: %02X%02X%02X\n",
__FUNCTION__,
value.os.data[0],
value.os.data[1],
value.os.data[2]);
} }
/* Adding the requested E-UTRAN authentication info AVP */ /* Adding the requested E-UTRAN authentication info AVP */
{ {
......
...@@ -28,45 +28,43 @@ ...@@ -28,45 +28,43 @@
*******************************************************************************/ *******************************************************************************/
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include <nettle/hmac.h> #include <nettle/hmac.h>
#include "security_types.h" #include "security_types.h"
#include "secu_defs.h" #include "secu_defs.h"
void kdf(const uint8_t *s, const uint32_t s_length, const uint8_t *key, void kdf(uint8_t *key, uint16_t key_len, uint8_t *s, uint16_t s_len, uint8_t *out,
const uint32_t key_length, uint8_t **out, uint32_t out_length) uint16_t out_len)
{ {
struct hmac_sha256_ctx ctx; struct hmac_sha256_ctx ctx;
uint8_t *buffer; memset(&ctx, 0, sizeof(ctx));
buffer = malloc(sizeof(uint8_t) * out_length); hmac_sha256_set_key(&ctx, key_len, key);
hmac_sha256_update(&ctx, s_len, s);
hmac_sha256_set_key(&ctx, key_length, key); hmac_sha256_digest(&ctx, out_len, out);
hmac_sha256_update(&ctx, s_length, s);
hmac_sha256_digest(&ctx, out_length, buffer);
*out = buffer;
} }
#ifndef NAS_UE #ifndef NAS_UE
int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keNB) int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB)
{ {
uint8_t string[7]; uint8_t s[7];
// FC // FC
string[0] = FC_KENB; s[0] = FC_KENB;
// P0 = Uplink NAS count // P0 = Uplink NAS count
string[1] = (nas_count & 0xff000000) >> 24; s[1] = (nas_count & 0xff000000) >> 24;
string[2] = (nas_count & 0x00ff0000) >> 16; s[2] = (nas_count & 0x00ff0000) >> 16;
string[3] = (nas_count & 0x0000ff00) >> 8; s[3] = (nas_count & 0x0000ff00) >> 8;
string[4] = (nas_count & 0x000000ff); s[4] = (nas_count & 0x000000ff);
// Length of NAS count // Length of NAS count
string[5] = 0x00; s[5] = 0x00;
string[6] = 0x04; s[6] = 0x04;
kdf(string, 7, kasme, 32, keNB, 32); kdf(kasme, 32, s, 7, keNB, 32);
return 0; return 0;
} }
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "security_types.h" #include "security_types.h"
#include "secu_defs.h" #include "secu_defs.h"
#define SECU_DEBUG 1
/*! /*!
* @brief Derive the kNASenc from kasme and perform truncate on the generated key to * @brief Derive the kNASenc from kasme and perform truncate on the generated key to
* reduce his size to 128 bits. Definition of the derivation function can * reduce his size to 128 bits. Definition of the derivation function can
...@@ -49,9 +50,10 @@ ...@@ -49,9 +50,10 @@
* NOTE: knas is dynamically allocated by the KDF function * NOTE: knas is dynamically allocated by the KDF function
*/ */
int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id, int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
const uint8_t kasme[32], uint8_t **knas) const uint8_t kasme[32], uint8_t *knas)
{ {
uint8_t s[7]; uint8_t s[7];
uint8_t out[32];
#if defined(SECU_DEBUG) #if defined(SECU_DEBUG)
int i; int i;
#endif #endif
...@@ -74,13 +76,17 @@ int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id, ...@@ -74,13 +76,17 @@ int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
s[6] = 0x01; s[6] = 0x01;
#if defined(SECU_DEBUG) #if defined(SECU_DEBUG)
printf("%s FC %d nas_alg_type distinguisher %d nas_enc_alg_identity %d\n",
__FUNCTION__, FC_ALG_KEY_DER, nas_alg_type, nas_enc_alg_id);
for (i = 0; i < 7; i ++) { for (i = 0; i < 7; i ++) {
printf("0x%02x ", s[i]); printf("0x%02x ", s[i]);
} }
printf("\n"); printf("\n");
#endif #endif
kdf(s, 7, kasme, 32, knas, 32); kdf(kasme, 32, s, 7, out, 32);
memcpy(knas, &out[31-16+1], 16);
return 0; return 0;
} }
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
s[5] = 0x00; s[5] = 0x00;
s[6] = 0x01; s[6] = 0x01;
kdf(s, 7, (uint8_t*)kasme, 32, (uint8_t**)&knas_temp, 32); kdf((uint8_t*)kasme, 32, s, 7, (uint8_t**)&knas_temp, 32);
// Truncate the generate key to 128 bits // Truncate the generate key to 128 bits
memcpy(knas, knas_temp, 16); memcpy(knas, knas_temp, 16);
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
// #define SECU_DEBUG // #define SECU_DEBUG
int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t **out) int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t *out)
{ {
snow_3g_context_t snow_3g_context; snow_3g_context_t snow_3g_context;
int n ; int n ;
...@@ -102,11 +102,17 @@ int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t **out) ...@@ -102,11 +102,17 @@ int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t **out)
for (i=0;i<n*4;i++) { for (i=0;i<n*4;i++) {
stream_cipher->message[i] ^= *(((uint8_t*)KS)+i); stream_cipher->message[i] ^= *(((uint8_t*)KS)+i);
} }
int ceil_index = 0;
if (zero_bit > 0) { if (zero_bit > 0) {
int ceil_index = (stream_cipher->blength+7) >> 3; ceil_index = (stream_cipher->blength+7) >> 3;
stream_cipher->message[ceil_index - 1] = stream_cipher->message[ceil_index - 1] & (uint8_t)(0xFF << (8 - zero_bit)); stream_cipher->message[ceil_index - 1] = stream_cipher->message[ceil_index - 1] & (uint8_t)(0xFF << (8 - zero_bit));
} }
free(KS); free(KS);
*out = stream_cipher->message; *out = stream_cipher->message;
memcpy(out, stream_cipher->message, n*4);
if (zero_bit > 0) {
out[ceil_index - 1] = stream_cipher->message[ceil_index - 1];
}
return 0; return 0;
} }
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
// #define SECU_DEBUG // #define SECU_DEBUG
int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t **out) int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t *out)
{ {
uint8_t m[16]; uint8_t m[16];
uint32_t local_count; uint32_t local_count;
...@@ -92,8 +92,9 @@ int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t **out) ...@@ -92,8 +92,9 @@ int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t **out)
if (zero_bit > 0) if (zero_bit > 0)
data[byte_length - 1] = data[byte_length - 1] & (uint8_t)(0xFF << (8 - zero_bit)); data[byte_length - 1] = data[byte_length - 1] & (uint8_t)(0xFF << (8 - zero_bit));
*out = data;
memcpy(out, data, byte_length);
free(data);
free(ctx); free(ctx);
return 0; return 0;
......
...@@ -42,13 +42,17 @@ ...@@ -42,13 +42,17 @@
#define SECU_DIRECTION_UPLINK 0 #define SECU_DIRECTION_UPLINK 0
#define SECU_DIRECTION_DOWNLINK 1 #define SECU_DIRECTION_DOWNLINK 1
void kdf(const uint8_t *s, const uint32_t s_length, const uint8_t *key, void kdf(uint8_t *key,
const uint32_t key_length, uint8_t **out, uint32_t out_length); uint16_t key_len,
uint8_t *s,
uint16_t s_len,
uint8_t *out,
uint16_t out_len);
int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keNB); int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB);
int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id, int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
const uint8_t kasme[32], uint8_t **knas); const uint8_t kasme[32], uint8_t *knas);
#define derive_key_nas_enc(aLGiD, kASME, kNAS) \ #define derive_key_nas_enc(aLGiD, kASME, kNAS) \
derive_key_nas(NAS_ENC_ALG, aLGiD, kASME, kNAS) derive_key_nas(NAS_ENC_ALG, aLGiD, kASME, kNAS)
...@@ -82,11 +86,11 @@ typedef struct { ...@@ -82,11 +86,11 @@ typedef struct {
uint32_t blength; uint32_t blength;
} nas_stream_cipher_t; } nas_stream_cipher_t;
int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t **out); int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t *out);
int nas_stream_encrypt_eia1(nas_stream_cipher_t *stream_cipher, uint8_t out[4]); int nas_stream_encrypt_eia1(nas_stream_cipher_t *stream_cipher, uint8_t out[4]);
int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t **out); int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t *out);
int nas_stream_encrypt_eia2(nas_stream_cipher_t *stream_cipher, uint8_t out[4]); int nas_stream_encrypt_eia2(nas_stream_cipher_t *stream_cipher, uint8_t out[4]);
......
...@@ -44,7 +44,7 @@ void do_kdf(uint8_t *key, unsigned key_length, uint8_t *data, unsigned data_leng ...@@ -44,7 +44,7 @@ void do_kdf(uint8_t *key, unsigned key_length, uint8_t *data, unsigned data_leng
{ {
uint8_t *result; uint8_t *result;
kdf(data, data_length, key, key_length, &result, 32); kdf(key, key_length, data, data_length, &result, 32);
if (compare_buffer(result, exp_length, exp, exp_length) != 0) { if (compare_buffer(result, exp_length, exp, exp_length) != 0) {
fail("Fail: kdf\n"); fail("Fail: kdf\n");
} }
......
...@@ -241,9 +241,14 @@ do { \ ...@@ -241,9 +241,14 @@ do { \
#define PLMN_T_TO_TBCD(pLMN, tBCDsTRING) \ #define PLMN_T_TO_TBCD(pLMN, tBCDsTRING) \
do { \ do { \
tBCDsTRING[0] = (pLMN.MCCdigit2 << 4) | pLMN.MCCdigit3; \ tBCDsTRING[0] = (pLMN.MCCdigit2 << 4) | pLMN.MCCdigit3; \
tBCDsTRING[1] = ((pLMN.MNCdigit1 == 0 ? 0xF : pLMN.MNCdigit1) << 4) \ /* ambiguous (think about len 2) */ \
| pLMN.MCCdigit1; \ if (pLMN.MNCdigit1 == 0) { \
tBCDsTRING[2] = (pLMN.MNCdigit2 << 4) | pLMN.MNCdigit3; \ tBCDsTRING[1] = (0x0F << 4) | pLMN.MCCdigit1; \
tBCDsTRING[2] = (pLMN.MNCdigit3 << 4) | pLMN.MNCdigit2; \
} else { \
tBCDsTRING[1] = (pLMN.MNCdigit3 << 4) | pLMN.MCCdigit1; \
tBCDsTRING[2] = (pLMN.MNCdigit2 << 4) | pLMN.MNCdigit1; \
} \
} while(0) } while(0)
#define PLMN_T_TO_MCC_MNC(pLMN, mCC, mNC, mNCdIGITlENGTH) \ #define PLMN_T_TO_MCC_MNC(pLMN, mCC, mNC, mNCdIGITlENGTH) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment