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

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

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

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5579 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent 65c84039
......@@ -65,6 +65,21 @@ int mme_app_request_authentication_info(const mme_app_imsi_t imsi,
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;
......
......@@ -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);
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",
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 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;
input[offset] = 0x11;
offset += 1;
input[offset] = count;
offset += length;
input[offset] = length;
/* TODO !!! Compute the derived key */
// todo_hmac_256(key, input, kasme->value);
UInt8_t input[32];
UInt16_t length = 4;
int offset = 0;
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;
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 */
{
......
......@@ -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) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment