Fix RRCReestablishment key derivation to use horizontal derivation

Per TS 33.501 6.9.2.3.4 and Fig 6.9.2.1.1-1, when sending
RRCReestablishment with nextHopChainingCount, the gNB is staying at
the same NCC level (not advancing). Therefore, horizontal derivation
from the currently active KgNB must be used, not vertical derivation
from NH.

Vertical derivation (from NH) is only used when advancing to a new
NCC level, which happens during handover or masterKeyUpdate procedures.

The previous implementation incorrectly used vertical derivation from
NH whenever nh_ncc > 0, which caused key mismatch between gNB and UE
during reestablishment after handover, leading to integrity check
failures.

This fix ensures both gNB and UE use horizontal derivation when
nextHopChainingCount matches the current NCC level, aligning with the
specification's "virtual NH at NCC=0" model where:
- Horizontal derivation = derive KNG-RAN* from currently active KgNB
- Vertical derivation = derive KNG-RAN* from NH (only when advancing NCC)
This commit is contained in:
Guido Casati
2025-12-19 17:16:17 +01:00
parent 4db49a8767
commit 5c601b7d62
+5 -2
View File
@@ -1093,8 +1093,11 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context
uint32_t ssb_arfcn = get_ssb_arfcn(du);
LOG_I(NR_RRC, "Reestablishment update key pci=%d, earfcn_dl=%u\n", cell_info->nr_pci, ssb_arfcn);
/* Derive KgNB* using NH if nh_ncc > 0 (vertical derivation), else use KgNB (horizontal derivation) */
const uint8_t *base_key = ue_p->nh_ncc > 0 ? ue_p->nh : ue_p->kgnb;
/* Per TS 33.501 6.9.2.3.4: When sending RRCReestablishment with nextHopChainingCount,
* we're staying at the same NCC level (not advancing), so use horizontal derivation
* from the currently active KgNB. Vertical derivation (from NH) is only used when
* advancing to a new NCC level, which happens during handover or masterKeyUpdate. */
const uint8_t *base_key = ue_p->kgnb;
nr_derive_key_ng_ran_star(cell_info->nr_pci, ssb_arfcn, base_key, ue_p->kgnb);
int size = do_RRCReestablishment(ue_context_pP->ue_context.nh_ncc, buffer, NR_RRC_BUF_SIZE, xid);