sm->reauthInit = false;
sm->erp_seq = (u32) -1;
sm->use_machine_cred = 0;
+ sm->eap_fast_mschapv2 = false;
}
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;
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;
/* 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;
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);
struct eap_mschapv2_data *data = priv;
u8 *key;
int key_len;
+ bool first_is_send;
if (!data->master_key_valid || !data->success)
return NULL;
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;
}
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;
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;
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;
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);
{
struct eap_mschapv2_data *data = priv;
u8 *key;
+ bool first_is_send;
if (data->state != SUCCESS || !data->master_key_valid)
return NULL;
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;
}