]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add support for an optional context parameter to TLS exporter
authorErvin Oro <ervin.oro@aalto.fi>
Mon, 11 Mar 2019 11:21:36 +0000 (13:21 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 16 Mar 2019 16:52:09 +0000 (18:52 +0200)
Allow an additional context value to be passed to TLS exporter as
specified in RFC 5705 section 4.

This does not yet implement it for the internal TLS implementation.
However, as currently nothing uses context yet, this will not break
anything right now. WolfSSL maintainers also stated that they are not
going to add context support yet, but would look into it if/when this is
required by a published draft or a standard.

Signed-off-by: Ervin Oro <ervin.oro@aalto.fi>
16 files changed:
src/crypto/tls.h
src/crypto/tls_gnutls.c
src/crypto/tls_internal.c
src/crypto/tls_none.c
src/crypto/tls_openssl.c
src/crypto/tls_wolfssl.c
src/eap_peer/eap_peap.c
src/eap_peer/eap_tls.c
src/eap_peer/eap_tls_common.c
src/eap_peer/eap_tls_common.h
src/eap_peer/eap_ttls.c
src/eap_server/eap_server_peap.c
src/eap_server/eap_server_tls.c
src/eap_server/eap_server_tls_common.c
src/eap_server/eap_server_ttls.c
src/eap_server/eap_tls_common.h

index 6cc924150d7d8dc34f5581ba8bf6b27585d96d72..9463f58f99dfd1b19e2a11db97bc823c2bafe42f 100644 (file)
@@ -370,15 +370,21 @@ 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)
+ * @context_len: The length of the context value
  * @out: Buffer for output data from TLS-PRF
  * @out_len: Length of the output buffer
  * Returns: 0 on success, -1 on failure
  *
- * Exports keying material using the mechanism described in RFC 5705.
+ * Exports keying material using the mechanism described in RFC 5705. If
+ * context is %NULL, context is not provided; otherwise, context is provided
+ * (including the case of empty context with context_len == 0).
  */
 int __must_check tls_connection_export_key(void *tls_ctx,
                                           struct tls_connection *conn,
                                           const char *label,
+                                          const u8 *context,
+                                          size_t context_len,
                                           u8 *out, size_t out_len);
 
 /**
index 73e80f3b782b3507713ff6dbd230b05176281916..ccd28842a20a8621e21d8a143ddf72aed9d44b33 100644 (file)
@@ -898,14 +898,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)
+                             const char *label, const u8 *context,
+                             size_t context_len, u8 *out, size_t out_len)
 {
        if (conn == NULL || conn->session == NULL)
                return -1;
 
+#if GNUTLS_VERSION_NUMBER >= 0x030404
+       return gnutls_prf_rfc5705(conn->session, os_strlen(label), label,
+                                 context_len, (const char *) context,
+                                 out_len, (char *) out);
+#else /* 3.4.4 */
+       if (context)
+               return -1;
        return gnutls_prf(conn->session, os_strlen(label), label,
                          0 /* client_random first */, 0, NULL, out_len,
                          (char *) out);
+#endif /* 3.4.4 */
 }
 
 
index 2876630aa8ad4be08fe5ceaf39ae9815cf5d9415..50a7b300dc94e0d347725697ae35f438a6fd09b9 100644 (file)
@@ -452,8 +452,11 @@ static int tls_connection_prf(void *tls_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)
+                             const char *label, const u8 *context,
+                             size_t context_len, u8 *out, size_t out_len)
 {
+       if (context)
+               return -1;
        return tls_connection_prf(tls_ctx, conn, label, 0, 0, out, out_len);
 }
 
index 108e9aa2e47e18d40a5a5aee1663d9d99648d1b6..6d6fb0cafd31cd997ea3f261071a62d671b39821 100644 (file)
@@ -94,7 +94,8 @@ int tls_connection_get_random(void *tls_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)
+                             const char *label, const u8 *context,
+                             size_t context_len, u8 *out, size_t out_len)
 {
        return -1;
 }
