summaryrefslogtreecommitdiffstats
path: root/contrib/wpa/src/eap_server/eap_server_peap.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wpa/src/eap_server/eap_server_peap.c')
-rw-r--r--contrib/wpa/src/eap_server/eap_server_peap.c82
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);
}
OpenPOWER on IntegriCloud