Commit 2fb38167 authored by Masayuki Harada's avatar Masayuki Harada

Fix NRUE NAS security configuration.

parent fccb986f
......@@ -1571,7 +1571,6 @@ int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB
}
extern uint8_t global_kgnb[32];
//-----------------------------------------------------------------------------
void
nr_rrc_ue_process_securityModeCommand(
......@@ -1658,7 +1657,6 @@ extern uint8_t global_kgnb[32];
uint8_t *kRRCint = NULL;
uint8_t *k_kdf = NULL;
#ifndef PHYSIM
memcpy(NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,global_kgnb,32);
k_kdf = NULL;
nr_derive_key_up_enc(NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
......@@ -2525,6 +2523,28 @@ nr_rrc_ue_establish_srb2(
NR_RRC_DCCH_DATA_IND (msg_p).gNB_index);
break;
case NAS_KENB_REFRESH_REQ:
memcpy((void *)NR_UE_rrc_inst[ue_mod_id].kgnb, (void *)NAS_KENB_REFRESH_REQ(msg_p).kenb, sizeof(NR_UE_rrc_inst[ue_mod_id].kgnb));
LOG_D(RRC, "[UE %d] Received %s: refreshed RRC::KgNB = "
"%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\n",
ue_mod_id, ITTI_MSG_NAME (msg_p),
NR_UE_rrc_inst[ue_mod_id].kgnb[0], NR_UE_rrc_inst[ue_mod_id].kgnb[1], NR_UE_rrc_inst[ue_mod_id].kgnb[2], NR_UE_rrc_inst[ue_mod_id].kgnb[3],
NR_UE_rrc_inst[ue_mod_id].kgnb[4], NR_UE_rrc_inst[ue_mod_id].kgnb[5], NR_UE_rrc_inst[ue_mod_id].kgnb[6], NR_UE_rrc_inst[ue_mod_id].kgnb[7],
NR_UE_rrc_inst[ue_mod_id].kgnb[8], NR_UE_rrc_inst[ue_mod_id].kgnb[9], NR_UE_rrc_inst[ue_mod_id].kgnb[10], NR_UE_rrc_inst[ue_mod_id].kgnb[11],
NR_UE_rrc_inst[ue_mod_id].kgnb[12], NR_UE_rrc_inst[ue_mod_id].kgnb[13], NR_UE_rrc_inst[ue_mod_id].kgnb[14], NR_UE_rrc_inst[ue_mod_id].kgnb[15],
NR_UE_rrc_inst[ue_mod_id].kgnb[16], NR_UE_rrc_inst[ue_mod_id].kgnb[17], NR_UE_rrc_inst[ue_mod_id].kgnb[18], NR_UE_rrc_inst[ue_mod_id].kgnb[19],
NR_UE_rrc_inst[ue_mod_id].kgnb[20], NR_UE_rrc_inst[ue_mod_id].kgnb[21], NR_UE_rrc_inst[ue_mod_id].kgnb[22], NR_UE_rrc_inst[ue_mod_id].kgnb[23],
NR_UE_rrc_inst[ue_mod_id].kgnb[24], NR_UE_rrc_inst[ue_mod_id].kgnb[25], NR_UE_rrc_inst[ue_mod_id].kgnb[26], NR_UE_rrc_inst[ue_mod_id].kgnb[27],
NR_UE_rrc_inst[ue_mod_id].kgnb[28], NR_UE_rrc_inst[ue_mod_id].kgnb[29], NR_UE_rrc_inst[ue_mod_id].kgnb[30], NR_UE_rrc_inst[ue_mod_id].kgnb[31]);
break;
case NAS_UPLINK_DATA_REQ: {
uint32_t length;
uint8_t *buffer;
......
......@@ -47,6 +47,8 @@
uint8_t *registration_request_buf;
uint32_t registration_request_len;
extern char *baseNetAddress;
extern uint16_t NB_UE_INST;
static ue_sa_security_key_t ** ue_security_key;
static int nas_protected_security_header_encode(
char *buffer,
......@@ -251,6 +253,108 @@ void derive_knas(algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t
knas_int[i] = out[16 + i];
}
void derive_kgnb(uint8_t kamf[32], uint32_t count, uint8_t *kgnb){
/* Compute the KDF input parameter
* S = FC(0x6E) || UL NAS Count || 0x00 0x04 || 0x01 || 0x00 0x01
*/
uint8_t input[32];
// uint16_t length = 4;
// int offset = 0;
uint8_t out[32] = { 0 };
LOG_TRACE(INFO, "%s with count= %d", __FUNCTION__, count);
memset(input, 0, 32);
input[0] = 0x6E;
// 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;
// P1
input[7] = 0x01;
// L1
input[8] = 0;
input[9] = 1;
kdf(kamf, 32, input, 10, out, 32);
for (int i = 0; i < 32; i++)
kgnb[i] = out[i];
printf("kgnb : ");
for(int pp=0;pp<32;pp++)
printf("%02x ",kgnb[pp]);
printf("\n");
}
void derive_ue_keys(int Mod_id, uint8_t *buf, uicc_t *uicc) {
uint8_t ak[6];
uint8_t sqn[6];
AssertFatal (Mod_id < NB_UE_INST, "Failed, Mod_id %d is over NB_UE_INST!\n", Mod_id);
if(ue_security_key[Mod_id]){
// clear old key
memset(ue_security_key[Mod_id],0,sizeof(ue_sa_security_key_t));
}else{
// Allocate new memory
ue_security_key[Mod_id]=(ue_sa_security_key_t *)calloc(1,sizeof(ue_sa_security_key_t));
}
uint8_t *kausf = ue_security_key[Mod_id]->kausf;
uint8_t *kseaf = ue_security_key[Mod_id]->kseaf;
uint8_t *kamf = ue_security_key[Mod_id]->kamf;
uint8_t *knas_int = ue_security_key[Mod_id]->knas_int;
uint8_t *output = ue_security_key[Mod_id]->res;
uint8_t *rand = ue_security_key[Mod_id]->rand;
uint8_t *kgnb = ue_security_key[Mod_id]->kgnb;
// get RAND for authentication request
for(int index = 0; index < 16;index++){
rand[index] = buf[8+index];
}
uint8_t resTemp[16];
uint8_t ck[16], ik[16];
f2345(uicc->key, rand, resTemp, ck, ik, ak, uicc->opc);
transferRES(ck, ik, resTemp, rand, output, uicc);
for(int index = 0; index < 6; index++){
sqn[index] = buf[26+index];
}
derive_kausf(ck, ik, sqn, kausf, uicc);
derive_kseaf(kausf, kseaf, uicc);
derive_kamf(kseaf, kamf, 0x0000, uicc);
derive_knas(0x02, 2, kamf, knas_int);
derive_kgnb(kamf,0,kgnb);
printf("kausf:");
for(int i = 0; i < 32; i++){
printf("%x ", kausf[i]);
}
printf("\n");
printf("kseaf:");
for(int i = 0; i < 32; i++){
printf("%x ", kseaf[i]);
}
printf("\n");
printf("kamf:");
for(int i = 0; i < 32; i++){
printf("%x ", kamf[i]);
}
printf("\n");
printf("knas_int:\n");
for(int i = 0; i < 16; i++){
printf("%x ", knas_int[i]);
}
printf("\n");
}
void generateRegistrationRequest(as_nas_info_t *initialNasMsg, int Mod_id) {
int size = sizeof(mm_msg_header_t);
fgs_nas_message_t nas_msg={0};
......@@ -373,69 +477,13 @@ void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype
}
OctetString knas_int;
uint8_t kamf[32];
static void generateAuthenticationResp(as_nas_info_t *initialNasMsg, uint8_t *buf, uicc_t *uicc){
uint8_t ak[6];
static void generateAuthenticationResp(int Mod_id,as_nas_info_t *initialNasMsg, uint8_t *buf, uicc_t *uicc){
uint8_t kausf[32];
uint8_t sqn[6];
uint8_t kseaf[32];
derive_ue_keys(Mod_id,buf,uicc);
OctetString res;
// get RAND for authentication request
unsigned char rand[16];
for(int index = 0; index < 16;index++){
rand[index] = buf[8+index];
}
uint8_t resTemp[16];
uint8_t ck[16], ik[16], output[16];
f2345(uicc->key, rand, resTemp, ck, ik, ak, uicc->opc);
transferRES(ck, ik, resTemp, rand, output, uicc);
// get knas_int
knas_int.length = 16;
knas_int.value = malloc(knas_int.length);
for(int index = 0; index < 6; index++){
sqn[index] = buf[26+index];
}
derive_kausf(ck, ik, sqn, kausf, uicc);
derive_kseaf(kausf, kseaf, uicc);
derive_kamf(kseaf, kamf, 0x0000, uicc);
derive_knas(0x02, 2, kamf, knas_int.value);
printf("kausf:");
for(int i = 0; i < 32; i++){
printf("%x ", kausf[i]);
}
printf("\n");
printf("kseaf:");
for(int i = 0; i < 32; i++){
printf("%x ", kseaf[i]);
}
printf("\n");
printf("kamf:");
for(int i = 0; i < 32; i++){
printf("%x ", kamf[i]);
}
printf("\n");
printf("knas_int:\n");
for(int i = 0; i < 16; i++){
printf("%x ", knas_int.value[i]);
}
printf("\n");
// set res
res.length = 16;
res.value = output;
res.value = calloc(1,16);
memcpy(res.value,ue_security_key[Mod_id]->res,16);
int size = sizeof(mm_msg_header_t);
fgs_nas_message_t nas_msg;
......@@ -465,41 +513,14 @@ static void generateAuthenticationResp(as_nas_info_t *initialNasMsg, uint8_t *bu
initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data), size);
}
uint8_t global_kgnb[32];
static void get_kgnb(uint32_t count)
{
/* Compute the KDF input parameter
* S = FC(0x11) || UL NAS Count || 0x00 0x04
*/
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] = 0x6E;
// 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;
// P1
input[7] = 0x01;
// L1
input[8] = 0;
input[9] = 1;
kdf(kamf, 32, input, 10, global_kgnb, 32);
printf("global_kgnb : ");
for(int pp=0;pp<32;pp++)
printf("%02x ",global_kgnb[pp]);
printf("\n");
int nas_itti_kgnb_refresh_req(const uint8_t kgnb[32], int instance) {
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_KENB_REFRESH_REQ);
memcpy(NAS_KENB_REFRESH_REQ(message_p).kenb, kgnb, sizeof(NAS_KENB_REFRESH_REQ(message_p).kenb));
return itti_send_msg_to_task(TASK_RRC_NRUE, instance, message_p);
}
static void generateSecurityModeComplete(as_nas_info_t *initialNasMsg)
static void generateSecurityModeComplete(int Mod_id,as_nas_info_t *initialNasMsg)
{
int size = sizeof(mm_msg_header_t);
fgs_nas_message_t nas_msg;
......@@ -546,7 +567,7 @@ static void generateSecurityModeComplete(as_nas_info_t *initialNasMsg)
initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len);
stream_cipher.key = knas_int.value;
stream_cipher.key = ue_security_key[Mod_id]->knas_int;
stream_cipher.key_length = 16;
stream_cipher.count = 0;
stream_cipher.bearer = 1;
......@@ -566,7 +587,7 @@ static void generateSecurityModeComplete(as_nas_info_t *initialNasMsg)
}
}
static void generateRegistrationComplete(as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer) {
static void generateRegistrationComplete(int Mod_id, as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer) {
//wait send RRCReconfigurationComplete and InitialContextSetupResponse
sleep(1);
int length = 0;
......@@ -626,7 +647,7 @@ static void generateRegistrationComplete(as_nas_info_t *initialNasMsg, SORTransp
}
initialNasMsg->length = length;
stream_cipher.key = knas_int.value;
stream_cipher.key = ue_security_key[Mod_id]->knas_int;
stream_cipher.key_length = 16;
stream_cipher.count = 1;
stream_cipher.bearer = 1;
......@@ -659,7 +680,7 @@ void decodeDownlinkNASTransport(as_nas_info_t *initialNasMsg, uint8_t * pdu_buff
}
}
static void generatePduSessionEstablishRequest(uicc_t * uicc, as_nas_info_t *initialNasMsg){
static void generatePduSessionEstablishRequest(int Mod_id, uicc_t * uicc, as_nas_info_t *initialNasMsg){
//wait send RegistrationComplete
usleep(100*150);
int size = 0;
......@@ -733,7 +754,7 @@ static void generatePduSessionEstablishRequest(uicc_t * uicc, as_nas_info_t *ini
initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len);
stream_cipher.key = knas_int.value;
stream_cipher.key = ue_security_key[Mod_id]->knas_int;
stream_cipher.key_length = 16;
stream_cipher.count = 0;
stream_cipher.bearer = 1;
......@@ -763,6 +784,8 @@ void *nas_nrue_task(void *args_p)
uint8_t msg_type = 0;
uint8_t *pdu_buffer = NULL;
ue_security_key=(ue_sa_security_key_t **)calloc(1,sizeof(ue_sa_security_key_t*)*NB_UE_INST);
itti_mark_task_ready (TASK_NAS_NRUE);
MSC_START_USE();
......@@ -847,7 +870,7 @@ void *nas_nrue_task(void *args_p)
as_nas_info_t initialNasMsg;
memset(&initialNasMsg, 0, sizeof(as_nas_info_t));
generateRegistrationComplete(&initialNasMsg, NULL);
generateRegistrationComplete(Mod_id,&initialNasMsg, NULL);
if(initialNasMsg.length > 0){
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_UPLINK_DATA_REQ);
......@@ -860,7 +883,7 @@ void *nas_nrue_task(void *args_p)
as_nas_info_t pduEstablishMsg;
memset(&pduEstablishMsg, 0, sizeof(as_nas_info_t));
generatePduSessionEstablishRequest(uicc, &pduEstablishMsg);
generatePduSessionEstablishRequest(Mod_id, uicc, &pduEstablishMsg);
if(pduEstablishMsg.length > 0){
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_UPLINK_DATA_REQ);
......@@ -924,11 +947,11 @@ void *nas_nrue_task(void *args_p)
generateIdentityResponse(&initialNasMsg,*(pdu_buffer+3), uicc);
break;
case FGS_AUTHENTICATION_REQUEST:
generateAuthenticationResp(&initialNasMsg, pdu_buffer, uicc);
generateAuthenticationResp(Mod_id,&initialNasMsg, pdu_buffer, uicc);
break;
case FGS_SECURITY_MODE_COMMAND:
get_kgnb(0);
generateSecurityModeComplete(&initialNasMsg);
nas_itti_kgnb_refresh_req(ue_security_key[Mod_id]->kgnb, instance);
generateSecurityModeComplete(Mod_id,&initialNasMsg);
break;
case FGS_DOWNLINK_NAS_TRANSPORT:
decodeDownlinkNASTransport(&initialNasMsg, pdu_buffer);
......
......@@ -64,6 +64,16 @@
#define INITIAL_REGISTRATION 0b001
/* Security Key for SA UE */
typedef struct {
uint8_t kausf[32];
uint8_t kseaf[32];
uint8_t kamf[32];
uint8_t knas_int[16];
uint8_t res[16];
uint8_t rand[16];
uint8_t kgnb[32];
} ue_sa_security_key_t;
typedef enum fgs_protocol_discriminator_e {
/* Protocol discriminator identifier for 5GS Mobility Management */
......
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