diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c index b19f298b6..07e345f1f 100644 --- a/src/eap_peer/eap_fast.c +++ b/src/eap_peer/eap_fast.c @@ -343,10 +343,8 @@ static int eap_fast_init_phase2_method(struct eap_sm *sm, sm->peer_challenge = data->key_block_p->client_challenge; } sm->init_phase2 = 1; - sm->mschapv2_full_key = 1; data->phase2_priv = data->phase2_method->init(sm); sm->init_phase2 = 0; - sm->mschapv2_full_key = 0; sm->auth_challenge = NULL; sm->peer_challenge = NULL; @@ -661,7 +659,18 @@ static int eap_fast_get_phase2_key(struct eap_sm *sm, if (key_len > isk_len) key_len = isk_len; - os_memcpy(isk, key, key_len); + if (key_len == 32 && + data->phase2_method->vendor == EAP_VENDOR_IETF && + data->phase2_method->method == EAP_TYPE_MSCHAPV2) { + /* + * EAP-FAST uses reverse order for MS-MPPE keys when deriving + * MSK from EAP-MSCHAPv2. Swap the keys here to get the correct + * ISK for EAP-FAST cryptobinding. + */ + os_memcpy(isk, key + 16, 16); + os_memcpy(isk + 16, key, 16); + } else + os_memcpy(isk, key, key_len); os_free(key); return 0; diff --git a/src/eap_peer/eap_i.h b/src/eap_peer/eap_i.h index 25c0bb6fc..4b7029ee5 100644 --- a/src/eap_peer/eap_i.h +++ b/src/eap_peer/eap_i.h @@ -328,7 +328,6 @@ struct eap_sm { /* Optional challenges generated in Phase 1 (EAP-FAST) */ u8 *peer_challenge, *auth_challenge; - int mschapv2_full_key; /* Request full MSCHAPv2 key */ int num_rounds; int force_disabled; diff --git a/src/eap_peer/eap_mschapv2.c b/src/eap_peer/eap_mschapv2.c index e025442cd..b0c3ab776 100644 --- a/src/eap_peer/eap_mschapv2.c +++ b/src/eap_peer/eap_mschapv2.c @@ -93,7 +93,6 @@ struct eap_mschapv2_data { */ u8 *peer_challenge; u8 *auth_challenge; - int full_key; int phase2; u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; @@ -114,10 +113,7 @@ static void * eap_mschapv2_init(struct eap_sm *sm) if (data == NULL) return NULL; - data->full_key = sm->mschapv2_full_key; - if (sm->peer_challenge) { - data->full_key = 1; data->peer_challenge = os_malloc(MSCHAPV2_CHAL_LEN); if (data->peer_challenge == NULL) { eap_mschapv2_deinit(sm, data); @@ -830,27 +826,17 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) if (!data->master_key_valid || !data->success) return NULL; - if (data->full_key) { - /* EAP-FAST needs both send and receive keys */ - key_len = 2 * MSCHAPV2_KEY_LEN; - } else { - key_len = MSCHAPV2_KEY_LEN; - } + key_len = 2 * MSCHAPV2_KEY_LEN; key = os_malloc(key_len); if (key == NULL) return NULL; - if (data->full_key) { - get_asymetric_start_key(data->master_key, key, - MSCHAPV2_KEY_LEN, 0, 0); - get_asymetric_start_key(data->master_key, - key + MSCHAPV2_KEY_LEN, - MSCHAPV2_KEY_LEN, 1, 0); - } else { - get_asymetric_start_key(data->master_key, key, - MSCHAPV2_KEY_LEN, 1, 0); - } + /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key, i.e., + * peer MS-MPPE-Send-Key | MS-MPPE-Recv-Key */ + get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 1, 0); + get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN, + MSCHAPV2_KEY_LEN, 0, 0); wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", key, key_len); diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c index f27049885..11c93ded7 100644 --- a/src/eap_peer/eap_peap.c +++ b/src/eap_peer/eap_peap.c @@ -238,21 +238,6 @@ static int eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data, return -1; } - if (key_len == 32 && - data->phase2_method->vendor == EAP_VENDOR_IETF && - data->phase2_method->method == EAP_TYPE_MSCHAPV2) { - /* - * Microsoft uses reverse order for MS-MPPE keys in - * EAP-PEAP when compared to EAP-FAST derivation of - * ISK. Swap the keys here to get the correct ISK for - * EAP-PEAPv0 cryptobinding. - */ - u8 tmp[16]; - os_memcpy(tmp, key, 16); - os_memcpy(key, key + 16, 16); - os_memcpy(key + 16, tmp, 16); - } - if (key_len > isk_len) key_len = isk_len; os_memcpy(isk, key, key_len); @@ -731,11 +716,9 @@ static int eap_peap_phase2_request(struct eap_sm *sm, data->phase2_type.method); if (data->phase2_method) { sm->init_phase2 = 1; - sm->mschapv2_full_key = 1; data->phase2_priv = data->phase2_method->init(sm); sm->init_phase2 = 0; - sm->mschapv2_full_key = 0; } } if (data->phase2_priv == NULL || data->phase2_method == NULL) { diff --git a/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c index 737c3c104..e1a0fbd6c 100644 --- a/src/eap_peer/eap_ttls.c +++ b/src/eap_peer/eap_ttls.c @@ -558,10 +558,8 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, EAP_VENDOR_IETF, method); if (data->phase2_method) { sm->init_phase2 = 1; - sm->mschapv2_full_key = 1; data->phase2_priv = data->phase2_method->init(sm); sm->init_phase2 = 0; - sm->mschapv2_full_key = 0; } } if (data->phase2_priv == NULL || data->phase2_method == NULL) { diff --git a/src/eap_server/eap_fast.c b/src/eap_server/eap_fast.c index da011d976..b474c99a1 100644 --- a/src/eap_server/eap_fast.c +++ b/src/eap_server/eap_fast.c @@ -354,7 +354,18 @@ static int eap_fast_get_phase2_key(struct eap_sm *sm, if (key_len > isk_len) key_len = isk_len; - os_memcpy(isk, key, key_len); + if (key_len == 32 && + data->phase2_method->vendor == EAP_VENDOR_IETF && + data->phase2_method->method == EAP_TYPE_MSCHAPV2) { + /* + * EAP-FAST uses reverse order for MS-MPPE keys when deriving + * MSK from EAP-MSCHAPv2. Swap the keys here to get the correct + * ISK for EAP-FAST cryptobinding. + */ + os_memcpy(isk, key + 16, 16); + os_memcpy(isk + 16, key, 16); + } else + os_memcpy(isk, key, key_len); os_free(key); return 0; diff --git a/src/eap_server/eap_mschapv2.c b/src/eap_server/eap_mschapv2.c index f83421f6a..20e7adee6 100644 --- a/src/eap_server/eap_mschapv2.c +++ b/src/eap_server/eap_mschapv2.c @@ -524,9 +524,10 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) key = os_malloc(*len); if (key == NULL) return NULL; - get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 0, 0); + /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key */ + get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 0, 1); get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN, - MSCHAPV2_KEY_LEN, 1, 0); + MSCHAPV2_KEY_LEN, 1, 1); wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", key, *len); return key; diff --git a/src/eap_server/eap_peap.c b/src/eap_server/eap_peap.c index 5007d87e9..4b2d5a5c8 100644 --- a/src/eap_server/eap_peap.c +++ b/src/eap_server/eap_peap.c @@ -975,21 +975,6 @@ static void eap_peap_process_phase2_response(struct eap_sm *sm, eap_peap_phase2_init(sm, data, EAP_TYPE_NONE); return; } - - if (data->phase2_key_len == 32 && - data->phase2_method->vendor == EAP_VENDOR_IETF && - data->phase2_method->method == EAP_TYPE_MSCHAPV2) { - /* - * Microsoft uses reverse order for MS-MPPE keys in - * EAP-PEAP when compared to EAP-FAST derivation of - * ISK. Swap the keys here to get the correct ISK for - * EAP-PEAPv0 cryptobinding. - */ - u8 tmp[16]; - os_memcpy(tmp, data->phase2_key, 16); - os_memcpy(data->phase2_key, data->phase2_key + 16, 16); - os_memcpy(data->phase2_key + 16, tmp, 16); - } } switch (data->state) { diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c index 4d9678569..ecb35916a 100644 --- a/wpa_supplicant/eapol_test.c +++ b/wpa_supplicant/eapol_test.c @@ -560,6 +560,16 @@ static void ieee802_1x_get_keys(struct eapol_test_data *e, keys->recv_len; os_memcpy(e->authenticator_pmk, keys->recv, e->authenticator_pmk_len); + if (e->authenticator_pmk_len == 16 && keys->send && + keys->send_len == 16) { + /* MS-CHAP-v2 derives 16 octet keys */ + wpa_printf(MSG_DEBUG, "Use MS-MPPE-Send-Key " + "to extend PMK to 32 octets"); + os_memcpy(e->authenticator_pmk + + e->authenticator_pmk_len, + keys->send, keys->send_len); + e->authenticator_pmk_len += keys->send_len; + } } os_free(keys->send);