diff mbox series

Add Type-Code context to EAP_TLS 1.3 exported Key_Material and Method-Id

Message ID 20190219104216.3986-1-ervin.oro@aalto.fi
State Changes Requested
Headers show
Series Add Type-Code context to EAP_TLS 1.3 exported Key_Material and Method-Id | expand

Commit Message

Ervin Oro Feb. 19, 2019, 10:42 a.m. UTC
According to the proposed standard change in
https://emu-wg.github.io/draft-ietf-emu-eap-tls13/draft-ietf-emu-eap-tls13.html#rfc.section.2.3

Internal SSL library nor the WolfSSL library seem to support
an additional context value as specified in rfc5705#section-4.
Therefore, this breaks EAP_TLS 1.3 with those. (However, TLS 1.3
remains disabled by default.)

Signed-off-by: Ervin Oro <ervin.oro@aalto.fi>
---
 src/crypto/tls.h                       | 10 +++++++++
 src/crypto/tls_gnutls.c                | 14 ++++++++++--
 src/crypto/tls_internal.c              |  9 ++++++++
 src/crypto/tls_none.c                  |  9 ++++++++
 src/crypto/tls_openssl.c               | 13 ++++++++++-
 src/crypto/tls_wolfssl.c               |  9 ++++++++
 src/eap_peer/eap_tls.c                 | 13 ++++++++---
 src/eap_peer/eap_tls_common.c          | 24 ++++++++++++++++-----
 src/eap_peer/eap_tls_common.h          |  3 +++
 src/eap_server/eap_server_tls.c        | 30 +++++++++++++++++++-------
 src/eap_server/eap_server_tls_common.c | 21 +++++++++++++-----
 src/eap_server/eap_tls_common.h        |  3 +++
 12 files changed, 134 insertions(+), 24 deletions(-)

Comments

Jouni Malinen March 10, 2019, 9:45 a.m. UTC | #1
On Tue, Feb 19, 2019 at 12:42:16PM +0200, Ervin Oro wrote:
> According to the proposed standard change in
> https://emu-wg.github.io/draft-ietf-emu-eap-tls13/draft-ietf-emu-eap-tls13.html#rfc.section.2.3

That has not yet been published in an actual draft, so I don't want to
apply such changes yet. Should it be included in
draft-ietf-emu-eap-tls13-04, this could be considered.

It would be useful to split this patch into two parts: one to add
support for the optional context parameter to the exporter (and that
could be applied now) and the other one for modifying EAP-TLS v1.3 to
use this (which would wait for the draft to be published).

> diff --git a/src/crypto/tls.h b/src/crypto/tls.h
> @@ -378,6 +381,13 @@ int __must_check tls_connection_export_key(void *tls_ctx,
>  					   const char *label,
>  					   u8 *out, size_t out_len);
>  
> +int __must_check tls_connection_export_key2(void *tls_ctx,
> +                                            struct tls_connection *conn,
> +                                            const char *label,
> +                                            const unsigned char *context,
> +                                            size_t contextlen, int use_context,
> +                                            u8 *out, size_t out_len);

I don't see any need for introducing a new function for this. The
existing tls_connection_export_key() should be extended with the new
parameters instead.

There should be no need for that use_context argument either. context !=
NULL can be used for that implicitly.

> diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c
> @@ -455,6 +455,15 @@ int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
>  }
>  
>  
> +int tls_connection_export_key2(void *tls_ctx, struct tls_connection *conn,
> +                               const char *label, const unsigned char *context,
> +                               size_t contextlen, int use_context, u8 *out,
> +                               size_t out_len)
> +{
> +	return -1;
> +}

It would be straightforward to support this new context argument with
the internal TLS implementation.
diff mbox series

Patch

diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index 413cccddc..3291ff877 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -367,6 +367,9 @@  int __must_check tls_connection_get_random(void *tls_ctx,
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
  * @label: Label (e.g., description of the key) for PRF
+ * @context: optional extra upper-layer context (max len 2^16)
+ * @contextlen: the length of the context value (MAY be zero)
+ * @use_context: 0 if context is not used (no context != 0-length context)
  * @out: Buffer for output data from TLS-PRF
  * @out_len: Length of the output buffer
  * Returns: 0 on success, -1 on failure
@@ -378,6 +381,13 @@  int __must_check tls_connection_export_key(void *tls_ctx,
 					   const char *label,
 					   u8 *out, size_t out_len);
 
+int __must_check tls_connection_export_key2(void *tls_ctx,
+                                            struct tls_connection *conn,
+                                            const char *label,
+                                            const unsigned char *context,
+                                            size_t contextlen, int use_context,
+                                            u8 *out, size_t out_len);
+
 /**
  * tls_connection_get_eap_fast_key - Derive key material for EAP-FAST
  * @tls_ctx: TLS context data from tls_init()
diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c
index 527d01ecf..9e213ea8a 100644
--- a/src/crypto/tls_gnutls.c
+++ b/src/crypto/tls_gnutls.c
@@ -896,13 +896,23 @@  int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
 
 int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
 			      const char *label, u8 *out, size_t out_len)
+{
+	return tls_connection_export_key2(tls_ctx, conn, label, NULL, 0, 0 out,
+                                          out_len);
+}
+
+
+int tls_connection_export_key2(void *tls_ctx, struct tls_connection *conn,
+                               const char *label, const unsigned char *context,
+                               size_t contextlen, int use_context, u8 *out,
+                               size_t out_len)
 {
 	if (conn == NULL || conn->session == NULL)
 		return -1;
 
 	return gnutls_prf(conn->session, os_strlen(label), label,
-			  0 /* client_random first */, 0, NULL, out_len,
-			  (char *) out);
+			  0 /* client_random first */, contextlen, context,
+                          out_len, (char *) out);
 }
 
 
diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c
index 57b3e632d..82177e327 100644
--- a/src/crypto/tls_internal.c
+++ b/src/crypto/tls_internal.c
@@ -455,6 +455,15 @@  int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
 }
 
 
+int tls_connection_export_key2(void *tls_ctx, struct tls_connection *conn,
+                               const char *label, const unsigned char *context,
+                               size_t contextlen, int use_context, u8 *out,
+                               size_t out_len)
+{
+	return -1;
+}
+
+
 int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
 				    u8 *out, size_t out_len)
 {
diff --git a/src/crypto/tls_none.c b/src/crypto/tls_none.c
index 108e9aa2e..99c7fdeac 100644
--- a/src/crypto/tls_none.c
+++ b/src/crypto/tls_none.c
@@ -100,6 +100,15 @@  int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
 }
 
 
+int tls_connection_export_key2(void *tls_ctx, struct tls_connection *conn,
+                               const char *label, const unsigned char *context,
+                               size_t contextlen, int use_context, u8 *out,
+                               size_t out_len)
+{
+	return -1;
+}
+
+
 int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
 				    u8 *out, size_t out_len)
 {
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 18d76737e..fbc6b60ea 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -3670,10 +3670,21 @@  static int openssl_get_keyblock_size(SSL *ssl)
 
 int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
 			      const char *label, u8 *out, size_t out_len)
+{
+	return tls_connection_export_key2(tls_ctx, conn, label, NULL, 0, 0, out,
+                                          out_len);
+}
+
+
+int tls_connection_export_key2(void *tls_ctx, struct tls_connection *conn,
+                               const char *label, const unsigned char *context,
+                               size_t contextlen, int use_context, u8 *out,
+                               size_t out_len)
 {
 	if (!conn ||
 	    SSL_export_keying_material(conn->ssl, out, out_len, label,
-				       os_strlen(label), NULL, 0, 0) != 1)
+				       os_strlen(label), context, contextlen,
+                                       use_context) != 1)
 		return -1;
 	return 0;
 }
diff --git a/src/crypto/tls_wolfssl.c b/src/crypto/tls_wolfssl.c
index b59622e5e..127c5dcd4 100644
--- a/src/crypto/tls_wolfssl.c
+++ b/src/crypto/tls_wolfssl.c
@@ -1978,6 +1978,15 @@  int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
 }
 
 
+int tls_connection_export_key2(void *tls_ctx, struct tls_connection *conn,
+                               const char *label, const unsigned char *context,
+                               size_t contextlen, int use_context, u8 *out,
+                               size_t out_len)
+{
+	return -1;
+}
+
+
 #define SEED_LEN	(RAN_LEN + RAN_LEN)
 
 int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
