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:
parent
81dedfbd77
commit
364b6500b8
7 changed files with 66 additions and 32 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue