Derive Serving Network Name from SIB1 PLMN

Extract MCC and MNC from the SIB1 PLMN identity and store them in the
UE NAS context to propogate them to NAS security procedures.

Previously, the Serving Network Name (SNN) used during authentication
was constructed from the IMSI, implicitly assuming the UE was attached
to its home network. In roaming scenarios, this produced an incorrect
SNN, causing authentication and key derivation failures.

The NAS key derivation functions (transferRES, derive_kausf, derive_kseaf)
now build the SNN using the MCC/MNC broadcast by the serving network in SIB1,
ensuring that authentication uses the correct serving PLMN during roaming.
This commit is contained in:
Aaron van Diepen
2026-03-17 18:42:11 +01:00
parent fdb6b44b05
commit abbd670e5d
3 changed files with 36 additions and 24 deletions
+24
View File
@@ -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) {