EAP-PEAP: Derive EMSK and use 128-octet derivation for MSK

Derive EMSK when using EAP-PEAP to enable ERP. In addition, change the
MSK derivation for EAP-PEAP to always derive 128 octets of key material
instead of the 64 octets to cover just the MSK. This is needed with the
PRF used in TLS 1.3 since the output length is mixed into the PRF
context.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2019-02-01 23:52:28 +02:00
parent a2674fd902
commit 4e1cd3468e
2 changed files with 72 additions and 6 deletions

View file

@ -1,6 +1,6 @@
/*
* EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -169,7 +169,7 @@ static void * eap_peap_init(struct eap_sm *sm)
static void eap_peap_free_key(struct eap_peap_data *data)
{
if (data->key_data) {
bin_clear_free(data->key_data, EAP_TLS_KEY_LEN);
bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
data->key_data = NULL;
}
}
@ -1081,12 +1081,18 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
"key derivation", label);
data->key_data =
eap_peer_tls_derive_key(sm, &data->ssl, label,
EAP_TLS_KEY_LEN);
EAP_TLS_KEY_LEN +
EAP_EMSK_LEN);
if (data->key_data) {
wpa_hexdump_key(MSG_DEBUG,
"EAP-PEAP: Derived key",
data->key_data,
EAP_TLS_KEY_LEN);
wpa_hexdump_key(MSG_DEBUG,
"EAP-PEAP: Derived EMSK",
data->key_data +
EAP_TLS_KEY_LEN,
EAP_EMSK_LEN);
} else {
wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to "
"derive key");
@ -1264,6 +1270,29 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
}
static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_peap_data *data = priv;
u8 *key;
if (!data->key_data || !data->phase2_success)
return NULL;
if (data->crypto_binding_used) {
/* [MS-PEAP] does not define EMSK derivation */
return NULL;
}
key = os_memdup(data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
if (!key)
return NULL;
*len = EAP_EMSK_LEN;
return key;
}
static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_peap_data *data = priv;
@ -1296,6 +1325,7 @@ int eap_peer_peap_register(void)
eap->process = eap_peap_process;
eap->isKeyAvailable = eap_peap_isKeyAvailable;
eap->getKey = eap_peap_getKey;
eap->get_emsk = eap_peap_get_emsk;
eap->get_status = eap_peap_get_status;
eap->has_reauth_data = eap_peap_has_reauth_data;
eap->deinit_for_reauth = eap_peap_deinit_for_reauth;

View file

@ -1,6 +1,6 @@
/*
* hostapd / EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -756,7 +756,7 @@ static void eap_peap_process_phase2_tlv(struct eap_sm *sm,
} else {
eap_peap_state(data, FAILURE);
}
} else if (status == EAP_TLV_RESULT_FAILURE) {
wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure "
"- requested %s", requested);
@ -1328,8 +1328,9 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
/* TODO: PEAPv1 - different label in some cases */
eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
"client EAP encryption",
EAP_TLS_KEY_LEN);
EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
if (eapKeyData) {
os_memset(eapKeyData + EAP_TLS_KEY_LEN, 0, EAP_EMSK_LEN);
*len = EAP_TLS_KEY_LEN;
wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
eapKeyData, EAP_TLS_KEY_LEN);
@ -1341,6 +1342,40 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
}
static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_peap_data *data = priv;
u8 *eapKeyData, *emsk;
if (data->state != SUCCESS)
return NULL;
if (data->crypto_binding_used) {
/* [MS-PEAP] does not define EMSK derivation */
return NULL;
}
/* TODO: PEAPv1 - different label in some cases */
eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
"client EAP encryption",
EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
if (eapKeyData) {
emsk = os_memdup(eapKeyData + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
bin_clear_free(eapKeyData, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
if (!emsk)
return NULL;
*len = EAP_EMSK_LEN;
wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived EMSK",
emsk, EAP_EMSK_LEN);
} else {
wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive EMSK");
emsk = NULL;
}
return emsk;
}
static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv)
{
struct eap_peap_data *data = priv;
@ -1376,6 +1411,7 @@ int eap_server_peap_register(void)
eap->process = eap_peap_process;
eap->isDone = eap_peap_isDone;
eap->getKey = eap_peap_getKey;
eap->get_emsk = eap_peap_get_emsk;
eap->isSuccess = eap_peap_isSuccess;
eap->getSessionId = eap_peap_get_session_id;