index b8d055664baa8b328acd5394996087565cd266cf..fc555182076969ce426c1a4a7dfb76006740e708 100644 (file)
@@ -3908,11 +3908,13 @@ 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)
+                             const char *label, const u8 *context,
+                             size_t context_len, 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, context_len,
+                                      context != NULL) != 1)
                return -1;
        return 0;
 }
index 39a24b3309a0c620e2980a5c0b421748d3db482b..41fc946bccae2e95039edaf898637511e9eb30ce 100644 (file)
@@ -1973,8 +1973,11 @@ 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)
+                             const char *label, const u8 *context,
+                             size_t context_len, u8 *out, size_t out_len)
 {
+       if (context)
+               return -1;
        if (!conn || wolfSSL_make_eap_keys(conn->ssl, out, out_len, label) != 0)
                return -1;
        return 0;
index 650bea6ada2f4235e23b018505a1166cb0b38884..8dcf7cc2926f88e70a112586b4b1472178f6a2d2 100644 (file)
@@ -1084,6 +1084,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,
                                                        EAP_TLS_KEY_LEN +
                                                        EAP_EMSK_LEN);
                        if (data->key_data) {
index cb747026cb8a59765412b2ff2c93a11a086adf84..ffea9d213855fa429b7bd2300a3988a4ab8a2979 100644 (file)
@@ -198,6 +198,7 @@ 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,
+                                                NULL, 0,
                                                 EAP_TLS_KEY_LEN +
                                                 EAP_EMSK_LEN);
        if (data->key_data) {
index 1ee01a2da98ebca7f96d36eaffcea641b304694b..cb94c452efcebeb0dce3beec3337c48bfb1924e7 100644 (file)
@@ -349,6 +349,8 @@ 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)
+ * @context_len: The length of the context value
  * @len: Length of the key material to generate (usually 64 for MSK)
  * Returns: Pointer to allocated key on success or %NULL on failure
  *
@@ -357,9 +359,12 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
  * different label to bind the key usage into the generated material.
  *
  * The caller is responsible for freeing the returned buffer.
+ *
+ * Note: To provide the RFC 5705 context, the context variable must be non-NULL.
  */
 u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
-                            const char *label, size_t len)
+                            const char *label, const u8 *context,
+                            size_t context_len, size_t len)
 {
        u8 *out;
 
@@ -367,8 +372,8 @@ 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_key(data->ssl_ctx, data->conn, label,
+                                     context, context_len, out, len)) {
                os_free(out);
                return NULL;
        }
@@ -409,7 +414,7 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
                if (!id)
                        return NULL;
                method_id = eap_peer_tls_derive_key(
-                       sm, data, "EXPORTER_EAP_TLS_Method-Id", 64);
+                       sm, data, "EXPORTER_EAP_TLS_Method-Id", NULL, 0, 64);
                if (!method_id) {
                        os_free(id);
                        return NULL;
index 306e6a98bc3f7fc85720c06854bb991814ffe0f7..5f825294d7871b5dac9b7152bba594bc4548d762 100644 (file)
@@ -99,7 +99,8 @@ int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
                          struct eap_peer_config *config, u8 eap_type);
 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);
+                            const char *label, const u8 *context,
+                            size_t context_len, 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);
index 5d267010e2fbd04473e8b297dfc1f82ea8ab6618..1c8dbe2b433101e51cc4c547dac05a494b30c6f2 100644 (file)
@@ -271,6 +271,7 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm,
        eap_ttls_free_key(data);
        data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
                                                 "ttls keying material",
+                                                NULL, 0,
                                                 EAP_TLS_KEY_LEN +
                                                 EAP_EMSK_LEN);
        if (!data->key_data) {
@@ -303,7 +304,8 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm,
 static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
                                        struct eap_ttls_data *data, size_t len)
 {
-       return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len);
+       return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge",
+                                      NULL, 0, len);
 }
 #endif /* CONFIG_FIPS */
 
index 3d334a0db78e1fc98e09e6a2bd31e1f6d93ed4e0..92c0e5ec971633214ddfea5316dc80ee56015e16 100644 (file)
@@ -331,7 +331,7 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
         * phase 1 of PEAP (based on TLS).
         */
        tk = eap_server_tls_derive_key(sm, &data->ssl, "client EAP encryption",
-                                      EAP_TLS_KEY_LEN);
+                                      NULL, 0, EAP_TLS_KEY_LEN);
        if (tk == NULL)
                return -1;
        wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
@@ -1333,7 +1333,7 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
 
        /* TODO: PEAPv1 - different label in some cases */
        eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
-                                              "client EAP encryption",
+                                              "client EAP encryption", NULL, 0,
                                               EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
        if (eapKeyData) {
                os_memset(eapKeyData + EAP_TLS_KEY_LEN, 0, EAP_EMSK_LEN);
@@ -1363,7 +1363,7 @@ static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 
        /* TODO: PEAPv1 - different label in some cases */
        eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
-                                              "client EAP encryption",
+                                              "client EAP encryption", NULL, 0,
                                               EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
        if (eapKeyData) {
                emsk = os_memdup(eapKeyData + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
index 13d2349823b543da3f7d66611e81a5075e8928a1..357e72a825f6d0271d6f3187d0b678e971086ab1 100644 (file)
@@ -331,6 +331,7 @@ static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
        else
                label = "client EAP encryption";
        eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, label,
+                                              NULL, 0,
                                               EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
        if (eapKeyData) {
                *len = EAP_TLS_KEY_LEN;
@@ -359,6 +360,7 @@ static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
        else
                label = "client EAP encryption";
        eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, label,
+                                              NULL, 0,
                                               EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
        if (eapKeyData) {
                emsk = os_malloc(EAP_EMSK_LEN);
index 4ba7c24993741d3e937434afd5a51aa52ccce934..0eca0ff774094f0dd39a4560c0c4945dae42a4fc 100644 (file)
@@ -107,7 +107,8 @@ 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)
+                              const char *label, const u8 *context,
+                              size_t context_len, size_t len)
 {
        u8 *out;
 
@@ -115,8 +116,8 @@ 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_key(sm->ssl_ctx, data->conn, label,
+                                     context, context_len, out, len)) {
                os_free(out);
                return NULL;
        }
@@ -157,7 +158,7 @@ u8 * eap_server_tls_derive_session_id(struct eap_sm *sm,
                if (!id)
                        return NULL;
                method_id = eap_server_tls_derive_key(
-                       sm, data, "EXPORTER_EAP_TLS_Method-Id", 64);
+                       sm, data, "EXPORTER_EAP_TLS_Method-Id", NULL, 0, 64);
                if (!method_id) {
                        os_free(id);
                        return NULL;
index b14996b0b9909fcde90848b2f5a02a804edd43cb..52bff8afe42d83202385cdee00f530e8a4887892 100644 (file)
@@ -332,7 +332,7 @@ static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
                                        struct eap_ttls_data *data, size_t len)
 {
        return eap_server_tls_derive_key(sm, &data->ssl, "ttls challenge",
-                                        len);
+                                        NULL, 0, len);
 }
 
 
@@ -1268,7 +1268,7 @@ static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
                return NULL;
 
        eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
-                                              "ttls keying material",
+                                              "ttls keying material", NULL, 0,
                                               EAP_TLS_KEY_LEN);
        if (eapKeyData) {
                *len = EAP_TLS_KEY_LEN;
@@ -1310,7 +1310,7 @@ static u8 * eap_ttls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
                return NULL;
 
        eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
-                                              "ttls keying material",
+                                              "ttls keying material", NULL, 0,
                                               EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
        if (eapKeyData) {
                emsk = os_malloc(EAP_EMSK_LEN);
index 31f6e72d779a175fadddc8b51bc612026e425d42..0b04983adb0e9b2713f80d37ebd2c9ad5f9f4cae 100644 (file)
@@ -78,7 +78,8 @@ int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
                            int verify_peer, int eap_type);
 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);
+                              const char *label, const u8 *context,
+                              size_t context_len, 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);