--- 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 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap