EAP-AKA': Derive keys using the new KDF (PRF')

This commit is contained in:
Jouni Malinen 2008-12-03 19:22:20 +02:00
parent f07688e37d
commit 9881795e2c
6 changed files with 320 additions and 51 deletions

View file

@ -28,6 +28,7 @@ struct eap_aka_data {
u8 nonce_s[EAP_SIM_NONCE_S_LEN];
u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN];
u8 k_encr[EAP_SIM_K_ENCR_LEN];
u8 k_re[EAP_AKA_PRIME_K_RE_LEN];
u8 msk[EAP_SIM_KEYING_DATA_LEN];
u8 emsk[EAP_EMSK_LEN];
u8 rand[EAP_AKA_RAND_LEN];
@ -365,11 +366,19 @@ static struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm,
wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S",
data->nonce_s, EAP_SIM_NONCE_S_LEN);
eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
data->emsk);
eap_sim_derive_keys_reauth(data->counter, sm->identity,
sm->identity_len, data->nonce_s, data->mk,
data->msk, data->emsk);
if (data->eap_method == EAP_TYPE_AKA_PRIME) {
eap_aka_prime_derive_keys_reauth(data->k_re, data->counter,
sm->identity,
sm->identity_len,
data->nonce_s,
data->msk, data->emsk);
} else {
eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
data->msk, data->emsk);
eap_sim_derive_keys_reauth(data->counter, sm->identity,
sm->identity_len, data->nonce_s,
data->mk, data->msk, data->emsk);
}
msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
EAP_AKA_SUBTYPE_REAUTHENTICATION);
@ -545,14 +554,33 @@ static void eap_aka_determine_identity(struct eap_sm *sm,
data->reauth = eap_sim_db_get_reauth_entry(
sm->eap_sim_db_priv, sm->identity,
sm->identity_len);
if (data->reauth &&
data->reauth->aka_prime !=
(data->eap_method == EAP_TYPE_AKA_PRIME)) {
wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth data "
"was for different AKA version");
data->reauth = NULL;
}
if (data->reauth) {
wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast "
"re-authentication");
identity = data->reauth->identity;
identity_len = data->reauth->identity_len;
data->counter = data->reauth->counter;
os_memcpy(data->mk, data->reauth->mk,
EAP_SIM_MK_LEN);
if (data->eap_method == EAP_TYPE_AKA_PRIME) {
os_memcpy(data->k_encr,
data->reauth->k_encr,
EAP_SIM_K_ENCR_LEN);
os_memcpy(data->k_aut,
data->reauth->k_aut,
EAP_AKA_PRIME_K_AUT_LEN);
os_memcpy(data->k_re,
data->reauth->k_re,
EAP_AKA_PRIME_K_RE_LEN);
} else {
os_memcpy(data->mk, data->reauth->mk,
EAP_SIM_MK_LEN);
}
}
}
}
@ -618,10 +646,16 @@ static void eap_aka_determine_identity(struct eap_sm *sm,
wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation",
sm->identity, identity_len);
eap_aka_derive_mk(sm->identity, identity_len, data->ik, data->ck,
data->mk);
eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
data->emsk);
if (data->eap_method == EAP_TYPE_AKA_PRIME) {
eap_aka_prime_derive_keys(identity, identity_len, data->ik,
data->ck, data->k_encr, data->k_aut,
data->k_re, data->msk, data->emsk);
} else {
eap_aka_derive_mk(sm->identity, identity_len, data->ik,
data->ck, data->mk);
eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
data->msk, data->emsk);
}
eap_aka_state(data, CHALLENGE);
}
@ -741,10 +775,21 @@ static void eap_aka_process_challenge(struct eap_sm *sm,
data->next_pseudonym = NULL;
}
if (data->next_reauth_id) {
eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
identity_len,
data->next_reauth_id, data->counter + 1,
data->mk);
if (data->eap_method == EAP_TYPE_AKA_PRIME) {
eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
identity,
identity_len,
data->next_reauth_id,
data->counter + 1,
data->k_encr, data->k_aut,
data->k_re);
} else {
eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
identity_len,
data->next_reauth_id,
data->counter + 1,
data->mk);
}
data->next_reauth_id = NULL;
}
}
@ -867,9 +912,21 @@ static void eap_aka_process_reauth(struct eap_sm *sm,
data->next_pseudonym = NULL;
}
if (data->next_reauth_id) {
eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
identity_len, data->next_reauth_id,
data->counter + 1, data->mk);
if (data->eap_method == EAP_TYPE_AKA_PRIME) {
eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
identity,
identity_len,
data->next_reauth_id,
data->counter + 1,
data->k_encr, data->k_aut,
data->k_re);
} else {
eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
identity_len,
data->next_reauth_id,
data->counter + 1,
data->mk);
}
data->next_reauth_id = NULL;
} else {
eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);

View file

@ -942,27 +942,12 @@ int eap_sim_db_add_pseudonym(void *priv, const u8 *identity,
}
/**
* eap_sim_db_add_reauth - EAP-SIM DB: Add new re-authentication entry
* @priv: Private data pointer from eap_sim_db_init()
* @identity: Identity of the user (may be permanent identity or pseudonym)
* @identity_len: Length of identity
* @reauth_id: reauth_id for this user. This needs to be an allocated buffer,
* e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not
* free it.
* @mk: 16-byte MK from the previous full authentication
* Returns: 0 on success, -1 on failure
*
* This function adds a new re-authentication entry for an EAP-SIM user.
* EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed
* anymore.
*/
int eap_sim_db_add_reauth(void *priv, const u8 *identity,
size_t identity_len, char *reauth_id, u16 counter,
const u8 *mk)
static struct eap_sim_reauth *
eap_sim_db_add_reauth_data(struct eap_sim_db_data *data, const u8 *identity,
size_t identity_len, char *reauth_id, u16 counter)
{
struct eap_sim_db_data *data = priv;
struct eap_sim_reauth *r;
wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Add reauth_id for identity",
identity, identity_len);
wpa_printf(MSG_DEBUG, "EAP-SIM DB: reauth_id: %s", reauth_id);
@ -980,7 +965,7 @@ int eap_sim_db_add_reauth(void *priv, const u8 *identity,
r = os_zalloc(sizeof(*r));
if (r == NULL) {
os_free(reauth_id);
return -1;
return NULL;
}
r->next = data->reauths;
@ -988,7 +973,7 @@ int eap_sim_db_add_reauth(void *priv, const u8 *identity,
if (r->identity == NULL) {
os_free(r);
os_free(reauth_id);
return -1;
return NULL;
}
os_memcpy(r->identity, identity, identity_len);
r->identity_len = identity_len;
@ -998,12 +983,84 @@ int eap_sim_db_add_reauth(void *priv, const u8 *identity,
}
r->counter = counter;
return r;
}
/**
* eap_sim_db_add_reauth - EAP-SIM DB: Add new re-authentication entry
* @priv: Private data pointer from eap_sim_db_init()
* @identity: Identity of the user (may be permanent identity or pseudonym)
* @identity_len: Length of identity
* @reauth_id: reauth_id for this user. This needs to be an allocated buffer,
* e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not
* free it.
* @mk: 16-byte MK from the previous full authentication or %NULL
* Returns: 0 on success, -1 on failure
*
* This function adds a new re-authentication entry for an EAP-SIM user.
* EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed
* anymore.
*/
int eap_sim_db_add_reauth(void *priv, const u8 *identity,
size_t identity_len, char *reauth_id, u16 counter,
const u8 *mk)
{
struct eap_sim_db_data *data = priv;
struct eap_sim_reauth *r;
r = eap_sim_db_add_reauth_data(data, identity, identity_len, reauth_id,
counter);
if (r == NULL)
return -1;
os_memcpy(r->mk, mk, EAP_SIM_MK_LEN);
r->aka_prime = 0;
return 0;
}
#ifdef EAP_AKA_PRIME
/**
* eap_sim_db_add_reauth_prime - EAP-AKA' DB: Add new re-authentication entry
* @priv: Private data pointer from eap_sim_db_init()
* @identity: Identity of the user (may be permanent identity or pseudonym)
* @identity_len: Length of identity
* @reauth_id: reauth_id for this user. This needs to be an allocated buffer,
* e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not
* free it.
* @k_re: 32-byte K_re from the previous full authentication or %NULL
* Returns: 0 on success, -1 on failure
*
* This function adds a new re-authentication entry for an EAP-AKA' user.
* EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed
* anymore.
*/
int eap_sim_db_add_reauth_prime(void *priv, const u8 *identity,
size_t identity_len, char *reauth_id,
u16 counter, const u8 *k_encr, const u8 *k_aut,
const u8 *k_re)
{
struct eap_sim_db_data *data = priv;
struct eap_sim_reauth *r;
r = eap_sim_db_add_reauth_data(data, identity, identity_len, reauth_id,
counter);
if (r == NULL)
return -1;
r->aka_prime = 1;
os_memcpy(r->k_encr, k_encr, EAP_SIM_K_ENCR_LEN);
os_memcpy(r->k_aut, k_aut, EAP_AKA_PRIME_K_AUT_LEN);
os_memcpy(r->k_re, k_re, EAP_AKA_PRIME_K_RE_LEN);
return 0;
}
#endif /* EAP_AKA_PRIME */
/**
* eap_sim_db_get_permanent - EAP-SIM DB: Get permanent identity
* @priv: Private data pointer from eap_sim_db_init()

View file

@ -54,6 +54,10 @@ int eap_sim_db_add_pseudonym(void *priv, const u8 *identity,
int eap_sim_db_add_reauth(void *priv, const u8 *identity,
size_t identity_len, char *reauth_id, u16 counter,
const u8 *mk);
int eap_sim_db_add_reauth_prime(void *priv, const u8 *identity,
size_t identity_len, char *reauth_id,
u16 counter, const u8 *k_encr, const u8 *k_aut,
const u8 *k_re);
const u8 * eap_sim_db_get_permanent(void *priv, const u8 *identity,
size_t identity_len, size_t *len);
@ -64,7 +68,11 @@ struct eap_sim_reauth {
size_t identity_len;
char *reauth_id;
u16 counter;
int aka_prime;
u8 mk[EAP_SIM_MK_LEN];
u8 k_encr[EAP_SIM_K_ENCR_LEN];
u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN];
u8 k_re[EAP_AKA_PRIME_K_RE_LEN];
};
struct eap_sim_reauth *