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.
This commit is contained in:
parent
a49c428a1b
commit
a478ef0d12
4 changed files with 101 additions and 3 deletions
|
@ -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",
|
wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC: MAC",
|
||||||
mac, EAP_SIM_MAC_LEN);
|
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, <access network identity>)
|
||||||
|
*/
|
||||||
|
/* 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 */
|
#endif /* EAP_AKA_PRIME */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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,
|
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);
|
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) */
|
/* EAP-SIM/AKA Attributes (0..127 non-skippable) */
|
||||||
#define EAP_SIM_AT_RAND 1
|
#define EAP_SIM_AT_RAND 1
|
||||||
|
|
|
@ -820,6 +820,16 @@ static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm,
|
||||||
return eap_aka_client_error(data, id,
|
return eap_aka_client_error(data, id,
|
||||||
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
|
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) {
|
if (data->last_eap_identity) {
|
||||||
identity = data->last_eap_identity;
|
identity = data->last_eap_identity;
|
||||||
identity_len = data->last_eap_identity_len;
|
identity_len = data->last_eap_identity_len;
|
||||||
|
|
|
@ -122,6 +122,8 @@ static void * eap_aka_init(struct eap_sm *sm)
|
||||||
static void * eap_aka_prime_init(struct eap_sm *sm)
|
static void * eap_aka_prime_init(struct eap_sm *sm)
|
||||||
{
|
{
|
||||||
struct eap_aka_data *data;
|
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) {
|
if (sm->eap_sim_db_priv == NULL) {
|
||||||
wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
|
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;
|
return NULL;
|
||||||
|
|
||||||
data->eap_method = EAP_TYPE_AKA_PRIME;
|
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) {
|
if (data->network_name == NULL) {
|
||||||
os_free(data);
|
os_free(data);
|
||||||
return NULL;
|
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;
|
data->state = IDENTITY;
|
||||||
eap_aka_determine_identity(sm, data, 1, 0);
|
eap_aka_determine_identity(sm, data, 1, 0);
|
||||||
|
@ -666,6 +669,17 @@ static void eap_aka_determine_identity(struct eap_sm *sm,
|
||||||
return;
|
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->reauth = NULL;
|
||||||
data->counter = 0; /* reset re-auth counter since this is full auth */
|
data->counter = 0; /* reset re-auth counter since this is full auth */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue