From a478ef0d127db57c1b9ec79f3819d6a921fa4b87 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 4 Dec 2008 21:50:56 +0200 Subject: [PATCH] EAP-AKA': Added CK',IK' derivation This is based on a change request 3GPP TS 33.402 CR 0033 for version 8.1.1. The hardcoded ANID is now 'WLAN' since that is used in 3GPP TS 24.302. --- src/eap_common/eap_sim_common.c | 70 +++++++++++++++++++++++++++++++++ src/eap_common/eap_sim_common.h | 4 ++ src/eap_peer/eap_aka_prime.c | 10 +++++ src/eap_server/eap_aka_prime.c | 20 ++++++++-- 4 files changed, 101 insertions(+), 3 deletions(-) diff --git a/src/eap_common/eap_sim_common.c b/src/eap_common/eap_sim_common.c index 9d1bf2ccd..0ab88c41d 100644 --- a/src/eap_common/eap_sim_common.c +++ b/src/eap_common/eap_sim_common.c @@ -426,6 +426,76 @@ void eap_sim_add_mac_sha256(const u8 *k_aut, const u8 *msg, size_t msg_len, wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC: MAC", mac, EAP_SIM_MAC_LEN); } + + +void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak, + const u8 *network_name, + size_t network_name_len) +{ + u8 key[EAP_AKA_CK_LEN + EAP_AKA_IK_LEN]; + u8 hash[SHA256_MAC_LEN]; + const u8 *addr[5]; + size_t len[5]; + u8 fc; + u8 l0[2], l1[2]; + + /* 3GPP TS 33.402 V8.0.0 + * (CK', IK') = F(CK, IK, ) + */ + /* TODO: CK', IK' generation should really be moved into the actual + * AKA procedure with network name passed in there and option to use + * AMF separation bit = 1 (3GPP TS 33.401). */ + + /* Change Request 334.02 CR 0033 to version 8.1.1 from + * 3GPP TSG-SA WG3 Meeting #53 in September 2008: + * + * CK' || IK' = HMAC-SHA-256(Key, S) + * S = FC || P0 || L0 || P1 || L1 || ... || Pn || Ln + * Key = CK || IK + * FC = 0x20 + * P0 = access network identity (3GPP TS 24.302) + * L0 = length of acceess network identity (2 octets, big endian) + * P1 = SQN xor AK (if AK is not used, AK is treaded as 000..0 + * L1 = 0x00 0x06 + */ + + fc = 0x20; + + wpa_printf(MSG_DEBUG, "EAP-AKA': Derive (CK',IK') from (CK,IK)"); + wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK", ck, EAP_AKA_CK_LEN); + wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK", ik, EAP_AKA_IK_LEN); + wpa_printf(MSG_DEBUG, "EAP-AKA': FC = 0x%x", fc); + wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': P0 = Access network identity", + network_name, network_name_len); + wpa_hexdump(MSG_DEBUG, "EAP-AKA': P1 = SQN xor AK", sqn_ak, 6); + + os_memcpy(key, ck, EAP_AKA_CK_LEN); + os_memcpy(key + EAP_AKA_CK_LEN, ik, EAP_AKA_IK_LEN); + wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': Key = CK || IK", + key, sizeof(key)); + + addr[0] = &fc; + len[0] = 1; + addr[1] = network_name; + len[1] = network_name_len; + WPA_PUT_BE16(l0, network_name_len); + addr[2] = l0; + len[2] = 2; + addr[3] = sqn_ak; + len[3] = 6; + WPA_PUT_BE16(l1, 6); + addr[4] = l1; + len[4] = 2; + + hmac_sha256_vector(key, sizeof(key), 5, addr, len, hash); + wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': KDF output (CK' || IK')", + hash, sizeof(hash)); + + os_memcpy(ck, hash, EAP_AKA_CK_LEN); + os_memcpy(ik, hash + EAP_AKA_CK_LEN, EAP_AKA_IK_LEN); + wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK'", ck, EAP_AKA_CK_LEN); + wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK'", ik, EAP_AKA_IK_LEN); +} #endif /* EAP_AKA_PRIME */ diff --git a/src/eap_common/eap_sim_common.h b/src/eap_common/eap_sim_common.h index c799f2fe5..83df8d554 100644 --- a/src/eap_common/eap_sim_common.h +++ b/src/eap_common/eap_sim_common.h @@ -106,6 +106,10 @@ int eap_sim_verify_mac_sha256(const u8 *k_aut, const struct wpabuf *req, void eap_sim_add_mac_sha256(const u8 *k_aut, const u8 *msg, size_t msg_len, u8 *mac, const u8 *extra, size_t extra_len); +void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak, + const u8 *network_name, + size_t network_name_len); + /* EAP-SIM/AKA Attributes (0..127 non-skippable) */ #define EAP_SIM_AT_RAND 1 diff --git a/src/eap_peer/eap_aka_prime.c b/src/eap_peer/eap_aka_prime.c index 243005af2..52f74eeef 100644 --- a/src/eap_peer/eap_aka_prime.c +++ b/src/eap_peer/eap_aka_prime.c @@ -820,6 +820,16 @@ static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm, return eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); } +#ifdef EAP_AKA_PRIME + if (data->eap_method == EAP_TYPE_AKA_PRIME) { + /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the + * needed 6-octet SQN ^AK for CK',IK' derivation */ + eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik, + data->autn, + data->network_name, + data->network_name_len); + } +#endif /* EAP_AKA_PRIME */ if (data->last_eap_identity) { identity = data->last_eap_identity; identity_len = data->last_eap_identity_len; diff --git a/src/eap_server/eap_aka_prime.c b/src/eap_server/eap_aka_prime.c index 4627a9406..7cd50445e 100644 --- a/src/eap_server/eap_aka_prime.c +++ b/src/eap_server/eap_aka_prime.c @@ -122,6 +122,8 @@ static void * eap_aka_init(struct eap_sm *sm) static void * eap_aka_prime_init(struct eap_sm *sm) { struct eap_aka_data *data; + /* TODO: make ANID configurable; see 3GPP TS 24.302 */ + char *network_name = "WLAN"; if (sm->eap_sim_db_priv == NULL) { wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured"); @@ -133,13 +135,14 @@ static void * eap_aka_prime_init(struct eap_sm *sm) return NULL; data->eap_method = EAP_TYPE_AKA_PRIME; - data->network_name = os_malloc(3); + data->network_name = os_malloc(os_strlen(network_name)); if (data->network_name == NULL) { os_free(data); return NULL; } - os_memcpy(data->network_name, "FOO", 3); /* FIX: 3GPP.24.302 */ - data->network_name_len = 3; + + data->network_name_len = os_strlen(network_name); + os_memcpy(data->network_name, network_name, data->network_name_len); data->state = IDENTITY; eap_aka_determine_identity(sm, data, 1, 0); @@ -666,6 +669,17 @@ static void eap_aka_determine_identity(struct eap_sm *sm, return; } +#ifdef EAP_AKA_PRIME + if (data->eap_method == EAP_TYPE_AKA_PRIME) { + /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the + * needed 6-octet SQN ^AK for CK',IK' derivation */ + eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik, + data->autn, + data->network_name, + data->network_name_len); + } +#endif /* EAP_AKA_PRIME */ + data->reauth = NULL; data->counter = 0; /* reset re-auth counter since this is full auth */