diff --git a/src/eap_peer/eap_tls.c b/src/eap_peer/eap_tls.c
index cb747026c..92c2081a4 100644
--- a/src/eap_peer/eap_tls.c
+++ b/src/eap_peer/eap_tls.c
@@ -174,6 +174,9 @@  static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
 			    struct eap_method_ret *ret)
 {
 	const char *label;
+	const unsigned char context[] = {EAP_TYPE_TLS};
+	size_t contextlen = 0;
+	int use_context = 0;
 
 	wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
 
@@ -184,6 +187,8 @@  static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
 
 	if (data->ssl.tls_v13) {
 		label = "EXPORTER_EAP_TLS_Key_Material";
+		contextlen = 1;
+		use_context = 1;
 
 		/* A possible NewSessionTicket may be received before
 		 * EAP-Success, so need to allow it to be received. */
@@ -197,9 +202,11 @@  static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
 	}
 
 	eap_tls_free_key(data);
-	data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label,
-						 EAP_TLS_KEY_LEN +
-						 EAP_EMSK_LEN);
+	data->key_data = eap_peer_tls_derive_key2(sm, &data->ssl, label,
+						  context, contextlen,
+						  use_context,
+						  EAP_TLS_KEY_LEN +
+						  EAP_EMSK_LEN);
 	if (data->key_data) {
 		wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key",
 				data->key_data, EAP_TLS_KEY_LEN);
diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
index 7dbd364a5..838dbabd2 100644
--- a/src/eap_peer/eap_tls_common.c
+++ b/src/eap_peer/eap_tls_common.c
@@ -347,6 +347,9 @@  void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
  * @data: Data for TLS processing
  * @label: Label string for deriving the keys, e.g., "client EAP encryption"
+ * @context: optional extra upper-layer context (max len 2^16)
+ * @contextlen: the length of the context value (MAY be zero)
+ * @use_context: 0 if context is not used (no context != 0-length context)
  * @len: Length of the key material to generate (usually 64 for MSK)
  * Returns: Pointer to allocated key on success or %NULL on failure
  *
@@ -358,6 +361,14 @@  void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
  */
 u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
 			     const char *label, size_t len)
