diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 65a8bf9432..e7edeca39b 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -486,6 +486,30 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf if(g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void *) sib1); LOG_A(NR_RRC, "SIB1 decoded\n"); + + plmn_id_t *plmn_id = malloc_or_fail(sizeof(plmn_id_t)); + + /* selected_plmn_identity is one-indexed */ + AssertFatal(rrc->selected_plmn_identity > 0, "No PLMN selected"); + /* only one PLMN info block is currently supported*/ + NR_PLMN_Identity_t *plmn = sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.array[0] + ->plmn_IdentityList.list.array[rrc->selected_plmn_identity - 1]; + + /* Convert MCC */ + plmn_id->mcc = (*plmn->mcc->list.array[0]) * 100 + (*plmn->mcc->list.array[1]) * 10 + (*plmn->mcc->list.array[2]); + + plmn_id->mnc_digit_length = plmn->mnc.list.count; + + /* Convert MNC (2 or 3 digits) */ + if (plmn->mnc.list.count == 3) { + plmn_id->mnc = (*plmn->mnc.list.array[0]) * 100 + (*plmn->mnc.list.array[1]) * 10 + (*plmn->mnc.list.array[2]); + } else { + plmn_id->mnc = (*plmn->mnc.list.array[0]) * 10 + (*plmn->mnc.list.array[1]); + } + + nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id); + nas->sn_id = plmn_id; + nr_timer_start(&SI_info->sib1_timer); SI_info->sib1_validity = true; if (rrc->nrRrcState == RRC_STATE_IDLE_NR) { diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index b52bb982fc..4cfb061cee 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -101,26 +101,13 @@ static fgmm_msg_header_t set_mm_header(fgs_nas_msg_t type, Security_header_t sec return mm_header; } -static void servingNetworkName(uint8_t *msg, char *imsiStr, int mnc_size) +static void servingNetworkName(uint8_t *msg, plmn_id_t *plmn_id) { // SNN-network-identifier in TS 24.501 // TS 24.501: If the MNC of the serving PLMN has two digits, then a zero is added at the beginning. - - // MNC - char mnc[4]; - if (mnc_size == 2) { - snprintf(mnc, sizeof(mnc), "0%c%c", imsiStr[3], imsiStr[4]); - } else { - snprintf(mnc, sizeof(mnc), "%c%c%c", imsiStr[3], imsiStr[4], imsiStr[5]); - } - - // MCC - char mcc[4]; - snprintf(mcc, sizeof(mcc), "%c%c%c", imsiStr[0], imsiStr[1], imsiStr[2]); - int size = 64; - snprintf((char *)msg, size, "5G:mnc%3s.mcc%3s.3gppnetwork.org", mnc, mcc); + snprintf((char *)msg, size, "5G:mnc%03d.mcc%03d.3gppnetwork.org", plmn_id->mnc, plmn_id->mcc); } static const char *print_info(uint8_t id, const text_info_t *array, uint8_t array_size) @@ -505,11 +492,11 @@ static int fill_imeisv(FGSMobileIdentity *mi, const uicc_t *uicc) return 19; } -void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], uint8_t *output, uicc_t *uicc) +void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], uint8_t *output, plmn_id_t *plmn_id) { uint8_t S[100] = {0}; S[0] = 0x6B; - servingNetworkName(S + 1, uicc->imsiStr, uicc->nmc_size); + servingNetworkName(S + 1, plmn_id); int netNamesize = strlen((char *)S + 1); S[1 + netNamesize] = (netNamesize & 0xff00) >> 8; S[2 + netNamesize] = (netNamesize & 0x00ff); @@ -548,7 +535,7 @@ void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16 memcpy(output, out + 16, 16); } -void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[32], uicc_t *uicc) +void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[32], plmn_id_t *plmn_id) { uint8_t S[100] = {0}; uint8_t key[32] = {0}; @@ -556,7 +543,7 @@ void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[ memcpy(&key[0], ck, 16); memcpy(&key[16], ik, 16); // KEY S[0] = 0x6A; - servingNetworkName(S + 1, uicc->imsiStr, uicc->nmc_size); + servingNetworkName(S + 1, plmn_id); int netNamesize = strlen((char *)S + 1); S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8); S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff); @@ -570,11 +557,11 @@ void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[ kdf(key, data, 32, kausf); } -void derive_kseaf(uint8_t kausf[32], uint8_t kseaf[32], uicc_t *uicc) +void derive_kseaf(uint8_t kausf[32], uint8_t kseaf[32], plmn_id_t *plmn_id) { uint8_t S[100] = {0}; S[0] = 0x6C; // FC - servingNetworkName(S + 1, uicc->imsiStr, uicc->nmc_size); + servingNetworkName(S + 1, plmn_id); int netNamesize = strlen((char *)S + 1); S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8); S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff); @@ -641,14 +628,14 @@ static void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) uint8_t ck[16], ik[16]; f2345(nas->uicc->key, rand, resTemp, ck, ik, ak, nas->uicc->opc); - transferRES(ck, ik, resTemp, rand, output, nas->uicc); + transferRES(ck, ik, resTemp, rand, output, nas->sn_id); for (int index = 0; index < 6; index++) { sqn[index] = buf[26 + index]; } - derive_kausf(ck, ik, sqn, kausf, nas->uicc); - derive_kseaf(kausf, kseaf, nas->uicc); + derive_kausf(ck, ik, sqn, kausf, nas->sn_id); + derive_kseaf(kausf, kseaf, nas->sn_id); derive_kamf(kseaf, kamf, 0x0000, nas->uicc); derive_kgnb(kamf, nas->security.nas_count_ul, kgnb); diff --git a/openair3/NAS/NR_UE/nr_nas_msg.h b/openair3/NAS/NR_UE/nr_nas_msg.h index f5e6b4db59..bbd3a13fe5 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.h +++ b/openair3/NAS/NR_UE/nr_nas_msg.h @@ -102,6 +102,7 @@ typedef struct { int t3446; /* NAS Key Set Identifier associated to the security context */ uint8_t *ksi; + plmn_id_t *sn_id; } nr_ue_nas_t; nr_ue_nas_t *get_ue_nas_info(module_id_t module_id);