EAP-FAST: Move EAP-MSCHAPv2 special MSK handling into MSCHAPv2

EAP-FAST uses a special variant of EAP-MSHCAPv2 called EAP-FAST-MSCHAPv2
in RFC 5422. The only difference between that and EAP-MSCHAPv2 is in how
the MSK is derived. While this was supposed to be specific to EAP-FAST,
the same design has ended up getting deployed with EAP-TEAP as well.
Move this special handling into EAP-MSCHAPv2 implementation so that it
can be shared for both needs.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2022-12-01 15:56:29 +02:00 committed by Jouni Malinen
parent 81dedfbd77
commit 364b6500b8
7 changed files with 66 additions and 32 deletions

View file

@ -267,6 +267,7 @@ SM_STATE(EAP, INITIALIZE)
sm->reauthInit = false;
sm->erp_seq = (u32) -1;
sm->use_machine_cred = 0;
sm->eap_fast_mschapv2 = false;
}

View file

@ -354,6 +354,7 @@ static int eap_fast_init_phase2_method(struct eap_sm *sm,
sm->auth_challenge = data->key_block_p->server_challenge;
sm->peer_challenge = data->key_block_p->client_challenge;
}
sm->eap_fast_mschapv2 = true;
sm->init_phase2 = 1;
data->phase2_priv = data->phase2_method->init(sm);
sm->init_phase2 = 0;
@ -693,18 +694,7 @@ static int eap_fast_get_phase2_key(struct eap_sm *sm,
if (key_len > isk_len)
key_len = isk_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_memcpy(isk, key, key_len);
os_free(key);
return 0;

View file

@ -365,6 +365,11 @@ struct eap_sm {
/* Optional challenges generated in Phase 1 (EAP-FAST) */
u8 *peer_challenge, *auth_challenge;
/* Whether to use the EAP-FAST-MSCHAPv2 instantiation of EAP-MSCHAPv2.
* That variant is otherwise identical, but it generates the MSK using
* MS-MPPE keys in reverse order. */
bool eap_fast_mschapv2;
int num_rounds;
int num_rounds_short;
int force_disabled;

View file

@ -108,6 +108,12 @@ static void * eap_mschapv2_init(struct eap_sm *sm)
if (data == NULL)
return NULL;
wpa_printf(MSG_DEBUG, "EAP-%sMSCHAPv2 init%s%s",
sm->eap_fast_mschapv2 ? "FAST-" : "",
sm->peer_challenge && sm->auth_challenge ?
" with preset challenges" : "",
sm->init_phase2 ? " for Phase 2" : "");
if (sm->peer_challenge) {
data->peer_challenge = os_memdup(sm->peer_challenge,
MSCHAPV2_CHAL_LEN);
@ -844,6 +850,7 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
struct eap_mschapv2_data *data = priv;
u8 *key;
int key_len;
bool first_is_send;
if (!data->master_key_valid || !data->success)
return NULL;
@ -854,12 +861,25 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
if (key == NULL)
return NULL;
/* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key, i.e.,
* peer MS-MPPE-Send-Key | MS-MPPE-Recv-Key */
if (get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 1,
0) < 0 ||
/*
* [MS-CHAP], 3.1.5.1 (Master Session Key (MSK) Derivation
* MSK = MasterReceiveKey + MasterSendKey + 32 bytes zeros (padding)
* On a Peer:
* MS-MPPE-Recv-Key = MasterSendKey
* MS-MPPE-Send-Key = MasterReceiveKey
*
* RFC 5422, 3.2.3 (Authenticating Using EAP-FAST-MSCHAPv2)
* MSK = MasterSendKey + MasterReceiveKey
* (i.e., reverse order and no padding)
*
* On Peer, EAP-MSCHAPv2 starts with Send key and EAP-FAST-MSCHAPv2
* starts with Receive key.
*/
first_is_send = !sm->eap_fast_mschapv2;
if (get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN,
first_is_send, 0) < 0 ||
get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
MSCHAPV2_KEY_LEN, 0, 0) < 0) {
MSCHAPV2_KEY_LEN, !first_is_send, 0) < 0) {
os_free(key);
return NULL;
}

View file

@ -176,9 +176,15 @@ struct eap_sm {
METHOD_PENDING_NONE, METHOD_PENDING_WAIT, METHOD_PENDING_CONT
} method_pending;
/* Optional challenges generated in Phase 1 (EAP-FAST) */
u8 *auth_challenge;
u8 *peer_challenge;
/* Whether to use the EAP-FAST-MSCHAPv2 instantiation of EAP-MSCHAPv2.
* That variant is otherwise identical, but it generates the MSK using
* MS-MPPE keys in reverse order. */
bool eap_fast_mschapv2;
struct wpabuf *assoc_wps_ie;
struct wpabuf *assoc_p2p_ie;

View file

@ -357,18 +357,7 @@ static int eap_fast_get_phase2_key(struct eap_sm *sm,
if (key_len > isk_len)
key_len = isk_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_memcpy(isk, key, key_len);
os_free(key);
return 0;
@ -961,6 +950,7 @@ static int eap_fast_phase2_init(struct eap_sm *sm, struct eap_fast_data *data,
sm->auth_challenge = data->key_block_p->server_challenge;
sm->peer_challenge = data->key_block_p->client_challenge;
}
sm->eap_fast_mschapv2 = true;
sm->init_phase2 = 1;
data->phase2_priv = data->phase2_method->init(sm);
sm->init_phase2 = 0;

View file

@ -64,6 +64,12 @@ static void * eap_mschapv2_init(struct eap_sm *sm)
return NULL;
data->state = CHALLENGE;
wpa_printf(MSG_DEBUG, "EAP-%sMSCHAPv2 init%s%s",
sm->eap_fast_mschapv2 ? "FAST-" : "",
sm->peer_challenge && sm->auth_challenge ?
" with preset challenges" : "",
sm->init_phase2 ? " for Phase 2" : "");
if (sm->auth_challenge) {
os_memcpy(data->auth_challenge, sm->auth_challenge,
CHALLENGE_LEN);
@ -542,6 +548,7 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_mschapv2_data *data = priv;
u8 *key;
bool first_is_send;
if (data->state != SUCCESS || !data->master_key_valid)
return NULL;
@ -550,11 +557,26 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
key = os_malloc(*len);
if (key == NULL)
return NULL;
/*
* [MS-CHAP], 3.1.5.1 (Master Session Key (MSK) Derivation
* MSK = MasterReceiveKey + MasterSendKey + 32 bytes zeros (padding)
* On an Authenticator:
* MS-MPPE-Recv-Key = MasterReceiveKey
* MS-MPPE-Send-Key = MasterSendKey
*
* RFC 5422, 3.2.3 (Authenticating Using EAP-FAST-MSCHAPv2)
* MSK = MasterSendKey + MasterReceiveKey
* (i.e., reverse order and no padding)
*
* On Peer, EAP-MSCHAPv2 starts with Send key and EAP-FAST-MSCHAPv2
* starts with Receive key.
*/
first_is_send = sm->eap_fast_mschapv2;
/* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key */
if (get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 0,
1) < 0 ||
if (get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN,
first_is_send, 1) < 0 ||
get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
MSCHAPV2_KEY_LEN, 1, 1) < 0) {
MSCHAPV2_KEY_LEN, !first_is_send, 1) < 0) {
os_free(key);
return NULL;
}