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
This commit is contained in:
@@ -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;
|
||||
MME_APP_IMSI_TO_STRING(imsi, auth_info_req->imsi);
|
||||
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;
|
||||
if (auts != NULL) {
|
||||
auth_info_req->re_synchronization = 1;
|
||||
|
||||
@@ -287,13 +287,15 @@ mme_app_handle_conn_est_cnf(
|
||||
mme_app_connection_establishment_cnf_t *establishment_cnf_p = NULL;
|
||||
bearer_context_t *current_bearer_p = NULL;
|
||||
ebi_t bearer_id = 0;
|
||||
uint8_t *keNB = NULL;
|
||||
uint8_t keNB[32];
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -332,9 +334,8 @@ mme_app_handle_conn_est_cnf(
|
||||
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);
|
||||
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);
|
||||
free(keNB);
|
||||
|
||||
itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p);
|
||||
}
|
||||
@@ -355,8 +356,9 @@ mme_app_handle_conn_est_ind(
|
||||
&mme_app_desc.mme_ue_contexts,
|
||||
conn_est_ind_pP->mme_ue_s1ap_id);
|
||||
if (ue_context_p == NULL) {
|
||||
MME_APP_DEBUG("We didn't find this mme_ue_s1ap_id in list of UE: %08x\n",
|
||||
conn_est_ind_pP->mme_ue_s1ap_id);
|
||||
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);
|
||||
MME_APP_DEBUG("UE context doesn't exist -> create one\n");
|
||||
if ((ue_context_p = mme_create_new_ue_context()) == NULL) {
|
||||
/* Error during ue context malloc */
|
||||
@@ -369,11 +371,15 @@ mme_app_handle_conn_est_ind(
|
||||
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);
|
||||
|
||||
// test
|
||||
// tests
|
||||
ue_context_p = mme_ue_context_exists_mme_ue_s1ap_id(
|
||||
&mme_app_desc.mme_ue_contexts,
|
||||
conn_est_ind_pP->mme_ue_s1ap_id);
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
} break;
|
||||
|
||||
//case NAS_CONNECTION_ESTABLISHMENT_CNF: {
|
||||
case NAS_CONNECTION_ESTABLISHMENT_CNF: {
|
||||
mme_app_handle_conn_est_cnf(&NAS_CONNECTION_ESTABLISHMENT_CNF(received_message_p));
|
||||
} break;
|
||||
|
||||
// From S1AP Initiating Message/EMM Attach Request
|
||||
case MME_APP_CONNECTION_ESTABLISHMENT_IND: {
|
||||
mme_app_handle_conn_est_ind(&MME_APP_CONNECTION_ESTABLISHMENT_IND(received_message_p));
|
||||
} break;
|
||||
|
||||
@@ -108,6 +108,7 @@ _nas_message_encrypt(
|
||||
UInt8_t type,
|
||||
UInt32_t code,
|
||||
UInt8_t seq,
|
||||
int const direction,
|
||||
int length,
|
||||
const emm_security_context_t * const emm_security_context);
|
||||
|
||||
@@ -166,6 +167,11 @@ nas_message_encrypt(
|
||||
header->security_header_type,
|
||||
header->message_authentication_code,
|
||||
header->sequence_number,
|
||||
#ifdef NAS_MME
|
||||
SECU_DIRECTION_DOWNLINK,
|
||||
#else
|
||||
SECU_DIRECTION_UPLINK,
|
||||
#endif
|
||||
length - size,
|
||||
emm_security_context);
|
||||
/* Integrity protected the NAS message */
|
||||
@@ -183,7 +189,7 @@ nas_message_encrypt(
|
||||
#endif
|
||||
emm_security_context);
|
||||
/* 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 {
|
||||
@@ -265,9 +271,22 @@ int nas_message_decrypt(
|
||||
int size = _nas_message_header_decode(inbuf, header, length);
|
||||
|
||||
if (size < 0) {
|
||||
LOG_TRACE(DEBUG, "MESSAGE TOO SHORT");
|
||||
LOG_FUNC_RETURN (TLV_DECODE_BUFFER_TOO_SHORT);
|
||||
}
|
||||
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 */
|
||||
int offset = size - sizeof(UInt8_t);
|
||||
/* Compute the NAS message authentication code */
|
||||
@@ -281,20 +300,29 @@ int nas_message_decrypt(
|
||||
#endif
|
||||
emm_security_context);
|
||||
|
||||
|
||||
/* Check NAS message integrity */
|
||||
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)
|
||||
LOG_FUNC_RETURN (TLV_DECODE_MAC_MISMATCH);
|
||||
#else
|
||||
#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 !=
|
||||
NAS_SECURITY_ALGORITHMS_EIA0) {
|
||||
LOG_FUNC_RETURN (TLV_DECODE_MAC_MISMATCH);
|
||||
LOG_FUNC_RETURN (TLV_DECODE_MAC_MISMATCH);
|
||||
} else {
|
||||
LOG_TRACE(WARNING,
|
||||
"MAC failure but continue due to EIA0 selected");
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
LOG_TRACE(DEBUG, "Integrity: MAC Success");
|
||||
}
|
||||
|
||||
/* Decrypt the security protected NAS message */
|
||||
@@ -307,6 +335,7 @@ int nas_message_decrypt(
|
||||
bytes = length - size;
|
||||
}
|
||||
else {
|
||||
LOG_TRACE(DEBUG, "Plain NAS message found");
|
||||
/* The input buffer contains a plain NAS message */
|
||||
memcpy(outbuf, inbuf, length);
|
||||
}
|
||||
@@ -341,15 +370,6 @@ int nas_message_decode(
|
||||
LOG_FUNC_IN;
|
||||
emm_security_context_t *emm_security_context = (emm_security_context_t*)security;
|
||||
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 */
|
||||
int size = _nas_message_header_decode(buffer, &msg->header, length);
|
||||
@@ -358,6 +378,18 @@ int nas_message_decode(
|
||||
LOG_FUNC_RETURN (TLV_DECODE_BUFFER_TOO_SHORT);
|
||||
}
|
||||
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 */
|
||||
int offset = size - sizeof(UInt8_t);
|
||||
/* Compute the NAS message authentication code */
|
||||
@@ -431,15 +463,7 @@ int nas_message_encode(
|
||||
|
||||
emm_security_context_t *emm_security_context = (emm_security_context_t*)security;
|
||||
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 */
|
||||
int size = _nas_message_header_encode(buffer, &msg->header, length);
|
||||
@@ -459,9 +483,13 @@ int nas_message_encode(
|
||||
/* Compute offset of the sequence number field */
|
||||
int offset = size - sizeof(UInt8_t);
|
||||
/* 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(
|
||||
buffer + offset,
|
||||
length - offset,
|
||||
bytes + size - offset,
|
||||
#ifdef NAS_MME
|
||||
SECU_DIRECTION_DOWNLINK,
|
||||
#else
|
||||
@@ -469,7 +497,7 @@ int nas_message_encode(
|
||||
#endif
|
||||
emm_security_context);
|
||||
/* 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) {
|
||||
#ifdef NAS_MME
|
||||
@@ -832,6 +860,11 @@ static int _nas_message_protected_encode(
|
||||
msg->header.security_header_type,
|
||||
msg->header.message_authentication_code,
|
||||
msg->header.sequence_number,
|
||||
#ifdef NAS_MME
|
||||
SECU_DIRECTION_DOWNLINK,
|
||||
#else
|
||||
SECU_DIRECTION_UPLINK,
|
||||
#endif
|
||||
size,
|
||||
emm_security_context);
|
||||
//seq, size);
|
||||
@@ -901,6 +934,7 @@ static int _nas_message_decrypt(
|
||||
** type: The security header type **
|
||||
** code: The message authentication code **
|
||||
** seq: The sequence number **
|
||||
** direction: The sequence number **
|
||||
** length: Maximal capacity of the output buffer **
|
||||
** Others: None **
|
||||
** **
|
||||
@@ -917,17 +951,60 @@ static int _nas_message_encrypt(
|
||||
UInt8_t type,
|
||||
UInt32_t code,
|
||||
UInt8_t seq,
|
||||
int const direction,
|
||||
int length,
|
||||
const emm_security_context_t * const emm_security_context)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* TODO: run the cyphering algorithm */
|
||||
memcpy(dest, src, length);
|
||||
switch (emm_security_context->selected_algorithms.encryption) {
|
||||
|
||||
LOG_FUNC_RETURN (size);
|
||||
case NAS_SECURITY_ALGORITHMS_EEA1: {
|
||||
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);
|
||||
|
||||
}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(
|
||||
|
||||
/****************************************************************************
|
||||
** **
|
||||
** Name: _nas_message_get_mac() **
|
||||
** Name: _nas_message_get_mac() **
|
||||
** **
|
||||
** Description: Run integrity algorithm onto cyphered or uncyphered NAS **
|
||||
** message encoded in the input buffer and return the compu- **
|
||||
** ted message authentication code **
|
||||
** message encoded in the input buffer and return the compu- **
|
||||
** ted message authentication code **
|
||||
** **
|
||||
** Inputs buffer: Pointer to the integrity protected data **
|
||||
** buffer **
|
||||
** count: Value of the uplink NAS counter **
|
||||
** length: Length of the input buffer **
|
||||
** Others: None **
|
||||
** Inputs buffer: Pointer to the integrity protected data **
|
||||
** buffer **
|
||||
** count: Value of the uplink NAS counter **
|
||||
** length: Length of the input buffer **
|
||||
** direction **
|
||||
** Others: None **
|
||||
** **
|
||||
** Outputs: None **
|
||||
** Return: The message authentication code **
|
||||
** Others: None **
|
||||
** Return: The message authentication code **
|
||||
** Others: None **
|
||||
** **
|
||||
***************************************************************************/
|
||||
static UInt32_t _nas_message_get_mac(
|
||||
@@ -982,11 +1060,8 @@ static UInt32_t _nas_message_get_mac(
|
||||
UInt32_t count;
|
||||
UInt32_t *mac32;
|
||||
|
||||
LOG_TRACE(DEBUG,
|
||||
"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);
|
||||
int i,bytes = 0;
|
||||
|
||||
if (direction == SECU_DIRECTION_UPLINK) {
|
||||
count = 0x00000000 ||
|
||||
((emm_security_context->ul_count.overflow && 0x0000FFFF) << 8) ||
|
||||
@@ -996,7 +1071,31 @@ static UInt32_t _nas_message_get_mac(
|
||||
((emm_security_context->dl_count.overflow && 0x0000FFFF) << 8) ||
|
||||
(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.count = count;
|
||||
stream_cipher.bearer = 0x00; //33.401 section 8.1.1
|
||||
@@ -1009,10 +1108,14 @@ static UInt32_t _nas_message_get_mac(
|
||||
&stream_cipher,
|
||||
mac);
|
||||
LOG_TRACE(DEBUG,
|
||||
"NAS_SECURITY_ALGORITHMS_EIA1 returned MAC %x.%x.%x.%x for length %d direction %d, count %d",
|
||||
mac[0], mac[1], mac[2],mac[3], length, direction, count);
|
||||
"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],
|
||||
*((UInt32_t*)&mac),
|
||||
length,
|
||||
direction,
|
||||
count);
|
||||
mac32 = (UInt32_t*)&mac;
|
||||
LOG_FUNC_RETURN (*mac32);
|
||||
LOG_FUNC_RETURN (ntohl(*mac32));
|
||||
}break;
|
||||
|
||||
case NAS_SECURITY_ALGORITHMS_EIA2: {
|
||||
@@ -1021,11 +1124,6 @@ static UInt32_t _nas_message_get_mac(
|
||||
UInt32_t count;
|
||||
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) {
|
||||
count = 0x00000000 ||
|
||||
((emm_security_context->ul_count.overflow && 0x0000FFFF) << 8) ||
|
||||
@@ -1035,6 +1133,12 @@ static UInt32_t _nas_message_get_mac(
|
||||
((emm_security_context->dl_count.overflow && 0x0000FFFF) << 8) ||
|
||||
(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_length = AUTH_KNAS_INT_SIZE;
|
||||
stream_cipher.count = count;
|
||||
@@ -1048,18 +1152,23 @@ static UInt32_t _nas_message_get_mac(
|
||||
&stream_cipher,
|
||||
mac);
|
||||
LOG_TRACE(DEBUG,
|
||||
"NAS_SECURITY_ALGORITHMS_EIA2 returned MAC %x.%x.%x.%x for length %d direction %d, count %d",
|
||||
mac[0], mac[1], mac[2],mac[3], length, direction, count);
|
||||
"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],
|
||||
*((UInt32_t*)&mac),
|
||||
length,
|
||||
direction,
|
||||
count);
|
||||
mac32 = (UInt32_t*)&mac;
|
||||
LOG_FUNC_RETURN (*mac32);
|
||||
LOG_FUNC_RETURN (ntohl(*mac32));
|
||||
}break;
|
||||
|
||||
case NAS_SECURITY_ALGORITHMS_EIA0:
|
||||
LOG_TRACE(DEBUG,
|
||||
"NAS_SECURITY_ALGORITHMS_EIA0 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);
|
||||
"NAS_SECURITY_ALGORITHMS_EIA0 dir %s count.seq_num %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
|
||||
);
|
||||
|
||||
#if defined(EPC_BUILD) || defined(UE_BUILD)
|
||||
LOG_FUNC_RETURN (0);
|
||||
#else
|
||||
@@ -1071,6 +1180,7 @@ static UInt32_t _nas_message_get_mac(
|
||||
LOG_TRACE(ERROR,
|
||||
"Unknown integrity protection algorithm %d",
|
||||
emm_security_context->selected_algorithms.integrity);
|
||||
break;
|
||||
}
|
||||
LOG_FUNC_RETURN (0);
|
||||
}
|
||||
|
||||
@@ -222,8 +222,8 @@ int usim_api_authenticate(const OctetString* rand_pP, const OctetString* autn_pP
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
LOG_TRACE(DEBUG, "USIM-API - rand :");dump_octet_string(rand_pP);
|
||||
LOG_TRACE(DEBUG, "USIM-API - autn :");dump_octet_string(autn_pP);
|
||||
LOG_TRACE(DEBUG, "USIM-API - rand :%s",dump_octet_string(rand_pP));
|
||||
LOG_TRACE(DEBUG, "USIM-API - autn :%s",dump_octet_string(autn_pP));
|
||||
|
||||
/* Compute the authentication response RES = f2K (RAND) */
|
||||
/* Compute the cipher key CK = f3K (RAND) */
|
||||
@@ -233,9 +233,9 @@ int usim_api_authenticate(const OctetString* rand_pP, const OctetString* autn_pP
|
||||
u8 ak[USIM_API_AK_SIZE];
|
||||
f2345(_usim_api_k, rand_pP->value,
|
||||
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 - ck(f3) :");dump_octet_string(ck_pP);
|
||||
LOG_TRACE(DEBUG, "USIM-API - ik(f4) :");dump_octet_string(ik_pP);
|
||||
LOG_TRACE(DEBUG, "USIM-API - res(f2) :%s",dump_octet_string(res_pP));
|
||||
LOG_TRACE(DEBUG, "USIM-API - ck(f3) :%s",dump_octet_string(ck_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",
|
||||
ak[0],ak[1],ak[2],ak[3],ak[4],ak[5]);
|
||||
|
||||
|
||||
@@ -1672,29 +1672,40 @@ static int _emm_attach_release(void *args)
|
||||
|
||||
if (emm_ctx->guti) {
|
||||
free(emm_ctx->guti);
|
||||
emm_ctx->guti = NULL;
|
||||
}
|
||||
if (emm_ctx->imsi) {
|
||||
free(emm_ctx->imsi);
|
||||
emm_ctx->imsi = NULL;
|
||||
}
|
||||
if (emm_ctx->imei) {
|
||||
free(emm_ctx->imei);
|
||||
emm_ctx->imei = NULL;
|
||||
}
|
||||
if (emm_ctx->esm_msg.length > 0) {
|
||||
free(emm_ctx->esm_msg.value);
|
||||
emm_ctx->esm_msg.value = NULL;
|
||||
}
|
||||
/* Release NAS security context */
|
||||
if (emm_ctx->security) {
|
||||
emm_security_context_t *security = emm_ctx->security;
|
||||
if (security->kasme.value) {
|
||||
free(security->kasme.value);
|
||||
security->kasme.value = NULL;
|
||||
security->kasme.length = 0;
|
||||
}
|
||||
if (security->knas_enc.value) {
|
||||
free(security->knas_enc.value);
|
||||
security->knas_enc.value = NULL;
|
||||
security->knas_enc.length = 0;
|
||||
}
|
||||
if (security->knas_int.value) {
|
||||
free(security->knas_int.value);
|
||||
security->knas_int.value = NULL;
|
||||
security->knas_int.length = 0;
|
||||
}
|
||||
free(emm_ctx->security);
|
||||
emm_ctx->security = NULL;
|
||||
}
|
||||
/* Release the EMM context */
|
||||
#if defined(EPC_BUILD)
|
||||
|
||||
@@ -59,6 +59,7 @@ Description Defines the authentication EMM procedure executed by the
|
||||
|
||||
#include <stdlib.h> // malloc, free
|
||||
#include <string.h> // memcpy, memcmp, memset
|
||||
#include <arpa/inet.h> // htons
|
||||
|
||||
#include "emm_proc.h"
|
||||
#include "nas_log.h"
|
||||
@@ -389,8 +390,7 @@ int emm_proc_authentication_request(int native_ksi, int ksi,
|
||||
/* Derive the Kasme from the authentication challenge using
|
||||
* the PLMN identity of the selected PLMN */
|
||||
_emm_data.non_current->kasme.length = AUTH_KASME_SIZE;
|
||||
_emm_data.non_current->kasme.value =
|
||||
(uint8_t *)malloc(sizeof(AUTH_KASME_SIZE));
|
||||
_emm_data.non_current->kasme.value = malloc(32);
|
||||
_authentication_kasme(autn, &ck, &ik, &_emm_data.splmn,
|
||||
&_emm_data.non_current->kasme);
|
||||
/* NAS integrity and cyphering keys are not yet available */
|
||||
@@ -1171,68 +1171,78 @@ static int _authentication_kasme(const OctetString *autn,
|
||||
{
|
||||
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 */
|
||||
UInt8_t key[ck->length + ik->length];
|
||||
memcpy(key, ck->value, ck->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
|
||||
*/
|
||||
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;
|
||||
int offset = 0;
|
||||
int size_of_length = sizeof(length);
|
||||
|
||||
// FC
|
||||
input[offset] = 0x10;
|
||||
input_s[offset] = 0x10;
|
||||
offset += 1;
|
||||
|
||||
// P0=SN id
|
||||
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",
|
||||
input[offset],
|
||||
input[offset+1],
|
||||
input[offset+2]);
|
||||
input_s[offset],
|
||||
input_s[offset+1],
|
||||
input_s[offset+2]);
|
||||
offset += 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;
|
||||
|
||||
// P1=Authentication token
|
||||
length = AUTH_SQN_SIZE;
|
||||
memcpy(input + offset, autn, length);
|
||||
memcpy(input_s + offset, autn->value, length);
|
||||
offset += length;
|
||||
// L1
|
||||
memcpy(input + offset, &length, size_of_length);
|
||||
length = htons(length);
|
||||
memcpy(input_s + offset, &length, size_of_length);
|
||||
offset += size_of_length;
|
||||
|
||||
/* TODO !!! Compute the Kasme key */
|
||||
// todo_hmac_256(key, input, kasme->value);
|
||||
kdf(input,
|
||||
LOG_TRACE(INFO,
|
||||
"EMM-PROC _authentication_kasme input S to KFD (length %u)%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
|
||||
offset,
|
||||
key,
|
||||
ck->length + ik->length , /*key_length*/
|
||||
&kasme->value,
|
||||
kasme->length);
|
||||
input_s[0],input_s[1],input_s[2],input_s[3],
|
||||
input_s[4],input_s[5],input_s[6],input_s[7],
|
||||
input_s[8],input_s[9],input_s[10],input_s[11],
|
||||
input_s[12],input_s[13]);
|
||||
/* TODO !!! Compute the Kasme key */
|
||||
// todo_hmac_256(key, input_s, kasme->value);
|
||||
kdf(key,
|
||||
ck->length + ik->length , /*key_length*/
|
||||
input_s,
|
||||
offset,
|
||||
kasme->value,
|
||||
kasme->length);
|
||||
|
||||
LOG_TRACE(INFO,"EMM-PROC CK (l=%d)", ck->length);
|
||||
LOG_TRACE(INFO,"EMM-PROC IK (l=%d)", ik->length);
|
||||
|
||||
LOG_TRACE(INFO,"EMM-PROC KASME (l=%d)%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
"%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
"%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
"%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
LOG_TRACE(INFO,"EMM-PROC KASME (l=%d)%s",
|
||||
kasme->length,
|
||||
kasme->value[0],kasme->value[1],kasme->value[2],kasme->value[3],
|
||||
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]);
|
||||
dump_octet_string(kasme));
|
||||
|
||||
LOG_FUNC_RETURN (RETURNok);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
* NAS signalling messages with the selected NAS ciphering and
|
||||
* NAS integrity algorithms */
|
||||
LOG_TRACE(WARNING,
|
||||
"EPS security context exists is new %u KSI %u SQN %u count %u knas_int %s",
|
||||
LOG_TRACE(INFO,
|
||||
"EPS security context exists is new %u KSI %u SQN %u count %u",
|
||||
is_new,
|
||||
context->eksi,
|
||||
context->ul_count.seq_num,
|
||||
*(UInt32_t *)(&context->ul_count),
|
||||
context->knas_int.value
|
||||
);
|
||||
*(UInt32_t *)(&context->ul_count));
|
||||
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->ksi = context->eksi;
|
||||
data->ksi = context->eksi;
|
||||
#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);
|
||||
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
|
||||
data->sqn = context->dl_count.seq_num;
|
||||
data->sqn = context->dl_count.seq_num;
|
||||
// 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
|
||||
/* NAS integrity and cyphering keys may not be available if the
|
||||
* 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,
|
||||
* The MME shall send the SECURITY MODE COMMAND message integrity
|
||||
* protected and unciphered */
|
||||
LOG_TRACE(WARNING,
|
||||
"EPS security context exists knas_enc %s",
|
||||
context->knas_enc.value
|
||||
);
|
||||
"EPS security context exists knas_enc");
|
||||
data->k_enc = &context->knas_enc;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -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);
|
||||
/* Update selected cyphering and integrity algorithms */
|
||||
_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 */
|
||||
if (_emm_data.non_current->knas_enc.value == NULL) {
|
||||
_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;
|
||||
}
|
||||
if (_emm_data.non_current->knas_enc.value != NULL) {
|
||||
@@ -250,26 +250,27 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
|
||||
/* Derive the NAS integrity key */
|
||||
if (_emm_data.non_current->knas_int.value == NULL) {
|
||||
_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;
|
||||
}
|
||||
if (_emm_data.non_current->knas_int.value != NULL) {
|
||||
if (rc != RETURNerror) {
|
||||
LOG_TRACE(INFO, "EMM-PROC - Update the non-current EPS security context knas_int");
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
if (_security_data.kenb.value != NULL) {
|
||||
if (rc != RETURNerror) {
|
||||
LOG_TRACE(INFO, "EMM-PROC - Update the non-current EPS security context kenb");
|
||||
rc = _security_kenb(&_security_data.kenb,
|
||||
&_emm_data.security->kasme,
|
||||
// LG COMMENT rc = _security_kenb(&_emm_data.security->kasme,
|
||||
rc = _security_kenb(&_emm_data.non_current->kasme,
|
||||
&_security_data.kenb,
|
||||
*(UInt32_t *)(&_emm_data.non_current->ul_count));
|
||||
}
|
||||
}
|
||||
@@ -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->selected_algorithms.encryption = seea;
|
||||
_emm_data.security->selected_algorithms.integrity = seia;
|
||||
|
||||
}
|
||||
/*
|
||||
* 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,
|
||||
// LG: Kasme should have been received from authentication
|
||||
// information request (S6A)
|
||||
// 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(
|
||||
eia,
|
||||
@@ -474,7 +486,7 @@ int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
|
||||
NAS_INT_ALG,
|
||||
emm_ctx->security->selected_algorithms.integrity,
|
||||
emm_ctx->vector.kasme,
|
||||
&emm_ctx->security->knas_int.value);
|
||||
emm_ctx->security->knas_int.value);
|
||||
|
||||
if ( ! emm_ctx->security->knas_enc.value) {
|
||||
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,
|
||||
NAS_ENC_ALG,
|
||||
emm_ctx->security->selected_algorithms.encryption,
|
||||
emm_ctx->vector.kasme,
|
||||
&emm_ctx->security->knas_enc.value);
|
||||
emm_ctx->security->knas_enc.value);
|
||||
|
||||
/* Set new security context indicator */
|
||||
security_context_is_new = TRUE;
|
||||
@@ -733,14 +745,20 @@ static void _security_release(emm_security_context_t *ctx)
|
||||
/* Release Kasme security key */
|
||||
if (ctx->kasme.value) {
|
||||
free(ctx->kasme.value);
|
||||
ctx->kasme.value = NULL;
|
||||
ctx->kasme.length = 0;
|
||||
}
|
||||
/* Release NAS cyphering key */
|
||||
if (ctx->knas_enc.value) {
|
||||
free(ctx->knas_enc.value);
|
||||
ctx->knas_enc.value = NULL;
|
||||
ctx->knas_enc.length = 0;
|
||||
}
|
||||
/* Release NAS integrity key */
|
||||
if (ctx->knas_int.value) {
|
||||
free(ctx->knas_int.value);
|
||||
ctx->knas_int.value = NULL;
|
||||
ctx->knas_int.length = 0;
|
||||
}
|
||||
/* Release the NAS security context */
|
||||
free(ctx);
|
||||
@@ -771,6 +789,7 @@ static int _security_knas_enc(const OctetString *kasme, OctetString *knas_enc,
|
||||
UInt8_t eea)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -796,6 +815,7 @@ static int _security_knas_int(const OctetString *kasme, OctetString *knas_int,
|
||||
UInt8_t eia)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -823,18 +843,24 @@ static int _security_kenb(const OctetString *kasme, OctetString *kenb,
|
||||
/* Compute the KDF input parameter
|
||||
* S = FC(0x11) || UL NAS Count || 0x00 0x04
|
||||
*/
|
||||
UInt8_t input[kasme->length];
|
||||
UInt16_t length = 4;
|
||||
int offset = 0;
|
||||
UInt8_t input[32];
|
||||
UInt16_t length = 4;
|
||||
int offset = 0;
|
||||
|
||||
input[offset] = 0x11;
|
||||
offset += 1;
|
||||
input[offset] = count;
|
||||
offset += length;
|
||||
input[offset] = length;
|
||||
LOG_TRACE(INFO, "%s with count= %d", __FUNCTION__, count);
|
||||
memset(input, 0, 32);
|
||||
input[0] = 0x11;
|
||||
// P0
|
||||
input[1] = count >> 24;
|
||||
input[2] = (UInt8_t)(count >> 16);
|
||||
input[3] = (UInt8_t)(count >> 8);
|
||||
input[4] = (UInt8_t)count;
|
||||
// L0
|
||||
input[5] = 0;
|
||||
input[6] = 4;
|
||||
|
||||
/* TODO !!! Compute the derived key */
|
||||
// todo_hmac_256(key, input, kasme->value);
|
||||
kdf(kasme->value, 32, input, 7, kenb->value, 32);
|
||||
kenb->length = 32;
|
||||
return (RETURNok);
|
||||
}
|
||||
|
||||
@@ -865,24 +891,29 @@ static int _security_kdf(const OctetString *kasme, OctetString *key,
|
||||
* S = FC(0x15) || Algorithm distinguisher || 0x00 0x01
|
||||
|| Algorithm identity || 0x00 0x01
|
||||
*/
|
||||
UInt8_t input[kasme->length];
|
||||
UInt16_t length = 1;
|
||||
int offset = 0;
|
||||
int size_of_length = sizeof(length);
|
||||
|
||||
input[offset] = 0x15;
|
||||
offset += 1;
|
||||
input[offset] = algo_dist;
|
||||
offset += length;
|
||||
input[offset] = length;
|
||||
offset += size_of_length;
|
||||
input[offset] = algo_id;
|
||||
offset += length;
|
||||
input[offset] = length;
|
||||
|
||||
/* TODO !!! Compute the derived key */
|
||||
// todo_hmac_256(key, input, kasme->value);
|
||||
UInt8_t input[32];
|
||||
UInt8_t output[32];
|
||||
LOG_TRACE(DEBUG, "%s:%u output key mem %p lenth %u",
|
||||
__FUNCTION__, __LINE__,
|
||||
key->value,
|
||||
key->length);
|
||||
memset(input, 0, 32);
|
||||
// FC
|
||||
input[0] = 0x15;
|
||||
// P0 = Algorithm distinguisher
|
||||
input[1] = algo_dist;
|
||||
// L0 = 0x00 01
|
||||
input[2] = 0x00;
|
||||
input[3] = 0x01;
|
||||
// P1 = Algorithm identity
|
||||
input[4] = algo_id;
|
||||
// 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);
|
||||
}
|
||||
#endif // NAS_UE
|
||||
|
||||
@@ -534,12 +534,18 @@ void emm_main_cleanup(void)
|
||||
emm_security_context_t *security = _emm_data.security;
|
||||
if (security->kasme.value) {
|
||||
free(security->kasme.value);
|
||||
security->kasme.value = NULL;
|
||||
security->kasme.length = 0;
|
||||
}
|
||||
if (security->knas_enc.value) {
|
||||
free(security->knas_enc.value);
|
||||
security->knas_enc.value = NULL;
|
||||
security->knas_enc.length = 0;
|
||||
}
|
||||
if (security->knas_int.value) {
|
||||
free(security->knas_int.value);
|
||||
security->knas_int.value = NULL;
|
||||
security->knas_int.length = 0;
|
||||
}
|
||||
free(_emm_data.security);
|
||||
_emm_data.security = NULL;
|
||||
|
||||
@@ -1263,6 +1263,9 @@ static int _emm_as_send(const emm_as_t *msg)
|
||||
as_msg.msg.nas_establish_rsp.nasMsg.length);
|
||||
LOG_FUNC_RETURN (RETURNok);
|
||||
} 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 */
|
||||
nas_itti_establish_cnf(
|
||||
as_msg.msg.nas_establish_rsp.UEid,
|
||||
|
||||
@@ -88,7 +88,7 @@ void dump_access_point_name_xml(AccessPointName *accesspointname, uint8_t iei)
|
||||
if (iei > 0)
|
||||
/* Don't display IEI if = 0 */
|
||||
printf(" <IEI>0x%X</IEI>\n", iei);
|
||||
dump_octet_string_xml(&accesspointname->accesspointnamevalue);
|
||||
printf("</Access Point Name>\n");
|
||||
printf("%s</Access Point Name>\n",
|
||||
dump_octet_string_xml(&accesspointname->accesspointnamevalue));
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ void dump_authentication_failure_parameter_xml(AuthenticationFailureParameter *a
|
||||
if (iei > 0)
|
||||
/* Don't display IEI if = 0 */
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ void dump_authentication_parameter_autn_xml(AuthenticationParameterAutn *authent
|
||||
if (iei > 0)
|
||||
/* Don't display IEI if = 0 */
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ void dump_authentication_parameter_rand_xml(AuthenticationParameterRand *authent
|
||||
if (iei > 0)
|
||||
/* Don't display IEI if = 0 */
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ void dump_cli_xml(Cli *cli, uint8_t iei)
|
||||
if (iei > 0)
|
||||
/* Don't display IEI if = 0 */
|
||||
printf(" <IEI>0x%X</IEI>\n", iei);
|
||||
dump_octet_string_xml(&cli->clivalue);
|
||||
printf("%s", dump_octet_string_xml(&cli->clivalue));
|
||||
printf("</Cli>\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ void dump_esm_message_container_xml(EsmMessageContainer *esmmessagecontainer, ui
|
||||
if (iei > 0)
|
||||
/* Don't display IEI if = 0 */
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ void dump_lcs_client_identity_xml(LcsClientIdentity *lcsclientidentity, uint8_t
|
||||
if (iei > 0)
|
||||
/* Don't display IEI if = 0 */
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ void dump_ms_network_capability_xml(MsNetworkCapability *msnetworkcapability, ui
|
||||
if (iei > 0)
|
||||
/* Don't display IEI if = 0 */
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ void dump_nas_message_container_xml(NasMessageContainer *nasmessagecontainer, ui
|
||||
if (iei > 0)
|
||||
/* Don't display IEI if = 0 */
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ void dump_network_name_xml(NetworkName *networkname, uint8_t iei)
|
||||
printf(" <Coding scheme>%u</Coding scheme>\n", networkname->codingscheme);
|
||||
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);
|
||||
dump_octet_string_xml(&networkname->textstring);
|
||||
printf("%s", dump_octet_string_xml(&networkname->textstring));
|
||||
printf("</Network Name>\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ void dump_p_tmsi_signature_xml(PTmsiSignature *ptmsisignature, uint8_t iei)
|
||||
if (iei > 0)
|
||||
/* Don't display IEI if = 0 */
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ void dump_pdn_address_xml(PdnAddress *pdnaddress, uint8_t iei)
|
||||
/* Don't display IEI if = 0 */
|
||||
printf(" <IEI>0x%X</IEI>\n", iei);
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ void dump_protocol_configuration_options_xml(ProtocolConfigurationOptions *proto
|
||||
printf(" <Configuration protol>%u</Configuration protol>\n", protocolconfigurationoptions->configurationprotol);
|
||||
printf(" <Protocol ID>%u</Protocol ID>\n", protocolconfigurationoptions->protocolid);
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
#include "TLVDecoder.h"
|
||||
#include "OctetString.h"
|
||||
|
||||
#define DUMP_OUTPUT_SIZE 1024
|
||||
static char _dump_output[DUMP_OUTPUT_SIZE];
|
||||
|
||||
OctetString* dup_octet_string(OctetString *octetstring)
|
||||
{
|
||||
OctetString *os_p = NULL;
|
||||
@@ -78,20 +81,29 @@ int decode_octet_string(OctetString *octetstring, uint16_t pdulen, uint8_t *buff
|
||||
return octetstring->length;
|
||||
}
|
||||
|
||||
void dump_octet_string_xml(OctetString *octetstring)
|
||||
char* dump_octet_string_xml( const OctetString * const octetstring)
|
||||
{
|
||||
int i;
|
||||
printf(" <Length>%u</Length>\n <values>", octetstring->length);
|
||||
for (i = 0; i < octetstring->length; i++)
|
||||
printf("0x%x ", octetstring->value[i]);
|
||||
printf("</values>\n");
|
||||
int remaining_size = DUMP_OUTPUT_SIZE;
|
||||
int size = 0;
|
||||
size = snprintf(_dump_output, remaining_size, "<Length>%u</Length>\n\t<values>", octetstring->length);
|
||||
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;
|
||||
printf(" <Length=%u><values>", octetstring->length);
|
||||
for (i = 0; i < octetstring->length; i++)
|
||||
printf("0x%x ", octetstring->value[i]);
|
||||
printf("</values>\n");
|
||||
int remaining_size = DUMP_OUTPUT_SIZE;
|
||||
int size = 0;
|
||||
for (i = 0; i < octetstring->length; i++) {
|
||||
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 {
|
||||
} \
|
||||
(oCTETsTRINGcOPY).length = strlen((const char*)(oCTETsTRINGoRIG).value);\
|
||||
assert((oCTETsTRINGoRIG).length == (oCTETsTRINGcOPY).length); \
|
||||
(oCTETsTRINGcOPY).value = malloc((oCTETsTRINGoRIG).length+1); \
|
||||
(oCTETsTRINGcOPY).value = malloc((oCTETsTRINGoRIG).length); \
|
||||
memcpy((oCTETsTRINGcOPY).value, \
|
||||
(oCTETsTRINGoRIG).value, \
|
||||
(oCTETsTRINGoRIG).length); \
|
||||
(oCTETsTRINGcOPY).value[(oCTETsTRINGoRIG).length] = '\0'; \
|
||||
} while (0);
|
||||
|
||||
OctetString* dup_octet_string(OctetString*octetstring);
|
||||
@@ -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);
|
||||
|
||||
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_ */
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
PLMN_T_TO_TBCD(air_p->visited_plmn, plmn);
|
||||
value.os.data = plmn;
|
||||
value.os.len = 3;
|
||||
CHECK_FCT(fd_msg_avp_setvalue(avp, &value));
|
||||
|
||||
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 */
|
||||
{
|
||||
|
||||
+18
-20
@@ -28,45 +28,43 @@
|
||||
*******************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nettle/hmac.h>
|
||||
|
||||
#include "security_types.h"
|
||||
#include "secu_defs.h"
|
||||
|
||||
void kdf(const uint8_t *s, const uint32_t s_length, const uint8_t *key,
|
||||
const uint32_t key_length, uint8_t **out, uint32_t out_length)
|
||||
void kdf(uint8_t *key, uint16_t key_len, uint8_t *s, uint16_t s_len, uint8_t *out,
|
||||
uint16_t out_len)
|
||||
{
|
||||
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_length, key);
|
||||
hmac_sha256_update(&ctx, s_length, s);
|
||||
hmac_sha256_digest(&ctx, out_length, buffer);
|
||||
|
||||
*out = buffer;
|
||||
hmac_sha256_set_key(&ctx, key_len, key);
|
||||
hmac_sha256_update(&ctx, s_len, s);
|
||||
hmac_sha256_digest(&ctx, out_len, out);
|
||||
}
|
||||
|
||||
#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
|
||||
string[0] = FC_KENB;
|
||||
s[0] = FC_KENB;
|
||||
// P0 = Uplink NAS count
|
||||
string[1] = (nas_count & 0xff000000) >> 24;
|
||||
string[2] = (nas_count & 0x00ff0000) >> 16;
|
||||
string[3] = (nas_count & 0x0000ff00) >> 8;
|
||||
string[4] = (nas_count & 0x000000ff);
|
||||
s[1] = (nas_count & 0xff000000) >> 24;
|
||||
s[2] = (nas_count & 0x00ff0000) >> 16;
|
||||
s[3] = (nas_count & 0x0000ff00) >> 8;
|
||||
s[4] = (nas_count & 0x000000ff);
|
||||
|
||||
// Length of NAS count
|
||||
string[5] = 0x00;
|
||||
string[6] = 0x04;
|
||||
s[5] = 0x00;
|
||||
s[6] = 0x04;
|
||||
|
||||
kdf(string, 7, kasme, 32, keNB, 32);
|
||||
kdf(kasme, 32, s, 7, keNB, 32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "security_types.h"
|
||||
#include "secu_defs.h"
|
||||
|
||||
#define SECU_DEBUG 1
|
||||
/*!
|
||||
* @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
|
||||
@@ -49,9 +50,10 @@
|
||||
* 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,
|
||||
const uint8_t kasme[32], uint8_t **knas)
|
||||
const uint8_t kasme[32], uint8_t *knas)
|
||||
{
|
||||
uint8_t s[7];
|
||||
uint8_t out[32];
|
||||
#if defined(SECU_DEBUG)
|
||||
int i;
|
||||
#endif
|
||||
@@ -74,13 +76,17 @@ int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
|
||||
s[6] = 0x01;
|
||||
|
||||
#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 ++) {
|
||||
printf("0x%02x ", s[i]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
kdf(s, 7, kasme, 32, knas, 32);
|
||||
kdf(kasme, 32, s, 7, out, 32);
|
||||
|
||||
memcpy(knas, &out[31-16+1], 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
s[5] = 0x00;
|
||||
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
|
||||
memcpy(knas, knas_temp, 16);
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
// #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;
|
||||
int n ;
|
||||
@@ -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++) {
|
||||
stream_cipher->message[i] ^= *(((uint8_t*)KS)+i);
|
||||
}
|
||||
int ceil_index = 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));
|
||||
}
|
||||
free(KS);
|
||||
*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;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
// #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];
|
||||
uint32_t local_count;
|
||||
@@ -92,8 +92,9 @@ int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t **out)
|
||||
if (zero_bit > 0)
|
||||
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);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -42,13 +42,17 @@
|
||||
#define SECU_DIRECTION_UPLINK 0
|
||||
#define SECU_DIRECTION_DOWNLINK 1
|
||||
|
||||
void kdf(const uint8_t *s, const uint32_t s_length, const uint8_t *key,
|
||||
const uint32_t key_length, uint8_t **out, uint32_t out_length);
|
||||
void kdf(uint8_t *key,
|
||||
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,
|
||||
const uint8_t kasme[32], uint8_t **knas);
|
||||
const uint8_t kasme[32], uint8_t *knas);
|
||||
|
||||
#define derive_key_nas_enc(aLGiD, kASME, kNAS) \
|
||||
derive_key_nas(NAS_ENC_ALG, aLGiD, kASME, kNAS)
|
||||
@@ -82,11 +86,11 @@ typedef struct {
|
||||
uint32_t blength;
|
||||
} 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_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]);
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ void do_kdf(uint8_t *key, unsigned key_length, uint8_t *data, unsigned data_leng
|
||||
{
|
||||
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) {
|
||||
fail("Fail: kdf\n");
|
||||
}
|
||||
|
||||
@@ -241,9 +241,14 @@ do { \
|
||||
#define PLMN_T_TO_TBCD(pLMN, tBCDsTRING) \
|
||||
do { \
|
||||
tBCDsTRING[0] = (pLMN.MCCdigit2 << 4) | pLMN.MCCdigit3; \
|
||||
tBCDsTRING[1] = ((pLMN.MNCdigit1 == 0 ? 0xF : pLMN.MNCdigit1) << 4) \
|
||||
| pLMN.MCCdigit1; \
|
||||
tBCDsTRING[2] = (pLMN.MNCdigit2 << 4) | pLMN.MNCdigit3; \
|
||||
/* ambiguous (think about len 2) */ \
|
||||
if (pLMN.MNCdigit1 == 0) { \
|
||||
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)
|
||||
|
||||
#define PLMN_T_TO_MCC_MNC(pLMN, mCC, mNC, mNCdIGITlENGTH) \
|
||||
|
||||
Reference in New Issue
Block a user