+{
+	return eap_peer_tls_derive_key2(sm, data, label, NULL, 0, 0, len);
+}
+
+
+u8 * eap_peer_tls_derive_key2(struct eap_sm *sm, struct eap_ssl_data *data,
+			      const char *label, const unsigned char *context,
+                              size_t contextlen, int use_context, size_t len)
 {
 	u8 *out;
 
@@ -365,8 +376,9 @@  u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
 	if (out == NULL)
 		return NULL;
 
-	if (tls_connection_export_key(data->ssl_ctx, data->conn, label, out,
-				      len)) {
+	if (tls_connection_export_key2(data->ssl_ctx, data->conn, label,
+                                       context, contextlen, use_context, out,
+                                       len)) {
 		os_free(out);
 		return NULL;
 	}
@@ -400,14 +412,16 @@  u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
 
 		/* Session-Id = <EAP-Type> || Method-Id
 		 * Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id",
-		 *                          "", 64)
+		 *                          Type-Code, 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", 64);
+		const unsigned char context[] = {EAP_TYPE_TLS};
+		method_id = eap_peer_tls_derive_key2(
+			sm, data, "EXPORTER_EAP_TLS_Method-Id", context, 1, 1,
+			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 306e6a98b..c2839922b 100644
--- a/src/eap_peer/eap_tls_common.h
+++ b/src/eap_peer/eap_tls_common.h
@@ -100,6 +100,9 @@  int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
 void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);
 u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
 			     const char *label, size_t len);
+u8 * eap_peer_tls_derive_key2(struct eap_sm *sm, struct eap_ssl_data *data,
+			      const char *label, const unsigned char *context,
+                	      size_t contextlen, int use_context, size_t len);
 u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
 				    struct eap_ssl_data *data, u8 eap_type,
 				    size_t *len);
diff --git a/src/eap_server/eap_server_tls.c b/src/eap_server/eap_server_tls.c
index 13d234982..c8ee49717 100644
--- a/src/eap_server/eap_server_tls.c
+++ b/src/eap_server/eap_server_tls.c
@@ -322,16 +322,23 @@  static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
 	struct eap_tls_data *data = priv;
 	u8 *eapKeyData;
 	const char *label;
+	const unsigned char context[] = {EAP_TYPE_TLS};
+	size_t contextlen = 0;
+	int use_context = 0;
 
 	if (data->state != SUCCESS)
 		return NULL;
 
-	if (data->ssl.tls_v13)
+	if (data->ssl.tls_v13) {
 		label = "EXPORTER_EAP_TLS_Key_Material";
-	else
+		contextlen = 1;
+		use_context = 1;
+	} else {
 		label = "client EAP encryption";
-	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, label,
-					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
+	}
+	eapKeyData = eap_server_tls_derive_key2(sm, &data->ssl, label,
+						context, contextlen, use_context,
+					        EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
 	if (eapKeyData) {
 		*len = EAP_TLS_KEY_LEN;
 		wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived key",
@@ -350,16 +357,23 @@  static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 	struct eap_tls_data *data = priv;
 	u8 *eapKeyData, *emsk;
 	const char *label;
+	const unsigned char context[] = {EAP_TYPE_TLS};
+	size_t contextlen = 0;
+	int use_context = 0;
 
 	if (data->state != SUCCESS)
 		return NULL;
 
-	if (data->ssl.tls_v13)
+	if (data->ssl.tls_v13) {
 		label = "EXPORTER_EAP_TLS_Key_Material";
-	else
+		contextlen = 1;
+		use_context = 1;
+	} else {
 		label = "client EAP encryption";
-	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, label,
-					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
+	}
+	eapKeyData = eap_server_tls_derive_key2(sm, &data->ssl, label,
+						context, contextlen, use_context,
+					        EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
 	if (eapKeyData) {
 		emsk = os_malloc(EAP_EMSK_LEN);
 		if (emsk)
diff --git a/src/eap_server/eap_server_tls_common.c b/src/eap_server/eap_server_tls_common.c
index 4ba7c2499..c6386cddd 100644
--- a/src/eap_server/eap_server_tls_common.c
+++ b/src/eap_server/eap_server_tls_common.c
@@ -108,6 +108,14 @@  void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
 
 u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
 			       const char *label, size_t len)
+{
+	return eap_server_tls_derive_key2(sm, data, label, NULL, 0, 0, len);
+}
+
+
+u8 * eap_server_tls_derive_key2(struct eap_sm *sm, struct eap_ssl_data *data,
+			        const char *label, const unsigned char *context,
+                                size_t contextlen, int use_context, size_t len)
 {
 	u8 *out;
 
@@ -115,8 +123,9 @@  u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
 	if (out == NULL)
 		return NULL;
 
-	if (tls_connection_export_key(sm->ssl_ctx, data->conn, label, out,
-				      len)) {
+	if (tls_connection_export_key2(sm->ssl_ctx, data->conn, label,
+                                       context, contextlen, use_context, out,
+                                       len)) {
 		os_free(out);
 		return NULL;
 	}
@@ -150,14 +159,16 @@  u8 * eap_server_tls_derive_session_id(struct eap_sm *sm,
 
 		/* Session-Id = <EAP-Type> || Method-Id
 		 * Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id",
-		 *                          "", 64)
+		 *                          Type-Code, 64)
 		 */
 		*len = 1 + 64;
 		id = os_malloc(*len);
 		if (!id)
 			return NULL;
-		method_id = eap_server_tls_derive_key(
-			sm, data, "EXPORTER_EAP_TLS_Method-Id", 64);
+		const unsigned char context[] = {EAP_TYPE_TLS};
+		method_id = eap_server_tls_derive_key2(
+			sm, data, "EXPORTER_EAP_TLS_Method-Id", context, 1, 1,
+			64);
 		if (!method_id) {
 			os_free(id);
 			return NULL;
diff --git a/src/eap_server/eap_tls_common.h b/src/eap_server/eap_tls_common.h
index 31f6e72d7..443260972 100644
--- a/src/eap_server/eap_tls_common.h
+++ b/src/eap_server/eap_tls_common.h
@@ -79,6 +79,9 @@  int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
 void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);
 u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
 			       const char *label, size_t len);
+u8 * eap_server_tls_derive_key2(struct eap_sm *sm, struct eap_ssl_data *data,
+			        const char *label, const unsigned char *context,
+                                size_t contextlen, int use_context, size_t len);
 u8 * eap_server_tls_derive_session_id(struct eap_sm *sm,
 				      struct eap_ssl_data *data, u8 eap_type,
 				      size_t *len);