#include "includes.h"
#include "common.h"
+#include "crypto/tls.h"
+#include "crypto/sha1.h"
+#include "eap_common/eap_tlv_common.h"
#include "eap_i.h"
#include "eap_tls_common.h"
#include "eap_config.h"
-#include "tls.h"
-#include "eap_tlv.h"
-#include "sha1.h"
#include "eap_fast_pac.h"
#ifdef EAP_FAST_DYNAMIC
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;
{
size_t i;
+ /* TODO: TNC with anonymous provisioning; need to require both
+ * completed MSCHAPv2 and TNC */
+
if (data->anon_provisioning && type != EAP_TYPE_MSCHAPV2) {
wpa_printf(MSG_INFO, "EAP-FAST: Only EAP-MSCHAPv2 is allowed "
"during unauthenticated provisioning; reject phase2"
return -1;
}
+#ifdef EAP_TNC
+ if (type == EAP_TYPE_TNC) {
+ data->phase2_type.vendor = EAP_VENDOR_IETF;
+ data->phase2_type.method = EAP_TYPE_TNC;
+ wpa_printf(MSG_DEBUG, "EAP-FAST: Selected Phase 2 EAP "
+ "vendor %d method %d for TNC",
+ data->phase2_type.vendor,
+ data->phase2_type.method);
+ return 0;
+ }
+#endif /* EAP_TNC */
+
for (i = 0; i < data->num_phase2_types; i++) {
if (data->phase2_types[i].vendor != EAP_VENDOR_IETF ||
data->phase2_types[i].method != type)
return 0;
}
+ if (data->phase2_priv && data->phase2_method &&
+ *pos != data->phase2_type.method) {
+ wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 EAP sequence - "
+ "deinitialize previous method");
+ data->phase2_method->deinit(sm, data->phase2_priv);
+ data->phase2_method = NULL;
+ data->phase2_priv = NULL;
+ data->phase2_type.vendor = EAP_VENDOR_IETF;
+ data->phase2_type.method = EAP_TYPE_NONE;
+ }
+
if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
data->phase2_type.method == EAP_TYPE_NONE &&
eap_fast_select_phase2_method(data, *pos) < 0) {
buf = wpabuf_alloc(sizeof(*result));
if (buf == NULL)
return NULL;
+ wpa_printf(MSG_DEBUG, "EAP-FAST: Add %sResult TLV(status=%d)",
+ intermediate ? "Intermediate " : "", status);
result = wpabuf_put(buf, sizeof(*result));
result->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
(intermediate ?
if (buf == NULL)
return NULL;
- res = wpabuf_put(buf, sizeof(*res));
- res->tlv_type = host_to_be16(EAP_TLV_RESULT_TLV |
- EAP_TLV_TYPE_MANDATORY);
- res->length = host_to_be16(sizeof(*res) - sizeof(struct eap_tlv_hdr));
- res->status = host_to_be16(EAP_TLV_RESULT_SUCCESS);
-
+ wpa_printf(MSG_DEBUG, "EAP-FAST: Add PAC TLV (ack)");
ack = wpabuf_put(buf, sizeof(*ack));
ack->tlv_type = host_to_be16(EAP_TLV_PAC_TLV |
EAP_TLV_TYPE_MANDATORY);
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;
entry->a_id_info_len = len;
break;
case PAC_TYPE_PAC_TYPE:
- /*
- * draft-cam-winget-eap-fast-provisioning-04.txt,
- * Section 4.2.6 - PAC-Type TLV
- */
+ /* RFC 5422, Section 4.2.6 - PAC-Type TLV */
if (len != 2) {
wpa_printf(MSG_INFO, "EAP-FAST: Invalid PAC-Type "
"length %lu (expected 2)",
size_t left, len;
int type;
- /* draft-cam-winget-eap-fast-provisioning-04.txt, Section 4.2.4 */
+ /* RFC 5422, Section 4.2.4 */
/* PAC-Type defaults to Tunnel PAC (Type 1) */
entry->pac_type = PAC_TYPE_TUNNEL_PAC;
}
if (data->current_pac == NULL && data->provisioning &&
- !data->anon_provisioning) {
+ !data->anon_provisioning && !tlv.pac &&
+ (tlv.iresult == EAP_TLV_RESULT_SUCCESS ||
+ tlv.result == EAP_TLV_RESULT_SUCCESS)) {
/*
* Need to request Tunnel PAC when using authenticated
* provisioning.
if (tlv.result == EAP_TLV_RESULT_SUCCESS && !failed) {
tmp = eap_fast_tlv_result(EAP_TLV_RESULT_SUCCESS, 0);
- resp = wpabuf_concat(resp, tmp);
+ resp = wpabuf_concat(tmp, resp);
} else if (failed) {
tmp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0);
- resp = wpabuf_concat(resp, tmp);
+ resp = wpabuf_concat(tmp, resp);
}
if (resp && tlv.result == EAP_TLV_RESULT_SUCCESS && !failed &&
/* EAP-FAST Version negotiation (section 3.1) */
wpa_printf(MSG_DEBUG, "EAP-FAST: Start (server ver=%d, own ver=%d)",
- flags & EAP_PEAP_VERSION_MASK, data->fast_version);
- if ((flags & EAP_PEAP_VERSION_MASK) < data->fast_version)
- data->fast_version = flags & EAP_PEAP_VERSION_MASK;
+ flags & EAP_TLS_VERSION_MASK, data->fast_version);
+ if ((flags & EAP_TLS_VERSION_MASK) < data->fast_version)
+ data->fast_version = flags & EAP_TLS_VERSION_MASK;
wpa_printf(MSG_DEBUG, "EAP-FAST: Using FAST version %d",
data->fast_version);