RRC: Implement proper NH chain synchronization for RRC Reestablishment
Refactor key derivation logic to properly handle Next Hop (NH) chain synchronization according to 3GPP TS 33.501 specifications for both RRC Reestablishment and Master Key Update procedures. Changes in rrc_gNB.c: - Clarify key derivation in rrc_gNB_generate_RRCReestablishment by explicitly selecting base key (NH or KgNB) based on nh_ncc value - Add comment explaining vertical vs horizontal derivation logic Changes in rrc_UE.c: - Add nr_sync_nh_chain(): Common helper to synchronize NH parameter chain per TS 33.501 Annex A.10, supporting both Master Key Update and RRC Reestablishment procedures - Add nr_derive_kgnb_horizontal(): Derive KNG-RAN* from current KgNB when NCC values match (horizontal derivation per TS 33.501 A.11/A.12) - Add nr_derive_kgnb_vertical(): Derive KNG-RAN* from synchronized NH after NH chain sync (vertical derivation per TS 33.501 A.11/A.12) - Add nr_update_kgnb_from_ncc(): Unified function implementing TS 33.501 6.9.2.3.4 logic for updating KgNB based on received nextHopChainingCount - Refactor as_security_key_update(): Use new nr_update_kgnb_from_ncc() helper function for cleaner, more maintainable code - Fix nr_rrc_ue_process_rrcReestablishment(): Properly handle received nextHopChainingCount and update KgNB using unified helper function - Add debug logging for key derivation process Key NAS deriver utils: - update derive_kgnb documentation and protect input keys with const attribute
This commit is contained in:
@@ -1092,7 +1092,10 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context
|
|||||||
const f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info;
|
const f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info;
|
||||||
uint32_t ssb_arfcn = get_ssb_arfcn(du);
|
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);
|
LOG_I(NR_RRC, "Reestablishment update key pci=%d, earfcn_dl=%u\n", cell_info->nr_pci, ssb_arfcn);
|
||||||
nr_derive_key_ng_ran_star(cell_info->nr_pci, ssb_arfcn, ue_p->nh_ncc > 0 ? ue_p->nh : ue_p->kgnb, ue_p->kgnb);
|
|
||||||
|
/* 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;
|
||||||
|
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);
|
int size = do_RRCReestablishment(ue_context_pP->ue_context.nh_ncc, buffer, NR_RRC_BUF_SIZE, xid);
|
||||||
|
|
||||||
LOG_A(NR_RRC, "Send RRCReestablishment [%d bytes] to RNTI %04x\n", size, ue_p->rnti);
|
LOG_A(NR_RRC, "Send RRCReestablishment [%d bytes] to RNTI %04x\n", size, ue_p->rnti);
|
||||||
|
|||||||
+155
-46
@@ -525,13 +525,141 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf
|
|||||||
nr_rrc_send_msg_to_mac(rrc, &rrc_msg);
|
nr_rrc_send_msg_to_mac(rrc, &rrc_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nr_rrc_nh_update(NR_UE_RRC_INST_t *rrc, uint8_t *kamf, uint8_t *sync_input)
|
/** @brief Synchronize NH chain based on nextHopChainingCount
|
||||||
|
*
|
||||||
|
* This function synchronizes the NH parameter chain as specified in 3GPP TS 33.501 Annex A.10.
|
||||||
|
* Use cases: Master Key Update, RRC Reestablishment: The UE receives an NCC value that is
|
||||||
|
* different from the NCC associated with the currently active KgNB. The NH chain is synchronized
|
||||||
|
* by computing the function defined in Annex A.10 iteratively (and increasing the NCC value until
|
||||||
|
* it matches the NCC value received from the source ng-gNB).
|
||||||
|
*
|
||||||
|
* @param kamf K_AMF key from NAS
|
||||||
|
* @param kgnb Current KgNB key (input/output)
|
||||||
|
* @param nh Current NH parameter (input/output)
|
||||||
|
* @param nhcc Pointer to current nextHopChainingCount (input/output)
|
||||||
|
* @param target_ncc Target nextHopChainingCount value to synchronize to */
|
||||||
|
static void nr_sync_nh_chain(const uint8_t kamf[SECURITY_KEY_LEN],
|
||||||
|
uint8_t kgnb[SECURITY_KEY_LEN],
|
||||||
|
uint8_t nh[SECURITY_KEY_LEN],
|
||||||
|
uint64_t *nhcc,
|
||||||
|
const int8_t target_ncc)
|
||||||
{
|
{
|
||||||
uint8_t nh[SECURITY_KEY_LEN] = {0};
|
// If the UE received an NCC value that was different from the NCC associated with the
|
||||||
nr_derive_nh(kamf, sync_input, nh);
|
// currently active KgNB, the UE shall first synchronize the locally kept NH
|
||||||
log_hex_buffer("Sync input = stored NH", rrc->nh, SECURITY_KEY_LEN);
|
// parameter by computing the function defined in Annex A.10 iteratively (and increasing
|
||||||
memcpy(rrc->nh, nh, SECURITY_KEY_LEN);
|
// the NCC value until it matches the NCC value received from the source ng-gNB).
|
||||||
rrc->nhcc++; // Increase stored nextHopChainingCount
|
if (target_ncc <= *nhcc) {
|
||||||
|
LOG_W(NR_RRC, "Received NCC=%d is less than or equal to current nhcc=%ld (nothing to sync)\n", target_ncc, *nhcc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (target_ncc > *nhcc) {
|
||||||
|
LOG_I(NR_RRC, "Synchronizing NH chain: current nhcc=%ld, target ncc=%d\n", *nhcc, target_ncc);
|
||||||
|
if (*nhcc == 0) {
|
||||||
|
// First derivation: derive KgNB from KAMF, then derive NH from KgNB (per TS 33.501 A.10)
|
||||||
|
// Note: For the first NH derivation, we use UL NAS COUNT = 0 to match the AMF's derivation
|
||||||
|
// during handover. The AMF derives the first NH using the UL NAS COUNT from the last
|
||||||
|
// successful NAS SMC, which is 0 for the initial derivation.
|
||||||
|
derive_kgnb(kamf, 0, kgnb);
|
||||||
|
nr_derive_nh(kamf, kgnb, nh);
|
||||||
|
*nhcc = 1;
|
||||||
|
}
|
||||||
|
// Following derivations: iterate from current nhcc to target_ncc
|
||||||
|
for (uint8_t i = *nhcc; i < target_ncc; i++) {
|
||||||
|
LOG_D(NR_RRC, "Derive keys for ChainingCount = %d\n", i);
|
||||||
|
nr_derive_nh(kamf, nh, nh);
|
||||||
|
}
|
||||||
|
*nhcc = target_ncc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Derive KNG-RAN* (KgNB*) using horizontal derivation
|
||||||
|
*
|
||||||
|
* This function derives KNG-RAN* from the currently active KgNB (horizontal derivation)
|
||||||
|
* as specified in 3GPP TS 33.501 Annex A.11 and A.12.
|
||||||
|
* Used when NCC values match (no NH synchronization needed).
|
||||||
|
*
|
||||||
|
* @param pci Physical Cell ID
|
||||||
|
* @param nr_arfcn_dl NR ARFCN-DL
|
||||||
|
* @param kgnb Current KgNB key (input/output)
|
||||||
|
*/
|
||||||
|
static void nr_derive_kgnb_horizontal(const uint16_t pci, const uint64_t nr_arfcn_dl, uint8_t kgnb[SECURITY_KEY_LEN])
|
||||||
|
{
|
||||||
|
// When the NCC values match, the UE shall derive the KNG-RAN* from the currently active
|
||||||
|
// KgNB and the target PCI and its frequency ARFCN-DL using the function defined in Annex A.11 and A.12.
|
||||||
|
LOG_D(NR_RRC, "Deriving KNG-RAN* using horizontal derivation (from current KgNB)\n");
|
||||||
|
nr_derive_key_ng_ran_star(pci, nr_arfcn_dl, kgnb, kgnb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Derive KNG-RAN* (KgNB*) using vertical derivation
|
||||||
|
*
|
||||||
|
* This function derives KNG-RAN* from the synchronized NH parameter (vertical derivation)
|
||||||
|
* as specified in 3GPP TS 33.501 Annex A.11 and A.12.
|
||||||
|
* Used after NH chain synchronization when NCC values differ.
|
||||||
|
*
|
||||||
|
* @param pci Physical Cell ID
|
||||||
|
* @param nr_arfcn_dl NR ARFCN-DL
|
||||||
|
* @param kgnb Current KgNB key (input/output)
|
||||||
|
* @param nh Synchronized NH parameter (input)
|
||||||
|
*/
|
||||||
|
static void nr_derive_kgnb_vertical(const uint16_t pci,
|
||||||
|
const uint64_t nr_arfcn_dl,
|
||||||
|
uint8_t kgnb[SECURITY_KEY_LEN],
|
||||||
|
const uint8_t nh[SECURITY_KEY_LEN])
|
||||||
|
{
|
||||||
|
// When the NCC values match (after synchronization), the UE shall compute the K NG-RAN *
|
||||||
|
// from the synchronized NH parameter and the target PCI and its frequency ARFCN-DL
|
||||||
|
// using the function defined in Annex A.11 and A.12.
|
||||||
|
LOG_D(NR_RRC, "Deriving KNG-RAN* using vertical derivation (from synchronized NH)\n");
|
||||||
|
nr_derive_key_ng_ran_star(pci, nr_arfcn_dl, nh, kgnb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Update KgNB based on received nextHopChainingCount
|
||||||
|
*
|
||||||
|
* This function implements the common logic for updating KgNB based on received NCC value,
|
||||||
|
* as specified in 3GPP TS 33.501 6.9.2.3.4.
|
||||||
|
*
|
||||||
|
* Per 33.501 6.9.2.3.4 and Fig 6.9.2.1.1-1:
|
||||||
|
* - If NCC received == current NCC: use horizontal derivation (from currently active KgNB)
|
||||||
|
* This applies regardless of whether NCC is 0 or >0. For a fixed NCC level, multiple
|
||||||
|
* horizontal derivations can be done within that level.
|
||||||
|
* - If NCC received > current NCC: synchronize NH chain (Annex A.10), then use vertical
|
||||||
|
* derivation (from NH) to enter the new NCC level.
|
||||||
|
*
|
||||||
|
* Horizontal derivation = derive KNG-RAN* from currently active KgNB + (PCI, ARFCN-DL)
|
||||||
|
* Vertical derivation = derive KNG-RAN* from NH + (PCI, ARFCN-DL)
|
||||||
|
*
|
||||||
|
* @param rrc RRC instance pointer
|
||||||
|
* @param kamf K_AMF key from NAS
|
||||||
|
* @param received_ncc Received nextHopChainingCount value */
|
||||||
|
static void nr_update_kgnb_from_ncc(NR_UE_RRC_INST_t *rrc, const uint8_t kamf[SECURITY_KEY_LEN], int8_t received_ncc)
|
||||||
|
{
|
||||||
|
const uint64_t original_nhcc = rrc->nhcc;
|
||||||
|
|
||||||
|
if (received_ncc == original_nhcc) {
|
||||||
|
// NCC values match: use horizontal derivation from currently active KgNB
|
||||||
|
// Per TS 33.501 6.9.2.3.4: "derive the KNG-RAN* from the currently active KgNB"
|
||||||
|
// This applies regardless of NCC being 0 or >0. For a fixed NCC level, we stay
|
||||||
|
// within that level using horizontal derivations.
|
||||||
|
LOG_D(NR_RRC, "NCC values match (%d), using horizontal derivation\n", received_ncc);
|
||||||
|
nr_derive_kgnb_horizontal(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb);
|
||||||
|
} else if (received_ncc < original_nhcc) {
|
||||||
|
// Note: According to spec, NCC should only increase. If received_ncc < original_nhcc,
|
||||||
|
// this is an error condition, but we handle it gracefully.
|
||||||
|
LOG_W(NR_RRC,
|
||||||
|
"Received NCC=%d is less than current nhcc=%ld (unexpected per spec, NH chain should only increase)\n",
|
||||||
|
received_ncc,
|
||||||
|
original_nhcc);
|
||||||
|
} else {
|
||||||
|
// received_ncc > original_nhcc: synchronize NH chain first (per 33.501 A.10)
|
||||||
|
nr_sync_nh_chain(kamf, rrc->kgnb, rrc->nh, &rrc->nhcc, received_ncc);
|
||||||
|
// Store the received nextHopChainingCount value (per 38.331 5.3.7.5)
|
||||||
|
LOG_D(NR_RRC, "Synchronizing NH chain to target NCC %d\n", received_ncc);
|
||||||
|
rrc->nhcc = received_ncc;
|
||||||
|
// After synchronization, derive KNG-RAN* from synchronized NH (vertical derivation)
|
||||||
|
// per 33.501 6.9.2.3.4: "When the NCC values match, the UE shall compute the K NG-RAN *
|
||||||
|
// from the synchronized NH parameter"
|
||||||
|
nr_derive_kgnb_vertical(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb, rrc->nh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief AS security key update procedure (5.3.5.7 3GPP TS 38.331) */
|
/** @brief AS security key update procedure (5.3.5.7 3GPP TS 38.331) */
|
||||||
@@ -543,40 +671,17 @@ void as_security_key_update(NR_UE_RRC_INST_t *rrc, NR_MasterKeyUpdate_t *mku)
|
|||||||
if (mku->keySetChangeIndicator) {
|
if (mku->keySetChangeIndicator) {
|
||||||
LOG_E(NR_RRC, "derive or update the K gNB key based on the K AMF key, as specified in TS 33.501: not implemented yet\n");
|
LOG_E(NR_RRC, "derive or update the K gNB key based on the K AMF key, as specified in TS 33.501: not implemented yet\n");
|
||||||
} else {
|
} else {
|
||||||
/* derive or update the K gNB key based on the current K gNB key or the NH, using the nextHopChainingCount
|
LOG_I(NR_RRC, "Received masterKeyUpdate (nextHopChainingCount %ld): update security keys\n", mku->nextHopChainingCount);
|
||||||
value indicated in the received masterKeyUpdate, as specified in 6.9.2.3.3 3GPP TS 33.501 */
|
/** @todo: The KAMF should be obtained from NAS. This exchange over ITTI must be synchronized
|
||||||
if (mku->nextHopChainingCount != rrc->nhcc) {
|
* with the rest of the RRCReconfiguration procedure, in particular, the RadioBearerConfig
|
||||||
// - If the UE received an NCC value that was different from the NCC associated with the currently active
|
* processing that triggers bearer modifications. Security configueration of bearers must
|
||||||
// K gNB/K eNB, the UE shall first synchronize the locally kept NH parameter by computing the function defined in
|
* complete using the newly derived keys. As a workaround NAS is directly accessed here. */
|
||||||
// Annex A.10 iteratively (and increasing the NCC value until it matches the NCC value received from the source
|
nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id);
|
||||||
// ng-eNB/gNB via the HO command message.
|
const uint8_t *kamf = nas->security.kamf;
|
||||||
LOG_A(NR_RRC, "Received masterKeyUpdate (nextHopChainingCount %ld): update security keys\n", mku->nextHopChainingCount);
|
// KgNB update (TS 33.501 §6.9.2.3.3):
|
||||||
/** @todo: The KAMF should be obtained from NAS. This exchange over ITTI must be synchronized
|
// If received NCC != local NCC, iteratively derive NH (Annex A.10) until NCC matches.
|
||||||
* with the rest of the RRCReconfiguration procedure, in particular, the RadioBearerConfig
|
// Then derive the new KgNB from the synchronized NH.
|
||||||
* processing that triggers bearer modifications. Security configueration of bearers must
|
nr_update_kgnb_from_ncc(rrc, kamf, mku->nextHopChainingCount);
|
||||||
* complete using the newly derived keys. As a workaround NAS is directly accessed here. */
|
|
||||||
nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id);
|
|
||||||
uint8_t *kamf = nas->security.kamf;
|
|
||||||
log_hex_buffer("Stored kamf", kamf, SECURITY_KEY_LEN);
|
|
||||||
if (rrc->nhcc == 0) { // First derivation
|
|
||||||
derive_kgnb(kamf, 0, rrc->kgnb);
|
|
||||||
log_hex_buffer("Sync input = derived kgnb", rrc->kgnb, SECURITY_KEY_LEN);
|
|
||||||
nr_rrc_nh_update(rrc, kamf, rrc->kgnb);
|
|
||||||
}
|
|
||||||
for (int i = rrc->nhcc; i < mku->nextHopChainingCount; i++) { // Following derivations
|
|
||||||
LOG_D(NR_RRC, "Derive keys for ChainingCount = %d\n", i);
|
|
||||||
nr_rrc_nh_update(rrc, kamf, rrc->nh);
|
|
||||||
}
|
|
||||||
nr_derive_key_ng_ran_star(rrc->phyCellID, rrc->arfcn_ssb, rrc->nh, rrc->kgnb);
|
|
||||||
// When the NCC values match, the UE shall compute the K NG-RAN *
|
|
||||||
// from the synchronized NH parameter and the target PCI and its frequency ARFCN-DL/EARFCN-DL using the
|
|
||||||
// function defined in Annex A.11 and A.12.
|
|
||||||
// The UE shall use the KNG-RAN * as the K gNB when communicating with the target gNB and as the KeNB when
|
|
||||||
// communicating with the target ng-eNB.
|
|
||||||
} else {
|
|
||||||
nr_derive_key_ng_ran_star(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb, rrc->kgnb);
|
|
||||||
}
|
|
||||||
log_hex_buffer("Derived kgnb", rrc->kgnb, SECURITY_KEY_LEN);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2196,6 +2301,9 @@ static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t
|
|||||||
nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL);
|
nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Process RRCReestablishment message
|
||||||
|
* This function processes the RRCReestablishment message received from the gNB,
|
||||||
|
* implementing procedures as described in 38.331 section 5.3.7.5 */
|
||||||
static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc,
|
static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc,
|
||||||
const int gNB_index,
|
const int gNB_index,
|
||||||
const NR_RRCReestablishment_t *rrcReestablishment,
|
const NR_RRCReestablishment_t *rrcReestablishment,
|
||||||
@@ -2204,18 +2312,19 @@ static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc,
|
|||||||
int msg_size,
|
int msg_size,
|
||||||
const nr_pdcp_integrity_data_t *msg_integrity)
|
const nr_pdcp_integrity_data_t *msg_integrity)
|
||||||
{
|
{
|
||||||
// implementign procedues as described in 38.331 section 5.3.7.5
|
|
||||||
// stop timer T301
|
// stop timer T301
|
||||||
NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
|
NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
|
||||||
nr_timer_stop(&timers->T301);
|
nr_timer_stop(&timers->T301);
|
||||||
// store the nextHopChainingCount value
|
|
||||||
NR_RRCReestablishment_IEs_t *ies = rrcReestablishment->criticalExtensions.choice.rrcReestablishment;
|
NR_RRCReestablishment_IEs_t *ies = rrcReestablishment->criticalExtensions.choice.rrcReestablishment;
|
||||||
AssertFatal(ies, "Not expecting RRCReestablishment_IEs to be NULL\n");
|
AssertFatal(ies, "Not expecting RRCReestablishment_IEs to be NULL\n");
|
||||||
// TODO need to understand how to use nextHopChainingCount
|
|
||||||
// int nh = rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nextHopChainingCount;
|
|
||||||
|
|
||||||
// update the K gNB key based on the current K gNB key or the NH, using the stored nextHopChainingCount value
|
// Update KgNB based on the current K gNB key or the NH,
|
||||||
nr_derive_key_ng_ran_star(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb, rrc->kgnb);
|
// using the received nextHopChainingCount (per 33.501 6.9.2.3.4)
|
||||||
|
// received from RRCReestablishment and update the stored value in rrc->nhcc
|
||||||
|
int8_t received_ncc = ies->nextHopChainingCount;
|
||||||
|
nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id);
|
||||||
|
const uint8_t *kamf = nas->security.kamf;
|
||||||
|
nr_update_kgnb_from_ncc(rrc, kamf, received_ncc);
|
||||||
|
|
||||||
// derive the K_RRCenc key associated with the previously configured cipheringAlgorithm
|
// derive the K_RRCenc key associated with the previously configured cipheringAlgorithm
|
||||||
// derive the K_RRCint key associated with the previously configured integrityProtAlgorithm
|
// derive the K_RRCint key associated with the previously configured integrityProtAlgorithm
|
||||||
|
|||||||
@@ -150,8 +150,23 @@ void nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t
|
|||||||
* NOTE: knas is dynamically allocated by the KDF function
|
* NOTE: knas is dynamically allocated by the KDF function
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @brief KgNB derivation (A.9 3GPP TS 33.501) */
|
/** @brief KgNB derivation function (Annex A.9 3GPP TS 33.501)
|
||||||
void derive_kgnb(uint8_t kamf[32], uint32_t count, uint8_t *kgnb)
|
*
|
||||||
|
* Derives KgNB from K_AMF and the uplink NAS COUNT.
|
||||||
|
* This function is applied when cryptographically protected 5G radio bearers are
|
||||||
|
* established and when a key change on-the-fly is performed.
|
||||||
|
*
|
||||||
|
* KDF input S structure (per Annex A.9):
|
||||||
|
* - FC = 0x6E
|
||||||
|
* - P0 = Uplink NAS COUNT (count parameter)
|
||||||
|
* - L0 = length of uplink NAS COUNT (0x00 0x04)
|
||||||
|
* - P1 = Access type distinguisher (0x01 for 3GPP access)
|
||||||
|
* - L1 = length of Access type distinguisher (0x00 0x01)
|
||||||
|
*
|
||||||
|
* @param[in] kamf 256-bit K_AMF key (input key KEY to KDF)
|
||||||
|
* @param[in] count Uplink NAS COUNT value (P0 in KDF input S)
|
||||||
|
* @param[out] kgnb Derived 256-bit KgNB key */
|
||||||
|
void derive_kgnb(const uint8_t kamf[32], const uint32_t count, uint8_t *kgnb)
|
||||||
{
|
{
|
||||||
/* Compute the KDF input parameter
|
/* Compute the KDF input parameter
|
||||||
* S = FC(0x6E) || UL NAS Count || 0x00 0x04 || 0x01 || 0x00 0x01
|
* S = FC(0x6E) || UL NAS Count || 0x00 0x04 || 0x01 || 0x00 0x01
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ typedef enum {
|
|||||||
UP_INT_ALG = 0x06
|
UP_INT_ALG = 0x06
|
||||||
} algorithm_type_dist_t;
|
} algorithm_type_dist_t;
|
||||||
|
|
||||||
void derive_kgnb(uint8_t kamf[32], uint32_t count, uint8_t *kgnb);
|
void derive_kgnb(const uint8_t kamf[32], const uint32_t count, uint8_t *kgnb);
|
||||||
|
|
||||||
void derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB);
|
void derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user