eap_aka_sim: allow externally-derived CK'/IK' for EAP-AKA' by paunadeu · Pull Request #5894 · FreeRADIUS/freeradius-server · GitHub
Skip to content

eap_aka_sim: allow externally-derived CK'/IK' for EAP-AKA'#5894

Open
paunadeu wants to merge 1 commit into
FreeRADIUS:masterfrom
networkheroad:eap-aka-prime-external-hss-keys
Open

eap_aka_sim: allow externally-derived CK'/IK' for EAP-AKA'#5894
paunadeu wants to merge 1 commit into
FreeRADIUS:masterfrom
networkheroad:eap-aka-prime-external-hss-keys

Conversation

@paunadeu

@paunadeu paunadeu commented Jun 22, 2026

Copy link
Copy Markdown

The EAP-AKA' module derives CK'/IK' from CK/IK locally using the RFC 5448 / TS 33.402 Annex A transform. When the quintuplet is fetched from a 3GPP HSS over SWx (TS 29.273 section 8.2.3.16/17), the HSS has already performed that transform and returns CK'/IK' bound to the Access Network Identity the AAA sent in the MAR. Running the transform again on the server produces keys that no longer match what the peer derives from its USIM-supplied CK/IK, and AT_MAC verification fails on the supplicant.

Concrete example (one Asian HSS vendor on SWx):

  1. AAA sends MAR with SIP-Authentication-Scheme = "EAP-AKA'" and ANID (AVP 1504) = "WLAN".
  2. HSS computes raw CK, IK from Ki/OPc + RAND using Milenage f3, f4.
  3. HSS applies TS 33.402 Annex A: CK' || IK' = HMAC-SHA-256(CK || IK, S), S = 0x20 || "WLAN" || 0x0004 || SQN ^ AK || 0x0006.
  4. HSS returns the resulting CK'/IK' in Confidentiality-Key (625) and Integrity-Key (626).
  5. Current FreeRADIUS 4.x runs Annex A again over those values with its configured network_name. K_aut is then derived from double-transformed key material; the supplicant, which derives K_aut from a single Annex A pass over its USIM CK/IK, rejects AT_MAC.

Add a per-instance config item derive_ck_ik_prime to the eap-aka-prime process module. Default yes, behavior unchanged. When set to no, the module reads CK'/IK' from new control.CK-Prime / control.IK-Prime attributes and skips the local derivation.

Changes:

  • share/dictionary/eap/aka-sim/dictionary.freeradius — add CK-Prime (284), IK-Prime (285).
  • src/lib/eap_aka_sim/base.h — add ck_ik_prime_provided on fr_aka_sim_keys_t.
  • src/lib/eap_aka_sim/vector.c — add fr_aka_sim_vector_umts_ck_ik_prime_from_attrs(); reads both attributes, validates lengths against AKA_SIM_VECTOR_UMTS_CK_SIZE / ..._IK_SIZE, sets the flag.
  • src/lib/eap_aka_sim/crypto.cfr_aka_sim_crypto_umts_kdf_1() skips ck_ik_prime_derive() when the flag is set.
  • src/lib/eap_aka_sim/state_machine.c — in RESUME(send_aka_challenge_request) for FR_EAP_METHOD_AKA_PRIME, pull CK'/IK' from control.* before invoking the KDF when derive_ck_ik_prime = no.
  • src/process/eap_aka_prime/base.c — config parser entry with default yes.

Tests:

  • New unit test test_eap_aka_kdf_1_umts_external_prime (crypto.c): starts from the RFC 5448 Appendix C / RFC 9048 Appendix D Case 1 vector, clobbers raw CK/IK to 0xff, supplies the expected CK'/IK' as if from an HSS, and asserts K_encr, K_aut, K_re, MSK and EMSK match the RFC vector byte for byte. If the local derivation were still running, the test would fail on the first downstream key.
  • Existing test_eap_aka_kdf_1_umts continues to pass; default config (no derive_ck_ik_prime set, or set to yes) is byte-identical to current behavior for the local Milenage / AuC path.

In a 3GPP SWx deployment the HSS performs the EAP-AKA' key transform
itself (TS 33.402 Annex A) and returns CK'/IK' already bound to the
Access Network Identity. The server must then not derive CK'/IK' a
second time from CK/IK, or the MSK will not match the peer.

Add a per-instance config item derive_ck_ik_prime (default yes,
unchanged behavior) to the eap-aka-prime process module. When set to
no, the module reads CK'/IK' from the new control.CK-Prime /
control.IK-Prime attributes and fr_aka_sim_crypto_umts_kdf_1() skips
its local derivation.

- dictionary: add CK-Prime (284) and IK-Prime (285)
- keys: add ck_ik_prime_provided flag
- vector: add fr_aka_sim_vector_umts_ck_ik_prime_from_attrs()
- crypto: guard ck_ik_prime_derive() on the flag; add unit test
- process/eap_aka_prime: add derive_ck_ik_prime config item

The default leaves existing EAP-AKA' (local Milenage / AuC) behavior
byte-identical.
@paunadeu paunadeu force-pushed the eap-aka-prime-external-hss-keys branch from 7bf10b3 to 03c81ef Compare June 22, 2026 09:50
@arr2036

arr2036 commented Jun 22, 2026

Copy link
Copy Markdown
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants