diff options
Diffstat (limited to 'contrib/wpa/src/eap_server/eap_server_peap.c')
-rw-r--r-- | contrib/wpa/src/eap_server/eap_server_peap.c | 82 |
1 files changed, 66 insertions, 16 deletions
diff --git a/contrib/wpa/src/eap_server/eap_server_peap.c b/contrib/wpa/src/eap_server/eap_server_peap.c index 51062b0..92c0e5e 100644 --- a/contrib/wpa/src/eap_server/eap_server_peap.c +++ b/contrib/wpa/src/eap_server/eap_server_peap.c @@ -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. @@ -324,17 +324,30 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) { u8 *tk; u8 isk[32], imck[60]; + int res; /* * Tunnel key (TK) is the first 60 octets of the key generated by * phase 1 of PEAP (based on TLS). */ tk = eap_server_tls_derive_key(sm, &data->ssl, "client EAP encryption", - EAP_TLS_KEY_LEN); + NULL, 0, EAP_TLS_KEY_LEN); if (tk == NULL) return -1; wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60); + if (tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { + /* Fast-connect: IPMK|CMK = TK */ + os_memcpy(data->ipmk, tk, 40); + wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK", + data->ipmk, 40); + os_memcpy(data->cmk, tk + 40, 20); + wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK", + data->cmk, 20); + os_free(tk); + return 0; + } + eap_peap_get_isk(data, isk, sizeof(isk)); wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk)); @@ -346,9 +359,11 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) * in the end of the label just before ISK; is that just a typo?) */ wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40); - if (peap_prfplus(data->peap_version, tk, 40, - "Inner Methods Compound Keys", - isk, sizeof(isk), imck, sizeof(imck)) < 0) { + res = peap_prfplus(data->peap_version, tk, 40, + "Inner Methods Compound Keys", + isk, sizeof(isk), imck, sizeof(imck)); + os_memset(isk, 0, sizeof(isk)); + if (res < 0) { os_free(tk); return -1; } @@ -357,11 +372,11 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) os_free(tk); - /* TODO: fast-connect: IPMK|CMK = TK */ os_memcpy(data->ipmk, imck, 40); wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40); os_memcpy(data->cmk, imck + 40, 20); wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20); + os_memset(imck, 0, sizeof(imck)); return 0; } @@ -745,7 +760,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); @@ -1267,8 +1282,9 @@ static void eap_peap_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_DEBUG, "EAP-PEAP: Resuming previous session - skip Phase2"); - eap_peap_state(data, SUCCESS_REQ); - tls_connection_set_success_data_resumed(data->ssl.conn); + eap_peap_req_success(sm, data); + if (data->state == SUCCESS_REQ) + tls_connection_set_success_data_resumed(data->ssl.conn); } @@ -1310,14 +1326,17 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) "key"); } + os_memset(csk, 0, sizeof(csk)); + return eapKeyData; } /* TODO: PEAPv1 - different label in some cases */ eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, - "client EAP encryption", - EAP_TLS_KEY_LEN); + "client EAP encryption", NULL, 0, + 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); @@ -1329,6 +1348,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", NULL, 0, + 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; @@ -1351,7 +1404,6 @@ static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len) int eap_server_peap_register(void) { struct eap_method *eap; - int ret; eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); @@ -1365,11 +1417,9 @@ 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; - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; + return eap_server_method_register(eap); } |