Revert "[wpa_supplicant] Cumulative patch from b8491ae5a"
This reverts commit 878cf7bcbf2d7d8f08c3d060b8c5fbfcf0743eda.
Reason for revert: git_master/sdk_phone_armv7-sdk
Change-Id: I6070fc5c1f9c20867f6dfce90e529e35578d572e
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index ac15e0e..974c475 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -2097,8 +2097,12 @@
}
}
- sm->eapol_cb->notify_cert(sm->eapol_ctx, &data->peer_cert,
- hash_hex);
+ sm->eapol_cb->notify_cert(sm->eapol_ctx,
+ data->peer_cert.depth,
+ data->peer_cert.subject,
+ data->peer_cert.altsubject,
+ data->peer_cert.num_altsubject,
+ hash_hex, data->peer_cert.cert);
break;
case TLS_ALERT:
if (data->alert.is_local)
@@ -2603,7 +2607,7 @@
if (vendor != EAP_VENDOR_IETF)
return 0;
return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
- type != EAP_TYPE_FAST && type != EAP_TYPE_TEAP;
+ type != EAP_TYPE_FAST;
}
diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h
index acd70d0..d0837e3 100644
--- a/src/eap_peer/eap.h
+++ b/src/eap_peer/eap.h
@@ -16,7 +16,6 @@
struct eap_sm;
struct wpa_config_blob;
struct wpabuf;
-struct tls_cert_data;
struct eap_method_type {
int vendor;
@@ -227,11 +226,16 @@
/**
* notify_cert - Notification of a peer certificate
* @ctx: eapol_ctx from eap_peer_sm_init() call
- * @cert: Certificate information
+ * @depth: Depth in certificate chain (0 = server)
+ * @subject: Subject of the peer certificate
+ * @altsubject: Select fields from AltSubject of the peer certificate
+ * @num_altsubject: Number of altsubject values
* @cert_hash: SHA-256 hash of the certificate
+ * @cert: Peer certificate
*/
- void (*notify_cert)(void *ctx, struct tls_cert_data *cert,
- const char *cert_hash);
+ void (*notify_cert)(void *ctx, int depth, const char *subject,
+ const char *altsubject[], int num_altsubject,
+ const char *cert_hash, const struct wpabuf *cert);
/**
* notify_status - Notification of the current EAP state
diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c
index f5abb79..a96a39f 100644
--- a/src/eap_peer/eap_aka.c
+++ b/src/eap_peer/eap_aka.c
@@ -31,7 +31,6 @@
u8 emsk[EAP_EMSK_LEN];
u8 rand[EAP_AKA_RAND_LEN], autn[EAP_AKA_AUTN_LEN];
u8 auts[EAP_AKA_AUTS_LEN];
- u8 reauth_mac[EAP_SIM_MAC_LEN];
int num_id_req, num_notification;
u8 *pseudonym;
@@ -58,6 +57,7 @@
u16 last_kdf_attrs[EAP_AKA_PRIME_KDF_MAX];
size_t last_kdf_count;
int error_code;
+ int anonymous_flag;
};
@@ -94,6 +94,7 @@
struct eap_aka_data *data;
const char *phase1 = eap_get_config_phase1(sm);
struct eap_peer_config *config = eap_get_config(sm);
+ static const char *anonymous_id_prefix = "anonymous@";
data = os_zalloc(sizeof(*data));
if (data == NULL)
@@ -108,6 +109,7 @@
data->prev_id = -1;
data->result_ind = phase1 && os_strstr(phase1, "result_ind=1") != NULL;
+ data->anonymous_flag = 0;
data->use_pseudonym = !sm->init_phase2;
if (config && config->anonymous_identity && data->use_pseudonym) {
@@ -116,6 +118,13 @@
os_memcpy(data->pseudonym, config->anonymous_identity,
config->anonymous_identity_len);
data->pseudonym_len = config->anonymous_identity_len;
+ if (data->pseudonym_len > os_strlen(anonymous_id_prefix) &&
+ !os_memcmp(data->pseudonym, anonymous_id_prefix,
+ os_strlen(anonymous_id_prefix))) {
+ data->anonymous_flag = 1;
+ wpa_printf(MSG_DEBUG,
+ "EAP-AKA: Setting anonymous@realm flag");
+ }
}
}
@@ -418,6 +427,7 @@
if (data->use_pseudonym)
eap_set_anon_id(sm, data->pseudonym,
data->pseudonym_len);
+ data->anonymous_flag = 0;
}
if (attr->next_reauth_id) {
@@ -623,9 +633,7 @@
identity_len = data->reauth_id_len;
data->reauth = 1;
} else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
- data->pseudonym &&
- !eap_sim_anonymous_username(data->pseudonym,
- data->pseudonym_len)) {
+ data->pseudonym && !data->anonymous_flag) {
identity = data->pseudonym;
identity_len = data->pseudonym_len;
eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID);
@@ -927,13 +935,8 @@
attr->checkcode_len)) {
wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
"message");
-#ifdef TEST_FUZZ
- wpa_printf(MSG_INFO,
- "TEST: Ignore AT_CHECKCODE mismatch for fuzz testing");
-#else /* TEST_FUZZ */
return eap_aka_client_error(data, id,
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
-#endif /* TEST_FUZZ */
}
#ifdef EAP_AKA_PRIME
@@ -1034,9 +1037,7 @@
if (data->last_eap_identity) {
identity = data->last_eap_identity;
identity_len = data->last_eap_identity_len;
- } else if (data->pseudonym &&
- !eap_sim_anonymous_username(data->pseudonym,
- data->pseudonym_len)) {
+ } else if (data->pseudonym && !data->anonymous_flag) {
identity = data->pseudonym;
identity_len = data->pseudonym_len;
} else {
@@ -1065,13 +1066,8 @@
if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) {
wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
"used invalid AT_MAC");
-#ifdef TEST_FUZZ
- wpa_printf(MSG_INFO,
- "TEST: Ignore AT_MAC mismatch for fuzz testing");
-#else /* TEST_FUZZ */
return eap_aka_client_error(data, id,
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
-#endif /* TEST_FUZZ */
}
/* Old reauthentication identity must not be used anymore. In
@@ -1220,13 +1216,8 @@
if (attr->checkcode &&
eap_aka_verify_checkcode(data, attr->checkcode,
attr->checkcode_len)) {
-#ifdef TEST_FUZZ
- wpa_printf(MSG_INFO,
- "TEST: Ignore AT_CHECKCODE mismatch for fuzz testing");
-#else /* TEST_FUZZ */
wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
"message");
-#endif /* TEST_FUZZ */
return eap_aka_client_error(data, id,
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
}
@@ -1246,14 +1237,6 @@
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
}
- /* At this stage the received MAC has been verified. Use this MAC for
- * reauth Session-Id calculation if all other checks pass.
- * The peer does not use the local MAC but the received MAC in deriving
- * Session-Id. */
- os_memcpy(data->reauth_mac, attr->mac, EAP_SIM_MAC_LEN);
- wpa_hexdump(MSG_DEBUG, "EAP-AKA: Server MAC",
- data->reauth_mac, EAP_SIM_MAC_LEN);
-
if (attr->encr_data == NULL || attr->iv == NULL) {
wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
"message did not include encrypted data");
@@ -1525,24 +1508,14 @@
if (data->state != SUCCESS)
return NULL;
- if (!data->reauth)
- *len = 1 + EAP_AKA_RAND_LEN + EAP_AKA_AUTN_LEN;
- else
- *len = 1 + EAP_SIM_NONCE_S_LEN + EAP_SIM_MAC_LEN;
+ *len = 1 + EAP_AKA_RAND_LEN + EAP_AKA_AUTN_LEN;
id = os_malloc(*len);
if (id == NULL)
return NULL;
id[0] = data->eap_method;
- if (!data->reauth) {
- os_memcpy(id + 1, data->rand, EAP_AKA_RAND_LEN);
- os_memcpy(id + 1 + EAP_AKA_RAND_LEN, data->autn,
- EAP_AKA_AUTN_LEN);
- } else {
- os_memcpy(id + 1, data->nonce_s, EAP_SIM_NONCE_S_LEN);
- os_memcpy(id + 1 + EAP_SIM_NONCE_S_LEN, data->reauth_mac,
- EAP_SIM_MAC_LEN);
- }
+ os_memcpy(id + 1, data->rand, EAP_AKA_RAND_LEN);
+ os_memcpy(id + 1 + EAP_AKA_RAND_LEN, data->autn, EAP_AKA_AUTN_LEN);
wpa_hexdump(MSG_DEBUG, "EAP-AKA: Derived Session-Id", id, *len);
return id;
diff --git a/src/eap_peer/eap_config.h b/src/eap_peer/eap_config.h
index 148c906..3a88f2a 100644
--- a/src/eap_peer/eap_config.h
+++ b/src/eap_peer/eap_config.h
@@ -816,8 +816,6 @@
EXT_CERT_CHECK_GOOD,
EXT_CERT_CHECK_BAD,
} pending_ext_cert_check;
-
- int teap_anon_dh;
};
diff --git a/src/eap_peer/eap_eke.c b/src/eap_peer/eap_eke.c
index 534af26..0de7d6c 100644
--- a/src/eap_peer/eap_eke.c
+++ b/src/eap_peer/eap_eke.c
@@ -414,7 +414,7 @@
*/
if (eap_eke_dh_init(data->sess.dhgroup, data->dh_priv, pub) < 0) {
wpa_printf(MSG_INFO, "EAP-EKE: Failed to initialize DH");
- forced_memzero(key, sizeof(key));
+ os_memset(key, 0, sizeof(key));
return eap_eke_build_fail(data, ret, id,
EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
}
@@ -422,7 +422,7 @@
if (eap_eke_shared_secret(&data->sess, key, data->dh_priv, dhcomp) < 0)
{
wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive shared secret");
- forced_memzero(key, sizeof(key));
+ os_memset(key, 0, sizeof(key));
return eap_eke_build_fail(data, ret, id,
EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
}
@@ -431,7 +431,7 @@
data->serverid, data->serverid_len,
data->peerid, data->peerid_len) < 0) {
wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki");
- forced_memzero(key, sizeof(key));
+ os_memset(key, 0, sizeof(key));
return eap_eke_build_fail(data, ret, id,
EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
}
@@ -442,7 +442,7 @@
data->sess.dhcomp_len + data->sess.pnonce_len,
EAP_EKE_COMMIT);
if (resp == NULL) {
- forced_memzero(key, sizeof(key));
+ os_memset(key, 0, sizeof(key));
return eap_eke_build_fail(data, ret, id,
EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
}
@@ -452,11 +452,11 @@
if (eap_eke_dhcomp(&data->sess, key, pub, rpos) < 0) {
wpabuf_free(resp);
wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_P");
- forced_memzero(key, sizeof(key));
+ os_memset(key, 0, sizeof(key));
return eap_eke_build_fail(data, ret, id,
EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
}
- forced_memzero(key, sizeof(key));
+ os_memset(key, 0, sizeof(key));
wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_P",
rpos, data->sess.dhcomp_len);
diff --git a/src/eap_peer/eap_leap.c b/src/eap_peer/eap_leap.c
index 34758e0..233b9ee 100644
--- a/src/eap_peer/eap_leap.c
+++ b/src/eap_peer/eap_leap.c
@@ -390,8 +390,8 @@
wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: master key", key, LEAP_KEY_LEN);
*len = LEAP_KEY_LEN;
- forced_memzero(pw_hash, sizeof(pw_hash));
- forced_memzero(pw_hash_hash, sizeof(pw_hash_hash));
+ os_memset(pw_hash, 0, sizeof(pw_hash));
+ os_memset(pw_hash_hash, 0, sizeof(pw_hash_hash));
return key;
}
diff --git a/src/eap_peer/eap_methods.h b/src/eap_peer/eap_methods.h
index 09e08d3..b96b211 100644
--- a/src/eap_peer/eap_methods.h
+++ b/src/eap_peer/eap_methods.h
@@ -97,7 +97,6 @@
int eap_peer_aka_register(void);
int eap_peer_aka_prime_register(void);
int eap_peer_fast_register(void);
-int eap_peer_teap_register(void);
int eap_peer_pax_register(void);
int eap_peer_sake_register(void);
int eap_peer_gpsk_register(void);
diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c
index 6453afe..8dcf7cc 100644
--- a/src/eap_peer/eap_peap.c
+++ b/src/eap_peer/eap_peap.c
@@ -295,7 +295,7 @@
res = peap_prfplus(data->peap_version, tk, 40,
"Inner Methods Compound Keys",
isk, sizeof(isk), imck, sizeof(imck));
- forced_memzero(isk, sizeof(isk));
+ os_memset(isk, 0, sizeof(isk));
if (res < 0)
return -1;
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
@@ -305,7 +305,7 @@
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
os_memcpy(data->cmk, imck + 40, 20);
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
- forced_memzero(imck, sizeof(imck));
+ os_memset(imck, 0, sizeof(imck));
return 0;
}
@@ -1267,7 +1267,7 @@
os_memcpy(key, csk, EAP_TLS_KEY_LEN);
wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
key, EAP_TLS_KEY_LEN);
- forced_memzero(csk, sizeof(csk));
+ os_memset(csk, 0, sizeof(csk));
} else
os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
index 6cd72e0..76fcad4 100644
--- a/src/eap_peer/eap_pwd.c
+++ b/src/eap_peer/eap_pwd.c
@@ -362,7 +362,7 @@
data->password_len, pwhash);
if (res == 0)
res = hash_nt_password_hash(pwhash, pwhashhash);
- forced_memzero(pwhash, sizeof(pwhash));
+ os_memset(pwhash, 0, sizeof(pwhash));
}
if (res) {
@@ -514,8 +514,8 @@
data->id_server, data->id_server_len,
data->id_peer, data->id_peer_len,
data->token);
- forced_memzero(pwhashhash, sizeof(pwhashhash));
- forced_memzero(salthashpwd, sizeof(salthashpwd));
+ os_memset(pwhashhash, 0, sizeof(pwhashhash));
+ os_memset(salthashpwd, 0, sizeof(salthashpwd));
if (res) {
wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute PWE");
eap_pwd_state(data, FAILURE);
diff --git a/src/eap_peer/eap_sake.c b/src/eap_peer/eap_sake.c
index 255241f..0a6ce25 100644
--- a/src/eap_peer/eap_sake.c
+++ b/src/eap_peer/eap_sake.c
@@ -1,6 +1,6 @@
/*
* EAP peer method: EAP-SAKE (RFC 4763)
- * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -235,13 +235,9 @@
data->serverid_len = attr.serverid_len;
}
- if (eap_sake_derive_keys(data->root_secret_a, data->root_secret_b,
- data->rand_s, data->rand_p,
- (u8 *) &data->tek, data->msk,
- data->emsk) < 0) {
- wpa_printf(MSG_INFO, "EAP-SAKE: Failed to derive keys");
- return NULL;
- }
+ eap_sake_derive_keys(data->root_secret_a, data->root_secret_b,
+ data->rand_s, data->rand_p,
+ (u8 *) &data->tek, data->msk, data->emsk);
wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Challenge");
diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c
index c4070ab..6989aa8 100644
--- a/src/eap_peer/eap_sim.c
+++ b/src/eap_peer/eap_sim.c
@@ -32,7 +32,6 @@
u8 msk[EAP_SIM_KEYING_DATA_LEN];
u8 emsk[EAP_EMSK_LEN];
u8 rand[3][GSM_RAND_LEN];
- u8 reauth_mac[EAP_SIM_MAC_LEN];
int num_id_req, num_notification;
u8 *pseudonym;
@@ -49,6 +48,7 @@
int result_ind, use_result_ind;
int use_pseudonym;
int error_code;
+ int anonymous_flag;
};
@@ -84,6 +84,7 @@
{
struct eap_sim_data *data;
struct eap_peer_config *config = eap_get_config(sm);
+ static const char *anonymous_id_prefix = "anonymous@";
data = os_zalloc(sizeof(*data));
if (data == NULL)
@@ -98,7 +99,7 @@
/* Zero is a valid error code, so we need to initialize */
data->error_code = NO_EAP_METHOD_ERROR;
-
+ data->anonymous_flag = 0;
data->min_num_chal = 2;
if (config && config->phase1) {
char *pos = os_strstr(config->phase1, "sim_min_num_chal=");
@@ -128,6 +129,14 @@
os_memcpy(data->pseudonym, config->anonymous_identity,
config->anonymous_identity_len);
data->pseudonym_len = config->anonymous_identity_len;
+ if (data->pseudonym_len > os_strlen(anonymous_id_prefix) &&
+ !os_memcmp(data->pseudonym, anonymous_id_prefix,
+ os_strlen(anonymous_id_prefix))) {
+ data->anonymous_flag = 1;
+ wpa_printf(MSG_DEBUG,
+ "EAP-SIM: Setting anonymous@realm flag");
+ }
+
}
}
@@ -438,6 +447,7 @@
if (data->use_pseudonym)
eap_set_anon_id(sm, data->pseudonym,
data->pseudonym_len);
+ data->anonymous_flag = 0;
}
if (attr->next_reauth_id) {
@@ -493,9 +503,7 @@
identity_len = data->reauth_id_len;
data->reauth = 1;
} else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
- data->pseudonym &&
- !eap_sim_anonymous_username(data->pseudonym,
- data->pseudonym_len)) {
+ data->pseudonym && !data->anonymous_flag) {
identity = data->pseudonym;
identity_len = data->pseudonym_len;
eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID);
@@ -771,9 +779,7 @@
if (data->last_eap_identity) {
identity = data->last_eap_identity;
identity_len = data->last_eap_identity_len;
- } else if (data->pseudonym &&
- !eap_sim_anonymous_username(data->pseudonym,
- data->pseudonym_len)) {
+ } else if (data->pseudonym && !data->anonymous_flag) {
identity = data->pseudonym;
identity_len = data->pseudonym_len;
} else {
@@ -799,13 +805,8 @@
EAP_SIM_NONCE_MT_LEN)) {
wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
"used invalid AT_MAC");
-#ifdef TEST_FUZZ
- wpa_printf(MSG_INFO,
- "TEST: Ignore AT_MAC mismatch for fuzz testing");
-#else /* TEST_FUZZ */
return eap_sim_client_error(data, id,
EAP_SIM_UNABLE_TO_PROCESS_PACKET);
-#endif /* TEST_FUZZ */
}
/* Old reauthentication identity must not be used anymore. In
@@ -964,30 +965,10 @@
{
wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
"did not have valid AT_MAC");
-#ifdef TEST_FUZZ
- wpa_printf(MSG_INFO,
- "TEST: Ignore AT_MAC mismatch for fuzz testing");
-#else /* TEST_FUZZ */
return eap_sim_client_error(data, id,
EAP_SIM_UNABLE_TO_PROCESS_PACKET);
-#endif /* TEST_FUZZ */
}
- /* At this stage the received MAC has been verified. Use this MAC for
- * reauth Session-Id calculation if all other checks pass.
- * The peer does not use the local MAC but the received MAC in deriving
- * Session-Id. */
-#ifdef TEST_FUZZ
- if (attr->mac)
- os_memcpy(data->reauth_mac, attr->mac, EAP_SIM_MAC_LEN);
- else
- os_memset(data->reauth_mac, 0x12, EAP_SIM_MAC_LEN);
-#else /* TEST_FUZZ */
- os_memcpy(data->reauth_mac, attr->mac, EAP_SIM_MAC_LEN);
-#endif /* TEST_FUZZ */
- wpa_hexdump(MSG_DEBUG, "EAP-SIM: Server MAC",
- data->reauth_mac, EAP_SIM_MAC_LEN);
-
if (attr->encr_data == NULL || attr->iv == NULL) {
wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
"message did not include encrypted data");
@@ -1246,24 +1227,15 @@
if (data->state != SUCCESS)
return NULL;
- if (!data->reauth)
- *len = 1 + data->num_chal * GSM_RAND_LEN + EAP_SIM_NONCE_MT_LEN;
- else
- *len = 1 + EAP_SIM_NONCE_S_LEN + EAP_SIM_MAC_LEN;
+ *len = 1 + data->num_chal * GSM_RAND_LEN + EAP_SIM_NONCE_MT_LEN;
id = os_malloc(*len);
if (id == NULL)
return NULL;
id[0] = EAP_TYPE_SIM;
- if (!data->reauth) {
- os_memcpy(id + 1, data->rand, data->num_chal * GSM_RAND_LEN);
- os_memcpy(id + 1 + data->num_chal * GSM_RAND_LEN,
- data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
- } else {
- os_memcpy(id + 1, data->nonce_s, EAP_SIM_NONCE_S_LEN);
- os_memcpy(id + 1 + EAP_SIM_NONCE_S_LEN, data->reauth_mac,
- EAP_SIM_MAC_LEN);
- }
+ os_memcpy(id + 1, data->rand, data->num_chal * GSM_RAND_LEN);
+ os_memcpy(id + 1 + data->num_chal * GSM_RAND_LEN, data->nonce_mt,
+ EAP_SIM_NONCE_MT_LEN);
wpa_hexdump(MSG_DEBUG, "EAP-SIM: Derived Session-Id", id, *len);
return id;
diff --git a/src/eap_peer/eap_teap.c b/src/eap_peer/eap_teap.c
deleted file mode 100644
index eea7d6e..0000000
--- a/src/eap_peer/eap_teap.c
+++ /dev/null
@@ -1,2021 +0,0 @@
-/*
- * EAP peer method: EAP-TEAP (RFC 7170)
- * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
- *
- * 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/tls.h"
-#include "eap_common/eap_teap_common.h"
-#include "eap_i.h"
-#include "eap_tls_common.h"
-#include "eap_config.h"
-#include "eap_teap_pac.h"
-
-#ifdef EAP_TEAP_DYNAMIC
-#include "eap_teap_pac.c"
-#endif /* EAP_TEAP_DYNAMIC */
-
-
-static void eap_teap_deinit(struct eap_sm *sm, void *priv);
-
-
-struct eap_teap_data {
- struct eap_ssl_data ssl;
-
- u8 teap_version; /* Negotiated version */
- u8 received_version; /* Version number received during negotiation */
- u16 tls_cs;
-
- const struct eap_method *phase2_method;
- void *phase2_priv;
- int phase2_success;
- int inner_method_done;
- int result_success_done;
-
- struct eap_method_type phase2_type;
- struct eap_method_type *phase2_types;
- size_t num_phase2_types;
- int resuming; /* starting a resumed session */
-#define EAP_TEAP_PROV_UNAUTH 1
-#define EAP_TEAP_PROV_AUTH 2
- int provisioning_allowed; /* Allowed PAC provisioning modes */
- int provisioning; /* doing PAC provisioning (not the normal auth) */
- int anon_provisioning; /* doing anonymous (unauthenticated)
- * provisioning */
- int session_ticket_used;
- int test_outer_tlvs;
-
- u8 key_data[EAP_TEAP_KEY_LEN];
- u8 *session_id;
- size_t id_len;
- u8 emsk[EAP_EMSK_LEN];
- int success;
-
- struct eap_teap_pac *pac;
- struct eap_teap_pac *current_pac;
- size_t max_pac_list_len;
- int use_pac_binary_format;
-
- u8 simck_msk[EAP_TEAP_SIMCK_LEN];
- u8 simck_emsk[EAP_TEAP_SIMCK_LEN];
- int simck_idx;
- int cmk_emsk_available;
-
- struct wpabuf *pending_phase2_req;
- struct wpabuf *pending_resp;
- struct wpabuf *server_outer_tlvs;
- struct wpabuf *peer_outer_tlvs;
-};
-
-
-static int eap_teap_session_ticket_cb(void *ctx, const u8 *ticket, size_t len,
- const u8 *client_random,
- const u8 *server_random,
- u8 *master_secret)
-{
- struct eap_teap_data *data = ctx;
-
- wpa_printf(MSG_DEBUG, "EAP-TEAP: SessionTicket callback");
-
- if (!master_secret) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: SessionTicket failed - fall back to full TLS handshake");
- data->session_ticket_used = 0;
- if (data->provisioning_allowed) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Try to provision a new PAC-Key");
- data->provisioning = 1;
- data->current_pac = NULL;
- }
- return 0;
- }
-
- wpa_hexdump(MSG_DEBUG, "EAP-TEAP: SessionTicket", ticket, len);
-
- if (!data->current_pac) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: No PAC-Key available for using SessionTicket");
- data->session_ticket_used = 0;
- return 0;
- }
-
- /* EAP-TEAP uses PAC-Key as the TLS master_secret */
- os_memcpy(master_secret, data->current_pac->pac_key,
- EAP_TEAP_PAC_KEY_LEN);
-
- data->session_ticket_used = 1;
-
- return 1;
-}
-
-
-static void eap_teap_parse_phase1(struct eap_teap_data *data,
- const char *phase1)
-{
- const char *pos;
-
- pos = os_strstr(phase1, "teap_provisioning=");
- if (pos) {
- data->provisioning_allowed = atoi(pos + 18);
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Automatic PAC provisioning mode: %d",
- data->provisioning_allowed);
- }
-
- pos = os_strstr(phase1, "teap_max_pac_list_len=");
- if (pos) {
- data->max_pac_list_len = atoi(pos + 22);
- if (data->max_pac_list_len == 0)
- data->max_pac_list_len = 1;
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Maximum PAC list length: %lu",
- (unsigned long) data->max_pac_list_len);
- }
-
- if (os_strstr(phase1, "teap_pac_format=binary")) {
- data->use_pac_binary_format = 1;
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Using binary format for PAC list");
- }
-
-#ifdef CONFIG_TESTING_OPTIONS
- if (os_strstr(phase1, "teap_test_outer_tlvs=1"))
- data->test_outer_tlvs = 1;
-#endif /* CONFIG_TESTING_OPTIONS */
-}
-
-
-static void * eap_teap_init(struct eap_sm *sm)
-{
- struct eap_teap_data *data;
- struct eap_peer_config *config = eap_get_config(sm);
-
- if (!config)
- return NULL;
-
- data = os_zalloc(sizeof(*data));
- if (!data)
- return NULL;
- data->teap_version = EAP_TEAP_VERSION;
- data->max_pac_list_len = 10;
-
- if (config->phase1)
- eap_teap_parse_phase1(data, config->phase1);
-
- if ((data->provisioning_allowed & EAP_TEAP_PROV_AUTH) &&
- !config->ca_cert && !config->ca_path) {
- /* Prevent PAC provisioning without mutual authentication
- * (either by validating server certificate or by suitable
- * inner EAP method). */
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Disable authenticated provisioning due to no ca_cert/ca_path");
- data->provisioning_allowed &= ~EAP_TEAP_PROV_AUTH;
- }
-
- if (eap_peer_select_phase2_methods(config, "auth=",
- &data->phase2_types,
- &data->num_phase2_types) < 0) {
- eap_teap_deinit(sm, data);
- return NULL;
- }
-
- data->phase2_type.vendor = EAP_VENDOR_IETF;
- data->phase2_type.method = EAP_TYPE_NONE;
-
- config->teap_anon_dh = !!(data->provisioning_allowed &
- EAP_TEAP_PROV_UNAUTH);
- if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TEAP)) {
- wpa_printf(MSG_INFO, "EAP-TEAP: Failed to initialize SSL");
- eap_teap_deinit(sm, data);
- return NULL;
- }
-
- if (tls_connection_set_session_ticket_cb(sm->ssl_ctx, data->ssl.conn,
- eap_teap_session_ticket_cb,
- data) < 0) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Failed to set SessionTicket callback");
- eap_teap_deinit(sm, data);
- return NULL;
- }
-
- if (!config->pac_file) {
- wpa_printf(MSG_INFO, "EAP-TEAP: No PAC file configured");
- eap_teap_deinit(sm, data);
- return NULL;
- }
-
- if (data->use_pac_binary_format &&
- eap_teap_load_pac_bin(sm, &data->pac, config->pac_file) < 0) {
- wpa_printf(MSG_INFO, "EAP-TEAP: Failed to load PAC file");
- eap_teap_deinit(sm, data);
- return NULL;
- }
-
- if (!data->use_pac_binary_format &&
- eap_teap_load_pac(sm, &data->pac, config->pac_file) < 0) {
- wpa_printf(MSG_INFO, "EAP-TEAP: Failed to load PAC file");
- eap_teap_deinit(sm, data);
- return NULL;
- }
- eap_teap_pac_list_truncate(data->pac, data->max_pac_list_len);
-
- return data;
-}
-
-
-static void eap_teap_clear(struct eap_teap_data *data)
-{
- forced_memzero(data->key_data, EAP_TEAP_KEY_LEN);
- forced_memzero(data->emsk, EAP_EMSK_LEN);
- os_free(data->session_id);
- data->session_id = NULL;
- wpabuf_free(data->pending_phase2_req);
- data->pending_phase2_req = NULL;
- wpabuf_free(data->pending_resp);
- data->pending_resp = NULL;
- wpabuf_free(data->server_outer_tlvs);
- data->server_outer_tlvs = NULL;
- wpabuf_free(data->peer_outer_tlvs);
- data->peer_outer_tlvs = NULL;
- forced_memzero(data->simck_msk, EAP_TEAP_SIMCK_LEN);
- forced_memzero(data->simck_emsk, EAP_TEAP_SIMCK_LEN);
-}
-
-
-static void eap_teap_deinit(struct eap_sm *sm, void *priv)
-{
- struct eap_teap_data *data = priv;
- struct eap_teap_pac *pac, *prev;
-
- if (!data)
- return;
- if (data->phase2_priv && data->phase2_method)
- data->phase2_method->deinit(sm, data->phase2_priv);
- eap_teap_clear(data);
- os_free(data->phase2_types);
- eap_peer_tls_ssl_deinit(sm, &data->ssl);
-
- pac = data->pac;
- prev = NULL;
- while (pac) {
- prev = pac;
- pac = pac->next;
- eap_teap_free_pac(prev);
- }
-
- os_free(data);
-}
-
-
-static int eap_teap_derive_msk(struct eap_teap_data *data)
-{
- /* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
- * is used in this derivation */
- if (eap_teap_derive_eap_msk(data->simck_msk, data->key_data) < 0 ||
- eap_teap_derive_eap_emsk(data->simck_msk, data->emsk) < 0)
- return -1;
- data->success = 1;
- return 0;
-}
-
-
-static int eap_teap_derive_key_auth(struct eap_sm *sm,
- struct eap_teap_data *data)
-{
- int res;
-
- /* RFC 7170, Section 5.1 */
- res = tls_connection_export_key(sm->ssl_ctx, data->ssl.conn,
- TEAP_TLS_EXPORTER_LABEL_SKS, NULL, 0,
- data->simck_msk, EAP_TEAP_SIMCK_LEN);
- if (res)
- return res;
- wpa_hexdump_key(MSG_DEBUG,
- "EAP-TEAP: session_key_seed (S-IMCK[0])",
- data->simck_msk, EAP_TEAP_SIMCK_LEN);
- os_memcpy(data->simck_emsk, data->simck_msk, EAP_TEAP_SIMCK_LEN);
- data->simck_idx = 0;
- return 0;
-}
-
-
-static int eap_teap_init_phase2_method(struct eap_sm *sm,
- struct eap_teap_data *data)
-{
- data->inner_method_done = 0;
- data->phase2_method =
- eap_peer_get_eap_method(data->phase2_type.vendor,
- data->phase2_type.method);
- if (!data->phase2_method)
- return -1;
-
- sm->init_phase2 = 1;
- data->phase2_priv = data->phase2_method->init(sm);
- sm->init_phase2 = 0;
-
- return data->phase2_priv == NULL ? -1 : 0;
-}
-
-
-static int eap_teap_select_phase2_method(struct eap_teap_data *data, u8 type)
-{
- size_t i;
-
- /* TODO: TNC with anonymous provisioning; need to require both
- * completed inner EAP authentication (EAP-pwd or EAP-EKE) and TNC */
-
- if (data->anon_provisioning &&
- !eap_teap_allowed_anon_prov_phase2_method(type)) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: EAP type %u not allowed during unauthenticated provisioning",
- type);
- return -1;
- }
-
-#ifdef EAP_TNC
- if (type == EAP_TYPE_TNC) {
- data->phase2_type.vendor = EAP_VENDOR_IETF;
- data->phase2_type.method = EAP_TYPE_TNC;
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Selected Phase 2 EAP vendor %d method %d for TNC",
- data->phase2_type.vendor,
- data->phase2_type.method);
- return 0;
- }
-#endif /* EAP_TNC */
-
- for (i = 0; i < data->num_phase2_types; i++) {
- if (data->phase2_types[i].vendor != EAP_VENDOR_IETF ||
- data->phase2_types[i].method != type)
- continue;
-
- data->phase2_type.vendor = data->phase2_types[i].vendor;
- data->phase2_type.method = data->phase2_types[i].method;
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Selected Phase 2 EAP vendor %d method %d",
- data->phase2_type.vendor,
- data->phase2_type.method);
- break;
- }
-
- if (type != data->phase2_type.method || type == EAP_TYPE_NONE)
- return -1;
-
- return 0;
-}
-
-
-static int eap_teap_phase2_request(struct eap_sm *sm,
- struct eap_teap_data *data,
- struct eap_method_ret *ret,
- struct eap_hdr *hdr,
- struct wpabuf **resp)
-{
- size_t len = be_to_host16(hdr->length);
- u8 *pos;
- struct eap_method_ret iret;
- struct eap_peer_config *config = eap_get_config(sm);
- struct wpabuf msg;
-
- if (len <= sizeof(struct eap_hdr)) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: too short Phase 2 request (len=%lu)",
- (unsigned long) len);
- return -1;
- }
- pos = (u8 *) (hdr + 1);
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 Request: type=%d", *pos);
- if (*pos == EAP_TYPE_IDENTITY) {
- *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
- return 0;
- }
-
- if (data->phase2_priv && data->phase2_method &&
- *pos != data->phase2_type.method) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Phase 2 EAP sequence - deinitialize previous method");
- data->phase2_method->deinit(sm, data->phase2_priv);
- data->phase2_method = NULL;
- data->phase2_priv = NULL;
- data->phase2_type.vendor = EAP_VENDOR_IETF;
- data->phase2_type.method = EAP_TYPE_NONE;
- }
-
- if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
- data->phase2_type.method == EAP_TYPE_NONE &&
- eap_teap_select_phase2_method(data, *pos) < 0) {
- if (eap_peer_tls_phase2_nak(data->phase2_types,
- data->num_phase2_types,
- hdr, resp))
- return -1;
- return 0;
- }
-
- if ((!data->phase2_priv && eap_teap_init_phase2_method(sm, data) < 0) ||
- !data->phase2_method) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Failed to initialize Phase 2 EAP method %d",
- *pos);
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_FAIL;
- return -1;
- }
-
- os_memset(&iret, 0, sizeof(iret));
- wpabuf_set(&msg, hdr, len);
- *resp = data->phase2_method->process(sm, data->phase2_priv, &iret,
- &msg);
- if (iret.methodState == METHOD_DONE)
- data->inner_method_done = 1;
- if (!(*resp) ||
- (iret.methodState == METHOD_DONE &&
- iret.decision == DECISION_FAIL)) {
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_FAIL;
- } else if ((iret.methodState == METHOD_DONE ||
- iret.methodState == METHOD_MAY_CONT) &&
- (iret.decision == DECISION_UNCOND_SUCC ||
- iret.decision == DECISION_COND_SUCC)) {
- data->phase2_success = 1;
- }
-
- if (!(*resp) && config &&
- (config->pending_req_identity || config->pending_req_password ||
- config->pending_req_otp || config->pending_req_new_password ||
- config->pending_req_sim)) {
- wpabuf_free(data->pending_phase2_req);
- data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
- } else if (!(*resp))
- return -1;
-
- return 0;
-}
-
-
-static struct wpabuf * eap_teap_tlv_nak(int vendor_id, int tlv_type)
-{
- struct wpabuf *buf;
- struct teap_tlv_nak *nak;
-
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Add NAK TLV (Vendor-Id %u NAK-Type %u)",
- vendor_id, tlv_type);
- buf = wpabuf_alloc(sizeof(*nak));
- if (!buf)
- return NULL;
- nak = wpabuf_put(buf, sizeof(*nak));
- nak->tlv_type = host_to_be16(TEAP_TLV_MANDATORY | TEAP_TLV_NAK);
- nak->length = host_to_be16(6);
- nak->vendor_id = host_to_be32(vendor_id);
- nak->nak_type = host_to_be16(tlv_type);
- return buf;
-}
-
-
-static struct wpabuf * eap_teap_tlv_pac_ack(void)
-{
- struct wpabuf *buf;
- struct teap_tlv_result *res;
- struct teap_tlv_pac_ack *ack;
-
- buf = wpabuf_alloc(sizeof(*res) + sizeof(*ack));
- if (!buf)
- return NULL;
-
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Add PAC TLV (ack)");
- ack = wpabuf_put(buf, sizeof(*ack));
- ack->tlv_type = host_to_be16(TEAP_TLV_PAC | TEAP_TLV_MANDATORY);
- ack->length = host_to_be16(sizeof(*ack) - sizeof(struct teap_tlv_hdr));
- ack->pac_type = host_to_be16(PAC_TYPE_PAC_ACKNOWLEDGEMENT);
- ack->pac_len = host_to_be16(2);
- ack->result = host_to_be16(TEAP_STATUS_SUCCESS);
-
- return buf;
-}
-
-
-static struct wpabuf * eap_teap_process_eap_payload_tlv(
- struct eap_sm *sm, struct eap_teap_data *data,
- struct eap_method_ret *ret,
- u8 *eap_payload_tlv, size_t eap_payload_tlv_len)
-{
- struct eap_hdr *hdr;
- struct wpabuf *resp = NULL;
-
- if (eap_payload_tlv_len < sizeof(*hdr)) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: too short EAP Payload TLV (len=%lu)",
- (unsigned long) eap_payload_tlv_len);
- return NULL;
- }
-
- hdr = (struct eap_hdr *) eap_payload_tlv;
- if (be_to_host16(hdr->length) > eap_payload_tlv_len) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: EAP packet overflow in EAP Payload TLV");
- return NULL;
- }
-
- if (hdr->code != EAP_CODE_REQUEST) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Unexpected code=%d in Phase 2 EAP header",
- hdr->code);
- return NULL;
- }
-
- if (eap_teap_phase2_request(sm, data, ret, hdr, &resp)) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Phase 2 Request processing failed");
- return NULL;
- }
-
- return eap_teap_tlv_eap_payload(resp);
-}
-
-
-static struct wpabuf * eap_teap_process_basic_auth_req(
- struct eap_sm *sm, struct eap_teap_data *data,
- u8 *basic_auth_req, size_t basic_auth_req_len)
-{
- const u8 *identity, *password;
- size_t identity_len, password_len, plen;
- struct wpabuf *resp;
-
- wpa_hexdump_ascii(MSG_DEBUG, "EAP-TEAP: Basic-Password-Auth-Req prompt",
- basic_auth_req, basic_auth_req_len);
- /* TODO: send over control interface */
-
- identity = eap_get_config_identity(sm, &identity_len);
- password = eap_get_config_password(sm, &password_len);
- if (!identity || !password ||
- identity_len > 255 || password_len > 255) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: No username/password suitable for Basic-Password-Auth");
- return eap_teap_tlv_nak(0, TEAP_TLV_BASIC_PASSWORD_AUTH_REQ);
- }
-
- plen = 1 + identity_len + 1 + password_len;
- resp = wpabuf_alloc(sizeof(struct teap_tlv_hdr) + plen);
- if (!resp)
- return NULL;
- eap_teap_put_tlv_hdr(resp, TEAP_TLV_BASIC_PASSWORD_AUTH_RESP, plen);
- wpabuf_put_u8(resp, identity_len);
- wpabuf_put_data(resp, identity, identity_len);
- wpabuf_put_u8(resp, password_len);
- wpabuf_put_data(resp, password, password_len);
- wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TEAP: Basic-Password-Auth-Resp",
- resp);
-
- /* Assume this succeeds so that Result TLV(Success) from the server can
- * be used to terminate TEAP. */
- data->phase2_success = 1;
-
- return resp;
-}
-
-
-static int
-eap_teap_validate_crypto_binding(struct eap_teap_data *data,
- const struct teap_tlv_crypto_binding *cb)
-{
- u8 flags, subtype;
-
- subtype = cb->subtype & 0x0f;
- flags = cb->subtype >> 4;
-
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
- cb->version, cb->received_version, flags, subtype);
- wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Nonce",
- cb->nonce, sizeof(cb->nonce));
- wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: EMSK Compound MAC",
- cb->emsk_compound_mac, sizeof(cb->emsk_compound_mac));
- wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: MSK Compound MAC",
- cb->msk_compound_mac, sizeof(cb->msk_compound_mac));
-
- if (cb->version != EAP_TEAP_VERSION ||
- cb->received_version != data->received_version ||
- subtype != TEAP_CRYPTO_BINDING_SUBTYPE_REQUEST ||
- flags < 1 || flags > 3) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Invalid Version/Flags/Sub-Type in Crypto-Binding TLV: Version %u Received Version %u Flags %u Sub-Type %u",
- cb->version, cb->received_version, flags, subtype);
- return -1;
- }
-
- if (cb->nonce[EAP_TEAP_NONCE_LEN - 1] & 0x01) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Invalid Crypto-Binding TLV Nonce in request");
- return -1;
- }
-
- return 0;
-}
-
-
-static int eap_teap_write_crypto_binding(
- struct eap_teap_data *data,
- struct teap_tlv_crypto_binding *rbind,
- const struct teap_tlv_crypto_binding *cb,
- const u8 *cmk_msk, const u8 *cmk_emsk)
-{
- u8 subtype, flags;
-
- rbind->tlv_type = host_to_be16(TEAP_TLV_MANDATORY |
- TEAP_TLV_CRYPTO_BINDING);
- rbind->length = host_to_be16(sizeof(*rbind) -
- sizeof(struct teap_tlv_hdr));
- rbind->version = EAP_TEAP_VERSION;
- rbind->received_version = data->received_version;
- /* FIX: RFC 7170 is not clear on which Flags value to use when
- * Crypto-Binding TLV is used with Basic-Password-Auth */
- flags = cmk_emsk ? TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC :
- TEAP_CRYPTO_BINDING_MSK_CMAC;
- subtype = TEAP_CRYPTO_BINDING_SUBTYPE_RESPONSE;
- rbind->subtype = (flags << 4) | subtype;
- os_memcpy(rbind->nonce, cb->nonce, sizeof(cb->nonce));
- inc_byte_array(rbind->nonce, sizeof(rbind->nonce));
- os_memset(rbind->emsk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
- os_memset(rbind->msk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
-
- if (eap_teap_compound_mac(data->tls_cs, rbind, data->server_outer_tlvs,
- data->peer_outer_tlvs, cmk_msk,
- rbind->msk_compound_mac) < 0)
- return -1;
- if (cmk_emsk &&
- eap_teap_compound_mac(data->tls_cs, rbind, data->server_outer_tlvs,
- data->peer_outer_tlvs, cmk_emsk,
- rbind->emsk_compound_mac) < 0)
- return -1;
-
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Reply Crypto-Binding TLV: Version %u Received Version %u Flags %u SubType %u",
- rbind->version, rbind->received_version, flags, subtype);
- wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Nonce",
- rbind->nonce, sizeof(rbind->nonce));
- wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: EMSK Compound MAC",
- rbind->emsk_compound_mac, sizeof(rbind->emsk_compound_mac));
- wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: MSK Compound MAC",
- rbind->msk_compound_mac, sizeof(rbind->msk_compound_mac));
-
- return 0;
-}
-
-
-static int eap_teap_get_cmk(struct eap_sm *sm, struct eap_teap_data *data,
- u8 *cmk_msk, u8 *cmk_emsk)
-{
- u8 *msk = NULL, *emsk = NULL;
- size_t msk_len = 0, emsk_len = 0;
- int res;
-
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Determining CMK[%d] for Compound MAC calculation",
- data->simck_idx + 1);
-
- if (!data->phase2_method)
- return eap_teap_derive_cmk_basic_pw_auth(data->simck_msk,
- cmk_msk);
-
- if (!data->phase2_method || !data->phase2_priv) {
- wpa_printf(MSG_INFO, "EAP-TEAP: Phase 2 method not available");
- return -1;
- }
-
- if (data->phase2_method->isKeyAvailable &&
- !data->phase2_method->isKeyAvailable(sm, data->phase2_priv)) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Phase 2 key material not available");
- return -1;
- }
-
- if (data->phase2_method->isKeyAvailable &&
- data->phase2_method->getKey) {
- msk = data->phase2_method->getKey(sm, data->phase2_priv,
- &msk_len);
- if (!msk) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Could not fetch Phase 2 MSK");
- return -1;
- }
- }
-
- if (data->phase2_method->isKeyAvailable &&
- data->phase2_method->get_emsk) {
- emsk = data->phase2_method->get_emsk(sm, data->phase2_priv,
- &emsk_len);
- }
-
- res = eap_teap_derive_imck(data->simck_msk, data->simck_emsk,
- msk, msk_len, emsk, emsk_len,
- data->simck_msk, cmk_msk,
- data->simck_emsk, cmk_emsk);
- bin_clear_free(msk, msk_len);
- bin_clear_free(emsk, emsk_len);
- if (res == 0) {
- data->simck_idx++;
- if (emsk)
- data->cmk_emsk_available = 1;
- }
- return res;
-}
-
-
-static int eap_teap_session_id(struct eap_teap_data *data)
-{
- const size_t max_id_len = 100;
- int res;
-
- os_free(data->session_id);
- data->session_id = os_malloc(max_id_len);
- if (!data->session_id)
- return -1;
-
- data->session_id[0] = EAP_TYPE_TEAP;
- res = tls_get_tls_unique(data->ssl.conn, data->session_id + 1,
- max_id_len - 1);
- if (res < 0) {
- os_free(data->session_id);
- data->session_id = NULL;
- wpa_printf(MSG_ERROR, "EAP-TEAP: Failed to derive Session-Id");
- return -1;
- }
-
- data->id_len = 1 + res;
- wpa_hexdump(MSG_DEBUG, "EAP-TEAP: Derived Session-Id",
- data->session_id, data->id_len);
- return 0;
-}
-
-
-static struct wpabuf * eap_teap_process_crypto_binding(
- struct eap_sm *sm, struct eap_teap_data *data,
- struct eap_method_ret *ret,
- const struct teap_tlv_crypto_binding *cb, size_t bind_len)
-{
- struct wpabuf *resp;
- u8 *pos;
- u8 cmk_msk[EAP_TEAP_CMK_LEN];
- u8 cmk_emsk[EAP_TEAP_CMK_LEN];
- const u8 *cmk_emsk_ptr = NULL;
- int res;
- size_t len;
- u8 flags;
-
- if (eap_teap_validate_crypto_binding(data, cb) < 0 ||
- eap_teap_get_cmk(sm, data, cmk_msk, cmk_emsk) < 0)
- return NULL;
-
- /* Validate received MSK/EMSK Compound MAC */
- flags = cb->subtype >> 4;
-
- if (flags == TEAP_CRYPTO_BINDING_MSK_CMAC ||
- flags == TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC) {
- u8 msk_compound_mac[EAP_TEAP_COMPOUND_MAC_LEN];
-
- if (eap_teap_compound_mac(data->tls_cs, cb,
- data->server_outer_tlvs,
- data->peer_outer_tlvs, cmk_msk,
- msk_compound_mac) < 0)
- return NULL;
- res = os_memcmp_const(msk_compound_mac, cb->msk_compound_mac,
- EAP_TEAP_COMPOUND_MAC_LEN);
- wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Received MSK Compound MAC",
- cb->msk_compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
- wpa_hexdump(MSG_MSGDUMP,
- "EAP-TEAP: Calculated MSK Compound MAC",
- msk_compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
- if (res != 0) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: MSK Compound MAC did not match");
- return NULL;
- }
- }
-
- if ((flags == TEAP_CRYPTO_BINDING_EMSK_CMAC ||
- flags == TEAP_CRYPTO_BINDING_EMSK_AND_MSK_CMAC) &&
- data->cmk_emsk_available) {
- u8 emsk_compound_mac[EAP_TEAP_COMPOUND_MAC_LEN];
-
- if (eap_teap_compound_mac(data->tls_cs, cb,
- data->server_outer_tlvs,
- data->peer_outer_tlvs, cmk_emsk,
- emsk_compound_mac) < 0)
- return NULL;
- res = os_memcmp_const(emsk_compound_mac, cb->emsk_compound_mac,
- EAP_TEAP_COMPOUND_MAC_LEN);
- wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Received EMSK Compound MAC",
- cb->emsk_compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
- wpa_hexdump(MSG_MSGDUMP,
- "EAP-TEAP: Calculated EMSK Compound MAC",
- emsk_compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
- if (res != 0) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: EMSK Compound MAC did not match");
- return NULL;
- }
-
- cmk_emsk_ptr = cmk_emsk;
- }
-
- if (flags == TEAP_CRYPTO_BINDING_EMSK_CMAC &&
- !data->cmk_emsk_available) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Server included only EMSK Compound MAC, but no locally generated inner EAP EMSK to validate this");
- return NULL;
- }
-
- /*
- * Compound MAC was valid, so authentication succeeded. Reply with
- * crypto binding to allow server to complete authentication.
- */
-
- len = sizeof(struct teap_tlv_crypto_binding);
- resp = wpabuf_alloc(len);
- if (!resp)
- return NULL;
-
- if (data->phase2_success && eap_teap_derive_msk(data) < 0) {
- wpa_printf(MSG_INFO, "EAP-TEAP: Failed to generate MSK");
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_FAIL;
- data->phase2_success = 0;
- wpabuf_free(resp);
- return NULL;
- }
-
- if (data->phase2_success && eap_teap_session_id(data) < 0) {
- wpabuf_free(resp);
- return NULL;
- }
-
- pos = wpabuf_put(resp, sizeof(struct teap_tlv_crypto_binding));
- if (eap_teap_write_crypto_binding(
- data, (struct teap_tlv_crypto_binding *) pos,
- cb, cmk_msk, cmk_emsk_ptr) < 0) {
- wpabuf_free(resp);
- return NULL;
- }
-
- return resp;
-}
-
-
-static void eap_teap_parse_pac_tlv(struct eap_teap_pac *entry, int type,
- u8 *pos, size_t len, int *pac_key_found)
-{
- switch (type & 0x7fff) {
- case PAC_TYPE_PAC_KEY:
- wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: PAC-Key", pos, len);
- if (len != EAP_TEAP_PAC_KEY_LEN) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Invalid PAC-Key length %lu",
- (unsigned long) len);
- break;
- }
- *pac_key_found = 1;
- os_memcpy(entry->pac_key, pos, len);
- break;
- case PAC_TYPE_PAC_OPAQUE:
- wpa_hexdump(MSG_DEBUG, "EAP-TEAP: PAC-Opaque", pos, len);
- entry->pac_opaque = pos;
- entry->pac_opaque_len = len;
- break;
- case PAC_TYPE_PAC_INFO:
- wpa_hexdump(MSG_DEBUG, "EAP-TEAP: PAC-Info", pos, len);
- entry->pac_info = pos;
- entry->pac_info_len = len;
- break;
- default:
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Ignored unknown PAC type %d",
- type);
- break;
- }
-}
-
-
-static int eap_teap_process_pac_tlv(struct eap_teap_pac *entry,
- u8 *pac, size_t pac_len)
-{
- struct pac_attr_hdr *hdr;
- u8 *pos;
- size_t left, len;
- int type, pac_key_found = 0;
-
- pos = pac;
- left = pac_len;
-
- while (left > sizeof(*hdr)) {
- hdr = (struct pac_attr_hdr *) pos;
- type = be_to_host16(hdr->type);
- len = be_to_host16(hdr->len);
- pos += sizeof(*hdr);
- left -= sizeof(*hdr);
- if (len > left) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: PAC TLV overrun (type=%d len=%lu left=%lu)",
- type, (unsigned long) len,
- (unsigned long) left);
- return -1;
- }
-
- eap_teap_parse_pac_tlv(entry, type, pos, len, &pac_key_found);
-
- pos += len;
- left -= len;
- }
-
- if (!pac_key_found || !entry->pac_opaque || !entry->pac_info) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: PAC TLV does not include all the required fields");
- return -1;
- }
-
- return 0;
-}
-
-
-static int eap_teap_parse_pac_info(struct eap_teap_pac *entry, int type,
- u8 *pos, size_t len)
-{
- u16 pac_type;
- u32 lifetime;
- struct os_time now;
-
- switch (type & 0x7fff) {
- case PAC_TYPE_CRED_LIFETIME:
- if (len != 4) {
- wpa_hexdump(MSG_DEBUG,
- "EAP-TEAP: PAC-Info - Invalid CRED_LIFETIME length - ignored",
- pos, len);
- return 0;
- }
-
- /*
- * This is not currently saved separately in PAC files since
- * the server can automatically initiate PAC update when
- * needed. Anyway, the information is available from PAC-Info
- * dump if it is needed for something in the future.
- */
- lifetime = WPA_GET_BE32(pos);
- os_get_time(&now);
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: PAC-Info - CRED_LIFETIME %d (%d days)",
- lifetime, (lifetime - (u32) now.sec) / 86400);
- break;
- case PAC_TYPE_A_ID:
- wpa_hexdump_ascii(MSG_DEBUG, "EAP-TEAP: PAC-Info - A-ID",
- pos, len);
- entry->a_id = pos;
- entry->a_id_len = len;
- break;
- case PAC_TYPE_I_ID:
- wpa_hexdump_ascii(MSG_DEBUG, "EAP-TEAP: PAC-Info - I-ID",
- pos, len);
- entry->i_id = pos;
- entry->i_id_len = len;
- break;
- case PAC_TYPE_A_ID_INFO:
- wpa_hexdump_ascii(MSG_DEBUG, "EAP-TEAP: PAC-Info - A-ID-Info",
- pos, len);
- entry->a_id_info = pos;
- entry->a_id_info_len = len;
- break;
- case PAC_TYPE_PAC_TYPE:
- /* RFC 7170, Section 4.2.12.6 - PAC-Type TLV */
- if (len != 2) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Invalid PAC-Type length %lu (expected 2)",
- (unsigned long) len);
- wpa_hexdump_ascii(MSG_DEBUG,
- "EAP-TEAP: PAC-Info - PAC-Type",
- pos, len);
- return -1;
- }
- pac_type = WPA_GET_BE16(pos);
- if (pac_type != PAC_TYPE_TUNNEL_PAC) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Unsupported PAC Type %d",
- pac_type);
- return -1;
- }
-
- wpa_printf(MSG_DEBUG, "EAP-TEAP: PAC-Info - PAC-Type %d",
- pac_type);
- entry->pac_type = pac_type;
- break;
- default:
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Ignored unknown PAC-Info type %d", type);
- break;
- }
-
- return 0;
-}
-
-
-static int eap_teap_process_pac_info(struct eap_teap_pac *entry)
-{
- struct pac_attr_hdr *hdr;
- u8 *pos;
- size_t left, len;
- int type;
-
- /* RFC 7170, Section 4.2.12.4 */
-
- /* PAC-Type defaults to Tunnel PAC (Type 1) */
- entry->pac_type = PAC_TYPE_TUNNEL_PAC;
-
- pos = entry->pac_info;
- left = entry->pac_info_len;
- while (left > sizeof(*hdr)) {
- hdr = (struct pac_attr_hdr *) pos;
- type = be_to_host16(hdr->type);
- len = be_to_host16(hdr->len);
- pos += sizeof(*hdr);
- left -= sizeof(*hdr);
- if (len > left) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: PAC-Info overrun (type=%d len=%lu left=%lu)",
- type, (unsigned long) len,
- (unsigned long) left);
- return -1;
- }
-
- if (eap_teap_parse_pac_info(entry, type, pos, len) < 0)
- return -1;
-
- pos += len;
- left -= len;
- }
-
- if (!entry->a_id || !entry->a_id_info) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: PAC-Info does not include all the required fields");
- return -1;
- }
-
- return 0;
-}
-
-
-static struct wpabuf * eap_teap_process_pac(struct eap_sm *sm,
- struct eap_teap_data *data,
- struct eap_method_ret *ret,
- u8 *pac, size_t pac_len)
-{
- struct eap_peer_config *config = eap_get_config(sm);
- struct eap_teap_pac entry;
-
- os_memset(&entry, 0, sizeof(entry));
- if (eap_teap_process_pac_tlv(&entry, pac, pac_len) ||
- eap_teap_process_pac_info(&entry))
- return NULL;
-
- eap_teap_add_pac(&data->pac, &data->current_pac, &entry);
- eap_teap_pac_list_truncate(data->pac, data->max_pac_list_len);
- if (data->use_pac_binary_format)
- eap_teap_save_pac_bin(sm, data->pac, config->pac_file);
- else
- eap_teap_save_pac(sm, data->pac, config->pac_file);
-
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Send PAC-Acknowledgement - %s initiated provisioning completed successfully",
- data->provisioning ? "peer" : "server");
- return eap_teap_tlv_pac_ack();
-}
-
-
-static int eap_teap_parse_decrypted(struct wpabuf *decrypted,
- struct eap_teap_tlv_parse *tlv,
- struct wpabuf **resp)
-{
- u16 tlv_type;
- int mandatory, res;
- size_t len;
- u8 *pos, *end;
-
- os_memset(tlv, 0, sizeof(*tlv));
-
- /* Parse TLVs from the decrypted Phase 2 data */
- pos = wpabuf_mhead(decrypted);
- end = pos + wpabuf_len(decrypted);
- while (end - pos >= 4) {
- mandatory = pos[0] & 0x80;
- tlv_type = WPA_GET_BE16(pos) & 0x3fff;
- pos += 2;
- len = WPA_GET_BE16(pos);
- pos += 2;
- if (len > (size_t) (end - pos)) {
- wpa_printf(MSG_INFO, "EAP-TEAP: TLV overflow");
- return -1;
- }
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Received Phase 2: TLV type %u (%s) length %u%s",
- tlv_type, eap_teap_tlv_type_str(tlv_type),
- (unsigned int) len,
- mandatory ? " (mandatory)" : "");
-
- res = eap_teap_parse_tlv(tlv, tlv_type, pos, len);
- if (res == -2)
- break;
- if (res < 0) {
- if (mandatory) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: NAK unknown mandatory TLV type %u",
- tlv_type);
- *resp = eap_teap_tlv_nak(0, tlv_type);
- break;
- }
-
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Ignore unknown optional TLV type %u",
- tlv_type);
- }
-
- pos += len;
- }
-
- return 0;
-}
-
-
-static struct wpabuf * eap_teap_pac_request(void)
-{
- struct wpabuf *req;
- struct teap_tlv_request_action *act;
- struct teap_tlv_hdr *pac;
- struct teap_attr_pac_type *type;
-
- req = wpabuf_alloc(sizeof(*act) + sizeof(*pac) + sizeof(*type));
- if (!req)
- return NULL;
-
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Add Request Action TLV (Process TLV)");
- act = wpabuf_put(req, sizeof(*act));
- act->tlv_type = host_to_be16(TEAP_TLV_REQUEST_ACTION);
- act->length = host_to_be16(2);
- act->status = TEAP_STATUS_SUCCESS;
- act->action = TEAP_REQUEST_ACTION_PROCESS_TLV;
-
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Add PAC TLV (PAC-Type = Tunnel)");
- pac = wpabuf_put(req, sizeof(*pac));
- pac->tlv_type = host_to_be16(TEAP_TLV_PAC);
- pac->length = host_to_be16(sizeof(*type));
-
- type = wpabuf_put(req, sizeof(*type));
- type->type = host_to_be16(PAC_TYPE_PAC_TYPE);
- type->length = host_to_be16(2);
- type->pac_type = host_to_be16(PAC_TYPE_TUNNEL_PAC);
-
- return req;
-}
-
-
-static int eap_teap_process_decrypted(struct eap_sm *sm,
- struct eap_teap_data *data,
- struct eap_method_ret *ret,
- u8 identifier,
- struct wpabuf *decrypted,
- struct wpabuf **out_data)
-{
- struct wpabuf *resp = NULL, *tmp;
- struct eap_teap_tlv_parse tlv;
- int failed = 0;
- enum teap_error_codes error = 0;
-
- if (eap_teap_parse_decrypted(decrypted, &tlv, &resp) < 0) {
- /* Parsing failed - no response available */
- return 0;
- }
-
- if (resp) {
- /* Parsing rejected the message - send out an error response */
- goto send_resp;
- }
-
- if (tlv.result == TEAP_STATUS_FAILURE) {
- /* Server indicated failure - respond similarly per
- * RFC 7170, 3.6.3. This authentication exchange cannot succeed
- * and will be terminated with a cleartext EAP Failure. */
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Server rejected authentication");
- resp = eap_teap_tlv_result(TEAP_STATUS_FAILURE, 0);
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_FAIL;
- goto send_resp;
- }
-
- if ((tlv.iresult == TEAP_STATUS_SUCCESS ||
- (!data->result_success_done &&
- tlv.result == TEAP_STATUS_SUCCESS)) &&
- !tlv.crypto_binding) {
- /* Result TLV or Intermediate-Result TLV indicating success,
- * but no Crypto-Binding TLV */
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Result TLV or Intermediate-Result TLV indicating success, but no Crypto-Binding TLV");
- failed = 1;
- error = TEAP_ERROR_TUNNEL_COMPROMISE_ERROR;
- goto done;
- }
-
- if (tlv.iresult != TEAP_STATUS_SUCCESS &&
- tlv.iresult != TEAP_STATUS_FAILURE &&
- data->inner_method_done) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Inner EAP method exchange completed, but no Intermediate-Result TLV included");
- failed = 1;
- error = TEAP_ERROR_TUNNEL_COMPROMISE_ERROR;
- goto done;
- }
-
- if (tlv.basic_auth_req) {
- tmp = eap_teap_process_basic_auth_req(sm, data,
- tlv.basic_auth_req,
- tlv.basic_auth_req_len);
- if (!tmp)
- failed = 1;
- resp = wpabuf_concat(resp, tmp);
- } else if (tlv.eap_payload_tlv) {
- tmp = eap_teap_process_eap_payload_tlv(sm, data, ret,
- tlv.eap_payload_tlv,
- tlv.eap_payload_tlv_len);
- if (!tmp)
- failed = 1;
- resp = wpabuf_concat(resp, tmp);
-
- if (tlv.iresult == TEAP_STATUS_SUCCESS ||
- tlv.iresult == TEAP_STATUS_FAILURE) {
- tmp = eap_teap_tlv_result(failed ?
- TEAP_STATUS_FAILURE :
- TEAP_STATUS_SUCCESS, 1);
- resp = wpabuf_concat(resp, tmp);
- if (tlv.iresult == TEAP_STATUS_FAILURE)
- failed = 1;
- }
- }
-
- if (tlv.crypto_binding) {
- if (tlv.iresult != TEAP_STATUS_SUCCESS &&
- tlv.result != TEAP_STATUS_SUCCESS) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Unexpected Crypto-Binding TLV without Result TLV or Intermediate-Result TLV indicating success");
- failed = 1;
- error = TEAP_ERROR_UNEXPECTED_TLVS_EXCHANGED;
- goto done;
- }
-
- tmp = eap_teap_process_crypto_binding(sm, data, ret,
- tlv.crypto_binding,
- tlv.crypto_binding_len);
- if (!tmp) {
- failed = 1;
- error = TEAP_ERROR_TUNNEL_COMPROMISE_ERROR;
- } else {
- resp = wpabuf_concat(resp, tmp);
- if (tlv.result == TEAP_STATUS_SUCCESS && !failed)
- data->result_success_done = 1;
- if (tlv.iresult == TEAP_STATUS_SUCCESS && !failed)
- data->inner_method_done = 0;
- }
- }
-
- if (data->result_success_done && data->session_ticket_used &&
- eap_teap_derive_msk(data) == 0) {
- /* Assume the server might accept authentication without going
- * through inner authentication. */
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: PAC used - server may decide to skip inner authentication");
- ret->methodState = METHOD_MAY_CONT;
- ret->decision = DECISION_COND_SUCC;
- }
-
- if (tlv.pac) {
- if (tlv.result == TEAP_STATUS_SUCCESS) {
- tmp = eap_teap_process_pac(sm, data, ret,
- tlv.pac, tlv.pac_len);
- resp = wpabuf_concat(resp, tmp);
- } else {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: PAC TLV without Result TLV acknowledging success");
- failed = 1;
- error = TEAP_ERROR_UNEXPECTED_TLVS_EXCHANGED;
- }
- }
-
- if (!data->current_pac && data->provisioning && !failed && !tlv.pac &&
- tlv.crypto_binding &&
- (!data->anon_provisioning ||
- (data->phase2_success && data->phase2_method &&
- data->phase2_method->vendor == 0 &&
- eap_teap_allowed_anon_prov_cipher_suite(data->tls_cs) &&
- eap_teap_allowed_anon_prov_phase2_method(
- data->phase2_method->method))) &&
- (tlv.iresult == TEAP_STATUS_SUCCESS ||
- tlv.result == TEAP_STATUS_SUCCESS)) {
- /*
- * Need to request Tunnel PAC when using authenticated
- * provisioning.
- */
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Request Tunnel PAC");
- tmp = eap_teap_pac_request();
- resp = wpabuf_concat(resp, tmp);
- }
-
-done:
- if (failed) {
- tmp = eap_teap_tlv_result(TEAP_STATUS_FAILURE, 0);
- resp = wpabuf_concat(tmp, resp);
-
- if (error != 0) {
- tmp = eap_teap_tlv_error(error);
- resp = wpabuf_concat(tmp, resp);
- }
-
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_FAIL;
- } else if (tlv.result == TEAP_STATUS_SUCCESS) {
- tmp = eap_teap_tlv_result(TEAP_STATUS_SUCCESS, 0);
- resp = wpabuf_concat(tmp, resp);
- }
-
- if (resp && tlv.result == TEAP_STATUS_SUCCESS && !failed &&
- tlv.crypto_binding && data->phase2_success) {
- /* Successfully completed Phase 2 */
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Authentication completed successfully");
- ret->methodState = data->provisioning ?
- METHOD_MAY_CONT : METHOD_DONE;
- ret->decision = DECISION_UNCOND_SUCC;
- }
-
- if (!resp) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: No recognized TLVs - send empty response packet");
- resp = wpabuf_alloc(1);
- }
-
-send_resp:
- if (!resp)
- return 0;
-
- wpa_hexdump_buf(MSG_DEBUG, "EAP-TEAP: Encrypting Phase 2 data", resp);
- if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TEAP,
- data->teap_version, identifier,
- resp, out_data)) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Failed to encrypt a Phase 2 frame");
- }
- wpabuf_free(resp);
-
- return 0;
-}
-
-
-static int eap_teap_decrypt(struct eap_sm *sm, struct eap_teap_data *data,
- struct eap_method_ret *ret, u8 identifier,
- const struct wpabuf *in_data,
- struct wpabuf **out_data)
-{
- struct wpabuf *in_decrypted;
- int res;
-
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Received %lu bytes encrypted data for Phase 2",
- (unsigned long) wpabuf_len(in_data));
-
- if (data->pending_phase2_req) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Pending Phase 2 request - skip decryption and use old data");
- /* Clear TLS reassembly state. */
- eap_peer_tls_reset_input(&data->ssl);
-
- in_decrypted = data->pending_phase2_req;
- data->pending_phase2_req = NULL;
- goto continue_req;
- }
-
- if (wpabuf_len(in_data) == 0) {
- /* Received TLS ACK - requesting more fragments */
- return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TEAP,
- data->teap_version,
- identifier, NULL, out_data);
- }
-
- res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
- if (res)
- return res;
-
-continue_req:
- wpa_hexdump_buf(MSG_MSGDUMP, "EAP-TEAP: Decrypted Phase 2 TLV(s)",
- in_decrypted);
-
- if (wpabuf_len(in_decrypted) < 4) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Too short Phase 2 TLV frame (len=%lu)",
- (unsigned long) wpabuf_len(in_decrypted));
- wpabuf_free(in_decrypted);
- return -1;
- }
-
- res = eap_teap_process_decrypted(sm, data, ret, identifier,
- in_decrypted, out_data);
-
- wpabuf_free(in_decrypted);
-
- return res;
-}
-
-
-static void eap_teap_select_pac(struct eap_teap_data *data,
- const u8 *a_id, size_t a_id_len)
-{
- if (!a_id)
- return;
- data->current_pac = eap_teap_get_pac(data->pac, a_id, a_id_len,
- PAC_TYPE_TUNNEL_PAC);
- if (data->current_pac) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: PAC found for this A-ID (PAC-Type %d)",
- data->current_pac->pac_type);
- wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TEAP: A-ID-Info",
- data->current_pac->a_id_info,
- data->current_pac->a_id_info_len);
- }
-}
-
-
-static int eap_teap_use_pac_opaque(struct eap_sm *sm,
- struct eap_teap_data *data,
- struct eap_teap_pac *pac)
-{
- u8 *tlv;
- size_t tlv_len, olen;
- struct teap_tlv_hdr *ehdr;
-
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Add PAC-Opaque TLS extension");
- olen = pac->pac_opaque_len;
- tlv_len = sizeof(*ehdr) + olen;
- tlv = os_malloc(tlv_len);
- if (tlv) {
- ehdr = (struct teap_tlv_hdr *) tlv;
- ehdr->tlv_type = host_to_be16(PAC_TYPE_PAC_OPAQUE);
- ehdr->length = host_to_be16(olen);
- os_memcpy(ehdr + 1, pac->pac_opaque, olen);
- }
- if (!tlv ||
- tls_connection_client_hello_ext(sm->ssl_ctx, data->ssl.conn,
- TLS_EXT_PAC_OPAQUE,
- tlv, tlv_len) < 0) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Failed to add PAC-Opaque TLS extension");
- os_free(tlv);
- return -1;
- }
- os_free(tlv);
-
- return 0;
-}
-
-
-static int eap_teap_clear_pac_opaque_ext(struct eap_sm *sm,
- struct eap_teap_data *data)
-{
- if (tls_connection_client_hello_ext(sm->ssl_ctx, data->ssl.conn,
- TLS_EXT_PAC_OPAQUE, NULL, 0) < 0) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Failed to remove PAC-Opaque TLS extension");
- return -1;
- }
- return 0;
-}
-
-
-static int eap_teap_process_start(struct eap_sm *sm,
- struct eap_teap_data *data, u8 flags,
- const u8 *pos, size_t left)
-{
- const u8 *a_id = NULL;
- size_t a_id_len = 0;
-
- /* TODO: Support (mostly theoretical) case of TEAP/Start request being
- * fragmented */
-
- /* EAP-TEAP version negotiation (RFC 7170, Section 3.2) */
- data->received_version = flags & EAP_TLS_VERSION_MASK;
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Start (server ver=%u, own ver=%u)",
- data->received_version, data->teap_version);
- if (data->received_version < 1) {
- /* Version 1 was the first defined version, so reject 0 */
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Server used unknown TEAP version %u",
- data->received_version);
- return -1;
- }
- if (data->received_version < data->teap_version)
- data->teap_version = data->received_version;
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Using TEAP version %d",
- data->teap_version);
- wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Start message payload", pos, left);
-
- /* Parse Authority-ID TLV from Outer TLVs, if present */
- if (flags & EAP_TEAP_FLAGS_OUTER_TLV_LEN) {
- const u8 *outer_pos, *outer_end;
- u32 outer_tlv_len;
-
- if (left < 4) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Not enough room for the Outer TLV Length field");
- return -1;
- }
-
- outer_tlv_len = WPA_GET_BE32(pos);
- pos += 4;
- left -= 4;
-
- if (outer_tlv_len > left) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Truncated Outer TLVs field (Outer TLV Length: %u; remaining buffer: %u)",
- outer_tlv_len, (unsigned int) left);
- return -1;
- }
-
- outer_pos = pos + left - outer_tlv_len;
- outer_end = outer_pos + outer_tlv_len;
- wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Start message Outer TLVs",
- outer_pos, outer_tlv_len);
- wpabuf_free(data->server_outer_tlvs);
- data->server_outer_tlvs = wpabuf_alloc_copy(outer_pos,
- outer_tlv_len);
- if (!data->server_outer_tlvs)
- return -1;
- left -= outer_tlv_len;
- if (left > 0) {
- wpa_hexdump(MSG_INFO,
- "EAP-TEAP: Unexpected TLS Data in Start message",
- pos, left);
- return -1;
- }
-
- while (outer_pos < outer_end) {
- u16 tlv_type, tlv_len;
-
- if (outer_end - outer_pos < 4) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Truncated Outer TLV header");
- return -1;
- }
- tlv_type = WPA_GET_BE16(outer_pos);
- outer_pos += 2;
- tlv_len = WPA_GET_BE16(outer_pos);
- outer_pos += 2;
- /* Outer TLVs are required to be optional, so no need to
- * check the M flag */
- tlv_type &= TEAP_TLV_TYPE_MASK;
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Outer TLV: Type=%u Length=%u",
- tlv_type, tlv_len);
- if (outer_end - outer_pos < tlv_len) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Truncated Outer TLV (Type %u)",
- tlv_type);
- return -1;
- }
- if (tlv_type == TEAP_TLV_AUTHORITY_ID) {
- wpa_hexdump(MSG_DEBUG, "EAP-TEAP: Authority-ID",
- outer_pos, tlv_len);
- if (a_id) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Multiple Authority-ID TLVs in TEAP/Start");
- return -1;
- }
- a_id = outer_pos;
- a_id_len = tlv_len;
- } else {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Ignore unknown Outer TLV (Type %u)",
- tlv_type);
- }
- outer_pos += tlv_len;
- }
- } else if (left > 0) {
- wpa_hexdump(MSG_INFO,
- "EAP-TEAP: Unexpected TLS Data in Start message",
- pos, left);
- return -1;
- }
-
- eap_teap_select_pac(data, a_id, a_id_len);
-
- if (data->resuming && data->current_pac) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Trying to resume session - do not add PAC-Opaque to TLS ClientHello");
- if (eap_teap_clear_pac_opaque_ext(sm, data) < 0)
- return -1;
- } else if (data->current_pac) {
- /*
- * PAC found for the A-ID and we are not resuming an old
- * session, so add PAC-Opaque extension to ClientHello.
- */
- if (eap_teap_use_pac_opaque(sm, data, data->current_pac) < 0)
- return -1;
- } else if (data->provisioning_allowed) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: No PAC found - starting provisioning");
- if (eap_teap_clear_pac_opaque_ext(sm, data) < 0)
- return -1;
- data->provisioning = 1;
- }
-
- return 0;
-}
-
-
-#ifdef CONFIG_TESTING_OPTIONS
-static struct wpabuf * eap_teap_add_dummy_outer_tlvs(struct eap_teap_data *data,
- struct wpabuf *resp)
-{
- struct wpabuf *resp2;
- u16 len;
- const u8 *pos;
- u8 flags;
-
- wpabuf_free(data->peer_outer_tlvs);
- data->peer_outer_tlvs = wpabuf_alloc(4 + 4);
- if (!data->peer_outer_tlvs) {
- wpabuf_free(resp);
- return NULL;
- }
-
- /* Outer TLVs (dummy Vendor-Specific TLV for testing) */
- wpabuf_put_be16(data->peer_outer_tlvs, TEAP_TLV_VENDOR_SPECIFIC);
- wpabuf_put_be16(data->peer_outer_tlvs, 4);
- wpabuf_put_be32(data->peer_outer_tlvs, EAP_VENDOR_HOSTAP);
- wpa_hexdump_buf(MSG_DEBUG, "EAP-TEAP: TESTING - Add dummy Outer TLVs",
- data->peer_outer_tlvs);
-
- wpa_hexdump_buf(MSG_DEBUG,
- "EAP-TEAP: TEAP/Start response before modification",
- resp);
- resp2 = wpabuf_alloc(wpabuf_len(resp) + 4 +
- wpabuf_len(data->peer_outer_tlvs));
- if (!resp2) {
- wpabuf_free(resp);
- return NULL;
- }
-
- pos = wpabuf_head(resp);
- wpabuf_put_u8(resp2, *pos++); /* Code */
- wpabuf_put_u8(resp2, *pos++); /* Identifier */
- len = WPA_GET_BE16(pos);
- pos += 2;
- wpabuf_put_be16(resp2, len + 4 + wpabuf_len(data->peer_outer_tlvs));
- wpabuf_put_u8(resp2, *pos++); /* Type */
- /* Flags | Ver (with Outer TLV length included flag set to 1) */
- flags = *pos++;
- if (flags & (EAP_TEAP_FLAGS_OUTER_TLV_LEN |
- EAP_TLS_FLAGS_LENGTH_INCLUDED)) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Cannot add Outer TLVs for testing");
- wpabuf_free(resp);
- wpabuf_free(resp2);
- return NULL;
- }
- flags |= EAP_TEAP_FLAGS_OUTER_TLV_LEN;
- wpabuf_put_u8(resp2, flags);
- /* Outer TLV Length */
- wpabuf_put_be32(resp2, wpabuf_len(data->peer_outer_tlvs));
- /* TLS Data */
- wpabuf_put_data(resp2, pos, wpabuf_len(resp) - 6);
- wpabuf_put_buf(resp2, data->peer_outer_tlvs); /* Outer TLVs */
-
- wpabuf_free(resp);
- wpa_hexdump_buf(MSG_DEBUG,
- "EAP-TEAP: TEAP/Start response after modification",
- resp2);
- return resp2;
-}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-
-static struct wpabuf * eap_teap_process(struct eap_sm *sm, void *priv,
- struct eap_method_ret *ret,
- const struct wpabuf *reqData)
-{
- const struct eap_hdr *req;
- size_t left;
- int res;
- u8 flags, id;
- struct wpabuf *resp;
- const u8 *pos;
- struct eap_teap_data *data = priv;
- struct wpabuf msg;
-
- pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TEAP, ret,
- reqData, &left, &flags);
- if (!pos)
- return NULL;
-
- req = wpabuf_head(reqData);
- id = req->identifier;
-
- if (flags & EAP_TLS_FLAGS_START) {
- if (eap_teap_process_start(sm, data, flags, pos, left) < 0)
- return NULL;
-
- /* Outer TLVs are not used in further packet processing and
- * there cannot be TLS Data in this TEAP/Start message, so
- * enforce that by ignoring whatever data might remain in the
- * buffer. */
- left = 0;
- } else if (flags & EAP_TEAP_FLAGS_OUTER_TLV_LEN) {
- /* TODO: RFC 7170, Section 4.3.1 indicates that the unexpected
- * Outer TLVs MUST be ignored instead of ignoring the full
- * message. */
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Outer TLVs present in non-Start message -> ignore message");
- return NULL;
- }
-
- wpabuf_set(&msg, pos, left);
-
- resp = NULL;
- if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
- !data->resuming) {
- /* Process tunneled (encrypted) phase 2 data. */
- res = eap_teap_decrypt(sm, data, ret, id, &msg, &resp);
- if (res < 0) {
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_FAIL;
- /*
- * Ack possible Alert that may have caused failure in
- * decryption.
- */
- 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-TEAP: 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-TEAP: 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-TEAP: 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_TEAP,
- data->teap_version, id, &msg,
- &resp);
- if (res < 0) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: TLS processing failed");
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_FAIL;
- return resp;
- }
-
- if (sm->waiting_ext_cert_check) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: 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,
- "EAP-TEAP: TLS done, proceed to Phase 2");
- data->tls_cs =
- tls_connection_get_cipher_suite(data->ssl.conn);
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: TLS cipher suite 0x%04x",
- data->tls_cs);
-
- if (data->provisioning &&
- (!(data->provisioning_allowed &
- EAP_TEAP_PROV_AUTH) ||
- tls_get_cipher(sm->ssl_ctx, data->ssl.conn,
- cipher, sizeof(cipher)) < 0 ||
- os_strstr(cipher, "ADH-") ||
- os_strstr(cipher, "anon"))) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Using anonymous (unauthenticated) provisioning");
- data->anon_provisioning = 1;
- } else {
- data->anon_provisioning = 0;
- }
- data->resuming = 0;
- if (eap_teap_derive_key_auth(sm, data) < 0) {
- wpa_printf(MSG_DEBUG,
- "EAP-TEAP: Could not derive keys");
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_FAIL;
- wpabuf_free(resp);
- return NULL;
- }
- }
-
- if (res == 2) {
- /*
- * Application data included in the handshake message.
- */
- wpabuf_free(data->pending_phase2_req);
- data->pending_phase2_req = resp;
- resp = NULL;
- res = eap_teap_decrypt(sm, data, ret, id, &msg, &resp);
- }
- }
-
- if (res == 1) {
- wpabuf_free(resp);
- return eap_peer_tls_build_ack(id, EAP_TYPE_TEAP,
- data->teap_version);
- }
-
-#ifdef CONFIG_TESTING_OPTIONS
- if (data->test_outer_tlvs && res == 0 && resp &&
- (flags & EAP_TLS_FLAGS_START) && wpabuf_len(resp) >= 6)
- resp = eap_teap_add_dummy_outer_tlvs(data, resp);
-#endif /* CONFIG_TESTING_OPTIONS */
-
- return resp;
-}
-
-
-#if 0 /* TODO */
-static Boolean eap_teap_has_reauth_data(struct eap_sm *sm, void *priv)
-{
- struct eap_teap_data *data = priv;
-
- return tls_connection_established(sm->ssl_ctx, data->ssl.conn);
-}
-
-
-static void eap_teap_deinit_for_reauth(struct eap_sm *sm, void *priv)
-{
- struct eap_teap_data *data = priv;
-
- if (data->phase2_priv && data->phase2_method &&
- data->phase2_method->deinit_for_reauth)
- data->phase2_method->deinit_for_reauth(sm, data->phase2_priv);
- eap_teap_clear(data);
-}
-
-
-static void * eap_teap_init_for_reauth(struct eap_sm *sm, void *priv)
-{
- struct eap_teap_data *data = priv;
-
- if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
- eap_teap_deinit(sm, data);
- return NULL;
- }
- if (data->phase2_priv && data->phase2_method &&
- data->phase2_method->init_for_reauth)
- data->phase2_method->init_for_reauth(sm, data->phase2_priv);
- data->phase2_success = 0;
- data->inner_method_done = 0;
- data->result_success_done = 0;
- data->resuming = 1;
- data->provisioning = 0;
- data->anon_provisioning = 0;
- data->simck_idx = 0;
- return priv;
-}
-#endif
-
-
-static int eap_teap_get_status(struct eap_sm *sm, void *priv, char *buf,
- size_t buflen, int verbose)
-{
- struct eap_teap_data *data = priv;
- int len, ret;
-
- len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
- if (data->phase2_method) {
- ret = os_snprintf(buf + len, buflen - len,
- "EAP-TEAP Phase 2 method=%s\n",
- data->phase2_method->name);
- if (os_snprintf_error(buflen - len, ret))
- return len;
- len += ret;
- }
- return len;
-}
-
-
-static Boolean eap_teap_isKeyAvailable(struct eap_sm *sm, void *priv)
-{
- struct eap_teap_data *data = priv;
-
- return data->success;
-}
-
-
-static u8 * eap_teap_getKey(struct eap_sm *sm, void *priv, size_t *len)
-{
- struct eap_teap_data *data = priv;
- u8 *key;
-
- if (!data->success)
- return NULL;
-
- key = os_memdup(data->key_data, EAP_TEAP_KEY_LEN);
- if (!key)
- return NULL;
-
- *len = EAP_TEAP_KEY_LEN;
-
- return key;
-}
-
-
-static u8 * eap_teap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
-{
- struct eap_teap_data *data = priv;
- u8 *id;
-
- if (!data->success || !data->session_id)
- return NULL;
-
- id = os_memdup(data->session_id, data->id_len);
- if (!id)
- return NULL;
-
- *len = data->id_len;
-
- return id;
-}
-
-
-static u8 * eap_teap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
-{
- struct eap_teap_data *data = priv;
- u8 *key;
-
- if (!data->success)
- return NULL;
-
- key = os_memdup(data->emsk, EAP_EMSK_LEN);
- if (!key)
- return NULL;
-
- *len = EAP_EMSK_LEN;
-
- return key;
-}
-
-
-int eap_peer_teap_register(void)
-{
- struct eap_method *eap;
-
- eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
- EAP_VENDOR_IETF, EAP_TYPE_TEAP, "TEAP");
- if (!eap)
- return -1;
-
- eap->init = eap_teap_init;
- eap->deinit = eap_teap_deinit;
- eap->process = eap_teap_process;
- eap->isKeyAvailable = eap_teap_isKeyAvailable;
- eap->getKey = eap_teap_getKey;
- eap->getSessionId = eap_teap_get_session_id;
- eap->get_status = eap_teap_get_status;
-#if 0 /* TODO */
- eap->has_reauth_data = eap_teap_has_reauth_data;
- eap->deinit_for_reauth = eap_teap_deinit_for_reauth;
- eap->init_for_reauth = eap_teap_init_for_reauth;
-#endif
- eap->get_emsk = eap_teap_get_emsk;
-
- return eap_peer_method_register(eap);
-}
diff --git a/src/eap_peer/eap_teap_pac.c b/src/eap_peer/eap_teap_pac.c
deleted file mode 100644
index 34a2743..0000000
--- a/src/eap_peer/eap_teap_pac.c
+++ /dev/null
@@ -1,931 +0,0 @@
-/*
- * EAP peer method: EAP-TEAP PAC file processing
- * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-
-#include "common.h"
-#include "eap_config.h"
-#include "eap_i.h"
-#include "eap_teap_pac.h"
-
-/* TODO: encrypt PAC-Key in the PAC file */
-
-
-/* Text data format */
-static const char *pac_file_hdr =
- "wpa_supplicant EAP-TEAP PAC file - version 1";
-
-/*
- * Binary data format
- * 4-octet magic value: 6A E4 92 1C
- * 2-octet version (big endian)
- * <version specific data>
- *
- * version=0:
- * Sequence of PAC entries:
- * 2-octet PAC-Type (big endian)
- * 32-octet PAC-Key
- * 2-octet PAC-Opaque length (big endian)
- * <variable len> PAC-Opaque data (length bytes)
- * 2-octet PAC-Info length (big endian)
- * <variable len> PAC-Info data (length bytes)
- */
-
-#define EAP_TEAP_PAC_BINARY_MAGIC 0x6ae4921c
-#define EAP_TEAP_PAC_BINARY_FORMAT_VERSION 0
-
-
-/**
- * eap_teap_free_pac - Free PAC data
- * @pac: Pointer to the PAC entry
- *
- * Note that the PAC entry must not be in a list since this function does not
- * remove the list links.
- */
-void eap_teap_free_pac(struct eap_teap_pac *pac)
-{
- os_free(pac->pac_opaque);
- os_free(pac->pac_info);
- os_free(pac->a_id);
- os_free(pac->i_id);
- os_free(pac->a_id_info);
- os_free(pac);
-}
-
-
-/**
- * eap_teap_get_pac - Get a PAC entry based on A-ID
- * @pac_root: Pointer to root of the PAC list
- * @a_id: A-ID to search for
- * @a_id_len: Length of A-ID
- * @pac_type: PAC-Type to search for
- * Returns: Pointer to the PAC entry, or %NULL if A-ID not found
- */
-struct eap_teap_pac * eap_teap_get_pac(struct eap_teap_pac *pac_root,
- const u8 *a_id, size_t a_id_len,
- u16 pac_type)
-{
- struct eap_teap_pac *pac = pac_root;
-
- while (pac) {
- if (pac->pac_type == pac_type && pac->a_id_len == a_id_len &&
- os_memcmp(pac->a_id, a_id, a_id_len) == 0) {
- return pac;
- }
- pac = pac->next;
- }
- return NULL;
-}
-
-
-static void eap_teap_remove_pac(struct eap_teap_pac **pac_root,
- struct eap_teap_pac **pac_current,
- const u8 *a_id, size_t a_id_len, u16 pac_type)
-{
- struct eap_teap_pac *pac, *prev;
-
- pac = *pac_root;
- prev = NULL;
-
- while (pac) {
- if (pac->pac_type == pac_type && pac->a_id_len == a_id_len &&
- os_memcmp(pac->a_id, a_id, a_id_len) == 0) {
- if (!prev)
- *pac_root = pac->next;
- else
- prev->next = pac->next;
- if (*pac_current == pac)
- *pac_current = NULL;
- eap_teap_free_pac(pac);
- break;
- }
- prev = pac;
- pac = pac->next;
- }
-}
-
-
-static int eap_teap_copy_buf(u8 **dst, size_t *dst_len,
- const u8 *src, size_t src_len)
-{
- if (src) {
- *dst = os_memdup(src, src_len);
- if (!(*dst))
- return -1;
- *dst_len = src_len;
- }
- return 0;
-}
-
-
-/**
- * eap_teap_add_pac - Add a copy of a PAC entry to a list
- * @pac_root: Pointer to PAC list root pointer
- * @pac_current: Pointer to the current PAC pointer
- * @entry: New entry to clone and add to the list
- * Returns: 0 on success, -1 on failure
- *
- * This function makes a clone of the given PAC entry and adds this copied
- * entry to the list (pac_root). If an old entry for the same A-ID is found,
- * it will be removed from the PAC list and in this case, pac_current entry
- * is set to %NULL if it was the removed entry.
- */
-int eap_teap_add_pac(struct eap_teap_pac **pac_root,
- struct eap_teap_pac **pac_current,
- struct eap_teap_pac *entry)
-{
- struct eap_teap_pac *pac;
-
- if (!entry || !entry->a_id)
- return -1;
-
- /* Remove a possible old entry for the matching A-ID. */
- eap_teap_remove_pac(pac_root, pac_current,
- entry->a_id, entry->a_id_len, entry->pac_type);
-
- /* Allocate a new entry and add it to the list of PACs. */
- pac = os_zalloc(sizeof(*pac));
- if (!pac)
- return -1;
-
- pac->pac_type = entry->pac_type;
- os_memcpy(pac->pac_key, entry->pac_key, EAP_TEAP_PAC_KEY_LEN);
- if (eap_teap_copy_buf(&pac->pac_opaque, &pac->pac_opaque_len,
- entry->pac_opaque, entry->pac_opaque_len) < 0 ||
- eap_teap_copy_buf(&pac->pac_info, &pac->pac_info_len,
- entry->pac_info, entry->pac_info_len) < 0 ||
- eap_teap_copy_buf(&pac->a_id, &pac->a_id_len,
- entry->a_id, entry->a_id_len) < 0 ||
- eap_teap_copy_buf(&pac->i_id, &pac->i_id_len,
- entry->i_id, entry->i_id_len) < 0 ||
- eap_teap_copy_buf(&pac->a_id_info, &pac->a_id_info_len,
- entry->a_id_info, entry->a_id_info_len) < 0) {
- eap_teap_free_pac(pac);
- return -1;
- }
-
- pac->next = *pac_root;
- *pac_root = pac;
-
- return 0;
-}
-
-
-struct eap_teap_read_ctx {
- FILE *f;
- const char *pos;
- const char *end;
- int line;
- char *buf;
- size_t buf_len;
-};
-
-static int eap_teap_read_line(struct eap_teap_read_ctx *rc, char **value)
-{
- char *pos;
-
- rc->line++;
- if (rc->f) {
- if (fgets(rc->buf, rc->buf_len, rc->f) == NULL)
- return -1;
- } else {
- const char *l_end;
- size_t len;
-
- if (rc->pos >= rc->end)
- return -1;
- l_end = rc->pos;
- while (l_end < rc->end && *l_end != '\n')
- l_end++;
- len = l_end - rc->pos;
- if (len >= rc->buf_len)
- len = rc->buf_len - 1;
- os_memcpy(rc->buf, rc->pos, len);
- rc->buf[len] = '\0';
- rc->pos = l_end + 1;
- }
-
- rc->buf[rc->buf_len - 1] = '\0';
- pos = rc->buf;
- while (*pos != '\0') {
- if (*pos == '\n' || *pos == '\r') {
- *pos = '\0';
- break;
- }
- pos++;
- }
-
- pos = os_strchr(rc->buf, '=');
- if (pos)
- *pos++ = '\0';
- *value = pos;
-
- return 0;
-}
-
-
-static u8 * eap_teap_parse_hex(const char *value, size_t *len)
-{
- int hlen;
- u8 *buf;
-
- if (!value)
- return NULL;
- hlen = os_strlen(value);
- if (hlen & 1)
- return NULL;
- *len = hlen / 2;
- buf = os_malloc(*len);
- if (!buf)
- return NULL;
- if (hexstr2bin(value, buf, *len)) {
- os_free(buf);
- return NULL;
- }
- return buf;
-}
-
-
-static int eap_teap_init_pac_data(struct eap_sm *sm, const char *pac_file,
- struct eap_teap_read_ctx *rc)
-{
- os_memset(rc, 0, sizeof(*rc));
-
- rc->buf_len = 2048;
- rc->buf = os_malloc(rc->buf_len);
- if (!rc->buf)
- return -1;
-
- if (os_strncmp(pac_file, "blob://", 7) == 0) {
- const struct wpa_config_blob *blob;
-
- blob = eap_get_config_blob(sm, pac_file + 7);
- if (!blob) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: No PAC blob '%s' - assume no PAC entries have been provisioned",
- pac_file + 7);
- os_free(rc->buf);
- return -1;
- }
- rc->pos = (char *) blob->data;
- rc->end = (char *) blob->data + blob->len;
- } else {
- rc->f = fopen(pac_file, "rb");
- if (!rc->f) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: No PAC file '%s' - assume no PAC entries have been provisioned",
- pac_file);
- os_free(rc->buf);
- return -1;
- }
- }
-
- return 0;
-}
-
-
-static void eap_teap_deinit_pac_data(struct eap_teap_read_ctx *rc)
-{
- os_free(rc->buf);
- if (rc->f)
- fclose(rc->f);
-}
-
-
-static const char * eap_teap_parse_start(struct eap_teap_pac **pac)
-{
- if (*pac)
- return "START line without END";
-
- *pac = os_zalloc(sizeof(struct eap_teap_pac));
- if (!(*pac))
- return "No memory for PAC entry";
- (*pac)->pac_type = PAC_TYPE_TUNNEL_PAC;
- return NULL;
-}
-
-
-static const char * eap_teap_parse_end(struct eap_teap_pac **pac_root,
- struct eap_teap_pac **pac)
-{
- if (!(*pac))
- return "END line without START";
- if (*pac_root) {
- struct eap_teap_pac *end = *pac_root;
-
- while (end->next)
- end = end->next;
- end->next = *pac;
- } else
- *pac_root = *pac;
-
- *pac = NULL;
- return NULL;
-}
-
-
-static const char * eap_teap_parse_pac_type(struct eap_teap_pac *pac,
- char *pos)
-{
- if (!pos)
- return "Cannot parse pac type";
- pac->pac_type = atoi(pos);
- if (pac->pac_type != PAC_TYPE_TUNNEL_PAC)
- return "Unrecognized PAC-Type";
-
- return NULL;
-}
-
-
-static const char * eap_teap_parse_pac_key(struct eap_teap_pac *pac, char *pos)
-{
- u8 *key;
- size_t key_len;
-
- key = eap_teap_parse_hex(pos, &key_len);
- if (!key || key_len != EAP_TEAP_PAC_KEY_LEN) {
- os_free(key);
- return "Invalid PAC-Key";
- }
-
- os_memcpy(pac->pac_key, key, EAP_TEAP_PAC_KEY_LEN);
- os_free(key);
-
- return NULL;
-}
-
-
-static const char * eap_teap_parse_pac_opaque(struct eap_teap_pac *pac,
- char *pos)
-{
- os_free(pac->pac_opaque);
- pac->pac_opaque = eap_teap_parse_hex(pos, &pac->pac_opaque_len);
- if (!pac->pac_opaque)
- return "Invalid PAC-Opaque";
- return NULL;
-}
-
-
-static const char * eap_teap_parse_a_id(struct eap_teap_pac *pac, char *pos)
-{
- os_free(pac->a_id);
- pac->a_id = eap_teap_parse_hex(pos, &pac->a_id_len);
- if (!pac->a_id)
- return "Invalid A-ID";
- return NULL;
-}
-
-
-static const char * eap_teap_parse_i_id(struct eap_teap_pac *pac, char *pos)
-{
- os_free(pac->i_id);
- pac->i_id = eap_teap_parse_hex(pos, &pac->i_id_len);
- if (!pac->i_id)
- return "Invalid I-ID";
- return NULL;
-}
-
-
-static const char * eap_teap_parse_a_id_info(struct eap_teap_pac *pac,
- char *pos)
-{
- os_free(pac->a_id_info);
- pac->a_id_info = eap_teap_parse_hex(pos, &pac->a_id_info_len);
- if (!pac->a_id_info)
- return "Invalid A-ID-Info";
- return NULL;
-}
-
-
-/**
- * eap_teap_load_pac - Load PAC entries (text format)
- * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
- * @pac_root: Pointer to root of the PAC list (to be filled)
- * @pac_file: Name of the PAC file/blob to load
- * Returns: 0 on success, -1 on failure
- */
-int eap_teap_load_pac(struct eap_sm *sm, struct eap_teap_pac **pac_root,
- const char *pac_file)
-{
- struct eap_teap_read_ctx rc;
- struct eap_teap_pac *pac = NULL;
- int count = 0;
- char *pos;
- const char *err = NULL;
-
- if (!pac_file)
- return -1;
-
- if (eap_teap_init_pac_data(sm, pac_file, &rc) < 0)
- return 0;
-
- if (eap_teap_read_line(&rc, &pos) < 0) {
- /* empty file - assume it is fine to overwrite */
- eap_teap_deinit_pac_data(&rc);
- return 0;
- }
- if (os_strcmp(pac_file_hdr, rc.buf) != 0)
- err = "Unrecognized header line";
-
- while (!err && eap_teap_read_line(&rc, &pos) == 0) {
- if (os_strcmp(rc.buf, "START") == 0)
- err = eap_teap_parse_start(&pac);
- else if (os_strcmp(rc.buf, "END") == 0) {
- err = eap_teap_parse_end(pac_root, &pac);
- count++;
- } else if (!pac)
- err = "Unexpected line outside START/END block";
- else if (os_strcmp(rc.buf, "PAC-Type") == 0)
- err = eap_teap_parse_pac_type(pac, pos);
- else if (os_strcmp(rc.buf, "PAC-Key") == 0)
- err = eap_teap_parse_pac_key(pac, pos);
- else if (os_strcmp(rc.buf, "PAC-Opaque") == 0)
- err = eap_teap_parse_pac_opaque(pac, pos);
- else if (os_strcmp(rc.buf, "A-ID") == 0)
- err = eap_teap_parse_a_id(pac, pos);
- else if (os_strcmp(rc.buf, "I-ID") == 0)
- err = eap_teap_parse_i_id(pac, pos);
- else if (os_strcmp(rc.buf, "A-ID-Info") == 0)
- err = eap_teap_parse_a_id_info(pac, pos);
- }
-
- if (pac) {
- if (!err)
- err = "PAC block not terminated with END";
- eap_teap_free_pac(pac);
- }
-
- eap_teap_deinit_pac_data(&rc);
-
- if (err) {
- wpa_printf(MSG_INFO, "EAP-TEAP: %s in '%s:%d'",
- err, pac_file, rc.line);
- return -1;
- }
-
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Read %d PAC entries from '%s'",
- count, pac_file);
-
- return 0;
-}
-
-
-static void eap_teap_write(char **buf, char **pos, size_t *buf_len,
- const char *field, const u8 *data,
- size_t len, int txt)
-{
- size_t i, need;
- int ret;
- char *end;
-
- if (!data || !buf || !(*buf) || !pos || !(*pos) || *pos < *buf)
- return;
-
- need = os_strlen(field) + len * 2 + 30;
- if (txt)
- need += os_strlen(field) + len + 20;
-
- if (*pos - *buf + need > *buf_len) {
- char *nbuf = os_realloc(*buf, *buf_len + need);
-
- if (!nbuf) {
- os_free(*buf);
- *buf = NULL;
- return;
- }
- *pos = nbuf + (*pos - *buf);
- *buf = nbuf;
- *buf_len += need;
- }
- end = *buf + *buf_len;
-
- ret = os_snprintf(*pos, end - *pos, "%s=", field);
- if (os_snprintf_error(end - *pos, ret))
- return;
- *pos += ret;
- *pos += wpa_snprintf_hex(*pos, end - *pos, data, len);
- ret = os_snprintf(*pos, end - *pos, "\n");
- if (os_snprintf_error(end - *pos, ret))
- return;
- *pos += ret;
-
- if (txt) {
- ret = os_snprintf(*pos, end - *pos, "%s-txt=", field);
- if (os_snprintf_error(end - *pos, ret))
- return;
- *pos += ret;
- for (i = 0; i < len; i++) {
- ret = os_snprintf(*pos, end - *pos, "%c", data[i]);
- if (os_snprintf_error(end - *pos, ret))
- return;
- *pos += ret;
- }
- ret = os_snprintf(*pos, end - *pos, "\n");
- if (os_snprintf_error(end - *pos, ret))
- return;
- *pos += ret;
- }
-}
-
-
-static int eap_teap_write_pac(struct eap_sm *sm, const char *pac_file,
- char *buf, size_t len)
-{
- if (os_strncmp(pac_file, "blob://", 7) == 0) {
- struct wpa_config_blob *blob;
-
- blob = os_zalloc(sizeof(*blob));
- if (!blob)
- return -1;
- blob->data = (u8 *) buf;
- blob->len = len;
- buf = NULL;
- blob->name = os_strdup(pac_file + 7);
- if (!blob->name) {
- os_free(blob);
- return -1;
- }
- eap_set_config_blob(sm, blob);
- } else {
- FILE *f;
-
- f = fopen(pac_file, "wb");
- if (!f) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Failed to open PAC file '%s' for writing",
- pac_file);
- return -1;
- }
- if (fwrite(buf, 1, len, f) != len) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: Failed to write all PACs into '%s'",
- pac_file);
- fclose(f);
- return -1;
- }
- os_free(buf);
- fclose(f);
- }
-
- return 0;
-}
-
-
-static int eap_teap_add_pac_data(struct eap_teap_pac *pac, char **buf,
- char **pos, size_t *buf_len)
-{
- int ret;
-
- ret = os_snprintf(*pos, *buf + *buf_len - *pos,
- "START\nPAC-Type=%d\n", pac->pac_type);
- if (os_snprintf_error(*buf + *buf_len - *pos, ret))
- return -1;
-
- *pos += ret;
- eap_teap_write(buf, pos, buf_len, "PAC-Key",
- pac->pac_key, EAP_TEAP_PAC_KEY_LEN, 0);
- eap_teap_write(buf, pos, buf_len, "PAC-Opaque",
- pac->pac_opaque, pac->pac_opaque_len, 0);
- eap_teap_write(buf, pos, buf_len, "PAC-Info",
- pac->pac_info, pac->pac_info_len, 0);
- eap_teap_write(buf, pos, buf_len, "A-ID",
- pac->a_id, pac->a_id_len, 0);
- eap_teap_write(buf, pos, buf_len, "I-ID",
- pac->i_id, pac->i_id_len, 1);
- eap_teap_write(buf, pos, buf_len, "A-ID-Info",
- pac->a_id_info, pac->a_id_info_len, 1);
- if (!(*buf)) {
- wpa_printf(MSG_DEBUG, "EAP-TEAP: No memory for PAC data");
- return -1;
- }
- ret = os_snprintf(*pos, *buf + *buf_len - *pos, "END\n");
- if (os_snprintf_error(*buf + *buf_len - *pos, ret))
- return -1;
- *pos += ret;
-
- return 0;
-}
-
-
-/**
- * eap_teap_save_pac - Save PAC entries (text format)
- * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
- * @pac_root: Root of the PAC list
- * @pac_file: Name of the PAC file/blob
- * Returns: 0 on success, -1 on failure
- */
-int eap_teap_save_pac(struct eap_sm *sm, struct eap_teap_pac *pac_root,
- const char *pac_file)
-{
- struct eap_teap_pac *pac;
- int ret, count = 0;
- char *buf, *pos;
- size_t buf_len;
-
- if (!pac_file)
- return -1;
-
- buf_len = 1024;
- pos = buf = os_malloc(buf_len);
- if (!buf)
- return -1;
-
- ret = os_snprintf(pos, buf + buf_len - pos, "%s\n", pac_file_hdr);
- if (os_snprintf_error(buf + buf_len - pos, ret)) {
- os_free(buf);
- return -1;
- }
- pos += ret;
-
- pac = pac_root;
- while (pac) {
- if (eap_teap_add_pac_data(pac, &buf, &pos, &buf_len)) {
- os_free(buf);
- return -1;
- }
- count++;
- pac = pac->next;
- }
-
- if (eap_teap_write_pac(sm, pac_file, buf, pos - buf)) {
- os_free(buf);
- return -1;
- }
-
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Wrote %d PAC entries into '%s'",
- count, pac_file);
-
- return 0;
-}
-
-
-/**
- * eap_teap_pac_list_truncate - Truncate a PAC list to the given length
- * @pac_root: Root of the PAC list
- * @max_len: Maximum length of the list (>= 1)
- * Returns: Number of PAC entries removed
- */
-size_t eap_teap_pac_list_truncate(struct eap_teap_pac *pac_root,
- size_t max_len)
-{
- struct eap_teap_pac *pac, *prev;
- size_t count;
-
- pac = pac_root;
- prev = NULL;
- count = 0;
-
- while (pac) {
- count++;
- if (count > max_len)
- break;
- prev = pac;
- pac = pac->next;
- }
-
- if (count <= max_len || !prev)
- return 0;
-
- count = 0;
- prev->next = NULL;
-
- while (pac) {
- prev = pac;
- pac = pac->next;
- eap_teap_free_pac(prev);
- count++;
- }
-
- return count;
-}
-
-
-static void eap_teap_pac_get_a_id(struct eap_teap_pac *pac)
-{
- u8 *pos, *end;
- u16 type, len;
-
- pos = pac->pac_info;
- end = pos + pac->pac_info_len;
-
- while (end - pos > 4) {
- type = WPA_GET_BE16(pos);
- pos += 2;
- len = WPA_GET_BE16(pos);
- pos += 2;
- if (len > (unsigned int) (end - pos))
- break;
-
- if (type == PAC_TYPE_A_ID) {
- os_free(pac->a_id);
- pac->a_id = os_memdup(pos, len);
- if (!pac->a_id)
- break;
- pac->a_id_len = len;
- }
-
- if (type == PAC_TYPE_A_ID_INFO) {
- os_free(pac->a_id_info);
- pac->a_id_info = os_memdup(pos, len);
- if (!pac->a_id_info)
- break;
- pac->a_id_info_len = len;
- }
-
- pos += len;
- }
-}
-
-
-/**
- * eap_teap_load_pac_bin - Load PAC entries (binary format)
- * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
- * @pac_root: Pointer to root of the PAC list (to be filled)
- * @pac_file: Name of the PAC file/blob to load
- * Returns: 0 on success, -1 on failure
- */
-int eap_teap_load_pac_bin(struct eap_sm *sm, struct eap_teap_pac **pac_root,
- const char *pac_file)
-{
- const struct wpa_config_blob *blob = NULL;
- u8 *buf, *end, *pos;
- size_t len, count = 0;
- struct eap_teap_pac *pac, *prev;
-
- *pac_root = NULL;
-
- if (!pac_file)
- return -1;
-
- if (os_strncmp(pac_file, "blob://", 7) == 0) {
- blob = eap_get_config_blob(sm, pac_file + 7);
- if (!blob) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: No PAC blob '%s' - assume no PAC entries have been provisioned",
- pac_file + 7);
- return 0;
- }
- buf = blob->data;
- len = blob->len;
- } else {
- buf = (u8 *) os_readfile(pac_file, &len);
- if (!buf) {
- wpa_printf(MSG_INFO,
- "EAP-TEAP: No PAC file '%s' - assume no PAC entries have been provisioned",
- pac_file);
- return 0;
- }
- }
-
- if (len == 0) {
- if (!blob)
- os_free(buf);
- return 0;
- }
-
- if (len < 6 || WPA_GET_BE32(buf) != EAP_TEAP_PAC_BINARY_MAGIC ||
- WPA_GET_BE16(buf + 4) != EAP_TEAP_PAC_BINARY_FORMAT_VERSION) {
- wpa_printf(MSG_INFO, "EAP-TEAP: Invalid PAC file '%s' (bin)",
- pac_file);
- if (!blob)
- os_free(buf);
- return -1;
- }
-
- pac = prev = NULL;
- pos = buf + 6;
- end = buf + len;
- while (pos < end) {
- u16 val;
-
- if (end - pos < 2 + EAP_TEAP_PAC_KEY_LEN + 2 + 2) {
- pac = NULL;
- goto parse_fail;
- }
-
- pac = os_zalloc(sizeof(*pac));
- if (!pac)
- goto parse_fail;
-
- pac->pac_type = WPA_GET_BE16(pos);
- pos += 2;
- os_memcpy(pac->pac_key, pos, EAP_TEAP_PAC_KEY_LEN);
- pos += EAP_TEAP_PAC_KEY_LEN;
- val = WPA_GET_BE16(pos);
- pos += 2;
- if (val > end - pos)
- goto parse_fail;
- pac->pac_opaque_len = val;
- pac->pac_opaque = os_memdup(pos, pac->pac_opaque_len);
- if (!pac->pac_opaque)
- goto parse_fail;
- pos += pac->pac_opaque_len;
- if (end - pos < 2)
- goto parse_fail;
- val = WPA_GET_BE16(pos);
- pos += 2;
- if (val > end - pos)
- goto parse_fail;
- pac->pac_info_len = val;
- pac->pac_info = os_memdup(pos, pac->pac_info_len);
- if (!pac->pac_info)
- goto parse_fail;
- pos += pac->pac_info_len;
- eap_teap_pac_get_a_id(pac);
-
- count++;
- if (prev)
- prev->next = pac;
- else
- *pac_root = pac;
- prev = pac;
- }
-
- if (!blob)
- os_free(buf);
-
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Read %lu PAC entries from '%s' (bin)",
- (unsigned long) count, pac_file);
-
- return 0;
-
-parse_fail:
- wpa_printf(MSG_INFO, "EAP-TEAP: Failed to parse PAC file '%s' (bin)",
- pac_file);
- if (!blob)
- os_free(buf);
- if (pac)
- eap_teap_free_pac(pac);
- return -1;
-}
-
-
-/**
- * eap_teap_save_pac_bin - Save PAC entries (binary format)
- * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
- * @pac_root: Root of the PAC list
- * @pac_file: Name of the PAC file/blob
- * Returns: 0 on success, -1 on failure
- */
-int eap_teap_save_pac_bin(struct eap_sm *sm, struct eap_teap_pac *pac_root,
- const char *pac_file)
-{
- size_t len, count = 0;
- struct eap_teap_pac *pac;
- u8 *buf, *pos;
-
- len = 6;
- pac = pac_root;
- while (pac) {
- if (pac->pac_opaque_len > 65535 ||
- pac->pac_info_len > 65535)
- return -1;
- len += 2 + EAP_TEAP_PAC_KEY_LEN + 2 + pac->pac_opaque_len +
- 2 + pac->pac_info_len;
- pac = pac->next;
- }
-
- buf = os_malloc(len);
- if (!buf)
- return -1;
-
- pos = buf;
- WPA_PUT_BE32(pos, EAP_TEAP_PAC_BINARY_MAGIC);
- pos += 4;
- WPA_PUT_BE16(pos, EAP_TEAP_PAC_BINARY_FORMAT_VERSION);
- pos += 2;
-
- pac = pac_root;
- while (pac) {
- WPA_PUT_BE16(pos, pac->pac_type);
- pos += 2;
- os_memcpy(pos, pac->pac_key, EAP_TEAP_PAC_KEY_LEN);
- pos += EAP_TEAP_PAC_KEY_LEN;
- WPA_PUT_BE16(pos, pac->pac_opaque_len);
- pos += 2;
- os_memcpy(pos, pac->pac_opaque, pac->pac_opaque_len);
- pos += pac->pac_opaque_len;
- WPA_PUT_BE16(pos, pac->pac_info_len);
- pos += 2;
- os_memcpy(pos, pac->pac_info, pac->pac_info_len);
- pos += pac->pac_info_len;
-
- pac = pac->next;
- count++;
- }
-
- if (eap_teap_write_pac(sm, pac_file, (char *) buf, len)) {
- os_free(buf);
- return -1;
- }
-
- wpa_printf(MSG_DEBUG, "EAP-TEAP: Wrote %lu PAC entries into '%s' (bin)",
- (unsigned long) count, pac_file);
-
- return 0;
-}
diff --git a/src/eap_peer/eap_teap_pac.h b/src/eap_peer/eap_teap_pac.h
deleted file mode 100644
index edf4c57..0000000
--- a/src/eap_peer/eap_teap_pac.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * EAP peer method: EAP-TEAP PAC file processing
- * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef EAP_TEAP_PAC_H
-#define EAP_TEAP_PAC_H
-
-#include "eap_common/eap_teap_common.h"
-
-struct eap_teap_pac {
- struct eap_teap_pac *next;
-
- u8 pac_key[EAP_TEAP_PAC_KEY_LEN];
- u8 *pac_opaque;
- size_t pac_opaque_len;
- u8 *pac_info;
- size_t pac_info_len;
- u8 *a_id;
- size_t a_id_len;
- u8 *i_id;
- size_t i_id_len;
- u8 *a_id_info;
- size_t a_id_info_len;
- u16 pac_type;
-};
-
-
-void eap_teap_free_pac(struct eap_teap_pac *pac);
-struct eap_teap_pac * eap_teap_get_pac(struct eap_teap_pac *pac_root,
- const u8 *a_id, size_t a_id_len,
- u16 pac_type);
-int eap_teap_add_pac(struct eap_teap_pac **pac_root,
- struct eap_teap_pac **pac_current,
- struct eap_teap_pac *entry);
-int eap_teap_load_pac(struct eap_sm *sm, struct eap_teap_pac **pac_root,
- const char *pac_file);
-int eap_teap_save_pac(struct eap_sm *sm, struct eap_teap_pac *pac_root,
- const char *pac_file);
-size_t eap_teap_pac_list_truncate(struct eap_teap_pac *pac_root,
- size_t max_len);
-int eap_teap_load_pac_bin(struct eap_sm *sm, struct eap_teap_pac **pac_root,
- const char *pac_file);
-int eap_teap_save_pac_bin(struct eap_sm *sm, struct eap_teap_pac *pac_root,
- const char *pac_file);
-
-#endif /* EAP_TEAP_PAC_H */
diff --git a/src/eap_peer/eap_tls.c b/src/eap_peer/eap_tls.c
index 15d60d7..ffea9d2 100644
--- a/src/eap_peer/eap_tls.c
+++ b/src/eap_peer/eap_tls.c
@@ -174,9 +174,6 @@
struct eap_method_ret *ret)
{
const char *label;
- const u8 eap_tls13_context[] = { EAP_TYPE_TLS };
- const u8 *context = NULL;
- size_t context_len = 0;
wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
@@ -187,8 +184,6 @@
if (data->ssl.tls_v13) {
label = "EXPORTER_EAP_TLS_Key_Material";
- context = eap_tls13_context;
- context_len = 1;
/* A possible NewSessionTicket may be received before
* EAP-Success, so need to allow it to be received. */
@@ -203,7 +198,7 @@
eap_tls_free_key(data);
data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label,
- context, context_len,
+ NULL, 0,
EAP_TLS_KEY_LEN +
EAP_EMSK_LEN);
if (data->key_data) {
@@ -296,18 +291,6 @@
return NULL;
}
- if (res == 2) {
- /* Application data included in the handshake message (used by
- * EAP-TLS 1.3 to indicate conclusion of the exchange). */
- wpa_hexdump_buf(MSG_DEBUG, "EAP-TLS: Received Application Data",
- resp);
- wpa_hexdump_buf(MSG_DEBUG, "EAP-TLS: Remaining tls_out data",
- data->ssl.tls_out);
- eap_peer_tls_reset_output(&data->ssl);
- /* Send an ACK to allow the server to complete exchange */
- res = 1;
- }
-
if (tls_connection_established(data->ssl_ctx, data->ssl.conn))
eap_tls_success(sm, data, ret);
diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
index 7e0690c..cb94c45 100644
--- a/src/eap_peer/eap_tls_common.c
+++ b/src/eap_peer/eap_tls_common.c
@@ -159,8 +159,7 @@
struct eap_peer_config *config, int phase2)
{
os_memset(params, 0, sizeof(*params));
- if (sm->workaround && data->eap_type != EAP_TYPE_FAST &&
- data->eap_type != EAP_TYPE_TEAP) {
+ 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
@@ -172,15 +171,7 @@
*/
params->flags |= TLS_CONN_DISABLE_SESSION_TICKET;
}
- if (data->eap_type == EAP_TYPE_TEAP) {
- /* RFC 7170 requires TLS v1.2 or newer to be used with TEAP */
- params->flags |= TLS_CONN_DISABLE_TLSv1_0 |
- TLS_CONN_DISABLE_TLSv1_1;
- if (config->teap_anon_dh)
- params->flags |= TLS_CONN_TEAP_ANON_DH;
- }
if (data->eap_type == EAP_TYPE_FAST ||
- data->eap_type == EAP_TYPE_TEAP ||
data->eap_type == EAP_TYPE_TTLS ||
data->eap_type == EAP_TYPE_PEAP) {
/* The current EAP peer implementation is not yet ready for the
@@ -413,18 +404,17 @@
if (eap_type == EAP_TYPE_TLS && data->tls_v13) {
u8 *id, *method_id;
- const u8 context[] = { EAP_TYPE_TLS };
/* Session-Id = <EAP-Type> || Method-Id
* Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id",
- * Type-Code, 64)
+ * "", 64)
*/
*len = 1 + 64;
id = os_malloc(*len);
if (!id)
return NULL;
method_id = eap_peer_tls_derive_key(
- sm, data, "EXPORTER_EAP_TLS_Method-Id", context, 1, 64);
+ sm, data, "EXPORTER_EAP_TLS_Method-Id", NULL, 0, 64);
if (!method_id) {
os_free(id);
return NULL;
diff --git a/src/eap_peer/eap_tls_common.h b/src/eap_peer/eap_tls_common.h
index d96eff1..5f82529 100644
--- a/src/eap_peer/eap_tls_common.h
+++ b/src/eap_peer/eap_tls_common.h
@@ -70,8 +70,7 @@
void *ssl_ctx;
/**
- * eap_type - EAP method used in Phase 1
- * (EAP_TYPE_TLS/PEAP/TTLS/FAST/TEAP)
+ * eap_type - EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
*/
u8 eap_type;
@@ -86,7 +85,6 @@
#define EAP_TLS_FLAGS_LENGTH_INCLUDED 0x80
#define EAP_TLS_FLAGS_MORE_FRAGMENTS 0x40
#define EAP_TLS_FLAGS_START 0x20
-#define EAP_TEAP_FLAGS_OUTER_TLV_LEN 0x10
#define EAP_TLS_VERSION_MASK 0x07
/* could be up to 128 bytes, but only the first 64 bytes are used */