Cleaned up EAP-MSCHAPv2 key derivation
Changed peer to derive the full key (both MS-MPPE-Recv-Key and MS-MPPE-Send-Key for total of 32 octets) to match with server implementation. Swapped the order of MPPE keys in MSK derivation since server MS-MPPE-Recv-Key | MS-MPPE-Send-Key matches with the order specified for EAP-TLS MSK derivation. This means that PEAPv0 cryptobinding is now using EAP-MSCHAPv2 MSK as-is for ISK while EAP-FAST will need to swap the order of the MPPE keys to get ISK in a way that interoperates with Cisco EAP-FAST implementation.
This commit is contained in:
parent
6e783c6da9
commit
000a1de72b
9 changed files with 43 additions and 61 deletions
|
@ -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->peer_challenge = data->key_block_p->client_challenge;
|
||||||
}
|
}
|
||||||
sm->init_phase2 = 1;
|
sm->init_phase2 = 1;
|
||||||
sm->mschapv2_full_key = 1;
|
|
||||||
data->phase2_priv = data->phase2_method->init(sm);
|
data->phase2_priv = data->phase2_method->init(sm);
|
||||||
sm->init_phase2 = 0;
|
sm->init_phase2 = 0;
|
||||||
sm->mschapv2_full_key = 0;
|
|
||||||
sm->auth_challenge = NULL;
|
sm->auth_challenge = NULL;
|
||||||
sm->peer_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)
|
if (key_len > isk_len)
|
||||||
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);
|
os_free(key);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -328,7 +328,6 @@ struct eap_sm {
|
||||||
|
|
||||||
/* Optional challenges generated in Phase 1 (EAP-FAST) */
|
/* Optional challenges generated in Phase 1 (EAP-FAST) */
|
||||||
u8 *peer_challenge, *auth_challenge;
|
u8 *peer_challenge, *auth_challenge;
|
||||||
int mschapv2_full_key; /* Request full MSCHAPv2 key */
|
|
||||||
|
|
||||||
int num_rounds;
|
int num_rounds;
|
||||||
int force_disabled;
|
int force_disabled;
|
||||||
|
|
|
@ -93,7 +93,6 @@ struct eap_mschapv2_data {
|
||||||
*/
|
*/
|
||||||
u8 *peer_challenge;
|
u8 *peer_challenge;
|
||||||
u8 *auth_challenge;
|
u8 *auth_challenge;
|
||||||
int full_key;
|
|
||||||
|
|
||||||
int phase2;
|
int phase2;
|
||||||
u8 master_key[MSCHAPV2_MASTER_KEY_LEN];
|
u8 master_key[MSCHAPV2_MASTER_KEY_LEN];
|
||||||
|
@ -114,10 +113,7 @@ static void * eap_mschapv2_init(struct eap_sm *sm)
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
data->full_key = sm->mschapv2_full_key;
|
|
||||||
|
|
||||||
if (sm->peer_challenge) {
|
if (sm->peer_challenge) {
|
||||||
data->full_key = 1;
|
|
||||||
data->peer_challenge = os_malloc(MSCHAPV2_CHAL_LEN);
|
data->peer_challenge = os_malloc(MSCHAPV2_CHAL_LEN);
|
||||||
if (data->peer_challenge == NULL) {
|
if (data->peer_challenge == NULL) {
|
||||||
eap_mschapv2_deinit(sm, data);
|
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)
|
if (!data->master_key_valid || !data->success)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (data->full_key) {
|
key_len = 2 * MSCHAPV2_KEY_LEN;
|
||||||
/* EAP-FAST needs both send and receive keys */
|
|
||||||
key_len = 2 * MSCHAPV2_KEY_LEN;
|
|
||||||
} else {
|
|
||||||
key_len = MSCHAPV2_KEY_LEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
key = os_malloc(key_len);
|
key = os_malloc(key_len);
|
||||||
if (key == NULL)
|
if (key == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (data->full_key) {
|
/* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key, i.e.,
|
||||||
get_asymetric_start_key(data->master_key, key,
|
* peer MS-MPPE-Send-Key | MS-MPPE-Recv-Key */
|
||||||
MSCHAPV2_KEY_LEN, 0, 0);
|
get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 1, 0);
|
||||||
get_asymetric_start_key(data->master_key,
|
get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
|
||||||
key + MSCHAPV2_KEY_LEN,
|
MSCHAPV2_KEY_LEN, 0, 0);
|
||||||
MSCHAPV2_KEY_LEN, 1, 0);
|
|
||||||
} else {
|
|
||||||
get_asymetric_start_key(data->master_key, key,
|
|
||||||
MSCHAPV2_KEY_LEN, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key",
|
wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key",
|
||||||
key, key_len);
|
key, key_len);
|
||||||
|
|
|
@ -238,21 +238,6 @@ static int eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data,
|
||||||
return -1;
|
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)
|
if (key_len > isk_len)
|
||||||
key_len = isk_len;
|
key_len = isk_len;
|
||||||
os_memcpy(isk, key, key_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);
|
data->phase2_type.method);
|
||||||
if (data->phase2_method) {
|
if (data->phase2_method) {
|
||||||
sm->init_phase2 = 1;
|
sm->init_phase2 = 1;
|
||||||
sm->mschapv2_full_key = 1;
|
|
||||||
data->phase2_priv =
|
data->phase2_priv =
|
||||||
data->phase2_method->init(sm);
|
data->phase2_method->init(sm);
|
||||||
sm->init_phase2 = 0;
|
sm->init_phase2 = 0;
|
||||||
sm->mschapv2_full_key = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data->phase2_priv == NULL || data->phase2_method == NULL) {
|
if (data->phase2_priv == NULL || data->phase2_method == NULL) {
|
||||||
|
|
|
@ -558,10 +558,8 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
|
||||||
EAP_VENDOR_IETF, method);
|
EAP_VENDOR_IETF, method);
|
||||||
if (data->phase2_method) {
|
if (data->phase2_method) {
|
||||||
sm->init_phase2 = 1;
|
sm->init_phase2 = 1;
|
||||||
sm->mschapv2_full_key = 1;
|
|
||||||
data->phase2_priv = data->phase2_method->init(sm);
|
data->phase2_priv = data->phase2_method->init(sm);
|
||||||
sm->init_phase2 = 0;
|
sm->init_phase2 = 0;
|
||||||
sm->mschapv2_full_key = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data->phase2_priv == NULL || data->phase2_method == NULL) {
|
if (data->phase2_priv == NULL || data->phase2_method == NULL) {
|
||||||
|
|
|
@ -354,7 +354,18 @@ static int eap_fast_get_phase2_key(struct eap_sm *sm,
|
||||||
|
|
||||||
if (key_len > isk_len)
|
if (key_len > isk_len)
|
||||||
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);
|
os_free(key);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -524,9 +524,10 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
|
||||||
key = os_malloc(*len);
|
key = os_malloc(*len);
|
||||||
if (key == NULL)
|
if (key == NULL)
|
||||||
return 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,
|
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);
|
wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", key, *len);
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
|
|
|
@ -975,21 +975,6 @@ static void eap_peap_process_phase2_response(struct eap_sm *sm,
|
||||||
eap_peap_phase2_init(sm, data, EAP_TYPE_NONE);
|
eap_peap_phase2_init(sm, data, EAP_TYPE_NONE);
|
||||||
return;
|
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) {
|
switch (data->state) {
|
||||||
|
|
|
@ -560,6 +560,16 @@ static void ieee802_1x_get_keys(struct eapol_test_data *e,
|
||||||
keys->recv_len;
|
keys->recv_len;
|
||||||
os_memcpy(e->authenticator_pmk, keys->recv,
|
os_memcpy(e->authenticator_pmk, keys->recv,
|
||||||
e->authenticator_pmk_len);
|
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);
|
os_free(keys->send);
|
||||||
|
|
Loading…
Reference in a new issue