summaryrefslogtreecommitdiffstats
path: root/contrib/wpa/src/eap_peer
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wpa/src/eap_peer')
-rw-r--r--contrib/wpa/src/eap_peer/Makefile11
-rw-r--r--contrib/wpa/src/eap_peer/eap.c341
-rw-r--r--contrib/wpa/src/eap_peer/eap.h54
-rw-r--r--contrib/wpa/src/eap_peer/eap_aka.c106
-rw-r--r--contrib/wpa/src/eap_peer/eap_config.h16
-rw-r--r--contrib/wpa/src/eap_peer/eap_fast.c29
-rw-r--r--contrib/wpa/src/eap_peer/eap_fast_pac.c19
-rw-r--r--contrib/wpa/src/eap_peer/eap_fast_pac.h10
-rw-r--r--contrib/wpa/src/eap_peer/eap_gpsk.c13
-rw-r--r--contrib/wpa/src/eap_peer/eap_gtc.c10
-rw-r--r--contrib/wpa/src/eap_peer/eap_i.h15
-rw-r--r--contrib/wpa/src/eap_peer/eap_ikev2.c10
-rw-r--r--contrib/wpa/src/eap_peer/eap_leap.c13
-rw-r--r--contrib/wpa/src/eap_peer/eap_md5.c20
-rw-r--r--contrib/wpa/src/eap_peer/eap_methods.c12
-rw-r--r--contrib/wpa/src/eap_peer/eap_methods.h12
-rw-r--r--contrib/wpa/src/eap_peer/eap_mschapv2.c19
-rw-r--r--contrib/wpa/src/eap_peer/eap_otp.c10
-rw-r--r--contrib/wpa/src/eap_peer/eap_pax.c13
-rw-r--r--contrib/wpa/src/eap_peer/eap_peap.c33
-rw-r--r--contrib/wpa/src/eap_peer/eap_psk.c13
-rw-r--r--contrib/wpa/src/eap_peer/eap_pwd.c922
-rw-r--r--contrib/wpa/src/eap_peer/eap_sake.c13
-rw-r--r--contrib/wpa/src/eap_peer/eap_sim.c117
-rw-r--r--contrib/wpa/src/eap_peer/eap_tls.c93
-rw-r--r--contrib/wpa/src/eap_peer/eap_tls_common.c125
-rw-r--r--contrib/wpa/src/eap_peer/eap_tls_common.h30
-rw-r--r--contrib/wpa/src/eap_peer/eap_tnc.c11
-rw-r--r--contrib/wpa/src/eap_peer/eap_ttls.c483
-rw-r--r--contrib/wpa/src/eap_peer/eap_vendor_test.c12
-rw-r--r--contrib/wpa/src/eap_peer/eap_wsc.c43
-rw-r--r--contrib/wpa/src/eap_peer/ikev2.c15
-rw-r--r--contrib/wpa/src/eap_peer/ikev2.h10
-rw-r--r--contrib/wpa/src/eap_peer/mschapv2.c45
-rw-r--r--contrib/wpa/src/eap_peer/mschapv2.h10
-rw-r--r--contrib/wpa/src/eap_peer/tncc.c14
-rw-r--r--contrib/wpa/src/eap_peer/tncc.h10
37 files changed, 1803 insertions, 929 deletions
diff --git a/contrib/wpa/src/eap_peer/Makefile b/contrib/wpa/src/eap_peer/Makefile
deleted file mode 100644
index 3651056..0000000
--- a/contrib/wpa/src/eap_peer/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-all:
- @echo Nothing to be made.
-
-clean:
- rm -f *~ *.o *.so *.d
-
-install:
- if ls *.so >/dev/null 2>&1; then \
- install -d $(DESTDIR)$(LIBDIR)/wpa_supplicant && \
- cp *.so $(DESTDIR)$(LIBDIR)/wpa_supplicant \
- ; fi
diff --git a/contrib/wpa/src/eap_peer/eap.c b/contrib/wpa/src/eap_peer/eap.c
index b9f186b..a4c9b25 100644
--- a/contrib/wpa/src/eap_peer/eap.c
+++ b/contrib/wpa/src/eap_peer/eap.c
@@ -1,15 +1,9 @@
/*
* EAP peer state machines (RFC 4137)
- * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*
* This file implements the Peer State Machine as defined in RFC 4137. The used
* states and state transitions match mostly with the RFC. However, there are
@@ -26,6 +20,7 @@
#include "common.h"
#include "pcsc_funcs.h"
#include "state_machine.h"
+#include "ext_password.h"
#include "crypto/crypto.h"
#include "crypto/tls.h"
#include "common/wpa_ctrl.h"
@@ -37,6 +32,7 @@
#define STATE_MACHINE_DEBUG_PREFIX "EAP"
#define EAP_MAX_AUTH_ROUNDS 50
+#define EAP_CLIENT_TIMEOUT_DEFAULT 60
static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,
@@ -86,8 +82,21 @@ static struct wpabuf * eapol_get_eapReqData(struct eap_sm *sm)
}
+static void eap_notify_status(struct eap_sm *sm, const char *status,
+ const char *parameter)
+{
+ wpa_printf(MSG_DEBUG, "EAP: Status notification: %s (param=%s)",
+ status, parameter);
+ if (sm->eapol_cb->notify_status)
+ sm->eapol_cb->notify_status(sm->eapol_ctx, status, parameter);
+}
+
+
static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
{
+ ext_password_free(sm->ext_pw_buf);
+ sm->ext_pw_buf = NULL;
+
if (sm->m == NULL || sm->eap_method_priv == NULL)
return;
@@ -146,6 +155,7 @@ SM_STATE(EAP, INITIALIZE)
sm->methodState = METHOD_NONE;
sm->allowNotifications = TRUE;
sm->decision = DECISION_FAIL;
+ sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);
eapol_set_bool(sm, EAPOL_eapFail, FALSE);
@@ -179,6 +189,12 @@ SM_STATE(EAP, DISABLED)
{
SM_ENTRY(EAP, DISABLED);
sm->num_rounds = 0;
+ /*
+ * RFC 4137 does not describe clearing of idleWhile here, but doing so
+ * allows the timer tick to be stopped more quickly when EAP is not in
+ * use.
+ */
+ eapol_set_int(sm, EAPOL_idleWhile, 0);
}
@@ -217,6 +233,7 @@ SM_STATE(EAP, GET_METHOD)
{
int reinit;
EapType method;
+ const struct eap_method *eap_method;
SM_ENTRY(EAP, GET_METHOD);
@@ -225,18 +242,24 @@ SM_STATE(EAP, GET_METHOD)
else
method = sm->reqMethod;
+ eap_method = eap_peer_get_eap_method(sm->reqVendor, method);
+
if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed",
sm->reqVendor, method);
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
"vendor=%u method=%u -> NAK",
sm->reqVendor, method);
+ eap_notify_status(sm, "refuse proposed method",
+ eap_method ? eap_method->name : "unknown");
goto nak;
}
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
"vendor=%u method=%u", sm->reqVendor, method);
+ eap_notify_status(sm, "accept proposed method",
+ eap_method ? eap_method->name : "unknown");
/*
* RFC 4137 does not define specific operation for fast
* re-authentication (session resumption). The design here is to allow
@@ -260,7 +283,7 @@ SM_STATE(EAP, GET_METHOD)
sm->selectedMethod = sm->reqMethod;
if (sm->m == NULL)
- sm->m = eap_peer_get_eap_method(sm->reqVendor, method);
+ sm->m = eap_method;
if (!sm->m) {
wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: "
"vendor %d method %d",
@@ -268,6 +291,8 @@ SM_STATE(EAP, GET_METHOD)
goto nak;
}
+ sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
+
wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: "
"vendor %u method %u (%s)",
sm->reqVendor, method, sm->m->name);
@@ -323,6 +348,7 @@ SM_STATE(EAP, METHOD)
{
struct wpabuf *eapReqData;
struct eap_method_ret ret;
+ int min_len = 1;
SM_ENTRY(EAP, METHOD);
if (sm->m == NULL) {
@@ -331,6 +357,10 @@ SM_STATE(EAP, METHOD)
}
eapReqData = eapol_get_eapReqData(sm);
+ if (sm->m->vendor == EAP_VENDOR_IETF && sm->m->method == EAP_TYPE_LEAP)
+ min_len = 0; /* LEAP uses EAP-Success without payload */
+ if (!eap_hdr_len_valid(eapReqData, min_len))
+ return;
/*
* Get ignore, methodState, decision, allowNotifications, and
@@ -419,6 +449,8 @@ SM_STATE(EAP, IDENTITY)
SM_ENTRY(EAP, IDENTITY);
eapReqData = eapol_get_eapReqData(sm);
+ if (!eap_hdr_len_valid(eapReqData, 1))
+ return;
eap_sm_processIdentity(sm, eapReqData);
wpabuf_free(sm->eapRespData);
sm->eapRespData = NULL;
@@ -435,6 +467,8 @@ SM_STATE(EAP, NOTIFICATION)
SM_ENTRY(EAP, NOTIFICATION);
eapReqData = eapol_get_eapReqData(sm);
+ if (!eap_hdr_len_valid(eapReqData, 1))
+ return;
eap_sm_processNotify(sm, eapReqData);
wpabuf_free(sm->eapRespData);
sm->eapRespData = NULL;
@@ -852,13 +886,17 @@ static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id)
static void eap_sm_processIdentity(struct eap_sm *sm, const struct wpabuf *req)
{
- const struct eap_hdr *hdr = wpabuf_head(req);
- const u8 *pos = (const u8 *) (hdr + 1);
- pos++;
+ const u8 *pos;
+ size_t msg_len;
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
"EAP authentication started");
+ pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req,
+ &msg_len);
+ if (pos == NULL)
+ return;
+
/*
* RFC 3748 - 5.1: Identity
* Data field may contain a displayable message in UTF-8. If this
@@ -869,15 +907,78 @@ static void eap_sm_processIdentity(struct eap_sm *sm, const struct wpabuf *req)
/* TODO: could save displayable message so that it can be shown to the
* user in case of interaction is required */
wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data",
- pos, be_to_host16(hdr->length) - 5);
+ pos, msg_len);
}
#ifdef PCSC_FUNCS
+
+/*
+ * Rules for figuring out MNC length based on IMSI for SIM cards that do not
+ * include MNC length field.
+ */
+static int mnc_len_from_imsi(const char *imsi)
+{
+ char mcc_str[4];
+ unsigned int mcc;
+
+ os_memcpy(mcc_str, imsi, 3);
+ mcc_str[3] = '\0';
+ mcc = atoi(mcc_str);
+
+ if (mcc == 244)
+ return 2; /* Networks in Finland use 2-digit MNC */
+
+ return -1;
+}
+
+
+static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi,
+ size_t max_len, size_t *imsi_len)
+{
+ int mnc_len;
+ char *pos, mnc[4];
+
+ if (*imsi_len + 36 > max_len) {
+ wpa_printf(MSG_WARNING, "No room for realm in IMSI buffer");
+ return -1;
+ }
+
+ /* MNC (2 or 3 digits) */
+ mnc_len = scard_get_mnc_len(sm->scard_ctx);
+ if (mnc_len < 0)
+ mnc_len = mnc_len_from_imsi(imsi);
+ if (mnc_len < 0) {
+ wpa_printf(MSG_INFO, "Failed to get MNC length from (U)SIM "
+ "assuming 3");
+ mnc_len = 3;
+ }
+
+ if (mnc_len == 2) {
+ mnc[0] = '0';
+ mnc[1] = imsi[3];
+ mnc[2] = imsi[4];
+ } else if (mnc_len == 3) {
+ mnc[0] = imsi[3];
+ mnc[1] = imsi[4];
+ mnc[2] = imsi[5];
+ }
+ mnc[3] = '\0';
+
+ pos = imsi + *imsi_len;
+ pos += os_snprintf(pos, imsi + max_len - pos,
+ "@wlan.mnc%s.mcc%c%c%c.3gppnetwork.org",
+ mnc, imsi[0], imsi[1], imsi[2]);
+ *imsi_len = pos - imsi;
+
+ return 0;
+}
+
+
static int eap_sm_imsi_identity(struct eap_sm *sm,
struct eap_peer_config *conf)
{
- int aka = 0;
+ enum { EAP_SM_SIM, EAP_SM_AKA, EAP_SM_AKA_PRIME } method = EAP_SM_SIM;
char imsi[100];
size_t imsi_len;
struct eap_method_type *m = conf->eap_methods;
@@ -891,11 +992,28 @@ static int eap_sm_imsi_identity(struct eap_sm *sm,
wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len);
+ if (imsi_len < 7) {
+ wpa_printf(MSG_WARNING, "Too short IMSI for SIM identity");
+ return -1;
+ }
+
+ if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len) < 0) {
+ wpa_printf(MSG_WARNING, "Could not add realm to SIM identity");
+ return -1;
+ }
+ wpa_hexdump_ascii(MSG_DEBUG, "IMSI + realm", (u8 *) imsi, imsi_len);
+
for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF ||
m[i].method != EAP_TYPE_NONE); i++) {
if (m[i].vendor == EAP_VENDOR_IETF &&
+ m[i].method == EAP_TYPE_AKA_PRIME) {
+ method = EAP_SM_AKA_PRIME;
+ break;
+ }
+
+ if (m[i].vendor == EAP_VENDOR_IETF &&
m[i].method == EAP_TYPE_AKA) {
- aka = 1;
+ method = EAP_SM_AKA;
break;
}
}
@@ -908,12 +1026,23 @@ static int eap_sm_imsi_identity(struct eap_sm *sm,
return -1;
}
- conf->identity[0] = aka ? '0' : '1';
+ switch (method) {
+ case EAP_SM_SIM:
+ conf->identity[0] = '1';
+ break;
+ case EAP_SM_AKA:
+ conf->identity[0] = '0';
+ break;
+ case EAP_SM_AKA_PRIME:
+ conf->identity[0] = '6';
+ break;
+ }
os_memcpy(conf->identity + 1, imsi, imsi_len);
conf->identity_len = 1 + imsi_len;
return 0;
}
+
#endif /* PCSC_FUNCS */
@@ -1146,10 +1275,12 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req)
break;
case EAP_CODE_SUCCESS:
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success");
+ eap_notify_status(sm, "completion", "success");
sm->rxSuccess = TRUE;
break;
case EAP_CODE_FAILURE:
wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
+ eap_notify_status(sm, "completion", "failure");
sm->rxFailure = TRUE;
break;
default:
@@ -1165,9 +1296,12 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
{
struct eap_sm *sm = ctx;
char *hash_hex = NULL;
- char *cert_hex = NULL;
switch (ev) {
+ case TLS_CERT_CHAIN_SUCCESS:
+ eap_notify_status(sm, "remote certificate verification",
+ "success");
+ break;
case TLS_CERT_CHAIN_FAILURE:
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR
"reason=%d depth=%d subject='%s' err='%s'",
@@ -1175,8 +1309,13 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
data->cert_fail.depth,
data->cert_fail.subject,
data->cert_fail.reason_txt);
+ eap_notify_status(sm, "remote certificate verification",
+ data->cert_fail.reason_txt);
break;
case TLS_PEER_CERTIFICATE:
+ if (!sm->eapol_cb->notify_cert)
+ break;
+
if (data->peer_cert.hash) {
size_t len = data->peer_cert.hash_len * 2 + 1;
hash_hex = os_malloc(len);
@@ -1186,31 +1325,23 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
data->peer_cert.hash_len);
}
}
- wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PEER_CERT
- "depth=%d subject='%s'%s%s",
- data->peer_cert.depth, data->peer_cert.subject,
- hash_hex ? " hash=" : "", hash_hex ? hash_hex : "");
-
- if (data->peer_cert.cert) {
- size_t len = wpabuf_len(data->peer_cert.cert) * 2 + 1;
- cert_hex = os_malloc(len);
- if (cert_hex == NULL)
- break;
- wpa_snprintf_hex(cert_hex, len,
- wpabuf_head(data->peer_cert.cert),
- wpabuf_len(data->peer_cert.cert));
- wpa_msg_ctrl(sm->msg_ctx, MSG_INFO,
- WPA_EVENT_EAP_PEER_CERT
- "depth=%d subject='%s' cert=%s",
- data->peer_cert.depth,
- data->peer_cert.subject,
- cert_hex);
- }
+
+ sm->eapol_cb->notify_cert(sm->eapol_ctx,
+ data->peer_cert.depth,
+ data->peer_cert.subject,
+ hash_hex, data->peer_cert.cert);
+ break;
+ case TLS_ALERT:
+ if (data->alert.is_local)
+ eap_notify_status(sm, "local TLS alert",
+ data->alert.description);
+ else
+ eap_notify_status(sm, "remote TLS alert",
+ data->alert.description);
break;
}
os_free(hash_hex);
- os_free(cert_hex);
}
@@ -1241,7 +1372,7 @@ struct eap_sm * eap_peer_sm_init(void *eapol_ctx,
sm->eapol_ctx = eapol_ctx;
sm->eapol_cb = eapol_cb;
sm->msg_ctx = msg_ctx;
- sm->ClientTimeout = 60;
+ sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT;
sm->wps = conf->wps;
os_memset(&tlsconf, 0, sizeof(tlsconf));
@@ -1253,6 +1384,7 @@ struct eap_sm * eap_peer_sm_init(void *eapol_ctx,
#endif /* CONFIG_FIPS */
tlsconf.event_cb = eap_peer_sm_tls_event;
tlsconf.cb_ctx = sm;
+ tlsconf.cert_in_cb = conf->cert_in_cb;
sm->ssl_ctx = tls_init(&tlsconf);
if (sm->ssl_ctx == NULL) {
wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
@@ -1261,6 +1393,13 @@ struct eap_sm * eap_peer_sm_init(void *eapol_ctx,
return NULL;
}
+ sm->ssl_ctx2 = tls_init(&tlsconf);
+ if (sm->ssl_ctx2 == NULL) {
+ wpa_printf(MSG_INFO, "SSL: Failed to initialize TLS "
+ "context (2).");
+ /* Run without separate TLS context within TLS tunnel */
+ }
+
return sm;
}
@@ -1278,6 +1417,8 @@ void eap_peer_sm_deinit(struct eap_sm *sm)
return;
eap_deinit_prev_method(sm, "EAP deinit");
eap_sm_abort(sm);
+ if (sm->ssl_ctx2)
+ tls_deinit(sm->ssl_ctx2);
tls_deinit(sm->ssl_ctx);
os_free(sm);
}
@@ -1477,16 +1618,11 @@ int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
-typedef enum {
- TYPE_IDENTITY, TYPE_PASSWORD, TYPE_OTP, TYPE_PIN, TYPE_NEW_PASSWORD,
- TYPE_PASSPHRASE
-} eap_ctrl_req_type;
-
-static void eap_sm_request(struct eap_sm *sm, eap_ctrl_req_type type,
+static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
const char *msg, size_t msglen)
{
struct eap_peer_config *config;
- char *field, *txt, *tmp;
+ char *txt = NULL, *tmp;
if (sm == NULL)
return;
@@ -1494,29 +1630,20 @@ static void eap_sm_request(struct eap_sm *sm, eap_ctrl_req_type type,
if (config == NULL)
return;
- switch (type) {
- case TYPE_IDENTITY:
- field = "IDENTITY";
- txt = "Identity";
+ switch (field) {
+ case WPA_CTRL_REQ_EAP_IDENTITY:
config->pending_req_identity++;
break;
- case TYPE_PASSWORD:
- field = "PASSWORD";
- txt = "Password";
+ case WPA_CTRL_REQ_EAP_PASSWORD:
config->pending_req_password++;
break;
- case TYPE_NEW_PASSWORD:
- field = "NEW_PASSWORD";
- txt = "New Password";
+ case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
config->pending_req_new_password++;
break;
- case TYPE_PIN:
- field = "PIN";
- txt = "PIN";
+ case WPA_CTRL_REQ_EAP_PIN:
config->pending_req_pin++;
break;
- case TYPE_OTP:
- field = "OTP";
+ case WPA_CTRL_REQ_EAP_OTP:
if (msg) {
tmp = os_malloc(msglen + 3);
if (tmp == NULL)
@@ -1535,9 +1662,7 @@ static void eap_sm_request(struct eap_sm *sm, eap_ctrl_req_type type,
txt = config->pending_req_otp;
}
break;
- case TYPE_PASSPHRASE:
- field = "PASSPHRASE";
- txt = "Private key passphrase";
+ case WPA_CTRL_REQ_EAP_PASSPHRASE:
config->pending_req_passphrase++;
break;
default:
@@ -1551,6 +1676,13 @@ static void eap_sm_request(struct eap_sm *sm, eap_ctrl_req_type type,
#define eap_sm_request(sm, type, msg, msglen) do { } while (0)
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
+const char * eap_sm_get_method_name(struct eap_sm *sm)
+{
+ if (sm->m == NULL)
+ return "UNKNOWN";
+ return sm->m->name;
+}
+
/**
* eap_sm_request_identity - Request identity from user (ctrl_iface)
@@ -1563,7 +1695,7 @@ static void eap_sm_request(struct eap_sm *sm, eap_ctrl_req_type type,
*/
void eap_sm_request_identity(struct eap_sm *sm)
{
- eap_sm_request(sm, TYPE_IDENTITY, NULL, 0);
+ eap_sm_request(sm, WPA_CTRL_REQ_EAP_IDENTITY, NULL, 0);
}
@@ -1578,7 +1710,7 @@ void eap_sm_request_identity(struct eap_sm *sm)
*/
void eap_sm_request_password(struct eap_sm *sm)
{
- eap_sm_request(sm, TYPE_PASSWORD, NULL, 0);
+ eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSWORD, NULL, 0);
}
@@ -1593,7 +1725,7 @@ void eap_sm_request_password(struct eap_sm *sm)
*/
void eap_sm_request_new_password(struct eap_sm *sm)
{
- eap_sm_request(sm, TYPE_NEW_PASSWORD, NULL, 0);
+ eap_sm_request(sm, WPA_CTRL_REQ_EAP_NEW_PASSWORD, NULL, 0);
}
@@ -1608,7 +1740,7 @@ void eap_sm_request_new_password(struct eap_sm *sm)
*/
void eap_sm_request_pin(struct eap_sm *sm)
{
- eap_sm_request(sm, TYPE_PIN, NULL, 0);
+ eap_sm_request(sm, WPA_CTRL_REQ_EAP_PIN, NULL, 0);
}
@@ -1624,7 +1756,7 @@ void eap_sm_request_pin(struct eap_sm *sm)
*/
void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len)
{
- eap_sm_request(sm, TYPE_OTP, msg, msg_len);
+ eap_sm_request(sm, WPA_CTRL_REQ_EAP_OTP, msg, msg_len);
}
@@ -1639,7 +1771,7 @@ void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len)
*/
void eap_sm_request_passphrase(struct eap_sm *sm)
{
- eap_sm_request(sm, TYPE_PASSPHRASE, NULL, 0);
+ eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSPHRASE, NULL, 0);
}
@@ -1806,6 +1938,27 @@ const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
}
+static int eap_get_ext_password(struct eap_sm *sm,
+ struct eap_peer_config *config)
+{
+ char *name;
+
+ if (config->password == NULL)
+ return -1;
+
+ name = os_zalloc(config->password_len + 1);
+ if (name == NULL)
+ return -1;
+ os_memcpy(name, config->password, config->password_len);
+
+ ext_password_free(sm->ext_pw_buf);
+ sm->ext_pw_buf = ext_password_get(sm->ext_pw, name);
+ os_free(name);
+
+ return sm->ext_pw_buf == NULL ? -1 : 0;
+}
+
+
/**
* eap_get_config_password - Get password from the network configuration
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
@@ -1817,6 +1970,14 @@ const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
struct eap_peer_config *config = eap_get_config(sm);
if (config == NULL)
return NULL;
+
+ if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
+ if (eap_get_ext_password(sm, config) < 0)
+ return NULL;
+ *len = wpabuf_len(sm->ext_pw_buf);
+ return wpabuf_head(sm->ext_pw_buf);
+ }
+
*len = config->password_len;
return config->password;
}
@@ -1836,6 +1997,14 @@ const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash)
struct eap_peer_config *config = eap_get_config(sm);
if (config == NULL)
return NULL;
+
+ if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
+ if (eap_get_ext_password(sm, config) < 0)
+ return NULL;
+ *len = wpabuf_len(sm->ext_pw_buf);
+ return wpabuf_head(sm->ext_pw_buf);
+ }
+
*len = config->password_len;
if (hash)
*hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH);
@@ -1923,6 +2092,15 @@ const char * eap_get_config_phase2(struct eap_sm *sm)
}
+int eap_get_config_fragment_size(struct eap_sm *sm)
+{
+ struct eap_peer_config *config = eap_get_config(sm);
+ if (config == NULL)
+ return -1;
+ return config->fragment_size;
+}
+
+
/**
* eap_key_available - Get key availability (eapKeyAvailable variable)
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
@@ -2138,3 +2316,24 @@ int eap_is_wps_pin_enrollee(struct eap_peer_config *conf)
return 1;
}
+
+
+void eap_sm_set_ext_pw_ctx(struct eap_sm *sm, struct ext_password_data *ext)
+{
+ ext_password_free(sm->ext_pw_buf);
+ sm->ext_pw_buf = NULL;
+ sm->ext_pw = ext;
+}
+
+
+/**
+ * eap_set_anon_id - Set or add anonymous identity
+ * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
+ * @id: Anonymous identity (e.g., EAP-SIM pseudonym) or %NULL to clear
+ * @len: Length of anonymous identity in octets
+ */
+void eap_set_anon_id(struct eap_sm *sm, const u8 *id, size_t len)
+{
+ if (sm->eapol_cb->set_anon_id)
+ sm->eapol_cb->set_anon_id(sm->eapol_ctx, id, len);
+}
diff --git a/contrib/wpa/src/eap_peer/eap.h b/contrib/wpa/src/eap_peer/eap.h
index 40d0b69..8bccef1 100644
--- a/contrib/wpa/src/eap_peer/eap.h
+++ b/contrib/wpa/src/eap_peer/eap.h
@@ -1,15 +1,9 @@
/*
* EAP peer state machine functions (RFC 4137)
- * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef EAP_H
@@ -216,11 +210,39 @@ struct eapol_callbacks {
/**
* eap_param_needed - Notify that EAP parameter is needed
* @ctx: eapol_ctx from eap_peer_sm_init() call
- * @field: Field name (e.g., "IDENTITY")
+ * @field: Field indicator (e.g., WPA_CTRL_REQ_EAP_IDENTITY)
* @txt: User readable text describing the required parameter
*/
- void (*eap_param_needed)(void *ctx, const char *field,
+ void (*eap_param_needed)(void *ctx, enum wpa_ctrl_req_type field,
const char *txt);
+
+ /**
+ * notify_cert - Notification of a peer certificate
+ * @ctx: eapol_ctx from eap_peer_sm_init() call
+ * @depth: Depth in certificate chain (0 = server)
+ * @subject: Subject of the peer certificate
+ * @cert_hash: SHA-256 hash of the certificate
+ * @cert: Peer certificate
+ */
+ void (*notify_cert)(void *ctx, int depth, const char *subject,
+ const char *cert_hash, const struct wpabuf *cert);
+
+ /**
+ * notify_status - Notification of the current EAP state
+ * @ctx: eapol_ctx from eap_peer_sm_init() call
+ * @status: Step in the process of EAP authentication
+ * @parameter: Step-specific parameter, e.g., EAP method name
+ */
+ void (*notify_status)(void *ctx, const char *status,
+ const char *parameter);
+
+ /**
+ * set_anon_id - Set or add anonymous identity
+ * @ctx: eapol_ctx from eap_peer_sm_init() call
+ * @id: Anonymous identity (e.g., EAP-SIM pseudonym) or %NULL to clear
+ * @len: Length of anonymous identity in octets
+ */
+ void (*set_anon_id)(void *ctx, const u8 *id, size_t len);
};
/**
@@ -251,6 +273,11 @@ struct eap_config {
* This is only used by EAP-WSC and can be left %NULL if not available.
*/
struct wps_context *wps;
+
+ /**
+ * cert_in_cb - Include server certificates in callback
+ */
+ int cert_in_cb;
};
struct eap_sm * eap_peer_sm_init(void *eapol_ctx,
@@ -261,6 +288,7 @@ int eap_peer_sm_step(struct eap_sm *sm);
void eap_sm_abort(struct eap_sm *sm);
int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen,
int verbose);
+const char * eap_sm_get_method_name(struct eap_sm *sm);
struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted);
void eap_sm_request_identity(struct eap_sm *sm);
void eap_sm_request_password(struct eap_sm *sm);
@@ -286,6 +314,10 @@ void eap_invalidate_cached_session(struct eap_sm *sm);
int eap_is_wps_pbc_enrollee(struct eap_peer_config *conf);
int eap_is_wps_pin_enrollee(struct eap_peer_config *conf);
+struct ext_password_data;
+void eap_sm_set_ext_pw_ctx(struct eap_sm *sm, struct ext_password_data *ext);
+void eap_set_anon_id(struct eap_sm *sm, const u8 *id, size_t len);
+
#endif /* IEEE8021X_EAPOL */
#endif /* EAP_H */
diff --git a/contrib/wpa/src/eap_peer/eap_aka.c b/contrib/wpa/src/eap_peer/eap_aka.c
index 182f01a..59861cb 100644
--- a/contrib/wpa/src/eap_peer/eap_aka.c
+++ b/contrib/wpa/src/eap_peer/eap_aka.c
@@ -1,15 +1,9 @@
/*
- * EAP peer method: EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf)
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * EAP peer method: EAP-AKA (RFC 4187) and EAP-AKA' (RFC 5448)
+ * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -96,6 +90,7 @@ static void * eap_aka_init(struct eap_sm *sm)
{
struct eap_aka_data *data;
const char *phase1 = eap_get_config_phase1(sm);
+ struct eap_peer_config *config = eap_get_config(sm);
data = os_zalloc(sizeof(*data));
if (data == NULL)
@@ -108,6 +103,15 @@ static void * eap_aka_init(struct eap_sm *sm)
data->result_ind = phase1 && os_strstr(phase1, "result_ind=1") != NULL;
+ if (config && config->anonymous_identity) {
+ data->pseudonym = os_malloc(config->anonymous_identity_len);
+ if (data->pseudonym) {
+ os_memcpy(data->pseudonym, config->anonymous_identity,
+ config->anonymous_identity_len);
+ data->pseudonym_len = config->anonymous_identity_len;
+ }
+ }
+
return data;
}
@@ -233,23 +237,24 @@ static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data)
#define CLEAR_REAUTH_ID 0x02
#define CLEAR_EAP_ID 0x04
-static void eap_aka_clear_identities(struct eap_aka_data *data, int id)
+static void eap_aka_clear_identities(struct eap_sm *sm,
+ struct eap_aka_data *data, int id)
{
- wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old%s%s%s",
- id & CLEAR_PSEUDONYM ? " pseudonym" : "",
- id & CLEAR_REAUTH_ID ? " reauth_id" : "",
- id & CLEAR_EAP_ID ? " eap_id" : "");
- if (id & CLEAR_PSEUDONYM) {
+ if ((id & CLEAR_PSEUDONYM) && data->pseudonym) {
+ wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old pseudonym");
os_free(data->pseudonym);
data->pseudonym = NULL;
data->pseudonym_len = 0;
+ eap_set_anon_id(sm, NULL, 0);
}
- if (id & CLEAR_REAUTH_ID) {
+ if ((id & CLEAR_REAUTH_ID) && data->reauth_id) {
+ wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old reauth_id");
os_free(data->reauth_id);
data->reauth_id = NULL;
data->reauth_id_len = 0;
}
- if (id & CLEAR_EAP_ID) {
+ if ((id & CLEAR_EAP_ID) && data->last_eap_identity) {
+ wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old eap_id");
os_free(data->last_eap_identity);
data->last_eap_identity = NULL;
data->last_eap_identity_len = 0;
@@ -257,24 +262,45 @@ static void eap_aka_clear_identities(struct eap_aka_data *data, int id)
}
-static int eap_aka_learn_ids(struct eap_aka_data *data,
+static int eap_aka_learn_ids(struct eap_sm *sm, struct eap_aka_data *data,
struct eap_sim_attrs *attr)
{
if (attr->next_pseudonym) {
+ const u8 *identity = NULL;
+ size_t identity_len = 0;
+ const u8 *realm = NULL;
+ size_t realm_len = 0;
+
+ wpa_hexdump_ascii(MSG_DEBUG,
+ "EAP-AKA: (encr) AT_NEXT_PSEUDONYM",
+ attr->next_pseudonym,
+ attr->next_pseudonym_len);
os_free(data->pseudonym);
- data->pseudonym = os_malloc(attr->next_pseudonym_len);
+ /* Look for the realm of the permanent identity */
+ identity = eap_get_config_identity(sm, &identity_len);
+ if (identity) {
+ for (realm = identity, realm_len = identity_len;
+ realm_len > 0; realm_len--, realm++) {
+ if (*realm == '@')
+ break;
+ }
+ }
+ data->pseudonym = os_malloc(attr->next_pseudonym_len +
+ realm_len);
if (data->pseudonym == NULL) {
wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
"next pseudonym");
+ data->pseudonym_len = 0;
return -1;
}
os_memcpy(data->pseudonym, attr->next_pseudonym,
attr->next_pseudonym_len);
- data->pseudonym_len = attr->next_pseudonym_len;
- wpa_hexdump_ascii(MSG_DEBUG,
- "EAP-AKA: (encr) AT_NEXT_PSEUDONYM",
- data->pseudonym,
- data->pseudonym_len);
+ if (realm_len) {
+ os_memcpy(data->pseudonym + attr->next_pseudonym_len,
+ realm, realm_len);
+ }
+ data->pseudonym_len = attr->next_pseudonym_len + realm_len;
+ eap_set_anon_id(sm, data->pseudonym, data->pseudonym_len);
}
if (attr->next_reauth_id) {
@@ -283,6 +309,7 @@ static int eap_aka_learn_ids(struct eap_aka_data *data,
if (data->reauth_id == NULL) {
wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for "
"next reauth_id");
+ data->reauth_id_len = 0;
return -1;
}
os_memcpy(data->reauth_id, attr->next_reauth_id,
@@ -411,6 +438,8 @@ static struct wpabuf * eap_aka_client_error(struct eap_aka_data *data, u8 id,
data->num_id_req = 0;
data->num_notification = 0;
+ wpa_printf(MSG_DEBUG, "EAP-AKA: Send Client-Error (error code %d)",
+ err);
msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
EAP_AKA_SUBTYPE_CLIENT_ERROR);
eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
@@ -472,16 +501,16 @@ static struct wpabuf * eap_aka_response_identity(struct eap_sm *sm,
data->pseudonym) {
identity = data->pseudonym;
identity_len = data->pseudonym_len;
- eap_aka_clear_identities(data, CLEAR_REAUTH_ID);
+ eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID);
} else if (id_req != NO_ID_REQ) {
identity = eap_get_config_identity(sm, &identity_len);
if (identity) {
- eap_aka_clear_identities(data, CLEAR_PSEUDONYM |
+ eap_aka_clear_identities(sm, data, CLEAR_PSEUDONYM |
CLEAR_REAUTH_ID);
}
}
if (id_req != NO_ID_REQ)
- eap_aka_clear_identities(data, CLEAR_EAP_ID);
+ eap_aka_clear_identities(sm, data, CLEAR_EAP_ID);
wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)", id);
msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method,
@@ -880,11 +909,11 @@ static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm,
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
}
- /* Old reauthentication and pseudonym identities must not be used
- * anymore. In other words, if no new identities are received, full
- * authentication will be used on next reauthentication. */
- eap_aka_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID |
- CLEAR_EAP_ID);
+ /* Old reauthentication identity must not be used anymore. In
+ * other words, if no new identities are received, full
+ * authentication will be used on next reauthentication (using
+ * pseudonym identity or permanent identity). */
+ eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
if (attr->encr_data) {
u8 *decrypted;
@@ -895,7 +924,7 @@ static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm,
return eap_aka_client_error(
data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET);
}
- eap_aka_learn_ids(data, &eattr);
+ eap_aka_learn_ids(sm, data, &eattr);
os_free(decrypted);
}
@@ -1112,8 +1141,8 @@ static struct wpabuf * eap_aka_process_reauthentication(
data->nonce_s, data->mk,
data->msk, data->emsk);
}
- eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
- eap_aka_learn_ids(data, &eattr);
+ eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
+ eap_aka_learn_ids(sm, data, &eattr);
if (data->result_ind && attr->result_ind)
data->use_result_ind = 1;
@@ -1128,7 +1157,8 @@ static struct wpabuf * eap_aka_process_reauthentication(
if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) {
wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of "
"fast reauths performed - force fullauth");
- eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
+ eap_aka_clear_identities(sm, data,
+ CLEAR_REAUTH_ID | CLEAR_EAP_ID);
}
os_free(decrypted);
return eap_aka_response_reauth(data, id, 0, data->nonce_s);
@@ -1246,7 +1276,7 @@ static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv)
static void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv)
{
struct eap_aka_data *data = priv;
- eap_aka_clear_identities(data, CLEAR_EAP_ID);
+ eap_aka_clear_identities(sm, data, CLEAR_EAP_ID);
data->prev_id = -1;
wpabuf_free(data->id_msgs);
data->id_msgs = NULL;
diff --git a/contrib/wpa/src/eap_peer/eap_config.h b/contrib/wpa/src/eap_peer/eap_config.h
index b64b68f..ed90919 100644
--- a/contrib/wpa/src/eap_peer/eap_config.h
+++ b/contrib/wpa/src/eap_peer/eap_config.h
@@ -2,14 +2,8 @@
* EAP peer configuration data
* Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef EAP_CONFIG_H
@@ -41,6 +35,9 @@ struct eap_peer_config {
*
* If not set, the identity field will be used for both unencrypted and
* protected fields.
+ *
+ * This field can also be used with EAP-SIM/AKA/AKA' to store the
+ * pseudonym identity.
*/
u8 *anonymous_identity;
@@ -625,6 +622,7 @@ struct eap_peer_config {
int fragment_size;
#define EAP_CONFIG_FLAGS_PASSWORD_NTHASH BIT(0)
+#define EAP_CONFIG_FLAGS_EXT_PASSWORD BIT(1)
/**
* flags - Network configuration flags (bitfield)
*
@@ -632,6 +630,8 @@ struct eap_peer_config {
* for the network parameters.
* bit 0 = password is represented as a 16-byte NtPasswordHash value
* instead of plaintext password
+ * bit 1 = password is stored in external storage; the value in the
+ * password field is the name of that external entry
*/
u32 flags;
};
diff --git a/contrib/wpa/src/eap_peer/eap_fast.c b/contrib/wpa/src/eap_peer/eap_fast.c
index 5d3e69d..7ca5288 100644
--- a/contrib/wpa/src/eap_peer/eap_fast.c
+++ b/contrib/wpa/src/eap_peer/eap_fast.c
@@ -2,14 +2,8 @@
* EAP peer method: EAP-FAST (RFC 4851)
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -175,7 +169,7 @@ static void * eap_fast_init(struct eap_sm *sm)
data->phase2_type.vendor = EAP_VENDOR_IETF;
data->phase2_type.method = EAP_TYPE_NONE;
- if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
+ if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_FAST)) {
wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize SSL.");
eap_fast_deinit(sm, data);
return NULL;
@@ -444,8 +438,9 @@ static int eap_fast_phase2_request(struct eap_sm *sm,
return 0;
}
- if (data->phase2_priv == NULL &&
- eap_fast_init_phase2_method(sm, data) < 0) {
+ if ((data->phase2_priv == NULL &&
+ eap_fast_init_phase2_method(sm, data) < 0) ||
+ data->phase2_method == NULL) {
wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize "
"Phase 2 EAP method %d", *pos);
ret->methodState = METHOD_DONE;
@@ -542,7 +537,7 @@ static struct wpabuf * eap_fast_tlv_pac_ack(void)
static struct wpabuf * eap_fast_process_eap_payload_tlv(
struct eap_sm *sm, struct eap_fast_data *data,
- struct eap_method_ret *ret, const struct eap_hdr *req,
+ struct eap_method_ret *ret,
u8 *eap_payload_tlv, size_t eap_payload_tlv_len)
{
struct eap_hdr *hdr;
@@ -1037,11 +1032,15 @@ static struct wpabuf * eap_fast_process_pac(struct eap_sm *sm,
} else {
/*
* This is PAC refreshing, i.e., normal authentication that is
- * expected to be completed with an EAP-Success.
+ * expected to be completed with an EAP-Success. However,
+ * RFC 5422, Section 3.5 allows EAP-Failure to be sent even
+ * after protected success exchange in case of EAP-Fast
+ * provisioning, so we better use DECISION_COND_SUCC here
+ * instead of DECISION_UNCOND_SUCC.
*/
wpa_printf(MSG_DEBUG, "EAP-FAST: Send PAC-Acknowledgement TLV "
"- PAC refreshing completed successfully");
- ret->decision = DECISION_UNCOND_SUCC;
+ ret->decision = DECISION_COND_SUCC;
}
ret->methodState = METHOD_DONE;
return eap_fast_tlv_pac_ack();
@@ -1184,7 +1183,7 @@ static int eap_fast_process_decrypted(struct eap_sm *sm,
if (tlv.eap_payload_tlv) {
tmp = eap_fast_process_eap_payload_tlv(
- sm, data, ret, req, tlv.eap_payload_tlv,
+ sm, data, ret, tlv.eap_payload_tlv,
tlv.eap_payload_tlv_len);
resp = wpabuf_concat(resp, tmp);
}
diff --git a/contrib/wpa/src/eap_peer/eap_fast_pac.c b/contrib/wpa/src/eap_peer/eap_fast_pac.c
index 541cce5..8c480b9 100644
--- a/contrib/wpa/src/eap_peer/eap_fast_pac.c
+++ b/contrib/wpa/src/eap_peer/eap_fast_pac.c
@@ -2,14 +2,8 @@
* EAP peer method: EAP-FAST PAC file processing
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -428,8 +422,12 @@ int eap_fast_load_pac(struct eap_sm *sm, struct eap_fast_pac **pac_root,
if (eap_fast_init_pac_data(sm, pac_file, &rc) < 0)
return 0;
- if (eap_fast_read_line(&rc, &pos) < 0 ||
- os_strcmp(pac_file_hdr, rc.buf) != 0)
+ if (eap_fast_read_line(&rc, &pos) < 0) {
+ /* empty file - assume it is fine to overwrite */
+ eap_fast_deinit_pac_data(&rc);
+ return 0;
+ }
+ if (os_strcmp(pac_file_hdr, rc.buf) != 0)
err = "Unrecognized header line";
while (!err && eap_fast_read_line(&rc, &pos) == 0) {
@@ -497,6 +495,7 @@ static void eap_fast_write(char **buf, char **pos, size_t *buf_len,
*buf = NULL;
return;
}
+ *pos = nbuf + (*pos - *buf);
*buf = nbuf;
*buf_len += need;
}
diff --git a/contrib/wpa/src/eap_peer/eap_fast_pac.h b/contrib/wpa/src/eap_peer/eap_fast_pac.h
index 9483f96..8815d91 100644
--- a/contrib/wpa/src/eap_peer/eap_fast_pac.h
+++ b/contrib/wpa/src/eap_peer/eap_fast_pac.h
@@ -2,14 +2,8 @@
* EAP peer method: EAP-FAST PAC file processing
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef EAP_FAST_PAC_H
diff --git a/contrib/wpa/src/eap_peer/eap_gpsk.c b/contrib/wpa/src/eap_peer/eap_gpsk.c
index f6a1955..2bd0d48 100644
--- a/contrib/wpa/src/eap_peer/eap_gpsk.c
+++ b/contrib/wpa/src/eap_peer/eap_gpsk.c
@@ -2,19 +2,14 @@
* EAP peer method: EAP-GPSK (RFC 5433)
* Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
#include "common.h"
+#include "crypto/random.h"
#include "eap_peer/eap_i.h"
#include "eap_common/eap_gpsk_common.h"
@@ -326,7 +321,7 @@ static struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data,
wpabuf_put_be16(resp, data->id_server_len);
wpabuf_put_data(resp, data->id_server, data->id_server_len);
- if (os_get_random(data->rand_peer, EAP_GPSK_RAND_LEN)) {
+ if (random_get_bytes(data->rand_peer, EAP_GPSK_RAND_LEN)) {
wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data "
"for RAND_Peer");
eap_gpsk_state(data, FAILURE);
diff --git a/contrib/wpa/src/eap_peer/eap_gtc.c b/contrib/wpa/src/eap_peer/eap_gtc.c
index b2b554b..9f3cfbd 100644
--- a/contrib/wpa/src/eap_peer/eap_gtc.c
+++ b/contrib/wpa/src/eap_peer/eap_gtc.c
@@ -2,14 +2,8 @@
* EAP peer method: EAP-GTC (RFC 3748)
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
diff --git a/contrib/wpa/src/eap_peer/eap_i.h b/contrib/wpa/src/eap_peer/eap_i.h
index e7c826e..dd94317 100644
--- a/contrib/wpa/src/eap_peer/eap_i.h
+++ b/contrib/wpa/src/eap_peer/eap_i.h
@@ -2,14 +2,8 @@
* EAP peer state machines internal structures (RFC 4137)
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef EAP_I_H
@@ -323,6 +317,7 @@ struct eap_sm {
void *msg_ctx;
void *scard_ctx;
void *ssl_ctx;
+ void *ssl_ctx2;
unsigned int workaround;
@@ -335,6 +330,9 @@ struct eap_sm {
struct wps_context *wps;
int prev_failure;
+
+ struct ext_password_data *ext_pw;
+ struct wpabuf *ext_pw_buf;
};
const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len);
@@ -345,6 +343,7 @@ const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len);
void eap_clear_config_otp(struct eap_sm *sm);
const char * eap_get_config_phase1(struct eap_sm *sm);
const char * eap_get_config_phase2(struct eap_sm *sm);
+int eap_get_config_fragment_size(struct eap_sm *sm);
struct eap_peer_config * eap_get_config(struct eap_sm *sm);
void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob);
const struct wpa_config_blob *
diff --git a/contrib/wpa/src/eap_peer/eap_ikev2.c b/contrib/wpa/src/eap_peer/eap_ikev2.c
index bb49a66..a227f8b 100644
--- a/contrib/wpa/src/eap_peer/eap_ikev2.c
+++ b/contrib/wpa/src/eap_peer/eap_ikev2.c
@@ -2,14 +2,8 @@
* EAP-IKEv2 peer (RFC 5106)
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
diff --git a/contrib/wpa/src/eap_peer/eap_leap.c b/contrib/wpa/src/eap_peer/eap_leap.c
index a7c94a4..df34013 100644
--- a/contrib/wpa/src/eap_peer/eap_leap.c
+++ b/contrib/wpa/src/eap_peer/eap_leap.c
@@ -2,14 +2,8 @@
* EAP peer method: LEAP
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -17,6 +11,7 @@
#include "common.h"
#include "crypto/ms_funcs.h"
#include "crypto/crypto.h"
+#include "crypto/random.h"
#include "eap_i.h"
#define LEAP_VERSION 1
@@ -167,7 +162,7 @@ static struct wpabuf * eap_leap_process_success(struct eap_sm *sm, void *priv,
wpabuf_put_u8(resp, 0); /* unused */
wpabuf_put_u8(resp, LEAP_CHALLENGE_LEN);
pos = wpabuf_put(resp, LEAP_CHALLENGE_LEN);
- if (os_get_random(pos, LEAP_CHALLENGE_LEN)) {
+ if (random_get_bytes(pos, LEAP_CHALLENGE_LEN)) {
wpa_printf(MSG_WARNING, "EAP-LEAP: Failed to read random data "
"for challenge");
wpabuf_free(resp);
diff --git a/contrib/wpa/src/eap_peer/eap_md5.c b/contrib/wpa/src/eap_peer/eap_md5.c
index 0edbae8..d06befa 100644
--- a/contrib/wpa/src/eap_peer/eap_md5.c
+++ b/contrib/wpa/src/eap_peer/eap_md5.c
@@ -1,15 +1,9 @@
/*
* EAP peer method: EAP-MD5 (RFC 3748 and RFC 1994)
- * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -92,7 +86,13 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv,
id = eap_get_id(resp);
rpos = wpabuf_put(resp, CHAP_MD5_LEN);
- chap_md5(id, password, password_len, challenge, challenge_len, rpos);
+ if (chap_md5(id, password, password_len, challenge, challenge_len,
+ rpos)) {
+ wpa_printf(MSG_INFO, "EAP-MD5: CHAP MD5 operation failed");
+ ret->ignore = TRUE;
+ wpabuf_free(resp);
+ return NULL;
+ }
wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, CHAP_MD5_LEN);
return resp;
diff --git a/contrib/wpa/src/eap_peer/eap_methods.c b/contrib/wpa/src/eap_peer/eap_methods.c
index 3b0af05..83a1457 100644
--- a/contrib/wpa/src/eap_peer/eap_methods.c
+++ b/contrib/wpa/src/eap_peer/eap_methods.c
@@ -2,14 +2,8 @@
* EAP peer: Method registration
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -77,6 +71,8 @@ EapType eap_peer_get_type(const char *name, int *vendor)
const char * eap_get_name(int vendor, EapType type)
{
struct eap_method *m;
+ if (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_EXPANDED)
+ return "expanded";
for (m = eap_methods; m; m = m->next) {
if (m->vendor == vendor && m->method == type)
return m->name;
diff --git a/contrib/wpa/src/eap_peer/eap_methods.h b/contrib/wpa/src/eap_peer/eap_methods.h
index 384c61b..4994ff1 100644
--- a/contrib/wpa/src/eap_peer/eap_methods.h
+++ b/contrib/wpa/src/eap_peer/eap_methods.h
@@ -2,14 +2,8 @@
* EAP peer: Method registration
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef EAP_METHODS_H
@@ -91,6 +85,7 @@ static inline int eap_peer_method_unload(struct eap_method *method)
/* EAP peer method registration calls for statically linked in methods */
int eap_peer_md5_register(void);
int eap_peer_tls_register(void);
+int eap_peer_unauth_tls_register(void);
int eap_peer_mschapv2_register(void);
int eap_peer_peap_register(void);
int eap_peer_ttls_register(void);
@@ -109,5 +104,6 @@ int eap_peer_wsc_register(void);
int eap_peer_ikev2_register(void);
int eap_peer_vendor_test_register(void);
int eap_peer_tnc_register(void);
+int eap_peer_pwd_register(void);
#endif /* EAP_METHODS_H */
diff --git a/contrib/wpa/src/eap_peer/eap_mschapv2.c b/contrib/wpa/src/eap_peer/eap_mschapv2.c
index cd410d9..fb6c282 100644
--- a/contrib/wpa/src/eap_peer/eap_mschapv2.c
+++ b/contrib/wpa/src/eap_peer/eap_mschapv2.c
@@ -2,14 +2,8 @@
* EAP peer method: EAP-MSCHAPV2 (draft-kamath-pppext-eap-mschapv2-00.txt)
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*
* This file implements EAP peer part of EAP-MSCHAPV2 method (EAP type 26).
* draft-kamath-pppext-eap-mschapv2-00.txt defines the Microsoft EAP CHAP
@@ -23,6 +17,7 @@
#include "common.h"
#include "crypto/ms_funcs.h"
+#include "crypto/random.h"
#include "common/wpa_ctrl.h"
#include "mschapv2.h"
#include "eap_i.h"
@@ -199,7 +194,7 @@ static struct wpabuf * eap_mschapv2_challenge_reply(
"in Phase 1");
peer_challenge = data->peer_challenge;
os_memset(r->peer_challenge, 0, MSCHAPV2_CHAL_LEN);
- } else if (os_get_random(peer_challenge, MSCHAPV2_CHAL_LEN)) {
+ } else if (random_get_bytes(peer_challenge, MSCHAPV2_CHAL_LEN)) {
wpabuf_free(resp);
return NULL;
}
@@ -309,7 +304,9 @@ static void eap_mschapv2_password_changed(struct eap_sm *sm,
"EAP-MSCHAPV2: Password changed successfully");
data->prev_error = 0;
os_free(config->password);
- if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) {
+ if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
+ /* TODO: update external storage */
+ } else if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) {
config->password = os_malloc(16);
config->password_len = 16;
if (config->password) {
@@ -564,7 +561,7 @@ static struct wpabuf * eap_mschapv2_change_password(
}
/* Peer-Challenge */
- if (os_get_random(cp->peer_challenge, MSCHAPV2_CHAL_LEN))
+ if (random_get_bytes(cp->peer_challenge, MSCHAPV2_CHAL_LEN))
goto fail;
/* Reserved, must be zero */
diff --git a/contrib/wpa/src/eap_peer/eap_otp.c b/contrib/wpa/src/eap_peer/eap_otp.c
index 556c22f..9ac744a 100644
--- a/contrib/wpa/src/eap_peer/eap_otp.c
+++ b/contrib/wpa/src/eap_peer/eap_otp.c
@@ -2,14 +2,8 @@
* EAP peer method: EAP-OTP (RFC 3748)
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
diff --git a/contrib/wpa/src/eap_peer/eap_pax.c b/contrib/wpa/src/eap_peer/eap_pax.c
index 2e04831..7f87052 100644
--- a/contrib/wpa/src/eap_peer/eap_pax.c
+++ b/contrib/wpa/src/eap_peer/eap_pax.c
@@ -2,19 +2,14 @@
* EAP peer method: EAP-PAX (RFC 4746)
* Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
#include "common.h"
+#include "crypto/random.h"
#include "eap_common/eap_pax_common.h"
#include "eap_i.h"
@@ -174,7 +169,7 @@ static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data,
pos, left);
}
- if (os_get_random(data->rand.r.y, EAP_PAX_RAND_LEN)) {
+ if (random_get_bytes(data->rand.r.y, EAP_PAX_RAND_LEN)) {
wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data");
ret->ignore = TRUE;
return NULL;
diff --git a/contrib/wpa/src/eap_peer/eap_peap.c b/contrib/wpa/src/eap_peer/eap_peap.c
index 2b72084..7fff145 100644
--- a/contrib/wpa/src/eap_peer/eap_peap.c
+++ b/contrib/wpa/src/eap_peer/eap_peap.c
@@ -2,14 +2,8 @@
* EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -165,7 +159,7 @@ static void * eap_peap_init(struct eap_sm *sm)
data->phase2_type.vendor = EAP_VENDOR_IETF;
data->phase2_type.method = EAP_TYPE_NONE;
- if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
+ if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_PEAP)) {
wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
eap_peap_deinit(sm, data);
return NULL;
@@ -196,7 +190,7 @@ static void eap_peap_deinit(struct eap_sm *sm, void *priv)
* @nak_type: TLV type (EAP_TLV_*)
* Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure
*
- * This funtion builds an EAP-TLV NAK message. The caller is responsible for
+ * This function builds an EAP-TLV NAK message. The caller is responsible for
* freeing the returned buffer.
*/
static struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type)
@@ -285,8 +279,10 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
* in the end of the label just before ISK; is that just a typo?)
*/
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
- peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys",
- isk, sizeof(isk), imck, sizeof(imck));
+ if (peap_prfplus(data->peap_version, tk, 40,
+ "Inner Methods Compound Keys",
+ isk, sizeof(isk), imck, sizeof(imck)) < 0)
+ return -1;
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
imck, sizeof(imck));
@@ -346,8 +342,8 @@ static int eap_tlv_add_cryptobinding(struct eap_sm *sm,
* @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE)
* Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure
*
- * This funtion builds an EAP-TLV Result message. The caller is responsible for
- * freeing the returned buffer.
+ * This function builds an EAP-TLV Result message. The caller is responsible
+ * for freeing the returned buffer.
*/
static struct wpabuf * eap_tlv_build_result(struct eap_sm *sm,
struct eap_peap_data *data,
@@ -1247,9 +1243,12 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
* termination for this label while the one used for deriving
* IPMK|CMK did not use null termination.
*/
- peap_prfplus(data->peap_version, data->ipmk, 40,
- "Session Key Generating Function",
- (u8 *) "\00", 1, csk, sizeof(csk));
+ if (peap_prfplus(data->peap_version, data->ipmk, 40,
+ "Session Key Generating Function",
+ (u8 *) "\00", 1, csk, sizeof(csk)) < 0) {
+ os_free(key);
+ return NULL;
+ }
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
os_memcpy(key, csk, EAP_TLS_KEY_LEN);
wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
diff --git a/contrib/wpa/src/eap_peer/eap_psk.c b/contrib/wpa/src/eap_peer/eap_psk.c
index ccf871e..d618fcf 100644
--- a/contrib/wpa/src/eap_peer/eap_psk.c
+++ b/contrib/wpa/src/eap_peer/eap_psk.c
@@ -2,14 +2,8 @@
* EAP peer method: EAP-PSK (RFC 4764)
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*
* Note: EAP-PSK is an EAP authentication method and as such, completely
* different from WPA-PSK. This file is not needed for WPA-PSK functionality.
@@ -19,6 +13,7 @@
#include "common.h"
#include "crypto/aes_wrap.h"
+#include "crypto/random.h"
#include "eap_common/eap_psk_common.h"
#include "eap_i.h"
@@ -130,7 +125,7 @@ static struct wpabuf * eap_psk_process_1(struct eap_psk_data *data,
wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S",
data->id_s, data->id_s_len);
- if (os_get_random(data->rand_p, EAP_PSK_RAND_LEN)) {
+ if (random_get_bytes(data->rand_p, EAP_PSK_RAND_LEN)) {
wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data");
ret->ignore = TRUE;
return NULL;
diff --git a/contrib/wpa/src/eap_peer/eap_pwd.c b/contrib/wpa/src/eap_peer/eap_pwd.c
new file mode 100644
index 0000000..267d0a5
--- /dev/null
+++ b/contrib/wpa/src/eap_peer/eap_pwd.c
@@ -0,0 +1,922 @@
+/*
+ * EAP peer method: EAP-pwd (RFC 5931)
+ * Copyright (c) 2010, Dan Harkins <dharkins@lounge.org>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "crypto/sha256.h"
+#include "eap_peer/eap_i.h"
+#include "eap_common/eap_pwd_common.h"
+
+
+struct eap_pwd_data {
+ enum {
+ PWD_ID_Req, PWD_Commit_Req, PWD_Confirm_Req, SUCCESS, FAILURE
+ } state;
+ u8 *id_peer;
+ size_t id_peer_len;
+ u8 *id_server;
+ size_t id_server_len;
+ u8 *password;
+ size_t password_len;
+ u16 group_num;
+ EAP_PWD_group *grp;
+
+ struct wpabuf *inbuf;
+ size_t in_frag_pos;
+ struct wpabuf *outbuf;
+ size_t out_frag_pos;
+ size_t mtu;
+
+ BIGNUM *k;
+ BIGNUM *private_value;
+ BIGNUM *server_scalar;
+ BIGNUM *my_scalar;
+ EC_POINT *my_element;
+ EC_POINT *server_element;
+
+ u8 msk[EAP_MSK_LEN];
+ u8 emsk[EAP_EMSK_LEN];
+
+ BN_CTX *bnctx;
+};
+
+
+#ifndef CONFIG_NO_STDOUT_DEBUG
+static const char * eap_pwd_state_txt(int state)
+{
+ switch (state) {
+ case PWD_ID_Req:
+ return "PWD-ID-Req";
+ case PWD_Commit_Req:
+ return "PWD-Commit-Req";
+ case PWD_Confirm_Req:
+ return "PWD-Confirm-Req";
+ case SUCCESS:
+ return "SUCCESS";
+ case FAILURE:
+ return "FAILURE";
+ default:
+ return "PWD-UNK";
+ }
+}
+#endif /* CONFIG_NO_STDOUT_DEBUG */
+
+
+static void eap_pwd_state(struct eap_pwd_data *data, int state)
+{
+ wpa_printf(MSG_DEBUG, "EAP-PWD: %s -> %s",
+ eap_pwd_state_txt(data->state), eap_pwd_state_txt(state));
+ data->state = state;
+}
+
+
+static void * eap_pwd_init(struct eap_sm *sm)
+{
+ struct eap_pwd_data *data;
+ const u8 *identity, *password;
+ size_t identity_len, password_len;
+
+ password = eap_get_config_password(sm, &password_len);
+ if (password == NULL) {
+ wpa_printf(MSG_INFO, "EAP-PWD: No password configured!");
+ return NULL;
+ }
+
+ identity = eap_get_config_identity(sm, &identity_len);
+ if (identity == NULL) {
+ wpa_printf(MSG_INFO, "EAP-PWD: No identity configured!");
+ return NULL;
+ }
+
+ if ((data = os_zalloc(sizeof(*data))) == NULL) {
+ wpa_printf(MSG_INFO, "EAP-PWD: memory allocation data fail");
+ return NULL;
+ }
+
+ if ((data->bnctx = BN_CTX_new()) == NULL) {
+ wpa_printf(MSG_INFO, "EAP-PWD: bn context allocation fail");
+ os_free(data);
+ return NULL;
+ }
+
+ if ((data->id_peer = os_malloc(identity_len)) == NULL) {
+ wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail");
+ BN_CTX_free(data->bnctx);
+ os_free(data);
+ return NULL;
+ }
+
+ os_memcpy(data->id_peer, identity, identity_len);
+ data->id_peer_len = identity_len;
+
+ if ((data->password = os_malloc(password_len)) == NULL) {
+ wpa_printf(MSG_INFO, "EAP-PWD: memory allocation psk fail");
+ BN_CTX_free(data->bnctx);
+ os_free(data->id_peer);
+ os_free(data);
+ return NULL;
+ }
+ os_memcpy(data->password, password, password_len);
+ data->password_len = password_len;
+
+ data->out_frag_pos = data->in_frag_pos = 0;
+ data->inbuf = data->outbuf = NULL;
+ data->mtu = 1020; /* default from RFC 5931, make it configurable! */
+
+ data->state = PWD_ID_Req;
+
+ return data;
+}
+
+
+static void eap_pwd_deinit(struct eap_sm *sm, void *priv)
+{
+ struct eap_pwd_data *data = priv;
+
+ BN_free(data->private_value);
+ BN_free(data->server_scalar);
+ BN_free(data->my_scalar);
+ BN_free(data->k);
+ BN_CTX_free(data->bnctx);
+ EC_POINT_free(data->my_element);
+ EC_POINT_free(data->server_element);
+ os_free(data->id_peer);
+ os_free(data->id_server);
+ os_free(data->password);
+ if (data->grp) {
+ EC_GROUP_free(data->grp->group);
+ EC_POINT_free(data->grp->pwe);
+ BN_free(data->grp->order);
+ BN_free(data->grp->prime);
+ os_free(data->grp);
+ }
+ os_free(data);
+}
+
+
+static u8 * eap_pwd_getkey(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_pwd_data *data = priv;
+ u8 *key;
+
+ if (data->state != SUCCESS)
+ return NULL;
+
+ key = os_malloc(EAP_MSK_LEN);
+ if (key == NULL)
+ return NULL;
+
+ os_memcpy(key, data->msk, EAP_MSK_LEN);
+ *len = EAP_MSK_LEN;
+
+ return key;
+}
+
+
+static void
+eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
+ struct eap_method_ret *ret,
+ const struct wpabuf *reqData,
+ const u8 *payload, size_t payload_len)
+{
+ struct eap_pwd_id *id;
+
+ if (data->state != PWD_ID_Req) {
+ ret->ignore = TRUE;
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+
+ if (payload_len < sizeof(struct eap_pwd_id)) {
+ ret->ignore = TRUE;
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+
+ id = (struct eap_pwd_id *) payload;
+ data->group_num = be_to_host16(id->group_num);
+ if ((id->random_function != EAP_PWD_DEFAULT_RAND_FUNC) ||
+ (id->prf != EAP_PWD_DEFAULT_PRF)) {
+ ret->ignore = TRUE;
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-PWD (peer): using group %d",
+ data->group_num);
+
+ data->id_server = os_malloc(payload_len - sizeof(struct eap_pwd_id));
+ if (data->id_server == NULL) {
+ wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail");
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+ data->id_server_len = payload_len - sizeof(struct eap_pwd_id);
+ os_memcpy(data->id_server, id->identity, data->id_server_len);
+ wpa_hexdump_ascii(MSG_INFO, "EAP-PWD (peer): server sent id of",
+ data->id_server, data->id_server_len);
+
+ if ((data->grp = (EAP_PWD_group *) os_malloc(sizeof(EAP_PWD_group))) ==
+ NULL) {
+ wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for "
+ "group");
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+
+ /* compute PWE */
+ if (compute_password_element(data->grp, data->group_num,
+ data->password, data->password_len,
+ data->id_server, data->id_server_len,
+ data->id_peer, data->id_peer_len,
+ id->token)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute PWE");
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-PWD (peer): computed %d bit PWE...",
+ BN_num_bits(data->grp->prime));
+
+ data->outbuf = wpabuf_alloc(sizeof(struct eap_pwd_id) +
+ data->id_peer_len);
+ if (data->outbuf == NULL) {
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+ wpabuf_put_be16(data->outbuf, data->group_num);
+ wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_RAND_FUNC);
+ wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_PRF);
+ wpabuf_put_data(data->outbuf, id->token, sizeof(id->token));
+ wpabuf_put_u8(data->outbuf, EAP_PWD_PREP_NONE);
+ wpabuf_put_data(data->outbuf, data->id_peer, data->id_peer_len);
+
+ eap_pwd_state(data, PWD_Commit_Req);
+}
+
+
+static void
+eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
+ struct eap_method_ret *ret,
+ const struct wpabuf *reqData,
+ const u8 *payload, size_t payload_len)
+{
+ EC_POINT *K = NULL, *point = NULL;
+ BIGNUM *mask = NULL, *x = NULL, *y = NULL, *cofactor = NULL;
+ u16 offset;
+ u8 *ptr, *scalar = NULL, *element = NULL;
+
+ if (((data->private_value = BN_new()) == NULL) ||
+ ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) ||
+ ((cofactor = BN_new()) == NULL) ||
+ ((data->my_scalar = BN_new()) == NULL) ||
+ ((mask = BN_new()) == NULL)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): scalar allocation fail");
+ goto fin;
+ }
+
+ if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) {
+ wpa_printf(MSG_INFO, "EAP-pwd (peer): unable to get cofactor "
+ "for curve");
+ goto fin;
+ }
+
+ BN_rand_range(data->private_value, data->grp->order);
+ BN_rand_range(mask, data->grp->order);
+ BN_add(data->my_scalar, data->private_value, mask);
+ BN_mod(data->my_scalar, data->my_scalar, data->grp->order,
+ data->bnctx);
+
+ if (!EC_POINT_mul(data->grp->group, data->my_element, NULL,
+ data->grp->pwe, mask, data->bnctx)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): element allocation "
+ "fail");
+ eap_pwd_state(data, FAILURE);
+ goto fin;
+ }
+
+ if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx))
+ {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail");
+ goto fin;
+ }
+ BN_free(mask);
+
+ if (((x = BN_new()) == NULL) ||
+ ((y = BN_new()) == NULL)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): point allocation fail");
+ goto fin;
+ }
+
+ /* process the request */
+ if (((data->server_scalar = BN_new()) == NULL) ||
+ ((data->k = BN_new()) == NULL) ||
+ ((K = EC_POINT_new(data->grp->group)) == NULL) ||
+ ((point = EC_POINT_new(data->grp->group)) == NULL) ||
+ ((data->server_element = EC_POINT_new(data->grp->group)) == NULL))
+ {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): peer data allocation "
+ "fail");
+ goto fin;
+ }
+
+ /* element, x then y, followed by scalar */
+ ptr = (u8 *) payload;
+ BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x);
+ ptr += BN_num_bytes(data->grp->prime);
+ BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y);
+ ptr += BN_num_bytes(data->grp->prime);
+ BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->server_scalar);
+ if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group,
+ data->server_element, x, y,
+ data->bnctx)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): setting peer element "
+ "fail");
+ goto fin;
+ }
+
+ /* check to ensure server's element is not in a small sub-group */
+ if (BN_cmp(cofactor, BN_value_one())) {
+ if (!EC_POINT_mul(data->grp->group, point, NULL,
+ data->server_element, cofactor, NULL)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "
+ "server element by order!\n");
+ goto fin;
+ }
+ if (EC_POINT_is_at_infinity(data->grp->group, point)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): server element "
+ "is at infinity!\n");
+ goto fin;
+ }
+ }
+
+ /* compute the shared key, k */
+ if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe,
+ data->server_scalar, data->bnctx)) ||
+ (!EC_POINT_add(data->grp->group, K, K, data->server_element,
+ data->bnctx)) ||
+ (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value,
+ data->bnctx))) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): computing shared key "
+ "fail");
+ goto fin;
+ }
+
+ /* ensure that the shared key isn't in a small sub-group */
+ if (BN_cmp(cofactor, BN_value_one())) {
+ if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor,
+ NULL)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply "
+ "shared key point by order");
+ goto fin;
+ }
+ }
+
+ /*
+ * This check is strictly speaking just for the case above where
+ * co-factor > 1 but it was suggested that even though this is probably
+ * never going to happen it is a simple and safe check "just to be
+ * sure" so let's be safe.
+ */
+ if (EC_POINT_is_at_infinity(data->grp->group, K)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): shared key point is at "
+ "infinity!\n");
+ goto fin;
+ }
+
+ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k,
+ NULL, data->bnctx)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to extract "
+ "shared secret from point");
+ goto fin;
+ }
+
+ /* now do the response */
+ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
+ data->my_element, x, y,
+ data->bnctx)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): point assignment fail");
+ goto fin;
+ }
+
+ if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) ||
+ ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) ==
+ NULL)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): data allocation fail");
+ goto fin;
+ }
+
+ /*
+ * bignums occupy as little memory as possible so one that is
+ * sufficiently smaller than the prime or order might need pre-pending
+ * with zeros.
+ */
+ os_memset(scalar, 0, BN_num_bytes(data->grp->order));
+ os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2);
+ offset = BN_num_bytes(data->grp->order) -
+ BN_num_bytes(data->my_scalar);
+ BN_bn2bin(data->my_scalar, scalar + offset);
+
+ offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
+ BN_bn2bin(x, element + offset);
+ offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
+ BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset);
+
+ data->outbuf = wpabuf_alloc(BN_num_bytes(data->grp->order) +
+ 2 * BN_num_bytes(data->grp->prime));
+ if (data->outbuf == NULL)
+ goto fin;
+
+ /* we send the element as (x,y) follwed by the scalar */
+ wpabuf_put_data(data->outbuf, element,
+ 2 * BN_num_bytes(data->grp->prime));
+ wpabuf_put_data(data->outbuf, scalar, BN_num_bytes(data->grp->order));
+
+fin:
+ os_free(scalar);
+ os_free(element);
+ BN_free(x);
+ BN_free(y);
+ BN_free(cofactor);
+ EC_POINT_free(K);
+ EC_POINT_free(point);
+ if (data->outbuf == NULL)
+ eap_pwd_state(data, FAILURE);
+ else
+ eap_pwd_state(data, PWD_Confirm_Req);
+}
+
+
+static void
+eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
+ struct eap_method_ret *ret,
+ const struct wpabuf *reqData,
+ const u8 *payload, size_t payload_len)
+{
+ BIGNUM *x = NULL, *y = NULL;
+ struct crypto_hash *hash;
+ u32 cs;
+ u16 grp;
+ u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
+ int offset;
+
+ /*
+ * first build up the ciphersuite which is group | random_function |
+ * prf
+ */
+ grp = htons(data->group_num);
+ ptr = (u8 *) &cs;
+ os_memcpy(ptr, &grp, sizeof(u16));
+ ptr += sizeof(u16);
+ *ptr = EAP_PWD_DEFAULT_RAND_FUNC;
+ ptr += sizeof(u8);
+ *ptr = EAP_PWD_DEFAULT_PRF;
+
+ /* each component of the cruft will be at most as big as the prime */
+ if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) ||
+ ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (server): confirm allocation "
+ "fail");
+ goto fin;
+ }
+
+ /*
+ * server's commit is H(k | server_element | server_scalar |
+ * peer_element | peer_scalar | ciphersuite)
+ */
+ hash = eap_pwd_h_init();
+ if (hash == NULL)
+ goto fin;
+
+ /*
+ * zero the memory each time because this is mod prime math and some
+ * value may start with a few zeros and the previous one did not.
+ */
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);
+ BN_bn2bin(data->k, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
+
+ /* server element: x, y */
+ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
+ data->server_element, x, y,
+ data->bnctx)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
+ "assignment fail");
+ goto fin;
+ }
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
+ BN_bn2bin(x, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
+ BN_bn2bin(y, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
+
+ /* server scalar */
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->order) -
+ BN_num_bytes(data->server_scalar);
+ BN_bn2bin(data->server_scalar, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
+
+ /* my element: x, y */
+ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
+ data->my_element, x, y,
+ data->bnctx)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point "
+ "assignment fail");
+ goto fin;
+ }
+
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
+ BN_bn2bin(x, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
+ BN_bn2bin(y, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
+
+ /* my scalar */
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->order) -
+ BN_num_bytes(data->my_scalar);
+ BN_bn2bin(data->my_scalar, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
+
+ /* the ciphersuite */
+ eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));
+
+ /* random function fin */
+ eap_pwd_h_final(hash, conf);
+
+ ptr = (u8 *) payload;
+ if (os_memcmp(conf, ptr, SHA256_MAC_LEN)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm did not verify");
+ goto fin;
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-pwd (peer): confirm verified");
+
+ /*
+ * compute confirm:
+ * H(k | peer_element | peer_scalar | server_element | server_scalar |
+ * ciphersuite)
+ */
+ hash = eap_pwd_h_init();
+ if (hash == NULL)
+ goto fin;
+
+ /* k */
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(data->k);
+ BN_bn2bin(data->k, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
+
+ /* my element */
+ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
+ data->my_element, x, y,
+ data->bnctx)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point "
+ "assignment fail");
+ goto fin;
+ }
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
+ BN_bn2bin(x, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
+ BN_bn2bin(y, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
+
+ /* my scalar */
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->order) -
+ BN_num_bytes(data->my_scalar);
+ BN_bn2bin(data->my_scalar, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
+
+ /* server element: x, y */
+ if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group,
+ data->server_element, x, y,
+ data->bnctx)) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point "
+ "assignment fail");
+ goto fin;
+ }
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x);
+ BN_bn2bin(x, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y);
+ BN_bn2bin(y, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->prime));
+
+ /* server scalar */
+ os_memset(cruft, 0, BN_num_bytes(data->grp->prime));
+ offset = BN_num_bytes(data->grp->order) -
+ BN_num_bytes(data->server_scalar);
+ BN_bn2bin(data->server_scalar, cruft + offset);
+ eap_pwd_h_update(hash, cruft, BN_num_bytes(data->grp->order));
+
+ /* the ciphersuite */
+ eap_pwd_h_update(hash, (u8 *) &cs, sizeof(u32));
+
+ /* all done */
+ eap_pwd_h_final(hash, conf);
+
+ if (compute_keys(data->grp, data->bnctx, data->k,
+ data->my_scalar, data->server_scalar, conf, ptr,
+ &cs, data->msk, data->emsk) < 0) {
+ wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute MSK | "
+ "EMSK");
+ goto fin;
+ }
+
+ data->outbuf = wpabuf_alloc(SHA256_MAC_LEN);
+ if (data->outbuf == NULL)
+ goto fin;
+
+ wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN);
+
+fin:
+ os_free(cruft);
+ BN_free(x);
+ BN_free(y);
+ ret->methodState = METHOD_DONE;
+ if (data->outbuf == NULL) {
+ ret->decision = DECISION_FAIL;
+ eap_pwd_state(data, FAILURE);
+ } else {
+ ret->decision = DECISION_UNCOND_SUCC;
+ eap_pwd_state(data, SUCCESS);
+ }
+}
+
+
+static struct wpabuf *
+eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret,
+ const struct wpabuf *reqData)
+{
+ struct eap_pwd_data *data = priv;
+ struct wpabuf *resp = NULL;
+ const u8 *pos, *buf;
+ size_t len;
+ u16 tot_len = 0;
+ u8 lm_exch;
+
+ pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PWD, reqData, &len);
+ if ((pos == NULL) || (len < 1)) {
+ wpa_printf(MSG_DEBUG, "EAP-pwd: Got a frame but pos is %s and "
+ "len is %d",
+ pos == NULL ? "NULL" : "not NULL", (int) len);
+ ret->ignore = TRUE;
+ return NULL;
+ }
+
+ ret->ignore = FALSE;
+ ret->methodState = METHOD_MAY_CONT;
+ ret->decision = DECISION_FAIL;
+ ret->allowNotifications = FALSE;
+
+ lm_exch = *pos;
+ pos++; /* skip over the bits and the exch */
+ len--;
+
+ /*
+ * we're fragmenting so send out the next fragment
+ */
+ if (data->out_frag_pos) {
+ /*
+ * this should be an ACK
+ */
+ if (len)
+ wpa_printf(MSG_INFO, "Bad Response! Fragmenting but "
+ "not an ACK");
+
+ wpa_printf(MSG_DEBUG, "EAP-pwd: Got an ACK for a fragment");
+ /*
+ * check if there are going to be more fragments
+ */
+ len = wpabuf_len(data->outbuf) - data->out_frag_pos;
+ if ((len + EAP_PWD_HDR_SIZE) > data->mtu) {
+ len = data->mtu - EAP_PWD_HDR_SIZE;
+ EAP_PWD_SET_MORE_BIT(lm_exch);
+ }
+ resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
+ EAP_PWD_HDR_SIZE + len,
+ EAP_CODE_RESPONSE, eap_get_id(reqData));
+ if (resp == NULL) {
+ wpa_printf(MSG_INFO, "Unable to allocate memory for "
+ "next fragment!");
+ return NULL;
+ }
+ wpabuf_put_u8(resp, lm_exch);
+ buf = wpabuf_head_u8(data->outbuf);
+ wpabuf_put_data(resp, buf + data->out_frag_pos, len);
+ data->out_frag_pos += len;
+ /*
+ * this is the last fragment so get rid of the out buffer
+ */
+ if (data->out_frag_pos >= wpabuf_len(data->outbuf)) {
+ wpabuf_free(data->outbuf);
+ data->outbuf = NULL;
+ data->out_frag_pos = 0;
+ }
+ wpa_printf(MSG_DEBUG, "EAP-pwd: Send %s fragment of %d bytes",
+ data->out_frag_pos == 0 ? "last" : "next",
+ (int) len);
+ return resp;
+ }
+
+ /*
+ * see if this is a fragment that needs buffering
+ *
+ * if it's the first fragment there'll be a length field
+ */
+ if (EAP_PWD_GET_LENGTH_BIT(lm_exch)) {
+ tot_len = WPA_GET_BE16(pos);
+ wpa_printf(MSG_DEBUG, "EAP-pwd: Incoming fragments whose "
+ "total length = %d", tot_len);
+ data->inbuf = wpabuf_alloc(tot_len);
+ if (data->inbuf == NULL) {
+ wpa_printf(MSG_INFO, "Out of memory to buffer "
+ "fragments!");
+ return NULL;
+ }
+ pos += sizeof(u16);
+ len -= sizeof(u16);
+ }
+ /*
+ * buffer and ACK the fragment
+ */
+ if (EAP_PWD_GET_MORE_BIT(lm_exch)) {
+ data->in_frag_pos += len;
+ if (data->in_frag_pos > wpabuf_size(data->inbuf)) {
+ wpa_printf(MSG_INFO, "EAP-pwd: Buffer overflow attack "
+ "detected (%d vs. %d)!",
+ (int) data->in_frag_pos,
+ (int) wpabuf_len(data->inbuf));
+ wpabuf_free(data->inbuf);
+ data->in_frag_pos = 0;
+ return NULL;
+ }
+ wpabuf_put_data(data->inbuf, pos, len);
+
+ resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
+ EAP_PWD_HDR_SIZE,
+ EAP_CODE_RESPONSE, eap_get_id(reqData));
+ if (resp != NULL)
+ wpabuf_put_u8(resp, (EAP_PWD_GET_EXCHANGE(lm_exch)));
+ wpa_printf(MSG_DEBUG, "EAP-pwd: ACKing a %d byte fragment",
+ (int) len);
+ return resp;
+ }
+ /*
+ * we're buffering and this is the last fragment
+ */
+ if (data->in_frag_pos) {
+ wpabuf_put_data(data->inbuf, pos, len);
+ wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
+ (int) len);
+ data->in_frag_pos += len;
+ pos = wpabuf_head_u8(data->inbuf);
+ len = data->in_frag_pos;
+ }
+ wpa_printf(MSG_DEBUG, "EAP-pwd: processing frame: exch %d, len %d",
+ EAP_PWD_GET_EXCHANGE(lm_exch), (int) len);
+
+ switch (EAP_PWD_GET_EXCHANGE(lm_exch)) {
+ case EAP_PWD_OPCODE_ID_EXCH:
+ eap_pwd_perform_id_exchange(sm, data, ret, reqData,
+ pos, len);
+ break;
+ case EAP_PWD_OPCODE_COMMIT_EXCH:
+ eap_pwd_perform_commit_exchange(sm, data, ret, reqData,
+ pos, len);
+ break;
+ case EAP_PWD_OPCODE_CONFIRM_EXCH:
+ eap_pwd_perform_confirm_exchange(sm, data, ret, reqData,
+ pos, len);
+ break;
+ default:
+ wpa_printf(MSG_INFO, "EAP-pwd: Ignoring message with unknown "
+ "opcode %d", lm_exch);
+ break;
+ }
+ /*
+ * if we buffered the just processed input now's the time to free it
+ */
+ if (data->in_frag_pos) {
+ wpabuf_free(data->inbuf);
+ data->in_frag_pos = 0;
+ }
+
+ if (data->outbuf == NULL)
+ return NULL; /* generic failure */
+
+ /*
+ * we have output! Do we need to fragment it?
+ */
+ len = wpabuf_len(data->outbuf);
+ if ((len + EAP_PWD_HDR_SIZE) > data->mtu) {
+ resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, data->mtu,
+ EAP_CODE_RESPONSE, eap_get_id(reqData));
+ /*
+ * if so it's the first so include a length field
+ */
+ EAP_PWD_SET_LENGTH_BIT(lm_exch);
+ EAP_PWD_SET_MORE_BIT(lm_exch);
+ tot_len = len;
+ /*
+ * keep the packet at the MTU
+ */
+ len = data->mtu - EAP_PWD_HDR_SIZE - sizeof(u16);
+ wpa_printf(MSG_DEBUG, "EAP-pwd: Fragmenting output, total "
+ "length = %d", tot_len);
+ } else {
+ resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
+ EAP_PWD_HDR_SIZE + len,
+ EAP_CODE_RESPONSE, eap_get_id(reqData));
+ }
+ if (resp == NULL)
+ return NULL;
+
+ wpabuf_put_u8(resp, lm_exch);
+ if (EAP_PWD_GET_LENGTH_BIT(lm_exch)) {
+ wpabuf_put_be16(resp, tot_len);
+ data->out_frag_pos += len;
+ }
+ buf = wpabuf_head_u8(data->outbuf);
+ wpabuf_put_data(resp, buf, len);
+ /*
+ * if we're not fragmenting then there's no need to carry this around
+ */
+ if (data->out_frag_pos == 0) {
+ wpabuf_free(data->outbuf);
+ data->outbuf = NULL;
+ data->out_frag_pos = 0;
+ }
+
+ return resp;
+}
+
+
+static Boolean eap_pwd_key_available(struct eap_sm *sm, void *priv)
+{
+ struct eap_pwd_data *data = priv;
+ return data->state == SUCCESS;
+}
+
+
+static u8 * eap_pwd_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_pwd_data *data = priv;
+ u8 *key;
+
+ if (data->state != SUCCESS)
+ return NULL;
+
+ if ((key = os_malloc(EAP_EMSK_LEN)) == NULL)
+ return NULL;
+
+ os_memcpy(key, data->emsk, EAP_EMSK_LEN);
+ *len = EAP_EMSK_LEN;
+
+ return key;
+}
+
+
+int eap_peer_pwd_register(void)
+{
+ struct eap_method *eap;
+ int ret;
+
+ EVP_add_digest(EVP_sha256());
+ eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+ EAP_VENDOR_IETF, EAP_TYPE_PWD, "PWD");
+ if (eap == NULL)
+ return -1;
+
+ eap->init = eap_pwd_init;
+ eap->deinit = eap_pwd_deinit;
+ eap->process = eap_pwd_process;
+ eap->isKeyAvailable = eap_pwd_key_available;
+ eap->getKey = eap_pwd_getkey;
+ eap->get_emsk = eap_pwd_get_emsk;
+
+ ret = eap_peer_method_register(eap);
+ if (ret)
+ eap_peer_method_free(eap);
+ return ret;
+}
diff --git a/contrib/wpa/src/eap_peer/eap_sake.c b/contrib/wpa/src/eap_peer/eap_sake.c
index bb06bb2..e072f46 100644
--- a/contrib/wpa/src/eap_peer/eap_sake.c
+++ b/contrib/wpa/src/eap_peer/eap_sake.c
@@ -2,19 +2,14 @@
* EAP peer method: EAP-SAKE (RFC 4763)
* Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
#include "common.h"
+#include "crypto/random.h"
#include "eap_peer/eap_i.h"
#include "eap_common/eap_sake_common.h"
@@ -223,7 +218,7 @@ static struct wpabuf * eap_sake_process_challenge(struct eap_sm *sm,
wpa_hexdump(MSG_MSGDUMP, "EAP-SAKE: RAND_S (server rand)",
data->rand_s, EAP_SAKE_RAND_LEN);
- if (os_get_random(data->rand_p, EAP_SAKE_RAND_LEN)) {
+ if (random_get_bytes(data->rand_p, EAP_SAKE_RAND_LEN)) {
wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to get random data");
return NULL;
}
diff --git a/contrib/wpa/src/eap_peer/eap_sim.c b/contrib/wpa/src/eap_peer/eap_sim.c
index 3d8afb2..c936a44 100644
--- a/contrib/wpa/src/eap_peer/eap_sim.c
+++ b/contrib/wpa/src/eap_peer/eap_sim.c
@@ -1,15 +1,9 @@
/*
* EAP peer method: EAP-SIM (RFC 4186)
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -17,6 +11,7 @@
#include "common.h"
#include "pcsc_funcs.h"
#include "crypto/milenage.h"
+#include "crypto/random.h"
#include "eap_peer/eap_i.h"
#include "eap_config.h"
#include "eap_common/eap_sim_common.h"
@@ -93,7 +88,7 @@ static void * eap_sim_init(struct eap_sm *sm)
if (data == NULL)
return NULL;
- if (os_get_random(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
+ if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
"for NONCE_MT");
os_free(data);
@@ -122,6 +117,15 @@ static void * eap_sim_init(struct eap_sm *sm)
NULL;
}
+ if (config && config->anonymous_identity) {
+ data->pseudonym = os_malloc(config->anonymous_identity_len);
+ if (data->pseudonym) {
+ os_memcpy(data->pseudonym, config->anonymous_identity,
+ config->anonymous_identity_len);
+ data->pseudonym_len = config->anonymous_identity_len;
+ }
+ }
+
eap_sim_state(data, CONTINUE);
return data;
@@ -263,23 +267,24 @@ static int eap_sim_supported_ver(int version)
#define CLEAR_REAUTH_ID 0x02
#define CLEAR_EAP_ID 0x04
-static void eap_sim_clear_identities(struct eap_sim_data *data, int id)
+static void eap_sim_clear_identities(struct eap_sm *sm,
+ struct eap_sim_data *data, int id)
{
- wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old%s%s%s",
- id & CLEAR_PSEUDONYM ? " pseudonym" : "",
- id & CLEAR_REAUTH_ID ? " reauth_id" : "",
- id & CLEAR_EAP_ID ? " eap_id" : "");
- if (id & CLEAR_PSEUDONYM) {
+ if ((id & CLEAR_PSEUDONYM) && data->pseudonym) {
+ wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old pseudonym");
os_free(data->pseudonym);
data->pseudonym = NULL;
data->pseudonym_len = 0;
+ eap_set_anon_id(sm, NULL, 0);
}
- if (id & CLEAR_REAUTH_ID) {
+ if ((id & CLEAR_REAUTH_ID) && data->reauth_id) {
+ wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old reauth_id");
os_free(data->reauth_id);
data->reauth_id = NULL;
data->reauth_id_len = 0;
}
- if (id & CLEAR_EAP_ID) {
+ if ((id & CLEAR_EAP_ID) && data->last_eap_identity) {
+ wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old eap_id");
os_free(data->last_eap_identity);
data->last_eap_identity = NULL;
data->last_eap_identity_len = 0;
@@ -287,24 +292,45 @@ static void eap_sim_clear_identities(struct eap_sim_data *data, int id)
}
-static int eap_sim_learn_ids(struct eap_sim_data *data,
+static int eap_sim_learn_ids(struct eap_sm *sm, struct eap_sim_data *data,
struct eap_sim_attrs *attr)
{
if (attr->next_pseudonym) {
+ const u8 *identity = NULL;
+ size_t identity_len = 0;
+ const u8 *realm = NULL;
+ size_t realm_len = 0;
+
+ wpa_hexdump_ascii(MSG_DEBUG,
+ "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
+ attr->next_pseudonym,
+ attr->next_pseudonym_len);
os_free(data->pseudonym);
- data->pseudonym = os_malloc(attr->next_pseudonym_len);
+ /* Look for the realm of the permanent identity */
+ identity = eap_get_config_identity(sm, &identity_len);
+ if (identity) {
+ for (realm = identity, realm_len = identity_len;
+ realm_len > 0; realm_len--, realm++) {
+ if (*realm == '@')
+ break;
+ }
+ }
+ data->pseudonym = os_malloc(attr->next_pseudonym_len +
+ realm_len);
if (data->pseudonym == NULL) {
wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
"next pseudonym");
+ data->pseudonym_len = 0;
return -1;
}
os_memcpy(data->pseudonym, attr->next_pseudonym,
attr->next_pseudonym_len);
- data->pseudonym_len = attr->next_pseudonym_len;
- wpa_hexdump_ascii(MSG_DEBUG,
- "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
- data->pseudonym,
- data->pseudonym_len);
+ if (realm_len) {
+ os_memcpy(data->pseudonym + attr->next_pseudonym_len,
+ realm, realm_len);
+ }
+ data->pseudonym_len = attr->next_pseudonym_len + realm_len;
+ eap_set_anon_id(sm, data->pseudonym, data->pseudonym_len);
}
if (attr->next_reauth_id) {
@@ -313,6 +339,7 @@ static int eap_sim_learn_ids(struct eap_sim_data *data,
if (data->reauth_id == NULL) {
wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
"next reauth_id");
+ data->reauth_id_len = 0;
return -1;
}
os_memcpy(data->reauth_id, attr->next_reauth_id,
@@ -337,6 +364,8 @@ static struct wpabuf * eap_sim_client_error(struct eap_sim_data *data, u8 id,
data->num_id_req = 0;
data->num_notification = 0;
+ wpa_printf(MSG_DEBUG, "EAP-SIM: Send Client-Error (error code %d)",
+ err);
msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
EAP_SIM_SUBTYPE_CLIENT_ERROR);
eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
@@ -361,16 +390,16 @@ static struct wpabuf * eap_sim_response_start(struct eap_sm *sm,
data->pseudonym) {
identity = data->pseudonym;
identity_len = data->pseudonym_len;
- eap_sim_clear_identities(data, CLEAR_REAUTH_ID);
+ eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID);
} else if (id_req != NO_ID_REQ) {
identity = eap_get_config_identity(sm, &identity_len);
if (identity) {
- eap_sim_clear_identities(data, CLEAR_PSEUDONYM |
+ eap_sim_clear_identities(sm, data, CLEAR_PSEUDONYM |
CLEAR_REAUTH_ID);
}
}
if (id_req != NO_ID_REQ)
- eap_sim_clear_identities(data, CLEAR_EAP_ID);
+ eap_sim_clear_identities(sm, data, CLEAR_EAP_ID);
wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", id);
msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id,
@@ -417,7 +446,8 @@ static struct wpabuf * eap_sim_response_challenge(struct eap_sim_data *data,
static struct wpabuf * eap_sim_response_reauth(struct eap_sim_data *data,
- u8 id, int counter_too_small)
+ u8 id, int counter_too_small,
+ const u8 *nonce_s)
{
struct eap_sim_msg *msg;
unsigned int counter;
@@ -452,7 +482,7 @@ static struct wpabuf * eap_sim_response_reauth(struct eap_sim_data *data,
}
wpa_printf(MSG_DEBUG, " AT_MAC");
eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
- return eap_sim_msg_finish(msg, data->k_aut, data->nonce_s,
+ return eap_sim_msg_finish(msg, data->k_aut, nonce_s,
EAP_SIM_NONCE_S_LEN);
}
@@ -648,11 +678,11 @@ static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm,
EAP_SIM_UNABLE_TO_PROCESS_PACKET);
}
- /* Old reauthentication and pseudonym identities must not be used
- * anymore. In other words, if no new identities are received, full
- * authentication will be used on next reauthentication. */
- eap_sim_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID |
- CLEAR_EAP_ID);
+ /* Old reauthentication identity must not be used anymore. In
+ * other words, if no new reauth identity is received, full
+ * authentication will be used on next reauthentication (using
+ * pseudonym identity or permanent identity). */
+ eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
if (attr->encr_data) {
u8 *decrypted;
@@ -663,7 +693,7 @@ static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm,
return eap_sim_client_error(
data, id, EAP_SIM_UNABLE_TO_PROCESS_PACKET);
}
- eap_sim_learn_ids(data, &eattr);
+ eap_sim_learn_ids(sm, data, &eattr);
os_free(decrypted);
}
@@ -848,7 +878,7 @@ static struct wpabuf * eap_sim_process_reauthentication(
data->reauth_id = NULL;
data->reauth_id_len = 0;
os_free(decrypted);
- return eap_sim_response_reauth(data, id, 1);
+ return eap_sim_response_reauth(data, id, 1, eattr.nonce_s);
}
data->counter = eattr.counter;
@@ -860,8 +890,8 @@ static struct wpabuf * eap_sim_process_reauthentication(
data->reauth_id, data->reauth_id_len,
data->nonce_s, data->mk, data->msk,
data->emsk);
- eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
- eap_sim_learn_ids(data, &eattr);
+ eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
+ eap_sim_learn_ids(sm, data, &eattr);
if (data->result_ind && attr->result_ind)
data->use_result_ind = 1;
@@ -876,10 +906,11 @@ static struct wpabuf * eap_sim_process_reauthentication(
if (data->counter > EAP_SIM_MAX_FAST_REAUTHS) {
wpa_printf(MSG_DEBUG, "EAP-SIM: Maximum number of "
"fast reauths performed - force fullauth");
- eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
+ eap_sim_clear_identities(sm, data,
+ CLEAR_REAUTH_ID | CLEAR_EAP_ID);
}
os_free(decrypted);
- return eap_sim_response_reauth(data, id, 0);
+ return eap_sim_response_reauth(data, id, 0, data->nonce_s);
}
@@ -987,7 +1018,7 @@ static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv)
static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv)
{
struct eap_sim_data *data = priv;
- eap_sim_clear_identities(data, CLEAR_EAP_ID);
+ eap_sim_clear_identities(sm, data, CLEAR_EAP_ID);
data->use_result_ind = 0;
}
@@ -995,7 +1026,7 @@ static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv)
static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv)
{
struct eap_sim_data *data = priv;
- if (os_get_random(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
+ if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
"for NONCE_MT");
os_free(data);
diff --git a/contrib/wpa/src/eap_peer/eap_tls.c b/contrib/wpa/src/eap_peer/eap_tls.c
index 20b2212..061a72b 100644
--- a/contrib/wpa/src/eap_peer/eap_tls.c
+++ b/contrib/wpa/src/eap_peer/eap_tls.c
@@ -1,15 +1,9 @@
/*
* EAP peer method: EAP-TLS (RFC 2716)
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -27,6 +21,8 @@ static void eap_tls_deinit(struct eap_sm *sm, void *priv);
struct eap_tls_data {
struct eap_ssl_data ssl;
u8 *key_data;
+ void *ssl_ctx;
+ u8 eap_type;
};
@@ -46,7 +42,10 @@ static void * eap_tls_init(struct eap_sm *sm)
if (data == NULL)
return NULL;
- if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
+ data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
+ sm->ssl_ctx;
+
+ if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TLS)) {
wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
eap_tls_deinit(sm, data);
if (config->engine) {
@@ -64,8 +63,37 @@ static void * eap_tls_init(struct eap_sm *sm)
return NULL;
}
+ data->eap_type = EAP_TYPE_TLS;
+
+ return data;
+}
+
+
+#ifdef EAP_UNAUTH_TLS
+static void * eap_unauth_tls_init(struct eap_sm *sm)
+{
+ struct eap_tls_data *data;
+ struct eap_peer_config *config = eap_get_config(sm);
+
+ data = os_zalloc(sizeof(*data));
+ if (data == NULL)
+ return NULL;
+
+ data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
+ sm->ssl_ctx;
+
+ if (eap_peer_tls_ssl_init(sm, &data->ssl, config,
+ EAP_UNAUTH_TLS_TYPE)) {
+ wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
+ eap_tls_deinit(sm, data);
+ return NULL;
+ }
+
+ data->eap_type = EAP_UNAUTH_TLS_TYPE;
+
return data;
}
+#endif /* EAP_UNAUTH_TLS */
static void eap_tls_deinit(struct eap_sm *sm, void *priv)
@@ -111,7 +139,7 @@ static struct wpabuf * eap_tls_failure(struct eap_sm *sm,
return resp;
}
- return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0);
+ return eap_peer_tls_build_ack(id, data->eap_type, 0);
}
@@ -151,7 +179,7 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
const u8 *pos;
struct eap_tls_data *data = priv;
- pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TLS, ret,
+ pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret,
reqData, &left, &flags);
if (pos == NULL)
return NULL;
@@ -164,19 +192,19 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
}
resp = NULL;
- res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TLS, 0, id,
- pos, left, &resp);
+ res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0,
+ id, pos, left, &resp);
if (res < 0) {
return eap_tls_failure(sm, data, ret, res, resp, id);
}
- if (tls_connection_established(sm->ssl_ctx, data->ssl.conn))
+ if (tls_connection_established(data->ssl_ctx, data->ssl.conn))
eap_tls_success(sm, data, ret);
if (res == 1) {
wpabuf_free(resp);
- return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0);
+ return eap_peer_tls_build_ack(id, data->eap_type, 0);
}
return resp;
@@ -186,7 +214,7 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv)
{
struct eap_tls_data *data = priv;
- return tls_connection_established(sm->ssl_ctx, data->ssl.conn);
+ return tls_connection_established(data->ssl_ctx, data->ssl.conn);
}
@@ -287,3 +315,34 @@ int eap_peer_tls_register(void)
eap_peer_method_free(eap);
return ret;
}
+
+
+#ifdef EAP_UNAUTH_TLS
+int eap_peer_unauth_tls_register(void)
+{
+ struct eap_method *eap;
+ int ret;
+
+ eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
+ EAP_VENDOR_UNAUTH_TLS,
+ EAP_VENDOR_TYPE_UNAUTH_TLS, "UNAUTH-TLS");
+ if (eap == NULL)
+ return -1;
+
+ eap->init = eap_unauth_tls_init;
+ eap->deinit = eap_tls_deinit;
+ eap->process = eap_tls_process;
+ eap->isKeyAvailable = eap_tls_isKeyAvailable;
+ eap->getKey = eap_tls_getKey;
+ eap->get_status = eap_tls_get_status;
+ eap->has_reauth_data = eap_tls_has_reauth_data;
+ eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
+ eap->init_for_reauth = eap_tls_init_for_reauth;
+ eap->get_emsk = eap_tls_get_emsk;
+
+ ret = eap_peer_method_register(eap);
+ if (ret)
+ eap_peer_method_free(eap);
+ return ret;
+}
+#endif /* EAP_UNAUTH_TLS */
diff --git a/contrib/wpa/src/eap_peer/eap_tls_common.c b/contrib/wpa/src/eap_peer/eap_tls_common.c
index 7bd50f6..aedd85a 100644
--- a/contrib/wpa/src/eap_peer/eap_tls_common.c
+++ b/contrib/wpa/src/eap_peer/eap_tls_common.c
@@ -1,15 +1,9 @@
/*
* EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -22,6 +16,18 @@
#include "eap_config.h"
+static struct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len,
+ u8 code, u8 identifier)
+{
+ if (type == EAP_UNAUTH_TLS_TYPE)
+ return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS,
+ EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len,
+ code, identifier);
+ return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code,
+ identifier);
+}
+
+
static int eap_tls_check_blob(struct eap_sm *sm, const char **name,
const u8 **data, size_t *data_len)
{
@@ -54,6 +60,10 @@ static void eap_tls_params_flags(struct tls_connection_params *params,
params->flags |= TLS_CONN_ALLOW_SIGN_RSA_MD5;
if (os_strstr(txt, "tls_disable_time_checks=1"))
params->flags |= TLS_CONN_DISABLE_TIME_CHECKS;
+ if (os_strstr(txt, "tls_disable_session_ticket=1"))
+ params->flags |= TLS_CONN_DISABLE_SESSION_TICKET;
+ if (os_strstr(txt, "tls_disable_session_ticket=0"))
+ params->flags &= ~TLS_CONN_DISABLE_SESSION_TICKET;
}
@@ -105,6 +115,18 @@ static int eap_tls_params_from_conf(struct eap_sm *sm,
struct eap_peer_config *config, int phase2)
{
os_memset(params, 0, sizeof(*params));
+ if (sm->workaround && data->eap_type != EAP_TYPE_FAST) {
+ /*
+ * Some deployed authentication servers seem to be unable to
+ * handle the TLS Session Ticket extension (they are supposed
+ * to ignore unrecognized TLS extensions, but end up rejecting
+ * the ClientHello instead). As a workaround, disable use of
+ * TLS Sesson Ticket extension for EAP-TLS, EAP-PEAP, and
+ * EAP-TTLS (EAP-FAST uses session ticket, so any server that
+ * supports EAP-FAST does not need this workaround).
+ */
+ params->flags |= TLS_CONN_DISABLE_SESSION_TICKET;
+ }
if (phase2) {
wpa_printf(MSG_DEBUG, "TLS: using phase2 config options");
eap_tls_params_from_conf2(params, config);
@@ -112,7 +134,6 @@ static int eap_tls_params_from_conf(struct eap_sm *sm,
wpa_printf(MSG_DEBUG, "TLS: using phase1 config options");
eap_tls_params_from_conf1(params, config);
}
- params->tls_ia = data->tls_ia;
/*
* Use blob data, if available. Otherwise, leave reference to external
@@ -143,14 +164,14 @@ static int eap_tls_init_connection(struct eap_sm *sm,
{
int res;
- data->conn = tls_connection_init(sm->ssl_ctx);
+ data->conn = tls_connection_init(data->ssl_ctx);
if (data->conn == NULL) {
wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
"connection");
return -1;
}
- res = tls_connection_set_params(sm->ssl_ctx, data->conn, params);
+ res = tls_connection_set_params(data->ssl_ctx, data->conn, params);
if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) {
/*
* At this point with the pkcs11 engine the PIN might be wrong.
@@ -169,13 +190,13 @@ static int eap_tls_init_connection(struct eap_sm *sm,
config->pin = NULL;
eap_sm_request_pin(sm);
sm->ignore = TRUE;
- tls_connection_deinit(sm->ssl_ctx, data->conn);
+ tls_connection_deinit(data->ssl_ctx, data->conn);
data->conn = NULL;
return -1;
} else if (res) {
wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection "
"parameters");
- tls_connection_deinit(sm->ssl_ctx, data->conn);
+ tls_connection_deinit(data->ssl_ctx, data->conn);
data->conn = NULL;
return -1;
}
@@ -189,13 +210,14 @@ static int eap_tls_init_connection(struct eap_sm *sm,
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
* @data: Data for TLS processing
* @config: Pointer to the network configuration
+ * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
* Returns: 0 on success, -1 on failure
*
* This function is used to initialize shared TLS functionality for EAP-TLS,
* EAP-PEAP, EAP-TTLS, and EAP-FAST.
*/
int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
- struct eap_peer_config *config)
+ struct eap_peer_config *config, u8 eap_type)
{
struct tls_connection_params params;
@@ -203,7 +225,10 @@ int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
return -1;
data->eap = sm;
+ data->eap_type = eap_type;
data->phase2 = sm->init_phase2;
+ data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 :
+ sm->ssl_ctx;
if (eap_tls_params_from_conf(sm, data, &params, config, data->phase2) <
0)
return -1;
@@ -241,7 +266,7 @@ int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
*/
void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
{
- tls_connection_deinit(sm->ssl_ctx, data->conn);
+ tls_connection_deinit(data->ssl_ctx, data->conn);
eap_peer_tls_reset_input(data);
eap_peer_tls_reset_output(data);
}
@@ -264,7 +289,9 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
const char *label, size_t len)
{
+#ifndef CONFIG_FIPS
struct tls_keys keys;
+#endif /* CONFIG_FIPS */
u8 *rnd = NULL, *out;
out = os_malloc(len);
@@ -272,16 +299,17 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
return NULL;
/* First, try to use TLS library function for PRF, if available. */
- if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
- 0)
+ if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len)
+ == 0)
return out;
+#ifndef CONFIG_FIPS
/*
* TLS library did not support key generation, so get the needed TLS
* session parameters and use an internal implementation of TLS PRF to
* derive the key.
*/
- if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
+ if (tls_connection_get_keys(data->ssl_ctx, data->conn, &keys))
goto fail;
if (keys.client_random == NULL || keys.server_random == NULL ||
@@ -295,15 +323,16 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
os_memcpy(rnd + keys.client_random_len, keys.server_random,
keys.server_random_len);
- if (tls_prf(keys.master_key, keys.master_key_len,
- label, rnd, keys.client_random_len +
- keys.server_random_len, out, len))
+ if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
+ label, rnd, keys.client_random_len +
+ keys.server_random_len, out, len))
goto fail;
os_free(rnd);
return out;
fail:
+#endif /* CONFIG_FIPS */
os_free(out);
os_free(rnd);
return NULL;
@@ -361,7 +390,8 @@ static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
eap_peer_tls_reset_input(data);
return -1;
}
- wpabuf_put_buf(data->tls_in, in_data);
+ if (in_data)
+ wpabuf_put_buf(data->tls_in, in_data);
data->tls_in_left -= in_len;
if (data->tls_in_left > 0) {
@@ -447,14 +477,14 @@ static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data,
WPA_ASSERT(data->tls_out == NULL);
}
appl_data = NULL;
- data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn,
+ data->tls_out = tls_connection_handshake(data->ssl_ctx, data->conn,
msg, &appl_data);
eap_peer_tls_reset_input(data);
if (appl_data &&
- tls_connection_established(sm->ssl_ctx, data->conn) &&
- !tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
+ tls_connection_established(data->ssl_ctx, data->conn) &&
+ !tls_connection_get_failed(data->ssl_ctx, data->conn)) {
wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application data",
appl_data);
*out_data = appl_data;
@@ -520,9 +550,8 @@ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
length_included = 1;
}
- *out_data = eap_msg_alloc(EAP_VENDOR_IETF, eap_type,
- 1 + length_included * 4 + len,
- EAP_CODE_RESPONSE, id);
+ *out_data = eap_tls_msg_alloc(eap_type, 1 + length_included * 4 + len,
+ EAP_CODE_RESPONSE, id);
if (*out_data == NULL)
return -1;
@@ -622,7 +651,7 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
return -1;
}
- if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
+ if (tls_connection_get_failed(data->ssl_ctx, data->conn)) {
/* TLS processing has failed - return error */
wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
"report error");
@@ -660,8 +689,7 @@ struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type,
{
struct wpabuf *resp;
- resp = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_RESPONSE,
- id);
+ resp = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_RESPONSE, id);
if (resp == NULL)
return NULL;
wpa_printf(MSG_DEBUG, "SSL: Building ACK (type=%d id=%d ver=%d)",
@@ -681,7 +709,7 @@ int eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data)
{
eap_peer_tls_reset_input(data);
eap_peer_tls_reset_output(data);
- return tls_connection_shutdown(sm->ssl_ctx, data->conn);
+ return tls_connection_shutdown(data->ssl_ctx, data->conn);
}
@@ -700,7 +728,8 @@ int eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data,
char name[128];
int len = 0, ret;
- if (tls_get_cipher(sm->ssl_ctx, data->conn, name, sizeof(name)) == 0) {
+ if (tls_get_cipher(data->ssl_ctx, data->conn, name, sizeof(name)) == 0)
+ {
ret = os_snprintf(buf + len, buflen - len,
"EAP TLS cipher=%s\n", name);
if (ret < 0 || (size_t) ret >= buflen - len)
@@ -747,13 +776,19 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm,
size_t left;
unsigned int tls_msg_len;
- if (tls_get_errors(sm->ssl_ctx)) {
+ if (tls_get_errors(data->ssl_ctx)) {
wpa_printf(MSG_INFO, "SSL: TLS errors detected");
ret->ignore = TRUE;
return NULL;
}
- pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, &left);
+ if (eap_type == EAP_UNAUTH_TLS_TYPE)
+ pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
+ EAP_VENDOR_TYPE_UNAUTH_TLS, reqData,
+ &left);
+ else
+ pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData,
+ &left);
if (pos == NULL) {
ret->ignore = TRUE;
return NULL;
@@ -794,6 +829,14 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm,
}
pos += 4;
left -= 4;
+
+ if (left > tls_msg_len) {
+ wpa_printf(MSG_INFO, "SSL: TLS Message Length (%d "
+ "bytes) smaller than this fragment (%d "
+ "bytes)", (int) tls_msg_len, (int) left);
+ ret->ignore = TRUE;
+ return NULL;
+ }
}
ret->ignore = FALSE;
@@ -855,7 +898,7 @@ int eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data,
if (msg == NULL)
return need_more_input ? 1 : -1;
- *in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->conn, msg);
+ *in_decrypted = tls_connection_decrypt(data->ssl_ctx, data->conn, msg);
eap_peer_tls_reset_input(data);
if (*in_decrypted == NULL) {
wpa_printf(MSG_INFO, "SSL: Failed to decrypt Phase 2 data");
@@ -883,8 +926,8 @@ int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data,
{
if (in_data) {
eap_peer_tls_reset_output(data);
- data->tls_out = tls_connection_encrypt(sm->ssl_ctx, data->conn,
- in_data);
+ data->tls_out = tls_connection_encrypt(data->ssl_ctx,
+ data->conn, in_data);
if (data->tls_out == NULL) {
wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 "
"data (in_len=%lu)",
@@ -949,8 +992,8 @@ int eap_peer_select_phase2_methods(struct eap_peer_config *config,
"method '%s'", start);
} else {
num_methods++;
- _methods = os_realloc(methods,
- num_methods * sizeof(*methods));
+ _methods = os_realloc_array(methods, num_methods,
+ sizeof(*methods));
if (_methods == NULL) {
os_free(methods);
os_free(buf);
diff --git a/contrib/wpa/src/eap_peer/eap_tls_common.h b/contrib/wpa/src/eap_peer/eap_tls_common.h
index e9e0998..91d3a25 100644
--- a/contrib/wpa/src/eap_peer/eap_tls_common.h
+++ b/contrib/wpa/src/eap_peer/eap_tls_common.h
@@ -1,15 +1,9 @@
/*
* EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2009, 2012, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef EAP_TLS_COMMON_H
@@ -66,14 +60,19 @@ struct eap_ssl_data {
int include_tls_length;
/**
- * tls_ia - Whether TLS/IA is enabled for this TLS connection
+ * eap - EAP state machine allocated with eap_peer_sm_init()
*/
- int tls_ia;
+ struct eap_sm *eap;
/**
- * eap - EAP state machine allocated with eap_peer_sm_init()
+ * ssl_ctx - TLS library context to use for the connection
*/
- struct eap_sm *eap;
+ void *ssl_ctx;
+
+ /**
+ * eap_type - EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
+ */
+ u8 eap_type;
};
@@ -86,9 +85,12 @@ struct eap_ssl_data {
/* could be up to 128 bytes, but only the first 64 bytes are used */
#define EAP_TLS_KEY_LEN 64
+/* dummy type used as a flag for UNAUTH-TLS */
+#define EAP_UNAUTH_TLS_TYPE 255
+
int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
- struct eap_peer_config *config);
+ struct eap_peer_config *config, u8 eap_type);
void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
const char *label, size_t len);
diff --git a/contrib/wpa/src/eap_peer/eap_tnc.c b/contrib/wpa/src/eap_peer/eap_tnc.c
index 6c95f72..bc13647 100644
--- a/contrib/wpa/src/eap_peer/eap_tnc.c
+++ b/contrib/wpa/src/eap_peer/eap_tnc.c
@@ -2,20 +2,13 @@
* EAP peer method: EAP-TNC (Trusted Network Connect)
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
#include "common.h"
-#include "base64.h"
#include "eap_i.h"
#include "tncc.h"
diff --git a/contrib/wpa/src/eap_peer/eap_ttls.c b/contrib/wpa/src/eap_peer/eap_ttls.c
index 2573780..9360a42 100644
--- a/contrib/wpa/src/eap_peer/eap_ttls.c
+++ b/contrib/wpa/src/eap_peer/eap_ttls.c
@@ -1,15 +1,9 @@
/*
* EAP peer method: EAP-TTLS (RFC 5281)
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -26,17 +20,7 @@
#include "eap_config.h"
-/* Maximum supported TTLS version
- * 0 = RFC 5281
- * 1 = draft-funk-eap-ttls-v1-00.txt
- */
-#ifndef EAP_TTLS_VERSION
-#define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */
-#endif /* EAP_TTLS_VERSION */
-
-
-#define MSCHAPV2_KEY_LEN 16
-#define MSCHAPV2_NT_RESPONSE_LEN 24
+#define EAP_TTLS_VERSION 0
static void eap_ttls_deinit(struct eap_sm *sm, void *priv);
@@ -44,9 +28,8 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv);
struct eap_ttls_data {
struct eap_ssl_data ssl;
- int ssl_initialized;
- int ttls_version, force_ttls_version;
+ int ttls_version;
const struct eap_method *phase2_method;
void *phase2_priv;
@@ -91,22 +74,9 @@ static void * eap_ttls_init(struct eap_sm *sm)
if (data == NULL)
return NULL;
data->ttls_version = EAP_TTLS_VERSION;
- data->force_ttls_version = -1;
selected = "EAP";
data->phase2_type = EAP_TTLS_PHASE2_EAP;
-#if EAP_TTLS_VERSION > 0
- if (config && config->phase1) {
- const char *pos = os_strstr(config->phase1, "ttlsver=");
- if (pos) {
- data->force_ttls_version = atoi(pos + 8);
- data->ttls_version = data->force_ttls_version;
- wpa_printf(MSG_DEBUG, "EAP-TTLS: Forced TTLS version "
- "%d", data->force_ttls_version);
- }
- }
-#endif /* EAP_TTLS_VERSION */
-
if (config && config->phase2) {
if (os_strstr(config->phase2, "autheap=")) {
selected = "EAP";
@@ -140,19 +110,11 @@ static void * eap_ttls_init(struct eap_sm *sm)
data->phase2_eap_type.method = EAP_TYPE_NONE;
}
-#if EAP_TTLS_VERSION > 0
- if (!(tls_capabilities(sm->ssl_ctx) & TLS_CAPABILITY_IA) &&
- data->ttls_version > 0) {
- if (data->force_ttls_version > 0) {
- wpa_printf(MSG_INFO, "EAP-TTLS: Forced TTLSv%d and "
- "TLS library does not support TLS/IA.",
- data->force_ttls_version);
- eap_ttls_deinit(sm, data);
- return NULL;
- }
- data->ttls_version = 0;
+ if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TTLS)) {
+ wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
+ eap_ttls_deinit(sm, data);
+ return NULL;
}
-#endif /* EAP_TTLS_VERSION */
return data;
}
@@ -176,8 +138,7 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
return;
eap_ttls_phase2_eap_deinit(sm, data);
os_free(data->phase2_eap_types);
- if (data->ssl_initialized)
- eap_peer_tls_ssl_deinit(sm, &data->ssl);
+ eap_peer_tls_ssl_deinit(sm, &data->ssl);
os_free(data->key_data);
wpabuf_free(data->pending_phase2_req);
os_free(data);
@@ -202,7 +163,7 @@ static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id,
}
avp->avp_code = host_to_be32(avp_code);
- avp->avp_length = host_to_be32((flags << 24) | (hdrlen + len));
+ avp->avp_length = host_to_be32((flags << 24) | (u32) (hdrlen + len));
return avphdr + hdrlen;
}
@@ -246,39 +207,6 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
}
-#if EAP_TTLS_VERSION > 0
-static int eap_ttls_ia_permute_inner_secret(struct eap_sm *sm,
- struct eap_ttls_data *data,
- const u8 *key, size_t key_len)
-{
- u8 *buf;
- size_t buf_len;
- int ret;
-
- if (key) {
- buf_len = 2 + key_len;
- buf = os_malloc(buf_len);
- if (buf == NULL)
- return -1;
- WPA_PUT_BE16(buf, key_len);
- os_memcpy(buf + 2, key, key_len);
- } else {
- buf = NULL;
- buf_len = 0;
- }
-
- wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Session keys for TLS/IA inner "
- "secret permutation", buf, buf_len);
- ret = tls_connection_ia_permute_inner_secret(sm->ssl_ctx,
- data->ssl.conn,
- buf, buf_len);
- os_free(buf);
-
- return ret;
-}
-#endif /* EAP_TTLS_VERSION */
-
-
static int eap_ttls_v0_derive_key(struct eap_sm *sm,
struct eap_ttls_data *data)
{
@@ -298,156 +226,10 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm,
}
-#if EAP_TTLS_VERSION > 0
-static int eap_ttls_v1_derive_key(struct eap_sm *sm,
- struct eap_ttls_data *data)
-{
- struct tls_keys keys;
- u8 *rnd;
-
- os_free(data->key_data);
- data->key_data = NULL;
-
- os_memset(&keys, 0, sizeof(keys));
- if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
- keys.client_random == NULL || keys.server_random == NULL ||
- keys.inner_secret == NULL) {
- wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
- "client random, or server random to derive keying "
- "material");
- return -1;
- }
-
- rnd = os_malloc(keys.client_random_len + keys.server_random_len);
- data->key_data = os_malloc(EAP_TLS_KEY_LEN);
- if (rnd == NULL || data->key_data == NULL) {
- wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation");
- os_free(rnd);
- os_free(data->key_data);
- data->key_data = NULL;
- return -1;
- }
- os_memcpy(rnd, keys.client_random, keys.client_random_len);
- os_memcpy(rnd + keys.client_random_len, keys.server_random,
- keys.server_random_len);
-
- if (tls_prf(keys.inner_secret, keys.inner_secret_len,
- "ttls v1 keying material", rnd, keys.client_random_len +
- keys.server_random_len, data->key_data, EAP_TLS_KEY_LEN)) {
- wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");
- os_free(rnd);
- os_free(data->key_data);
- data->key_data = NULL;
- return -1;
- }
-
- wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random",
- rnd, keys.client_random_len + keys.server_random_len);
- wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret",
- keys.inner_secret, keys.inner_secret_len);
-
- os_free(rnd);
-
- wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
- data->key_data, EAP_TLS_KEY_LEN);
-
- return 0;
-}
-#endif /* EAP_TTLS_VERSION */
-
-
static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
struct eap_ttls_data *data, size_t len)
{
-#if EAP_TTLS_VERSION > 0
- struct tls_keys keys;
- u8 *challenge, *rnd;
-#endif /* EAP_TTLS_VERSION */
-
- if (data->ttls_version == 0) {
- return eap_peer_tls_derive_key(sm, &data->ssl,
- "ttls challenge", len);
- }
-
-#if EAP_TTLS_VERSION > 0
-
- os_memset(&keys, 0, sizeof(keys));
- if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
- keys.client_random == NULL || keys.server_random == NULL ||
- keys.inner_secret == NULL) {
- wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
- "client random, or server random to derive "
- "implicit challenge");
- return NULL;
- }
-
- rnd = os_malloc(keys.client_random_len + keys.server_random_len);
- challenge = os_malloc(len);
- if (rnd == NULL || challenge == NULL) {
- wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit "
- "challenge derivation");
- os_free(rnd);
- os_free(challenge);
- return NULL;
- }
- os_memcpy(rnd, keys.server_random, keys.server_random_len);
- os_memcpy(rnd + keys.server_random_len, keys.client_random,
- keys.client_random_len);
-
- if (tls_prf(keys.inner_secret, keys.inner_secret_len,
- "inner application challenge", rnd,
- keys.client_random_len + keys.server_random_len,
- challenge, len)) {
- wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit "
- "challenge");
- os_free(rnd);
- os_free(challenge);
- return NULL;
- }
-
- os_free(rnd);
-
- wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge",
- challenge, len);
-
- return challenge;
-
-#else /* EAP_TTLS_VERSION */
-
- return NULL;
-
-#endif /* EAP_TTLS_VERSION */
-}
-
-
-static void eap_ttlsv1_phase2_eap_finish(struct eap_sm *sm,
- struct eap_ttls_data *data,
- struct eap_method_ret *ret)
-{
-#if EAP_TTLS_VERSION > 0
- if (data->ttls_version > 0) {
- const struct eap_method *m = data->phase2_method;
- void *priv = data->phase2_priv;
-
- /* TTLSv1 requires TLS/IA FinalPhaseFinished */
- if (ret->decision == DECISION_UNCOND_SUCC)
- ret->decision = DECISION_COND_SUCC;
- ret->methodState = METHOD_CONT;
-
- if (ret->decision == DECISION_COND_SUCC &&
- m->isKeyAvailable && m->getKey &&
- m->isKeyAvailable(sm, priv)) {
- u8 *key;
- size_t key_len;
- key = m->getKey(sm, priv, &key_len);
- if (key) {
- eap_ttls_ia_permute_inner_secret(
- sm, data, key, key_len);
- os_free(key);
- }
- }
- }
-#endif /* EAP_TTLS_VERSION */
+ return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len);
}
@@ -494,7 +276,6 @@ static int eap_ttls_phase2_eap_process(struct eap_sm *sm,
ret->methodState = iret.methodState;
ret->decision = iret.decision;
}
- eap_ttlsv1_phase2_eap_finish(sm, data, ret);
return 0;
}
@@ -615,31 +396,12 @@ static int eap_ttls_phase2_request_eap(struct eap_sm *sm,
}
-static void eap_ttlsv1_permute_inner(struct eap_sm *sm,
- struct eap_ttls_data *data)
-{
-#if EAP_TTLS_VERSION > 0
- u8 session_key[2 * MSCHAPV2_KEY_LEN];
-
- if (data->ttls_version == 0)
- return;
-
- get_asymetric_start_key(data->master_key, session_key,
- MSCHAPV2_KEY_LEN, 0, 0);
- get_asymetric_start_key(data->master_key,
- session_key + MSCHAPV2_KEY_LEN,
- MSCHAPV2_KEY_LEN, 1, 0);
- eap_ttls_ia_permute_inner_secret(sm, data, session_key,
- sizeof(session_key));
-#endif /* EAP_TTLS_VERSION */
-}
-
-
static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
struct eap_ttls_data *data,
struct eap_method_ret *ret,
struct wpabuf **resp)
{
+#ifdef EAP_MSCHAPv2
struct wpabuf *msg;
u8 *buf, *pos, *challenge, *peer_challenge;
const u8 *identity, *password;
@@ -674,7 +436,6 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
"implicit challenge");
return -1;
}
- peer_challenge = challenge + 1 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;
pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE,
RADIUS_VENDOR_ID_MICROSOFT, 1,
@@ -687,7 +448,14 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN];
*pos++ = data->ident;
*pos++ = 0; /* Flags */
- os_memcpy(pos, peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
+ if (os_get_random(pos, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) < 0) {
+ os_free(challenge);
+ wpabuf_free(msg);
+ wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to get "
+ "random data for peer challenge");
+ return -1;
+ }
+ peer_challenge = pos;
pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;
os_memset(pos, 0, 8); /* Reserved, must be zero */
pos += 8;
@@ -695,6 +463,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
password_len, pwhash, challenge,
peer_challenge, pos, data->auth_response,
data->master_key)) {
+ os_free(challenge);
wpabuf_free(msg);
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
"response");
@@ -702,8 +471,6 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
}
data->auth_response_valid = 1;
- eap_ttlsv1_permute_inner(sm, data);
-
pos += 24;
os_free(challenge);
AVP_PAD(buf, pos);
@@ -711,7 +478,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
wpabuf_put(msg, pos - buf);
*resp = msg;
- if (sm->workaround && data->ttls_version == 0) {
+ if (sm->workaround) {
/* At least FreeRADIUS seems to be terminating
* EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success
* packet. */
@@ -722,6 +489,10 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
}
return 0;
+#else /* EAP_MSCHAPv2 */
+ wpa_printf(MSG_ERROR, "EAP-TTLS: MSCHAPv2 not included in the build");
+ return -1;
+#endif /* EAP_MSCHAPv2 */
}
@@ -798,17 +569,10 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
wpabuf_put(msg, pos - buf);
*resp = msg;
- if (data->ttls_version > 0) {
- /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,
- * so do not allow connection to be terminated yet. */
- ret->methodState = METHOD_CONT;
- ret->decision = DECISION_COND_SUCC;
- } else {
- /* EAP-TTLS/MSCHAP does not provide tunneled success
- * notification, so assume that Phase2 succeeds. */
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_COND_SUCC;
- }
+ /* EAP-TTLS/MSCHAP does not provide tunneled success
+ * notification, so assume that Phase2 succeeds. */
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_COND_SUCC;
return 0;
}
@@ -859,17 +623,10 @@ static int eap_ttls_phase2_request_pap(struct eap_sm *sm,
wpabuf_put(msg, pos - buf);
*resp = msg;
- if (data->ttls_version > 0) {
- /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,
- * so do not allow connection to be terminated yet. */
- ret->methodState = METHOD_CONT;
- ret->decision = DECISION_COND_SUCC;
- } else {
- /* EAP-TTLS/PAP does not provide tunneled success notification,
- * so assume that Phase2 succeeds. */
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_COND_SUCC;
- }
+ /* EAP-TTLS/PAP does not provide tunneled success notification,
+ * so assume that Phase2 succeeds. */
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_COND_SUCC;
return 0;
}
@@ -942,17 +699,10 @@ static int eap_ttls_phase2_request_chap(struct eap_sm *sm,
wpabuf_put(msg, pos - buf);
*resp = msg;
- if (data->ttls_version > 0) {
- /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,
- * so do not allow connection to be terminated yet. */
- ret->methodState = METHOD_CONT;
- ret->decision = DECISION_COND_SUCC;
- } else {
- /* EAP-TTLS/CHAP does not provide tunneled success
- * notification, so assume that Phase2 succeeds. */
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_COND_SUCC;
- }
+ /* EAP-TTLS/CHAP does not provide tunneled success
+ * notification, so assume that Phase2 succeeds. */
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_COND_SUCC;
return 0;
}
@@ -1027,36 +777,6 @@ static int eap_ttls_phase2_request(struct eap_sm *sm,
}
-#if EAP_TTLS_VERSION > 0
-static struct wpabuf * eap_ttls_build_phase_finished(
- struct eap_sm *sm, struct eap_ttls_data *data, int id, int final)
-{
- struct wpabuf *req, *buf;
-
- buf = tls_connection_ia_send_phase_finished(sm->ssl_ctx,
- data->ssl.conn,
- final);
- if (buf == NULL)
- return NULL;
-
- req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS,
- 1 + wpabuf_len(buf),
- EAP_CODE_RESPONSE, id);
- if (req == NULL) {
- wpabuf_free(buf);
- return NULL;
- }
-
- wpabuf_put_u8(req, data->ttls_version);
- wpabuf_put_buf(req, buf);
- wpabuf_free(buf);
- eap_update_len(req);
-
- return req;
-}
-#endif /* EAP_TTLS_VERSION */
-
-
struct ttls_parse_avp {
u8 *mschapv2;
u8 *eapdata;
@@ -1327,6 +1047,7 @@ static int eap_ttls_process_phase2_mschapv2(struct eap_sm *sm,
struct eap_method_ret *ret,
struct ttls_parse_avp *parse)
{
+#ifdef EAP_MSCHAPv2
if (parse->mschapv2_error) {
wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Received "
"MS-CHAP-Error - failed");
@@ -1366,25 +1087,19 @@ static int eap_ttls_process_phase2_mschapv2(struct eap_sm *sm,
wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 MSCHAPV2 "
"authentication succeeded");
- if (data->ttls_version > 0) {
- /*
- * EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report
- * success, so do not allow connection to be terminated
- * yet.
- */
- ret->methodState = METHOD_CONT;
- ret->decision = DECISION_COND_SUCC;
- } else {
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_UNCOND_SUCC;
- data->phase2_success = 1;
- }
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_UNCOND_SUCC;
+ data->phase2_success = 1;
/*
* Reply with empty data; authentication server will reply
* with EAP-Success after this.
*/
return 1;
+#else /* EAP_MSCHAPv2 */
+ wpa_printf(MSG_ERROR, "EAP-TTLS: MSCHAPv2 not included in the build");
+ return -1;
+#endif /* EAP_MSCHAPv2 */
}
@@ -1493,24 +1208,6 @@ static int eap_ttls_process_decrypted(struct eap_sm *sm,
}
-#if EAP_TTLS_VERSION > 0
-static void eap_ttls_final_phase_finished(struct eap_sm *sm,
- struct eap_ttls_data *data,
- struct eap_method_ret *ret,
- u8 identifier,
- struct wpabuf **out_data)
-{
- wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished received");
- wpa_printf(MSG_INFO, "EAP-TTLS: TLS/IA authentication succeeded");
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_UNCOND_SUCC;
- data->phase2_success = 1;
- *out_data = eap_ttls_build_phase_finished(sm, data, identifier, 1);
- eap_ttls_v1_derive_key(sm, data);
-}
-#endif /* EAP_TTLS_VERSION */
-
-
static int eap_ttls_implicit_identity_request(struct eap_sm *sm,
struct eap_ttls_data *data,
struct eap_method_ret *ret,
@@ -1534,6 +1231,21 @@ static int eap_ttls_implicit_identity_request(struct eap_sm *sm,
"processing failed");
retval = -1;
} else {
+ struct eap_peer_config *config = eap_get_config(sm);
+ if (resp == NULL &&
+ (config->pending_req_identity ||
+ config->pending_req_password ||
+ config->pending_req_otp ||
+ config->pending_req_new_password)) {
+ /*
+ * Use empty buffer to force implicit request
+ * processing when EAP request is re-processed after
+ * user input.
+ */
+ wpabuf_free(data->pending_phase2_req);
+ data->pending_phase2_req = wpabuf_alloc(0);
+ }
+
retval = eap_ttls_encrypt_response(sm, data, resp, identifier,
out_data);
}
@@ -1627,17 +1339,6 @@ static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
if (retval)
goto done;
-#if EAP_TTLS_VERSION > 0
- if (data->ttls_version > 0 &&
- (in_decrypted == NULL || wpabuf_len(in_decrypted) == 0) &&
- tls_connection_ia_final_phase_finished(sm->ssl_ctx,
- data->ssl.conn)) {
- eap_ttls_final_phase_finished(sm, data, ret, identifier,
- out_data);
- goto done;
- }
-#endif /* EAP_TTLS_VERSION */
-
continue_req:
data->phase2_start = 0;
@@ -1662,46 +1363,6 @@ done:
}
-static int eap_ttls_process_start(struct eap_sm *sm,
- struct eap_ttls_data *data, u8 flags,
- struct eap_method_ret *ret)
-{
- struct eap_peer_config *config = eap_get_config(sm);
-
- wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own ver=%d)",
- flags & EAP_TLS_VERSION_MASK, data->ttls_version);
-#if EAP_TTLS_VERSION > 0
- if ((flags & EAP_TLS_VERSION_MASK) < data->ttls_version)
- data->ttls_version = flags & EAP_TLS_VERSION_MASK;
- if (data->force_ttls_version >= 0 &&
- data->force_ttls_version != data->ttls_version) {
- wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to select "
- "forced TTLS version %d",
- data->force_ttls_version);
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_FAIL;
- ret->allowNotifications = FALSE;
- return -1;
- }
- wpa_printf(MSG_DEBUG, "EAP-TTLS: Using TTLS version %d",
- data->ttls_version);
-
- if (data->ttls_version > 0)
- data->ssl.tls_ia = 1;
-#endif /* EAP_TTLS_VERSION */
- if (!data->ssl_initialized &&
- eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
- wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
- return -1;
- }
- data->ssl_initialized = 1;
-
- wpa_printf(MSG_DEBUG, "EAP-TTLS: Start");
-
- return 0;
-}
-
-
static int eap_ttls_process_handshake(struct eap_sm *sm,
struct eap_ttls_data *data,
struct eap_method_ret *ret,
@@ -1725,8 +1386,7 @@ static int eap_ttls_process_handshake(struct eap_sm *sm,
ret->methodState = METHOD_MAY_CONT;
}
data->phase2_start = 1;
- if (data->ttls_version == 0)
- eap_ttls_v0_derive_key(sm, data);
+ eap_ttls_v0_derive_key(sm, data);
if (*out_data == NULL || wpabuf_len(*out_data) == 0) {
if (eap_ttls_decrypt(sm, data, ret, identifier,
@@ -1761,7 +1421,7 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm,
struct eap_ttls_data *data,
struct eap_method_ret *ret)
{
- if (data->ttls_version == 0 && ret->methodState == METHOD_DONE) {
+ if (ret->methodState == METHOD_DONE) {
ret->allowNotifications = FALSE;
if (ret->decision == DECISION_UNCOND_SUCC ||
ret->decision == DECISION_COND_SUCC) {
@@ -1779,8 +1439,7 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm,
}
#endif /* EAP_TNC */
}
- } else if (data->ttls_version == 0 &&
- ret->methodState == METHOD_MAY_CONT &&
+ } else if (ret->methodState == METHOD_MAY_CONT &&
(ret->decision == DECISION_UNCOND_SUCC ||
ret->decision == DECISION_COND_SUCC)) {
wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
@@ -1808,8 +1467,9 @@ static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv,
id = eap_get_id(reqData);
if (flags & EAP_TLS_FLAGS_START) {
- if (eap_ttls_process_start(sm, data, flags, ret) < 0)
- return NULL;
+ wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own "
+ "ver=%d)", flags & EAP_TLS_VERSION_MASK,
+ data->ttls_version);
/* RFC 5281, Ch. 9.2:
* "This packet MAY contain additional information in the form
@@ -1817,13 +1477,6 @@ static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv,
* For now, ignore any potential extra data.
*/
left = 0;
- } else if (!data->ssl_initialized) {
- wpa_printf(MSG_DEBUG, "EAP-TTLS: First message did not "
- "include Start flag");
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_FAIL;
- ret->allowNotifications = FALSE;
- return NULL;
}
resp = NULL;
diff --git a/contrib/wpa/src/eap_peer/eap_vendor_test.c b/contrib/wpa/src/eap_peer/eap_vendor_test.c
index 3e114c1..040d1e7 100644
--- a/contrib/wpa/src/eap_peer/eap_vendor_test.c
+++ b/contrib/wpa/src/eap_peer/eap_vendor_test.c
@@ -2,14 +2,8 @@
* EAP peer method: Test method for vendor specific (expanded) EAP type
* Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*
* This file implements a vendor specific test method using EAP expanded types.
* This is only for test use and must not be used for authentication since no
@@ -25,7 +19,7 @@
#endif /* TEST_PENDING_REQUEST */
-#define EAP_VENDOR_ID 0xfffefd
+#define EAP_VENDOR_ID EAP_VENDOR_HOSTAP
#define EAP_VENDOR_TYPE 0xfcfbfaf9
diff --git a/contrib/wpa/src/eap_peer/eap_wsc.c b/contrib/wpa/src/eap_peer/eap_wsc.c
index 8317f72..d007a57 100644
--- a/contrib/wpa/src/eap_peer/eap_wsc.c
+++ b/contrib/wpa/src/eap_peer/eap_wsc.c
@@ -1,15 +1,9 @@
/*
* EAP-WSC peer for Wi-Fi Protected Setup
- * Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2007-2009, 2012, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -143,6 +137,8 @@ static void * eap_wsc_init(struct eap_sm *sm)
struct wps_context *wps;
struct wps_credential new_ap_settings;
int res;
+ u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN];
+ int nfc = 0;
wps = sm->wps;
if (wps == NULL) {
@@ -190,19 +186,36 @@ static void * eap_wsc_init(struct eap_sm *sm)
while (*pos != '\0' && *pos != ' ')
pos++;
cfg.pin_len = pos - (const char *) cfg.pin;
+ if (cfg.pin_len >= WPS_OOB_DEVICE_PASSWORD_MIN_LEN * 2 &&
+ cfg.pin_len <= WPS_OOB_DEVICE_PASSWORD_LEN * 2 &&
+ hexstr2bin((const char *) cfg.pin, dev_pw,
+ cfg.pin_len / 2) == 0) {
+ /* Convert OOB Device Password to binary */
+ cfg.pin = dev_pw;
+ cfg.pin_len /= 2;
+ }
+ if (cfg.pin_len == 6 && os_strncmp(pos, "nfc-pw", 6) == 0) {
+ cfg.pin = NULL;
+ cfg.pin_len = 0;
+ nfc = 1;
+ }
} else {
pos = os_strstr(phase1, "pbc=1");
if (pos)
cfg.pbc = 1;
}
- if (cfg.pin == NULL && !cfg.pbc) {
+ if (cfg.pin == NULL && !cfg.pbc && !nfc) {
wpa_printf(MSG_INFO, "EAP-WSC: PIN or PBC not set in phase1 "
"configuration data");
os_free(data);
return NULL;
}
+ pos = os_strstr(phase1, "dev_pw_id=");
+ if (pos && cfg.pin)
+ cfg.dev_pw_id = atoi(pos + 10);
+
res = eap_wsc_new_ap_settings(&new_ap_settings, phase1);
if (res < 0) {
os_free(data);
@@ -219,10 +232,16 @@ static void * eap_wsc_init(struct eap_sm *sm)
os_free(data);
return NULL;
}
- data->fragment_size = WSC_FRAGMENT_SIZE;
+ res = eap_get_config_fragment_size(sm);
+ if (res > 0)
+ data->fragment_size = res;
+ else
+ data->fragment_size = WSC_FRAGMENT_SIZE;
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment size limit %u",
+ (unsigned int) data->fragment_size);
if (registrar && cfg.pin) {
- wps_registrar_add_pin(data->wps_ctx->registrar, NULL,
+ wps_registrar_add_pin(data->wps_ctx->registrar, NULL, NULL,
cfg.pin, cfg.pin_len, 0);
}
diff --git a/contrib/wpa/src/eap_peer/ikev2.c b/contrib/wpa/src/eap_peer/ikev2.c
index 309a331..fcf4712 100644
--- a/contrib/wpa/src/eap_peer/ikev2.c
+++ b/contrib/wpa/src/eap_peer/ikev2.c
@@ -2,20 +2,15 @@
* IKEv2 responder (RFC 4306) for EAP-IKEV2
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "crypto/dh_groups.h"
+#include "crypto/random.h"
#include "ikev2.h"
@@ -424,7 +419,7 @@ static int ikev2_process_kei(struct ikev2_responder_data *data,
}
/* RFC 4306, Section 3.4:
- * The length of DH public value MUST be equal to the lenght of the
+ * The length of DH public value MUST be equal to the length of the
* prime modulus.
*/
if (kei_len - 4 != data->dh->prime_len) {
@@ -1133,7 +1128,7 @@ static struct wpabuf * ikev2_build_sa_init(struct ikev2_responder_data *data)
data->r_spi, IKEV2_SPI_LEN);
data->r_nonce_len = IKEV2_NONCE_MIN_LEN;
- if (os_get_random(data->r_nonce, data->r_nonce_len))
+ if (random_get_bytes(data->r_nonce, data->r_nonce_len))
return NULL;
#ifdef CCNS_PL
/* Zeros are removed incorrectly from the beginning of the nonces in
diff --git a/contrib/wpa/src/eap_peer/ikev2.h b/contrib/wpa/src/eap_peer/ikev2.h
index 9ca0ca5..627a2cb 100644
--- a/contrib/wpa/src/eap_peer/ikev2.h
+++ b/contrib/wpa/src/eap_peer/ikev2.h
@@ -2,14 +2,8 @@
* IKEv2 responder (RFC 4306) for EAP-IKEV2
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef IKEV2_H
diff --git a/contrib/wpa/src/eap_peer/mschapv2.c b/contrib/wpa/src/eap_peer/mschapv2.c
index b8fb075..37e6735 100644
--- a/contrib/wpa/src/eap_peer/mschapv2.c
+++ b/contrib/wpa/src/eap_peer/mschapv2.c
@@ -2,14 +2,8 @@
* MSCHAPV2 (RFC 2759)
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -69,22 +63,28 @@ int mschapv2_derive_response(const u8 *identity, size_t identity_len,
if (pwhash) {
wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: password hash",
password, password_len);
- generate_nt_response_pwhash(auth_challenge, peer_challenge,
- username, username_len,
- password, nt_response);
- generate_authenticator_response_pwhash(
- password, peer_challenge, auth_challenge,
- username, username_len, nt_response, auth_response);
+ if (generate_nt_response_pwhash(auth_challenge, peer_challenge,
+ username, username_len,
+ password, nt_response) ||
+ generate_authenticator_response_pwhash(
+ password, peer_challenge, auth_challenge,
+ username, username_len, nt_response,
+ auth_response))
+ return -1;
} else {
wpa_hexdump_ascii_key(MSG_DEBUG, "MSCHAPV2: password",
password, password_len);
- generate_nt_response(auth_challenge, peer_challenge,
- username, username_len,
- password, password_len, nt_response);
- generate_authenticator_response(password, password_len,
- peer_challenge, auth_challenge,
- username, username_len,
- nt_response, auth_response);
+ if (generate_nt_response(auth_challenge, peer_challenge,
+ username, username_len,
+ password, password_len,
+ nt_response) ||
+ generate_authenticator_response(password, password_len,
+ peer_challenge,
+ auth_challenge,
+ username, username_len,
+ nt_response,
+ auth_response))
+ return -1;
}
wpa_hexdump(MSG_DEBUG, "MSCHAPV2: NT Response",
nt_response, MSCHAPV2_NT_RESPONSE_LEN);
@@ -100,7 +100,8 @@ int mschapv2_derive_response(const u8 *identity, size_t identity_len,
hash_nt_password_hash(password_hash, password_hash_hash))
return -1;
}
- get_master_key(password_hash_hash, nt_response, master_key);
+ if (get_master_key(password_hash_hash, nt_response, master_key))
+ return -1;
wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: Master Key",
master_key, MSCHAPV2_MASTER_KEY_LEN);
diff --git a/contrib/wpa/src/eap_peer/mschapv2.h b/contrib/wpa/src/eap_peer/mschapv2.h
index 90dad31..edd458b 100644
--- a/contrib/wpa/src/eap_peer/mschapv2.h
+++ b/contrib/wpa/src/eap_peer/mschapv2.h
@@ -2,14 +2,8 @@
* MSCHAPV2 (RFC 2759)
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef MSCHAPV2_H
diff --git a/contrib/wpa/src/eap_peer/tncc.c b/contrib/wpa/src/eap_peer/tncc.c
index eaaa168..f5edfd5 100644
--- a/contrib/wpa/src/eap_peer/tncc.c
+++ b/contrib/wpa/src/eap_peer/tncc.c
@@ -2,14 +2,8 @@
* EAP-TNC - TNCC (IF-IMC and IF-TNCCS)
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -180,11 +174,11 @@ TNC_Result TNC_TNCC_ReportMessageTypes(
imc = tnc_imc[imcID];
os_free(imc->supported_types);
imc->supported_types =
- os_malloc(typeCount * sizeof(TNC_MessageTypeList));
+ os_malloc(typeCount * sizeof(TNC_MessageType));
if (imc->supported_types == NULL)
return TNC_RESULT_FATAL;
os_memcpy(imc->supported_types, supportedTypes,
- typeCount * sizeof(TNC_MessageTypeList));
+ typeCount * sizeof(TNC_MessageType));
imc->num_supported_types = typeCount;
return TNC_RESULT_SUCCESS;
diff --git a/contrib/wpa/src/eap_peer/tncc.h b/contrib/wpa/src/eap_peer/tncc.h
index 4d42a05..df2a287 100644
--- a/contrib/wpa/src/eap_peer/tncc.h
+++ b/contrib/wpa/src/eap_peer/tncc.h
@@ -2,14 +2,8 @@
* EAP-TNC - TNCC (IF-IMC and IF-TNCCS)
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef TNCC_H
OpenPOWER on IntegriCloud