summaryrefslogtreecommitdiff
path: root/src/eap_peer/eap_fast.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/eap_peer/eap_fast.c')
-rw-r--r--src/eap_peer/eap_fast.c83
1 files changed, 59 insertions, 24 deletions
diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c
index 4cbe3bacb0a6..964ebe74fede 100644
--- a/src/eap_peer/eap_fast.c
+++ b/src/eap_peer/eap_fast.c
@@ -1,6 +1,6 @@
/*
* EAP peer method: EAP-FAST (RFC 4851)
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -67,6 +67,7 @@ struct eap_fast_data {
int simck_idx;
struct wpabuf *pending_phase2_req;
+ struct wpabuf *pending_resp;
};
@@ -112,8 +113,8 @@ static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len,
}
-static int eap_fast_parse_phase1(struct eap_fast_data *data,
- const char *phase1)
+static void eap_fast_parse_phase1(struct eap_fast_data *data,
+ const char *phase1)
{
const char *pos;
@@ -139,8 +140,6 @@ static int eap_fast_parse_phase1(struct eap_fast_data *data,
wpa_printf(MSG_DEBUG, "EAP-FAST: Using binary format for PAC "
"list");
}
-
- return 0;
}
@@ -158,10 +157,8 @@ static void * eap_fast_init(struct eap_sm *sm)
data->fast_version = EAP_FAST_VERSION;
data->max_pac_list_len = 10;
- if (config->phase1 && eap_fast_parse_phase1(data, config->phase1) < 0) {
- eap_fast_deinit(sm, data);
- return NULL;
- }
+ if (config->phase1)
+ eap_fast_parse_phase1(data, config->phase1);
if (eap_peer_select_phase2_methods(config, "auth=",
&data->phase2_types,
@@ -254,14 +251,16 @@ static void eap_fast_deinit(struct eap_sm *sm, void *priv)
os_memset(data->emsk, 0, EAP_EMSK_LEN);
os_free(data->session_id);
wpabuf_free(data->pending_phase2_req);
+ wpabuf_free(data->pending_resp);
os_free(data);
}
static int eap_fast_derive_msk(struct eap_fast_data *data)
{
- eap_fast_derive_eap_msk(data->simck, data->key_data);
- eap_fast_derive_eap_emsk(data->simck, data->emsk);
+ if (eap_fast_derive_eap_msk(data->simck, data->key_data) < 0 ||
+ eap_fast_derive_eap_emsk(data->simck, data->emsk) < 0)
+ return -1;
data->success = 1;
return 0;
}
@@ -276,7 +275,7 @@ static int eap_fast_derive_key_auth(struct eap_sm *sm,
* Extra key material after TLS key_block: session_key_seed[40]
*/
- sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, "key expansion",
+ sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn,
EAP_FAST_SKS_LEN);
if (sks == NULL) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive "
@@ -304,7 +303,6 @@ static int eap_fast_derive_key_provisioning(struct eap_sm *sm,
os_free(data->key_block_p);
data->key_block_p = (struct eap_fast_key_block_provisioning *)
eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn,
- "key expansion",
sizeof(*data->key_block_p));
if (data->key_block_p == NULL) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block");
@@ -711,9 +709,10 @@ static int eap_fast_get_cmk(struct eap_sm *sm, struct eap_fast_data *data,
if (eap_fast_get_phase2_key(sm, data, isk, sizeof(isk)) < 0)
return -1;
wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: ISK[j]", isk, sizeof(isk));
- sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,
- "Inner Methods Compound Keys",
- isk, sizeof(isk), imck, sizeof(imck));
+ if (sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,
+ "Inner Methods Compound Keys",
+ isk, sizeof(isk), imck, sizeof(imck)) < 0)
+ return -1;
data->simck_idx++;
os_memcpy(data->simck, imck, EAP_FAST_SIMCK_LEN);
wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[j]",
@@ -1096,7 +1095,7 @@ static int eap_fast_parse_decrypted(struct wpabuf *decrypted,
/* Parse TLVs from the decrypted Phase 2 data */
pos = wpabuf_mhead(decrypted);
end = pos + wpabuf_len(decrypted);
- while (pos + 4 < end) {
+ while (end - pos > 4) {
mandatory = pos[0] & 0x80;
tlv_type = WPA_GET_BE16(pos) & 0x3fff;
pos += 2;
@@ -1443,7 +1442,7 @@ static int eap_fast_clear_pac_opaque_ext(struct eap_sm *sm,
static int eap_fast_set_provisioning_ciphers(struct eap_sm *sm,
struct eap_fast_data *data)
{
- u8 ciphers[5];
+ u8 ciphers[7];
int count = 0;
if (data->provisioning_allowed & EAP_FAST_PROV_UNAUTH) {
@@ -1455,7 +1454,9 @@ static int eap_fast_set_provisioning_ciphers(struct eap_sm *sm,
if (data->provisioning_allowed & EAP_FAST_PROV_AUTH) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Enabling authenticated "
"provisioning TLS cipher suites");
+ ciphers[count++] = TLS_CIPHER_RSA_DHE_AES256_SHA;
ciphers[count++] = TLS_CIPHER_RSA_DHE_AES128_SHA;
+ ciphers[count++] = TLS_CIPHER_AES256_SHA;
ciphers[count++] = TLS_CIPHER_AES128_SHA;
ciphers[count++] = TLS_CIPHER_RC4_SHA;
}
@@ -1567,6 +1568,34 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv,
res = 1;
}
} else {
+ if (sm->waiting_ext_cert_check && data->pending_resp) {
+ struct eap_peer_config *config = eap_get_config(sm);
+
+ if (config->pending_ext_cert_check ==
+ EXT_CERT_CHECK_GOOD) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-FAST: External certificate check succeeded - continue handshake");
+ resp = data->pending_resp;
+ data->pending_resp = NULL;
+ sm->waiting_ext_cert_check = 0;
+ return resp;
+ }
+
+ if (config->pending_ext_cert_check ==
+ EXT_CERT_CHECK_BAD) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-FAST: External certificate check failed - force authentication failure");
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
+ sm->waiting_ext_cert_check = 0;
+ return NULL;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "EAP-FAST: Continuing to wait external server certificate validation");
+ return NULL;
+ }
+
/* Continue processing TLS handshake (phase 1). */
res = eap_peer_tls_process_helper(sm, &data->ssl,
EAP_TYPE_FAST,
@@ -1580,6 +1609,14 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv,
return resp;
}
+ if (sm->waiting_ext_cert_check) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-FAST: Waiting external server certificate validation");
+ wpabuf_free(data->pending_resp);
+ data->pending_resp = resp;
+ return NULL;
+ }
+
if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
char cipher[80];
wpa_printf(MSG_DEBUG,
@@ -1644,6 +1681,8 @@ static void eap_fast_deinit_for_reauth(struct eap_sm *sm, void *priv)
data->key_block_p = NULL;
wpabuf_free(data->pending_phase2_req);
data->pending_phase2_req = NULL;
+ wpabuf_free(data->pending_resp);
+ data->pending_resp = NULL;
}
@@ -1721,7 +1760,7 @@ static u8 * eap_fast_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
struct eap_fast_data *data = priv;
u8 *id;
- if (!data->success)
+ if (!data->success || !data->session_id)
return NULL;
id = os_malloc(data->id_len);
@@ -1757,7 +1796,6 @@ static u8 * eap_fast_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
int eap_peer_fast_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_FAST, "FAST");
@@ -1778,8 +1816,5 @@ int eap_peer_fast_register(void)
#endif
eap->get_emsk = eap_fast_get_emsk;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}