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:
Lionel Gauthier
2014-07-22 16:48:45 +00:00
parent 65c84039ad
commit 5345032add
35 changed files with 454 additions and 217 deletions
@@ -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;
+13 -7
View File
@@ -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);
+1 -1
View File
@@ -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);
}
+16 -13
View File
@@ -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");
}
+1 -1
View File
@@ -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_ */
+11
View File
@@ -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
View File
@@ -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;
}
+8 -2
View File
@@ -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;
}
+1 -1
View File
@@ -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);
+8 -2
View File
@@ -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;
}
+3 -2
View File
@@ -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;
+10 -6
View File
@@ -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]);
+1 -1
View File
@@ -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");
}
+8 -3
View File
@@ -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) \