[PATCH v2 2/2] EAP peer/server: support for draft-ietf-emu-tls-eap-types-00
Alexander Clouter
alex at digriz.org.uk
Thu Sep 17 17:30:23 EDT 2020
---
src/eap_peer/eap_peap.c | 13 ++++--
src/eap_peer/eap_tls.c | 11 ++---
src/eap_peer/eap_tls_common.c | 4 +-
src/eap_peer/eap_ttls.c | 24 +++++++++-
src/eap_server/eap_server_peap.c | 65 ++++++++++++++++++++++----
src/eap_server/eap_server_tls.c | 33 -------------
src/eap_server/eap_server_tls_common.c | 51 +++++++++++++++++++-
src/eap_server/eap_server_ttls.c | 28 +++++++++--
8 files changed, 167 insertions(+), 62 deletions(-)
diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c
index cb34a0fc3..6997f71cd 100644
--- a/src/eap_peer/eap_peap.c
+++ b/src/eap_peer/eap_peap.c
@@ -1101,10 +1101,17 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
}
if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
- char *label;
+ const char *label;
+ const u8 eap_tls13_context[] = { EAP_TYPE_PEAP };
+ const u8 *context = NULL;
+ size_t context_len = 0;
wpa_printf(MSG_DEBUG,
"EAP-PEAP: TLS done, proceed to Phase 2");
eap_peap_free_key(data);
+ if (data->ssl.tls_v13) {
+ label = "EXPORTER_EAP_TLS_Key_Material";
+ context = eap_tls13_context;
+ context_len = 1;
/* draft-josefsson-ppext-eap-tls-eap-05.txt
* specifies that PEAPv1 would use "client PEAP
* encryption" as the label. However, most existing
@@ -1112,7 +1119,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
* label, "client EAP encryption", instead. Use the old
* label by default, but allow it to be configured with
* phase1 parameter peaplabel=1. */
- if (data->force_new_label)
+ } else if (data->force_new_label)
label = "client PEAP encryption";
else
label = "client EAP encryption";
@@ -1120,7 +1127,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
"key derivation", label);
data->key_data =
eap_peer_tls_derive_key(sm, &data->ssl, label,
- NULL, 0,
+ context, context_len,
EAP_TLS_KEY_LEN +
EAP_EMSK_LEN);
if (data->key_data) {
diff --git a/src/eap_peer/eap_tls.c b/src/eap_peer/eap_tls.c
index ad079a7b7..616cd947a 100644
--- a/src/eap_peer/eap_tls.c
+++ b/src/eap_peer/eap_tls.c
@@ -302,15 +302,10 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
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);
+ /* https://tools.ietf.org/html/draft-ietf-emu-eap-tls13#section-2.5 */
+ if (res == 2 && data->ssl.tls_v13 && wpabuf_len(resp) == 1 && *(u8 *)wpabuf_mhead(resp) == 0) {
+ wpa_printf(MSG_DEBUG, "EAP-TLS: ACKing Commitment Message");
eap_peer_tls_reset_output(&data->ssl);
- /* Send an ACK to allow the server to complete exchange */
res = 1;
}
diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
index ab1067878..c1837db06 100644
--- a/src/eap_peer/eap_tls_common.c
+++ b/src/eap_peer/eap_tls_common.c
@@ -413,9 +413,9 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
struct tls_random keys;
u8 *out;
- if (eap_type == EAP_TYPE_TLS && data->tls_v13) {
+ if (data->tls_v13) {
u8 *id, *method_id;
- const u8 context[] = { EAP_TYPE_TLS };
+ const u8 context[] = { eap_type };
/* Session-Id = <EAP-Type> || Method-Id
* Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id",
diff --git a/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c
index 3bf1e97e6..3e8676374 100644
--- a/src/eap_peer/eap_ttls.c
+++ b/src/eap_peer/eap_ttls.c
@@ -268,10 +268,22 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
static int eap_ttls_v0_derive_key(struct eap_sm *sm,
struct eap_ttls_data *data)
{
+ const char *label;
+ const u8 eap_tls13_context[] = { EAP_TYPE_TTLS };
+ const u8 *context = NULL;
+ size_t context_len = 0;
+
+ if (data->ssl.tls_v13) {
+ label = "EXPORTER_EAP_TLS_Key_Material";
+ context = eap_tls13_context;
+ context_len = 1;
+ } else
+ label = "ttls keying material";
+
eap_ttls_free_key(data);
data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
- "ttls keying material",
- NULL, 0,
+ label,
+ context, context_len,
EAP_TLS_KEY_LEN +
EAP_EMSK_LEN);
if (!data->key_data) {
@@ -1461,6 +1473,14 @@ start:
goto start;
}
+ /* https://tools.ietf.org/html/draft-ietf-emu-eap-tls13#section-2.5 */
+ if (data->ssl.tls_v13 && wpabuf_len(in_decrypted) == 1 && *(u8 *)wpabuf_mhead(in_decrypted) == 0) {
+ wpa_printf(MSG_DEBUG, "EAP-TTLS: ACKing EAP-TLS Commitment Message");
+ eap_peer_tls_reset_output(&data->ssl);
+ wpabuf_free(in_decrypted);
+ return 1;
+ }
+
continue_req:
data->phase2_start = 0;
diff --git a/src/eap_server/eap_server_peap.c b/src/eap_server/eap_server_peap.c
index f234f6fa5..6da4d69f6 100644
--- a/src/eap_server/eap_server_peap.c
+++ b/src/eap_server/eap_server_peap.c
@@ -325,13 +325,25 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
u8 *tk;
u8 isk[32], imck[60];
int res;
+ const char *label;
+ const u8 eap_tls13_context[] = { EAP_TYPE_PEAP };
+ const u8 *context = NULL;
+ size_t context_len = 0;
+
+ if (data->ssl.tls_v13) {
+ label = "EXPORTER_EAP_TLS_Key_Material";
+ context = eap_tls13_context;
+ context_len = 1;
+ } else
+ label = "client EAP encryption"; /* TODO: PEAPv1 - different label in some cases */
/*
* Tunnel key (TK) is the first 60 octets of the key generated by
* phase 1 of PEAP (based on TLS).
*/
- tk = eap_server_tls_derive_key(sm, &data->ssl, "client EAP encryption",
- NULL, 0, EAP_TLS_KEY_LEN);
+ tk = eap_server_tls_derive_key(sm, &data->ssl, label,
+ context, context_len,
+ EAP_TLS_KEY_LEN);
if (tk == NULL)
return -1;
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
@@ -498,7 +510,24 @@ static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
os_free(hdr);
- return encr_req;
+ if (!(data->ssl.tls_v13 && tls_connection_resumed(sm->cfg->ssl_ctx, data->ssl.conn))) {
+ wpabuf_free(data->ssl.tls_out);
+ data->ssl.tls_out_pos = 0;
+ return encr_req;
+ }
+
+ if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(encr_req)) < 0) {
+ wpa_printf(MSG_INFO,
+ "EAP-TLS: Failed to resize output buffer");
+ wpabuf_free(encr_req);
+ return NULL;
+ }
+ wpabuf_put_buf(data->ssl.tls_out, encr_req);
+ wpa_hexdump_buf(MSG_DEBUG,
+ "EAP-TLS: Data appended to the message", encr_req);
+ os_free(encr_req);
+
+ return data->ssl.tls_out;
}
@@ -547,8 +576,6 @@ static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id)
data->ssl.tls_out = eap_peap_build_phase2_tlv(sm, data, id);
break;
case SUCCESS_REQ:
- wpabuf_free(data->ssl.tls_out);
- data->ssl.tls_out_pos = 0;
data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id,
1);
break;
@@ -1300,6 +1327,10 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_peap_data *data = priv;
u8 *eapKeyData;
+ const char *label;
+ const u8 eap_tls13_context[] = { EAP_TYPE_PEAP };
+ const u8 *context = NULL;
+ size_t context_len = 0;
if (data->state != SUCCESS)
return NULL;
@@ -1332,9 +1363,15 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
return eapKeyData;
}
- /* TODO: PEAPv1 - different label in some cases */
+ if (data->ssl.tls_v13) {
+ label = "EXPORTER_EAP_TLS_Key_Material";
+ context = eap_tls13_context;
+ context_len = 1;
+ } else
+ label = "client EAP encryption"; /* TODO: PEAPv1 - different label in some cases */
+
eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
- "client EAP encryption", NULL, 0,
+ label, context, context_len,
EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
if (eapKeyData) {
os_memset(eapKeyData + EAP_TLS_KEY_LEN, 0, EAP_EMSK_LEN);
@@ -1353,6 +1390,10 @@ static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_peap_data *data = priv;
u8 *eapKeyData, *emsk;
+ const char *label;
+ const u8 eap_tls13_context[] = { EAP_TYPE_PEAP };
+ const u8 *context = NULL;
+ size_t context_len = 0;
if (data->state != SUCCESS)
return NULL;
@@ -1362,9 +1403,15 @@ static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
return NULL;
}
- /* TODO: PEAPv1 - different label in some cases */
+ if (data->ssl.tls_v13) {
+ label = "EXPORTER_EAP_TLS_Key_Material";
+ context = eap_tls13_context;
+ context_len = 1;
+ } else
+ label = "client EAP encryption"; /* TODO: PEAPv1 - different label in some cases */
+
eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
- "client EAP encryption", NULL, 0,
+ label, context, context_len,
EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
if (eapKeyData) {
emsk = os_memdup(eapKeyData + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
diff --git a/src/eap_server/eap_server_tls.c b/src/eap_server/eap_server_tls.c
index 769fd1fe0..00a496f2c 100644
--- a/src/eap_server/eap_server_tls.c
+++ b/src/eap_server/eap_server_tls.c
@@ -266,39 +266,6 @@ static void eap_tls_process_msg(struct eap_sm *sm, void *priv,
eap_tls_state(data, FAILURE);
return;
}
-
- if (data->ssl.tls_v13 &&
- tls_connection_established(sm->cfg->ssl_ctx, data->ssl.conn)) {
- struct wpabuf *plain, *encr;
-
- wpa_printf(MSG_DEBUG,
- "EAP-TLS: Send empty application data to indicate end of exchange");
- /* FIX: This should be an empty application data based on
- * draft-ietf-emu-eap-tls13-05, but OpenSSL does not allow zero
- * length payload (SSL_write() documentation explicitly
- * describes this as not allowed), so work around that for now
- * by sending out a payload of one octet. Hopefully the draft
- * specification will change to allow this so that no crypto
- * library changes are needed. */
- plain = wpabuf_alloc(1);
- if (!plain)
- return;
- wpabuf_put_u8(plain, 0);
- encr = eap_server_tls_encrypt(sm, &data->ssl, plain);
- wpabuf_free(plain);
- if (!encr)
- return;
- if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(encr)) < 0) {
- wpa_printf(MSG_INFO,
- "EAP-TLS: Failed to resize output buffer");
- wpabuf_free(encr);
- return;
- }
- wpabuf_put_buf(data->ssl.tls_out, encr);
- wpa_hexdump_buf(MSG_DEBUG,
- "EAP-TLS: Data appended to the message", encr);
- wpabuf_free(encr);
- }
}
diff --git a/src/eap_server/eap_server_tls_common.c b/src/eap_server/eap_server_tls_common.c
index b38f1e0ba..c06c85c87 100644
--- a/src/eap_server/eap_server_tls_common.c
+++ b/src/eap_server/eap_server_tls_common.c
@@ -146,10 +146,10 @@ u8 * eap_server_tls_derive_session_id(struct eap_sm *sm,
{
struct tls_random keys;
u8 *out;
- const u8 context[] = { EAP_TYPE_TLS };
- if (eap_type == EAP_TYPE_TLS && data->tls_v13) {
+ if (data->tls_v13) {
u8 *id, *method_id;
+ const u8 context[] = { eap_type };
/* Session-Id = <EAP-Type> || Method-Id
* Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id",
@@ -366,6 +366,53 @@ int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
sm->serial_num = tls_connection_peer_serial_num(
sm->cfg->ssl_ctx, data->conn);
+ /**
+ * https://tools.ietf.org/html/draft-ietf-emu-eap-tls13#section-2.5
+ *
+ * We need to signal the other end that TLS negotiation
+ * is done. We can't send a zero-length application data
+ * message, so we send application data which is one byte
+ * of zero.
+ *
+ * Note this is only done for when there is no application
+ * data to be sent. So this is done always for EAP-TLS but
+ * notibly not for PEAP even on resumption.
+ */
+ if (tls_connection_established(sm->cfg->ssl_ctx, data->conn) && data->tls_v13) {
+ switch (sm->currentMethod) {
+ case EAP_TYPE_PEAP:
+ break;
+ default:
+ if (!tls_connection_resumed(sm->cfg->ssl_ctx, data->conn)) break;
+ /* fallthrough */
+ case EAP_TYPE_TLS:
+ {
+ struct wpabuf *plain, *encr;
+
+ wpa_printf(MSG_DEBUG, "EAP-TLS: Send Commitment Message");
+
+ plain = wpabuf_alloc(1);
+ if (!plain)
+ return -1;
+ wpabuf_put_u8(plain, 0);
+ encr = eap_server_tls_encrypt(sm, data, plain);
+ wpabuf_free(plain);
+ if (!encr)
+ return -1;
+ if (wpabuf_resize(&data->tls_out, wpabuf_len(encr)) < 0) {
+ wpa_printf(MSG_INFO,
+ "EAP-TLS: Failed to resize output buffer");
+ wpabuf_free(encr);
+ return -1;
+ }
+ wpabuf_put_buf(data->tls_out, encr);
+ wpa_hexdump_buf(MSG_DEBUG,
+ "EAP-TLS: Data appended to the message", encr);
+ wpabuf_free(encr);
+ }
+ }
+ }
+
return 0;
}
diff --git a/src/eap_server/eap_server_ttls.c b/src/eap_server/eap_server_ttls.c
index 2f0c041d5..88493c58f 100644
--- a/src/eap_server/eap_server_ttls.c
+++ b/src/eap_server/eap_server_ttls.c
@@ -1271,13 +1271,24 @@ static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_ttls_data *data = priv;
u8 *eapKeyData;
+ const char *label;
+ const u8 eap_tls13_context[] = { EAP_TYPE_TTLS };
+ const u8 *context = NULL;
+ size_t context_len = 0;
if (data->state != SUCCESS)
return NULL;
+ if (data->ssl.tls_v13) {
+ label = "EXPORTER_EAP_TLS_Key_Material";
+ context = eap_tls13_context;
+ context_len = 1;
+ } else
+ label = "ttls keying material";
+
eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
- "ttls keying material", NULL, 0,
- EAP_TLS_KEY_LEN);
+ label, context, context_len,
+ EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
if (eapKeyData) {
*len = EAP_TLS_KEY_LEN;
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
@@ -1313,12 +1324,23 @@ static u8 * eap_ttls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_ttls_data *data = priv;
u8 *eapKeyData, *emsk;
+ const char *label;
+ const u8 eap_tls13_context[] = { EAP_TYPE_TTLS };
+ const u8 *context = NULL;
+ size_t context_len = 0;
if (data->state != SUCCESS)
return NULL;
+ if (data->ssl.tls_v13) {
+ label = "EXPORTER_EAP_TLS_Key_Material";
+ context = eap_tls13_context;
+ context_len = 1;
+ } else
+ label = "ttls keying material";
+
eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
- "ttls keying material", NULL, 0,
+ label, context, context_len,
EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
if (eapKeyData) {
emsk = os_malloc(EAP_EMSK_LEN);
--
2.20.1
More information about the Hostap
mailing list