]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
TLS: Add support for RFC 5705 TLS exporter context with internal TLS
authorJouni Malinen <j@w1.fi>
Sat, 16 Mar 2019 16:40:49 +0000 (18:40 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 16 Mar 2019 16:52:09 +0000 (18:52 +0200)
Use the provided context, if any, to generate the seed for TLS PRF.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/crypto/tls_internal.c
src/tls/tlsv1_client.c
src/tls/tlsv1_client.h
src/tls/tlsv1_server.c
src/tls/tlsv1_server.h

index 50a7b300dc94e0d347725697ae35f438a6fd09b9..8095b43bd21bc70ad2beb463900ee7bafb4c3906 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * TLS interface functions and an internal TLS implementation
- * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
+ * 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.
@@ -412,7 +412,8 @@ static int tls_get_keyblock_size(struct tls_connection *conn)
 
 
 static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
-                             const char *label, int server_random_first,
+                             const char *label, const u8 *context,
+                             size_t context_len, int server_random_first,
                              int skip_keyblock, u8 *out, size_t out_len)
 {
        int ret = -1, skip = 0;
@@ -431,15 +432,15 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
 
 #ifdef CONFIG_TLS_INTERNAL_CLIENT
        if (conn->client) {
-               ret = tlsv1_client_prf(conn->client, label,
-                                      server_random_first,
+               ret = tlsv1_client_prf(conn->client, label, context,
+                                      context_len, server_random_first,
                                       _out, skip + out_len);
        }
 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
 #ifdef CONFIG_TLS_INTERNAL_SERVER
        if (conn->server) {
-               ret = tlsv1_server_prf(conn->server, label,
-                                      server_random_first,
+               ret = tlsv1_server_prf(conn->server, label, context,
+                                      context_len, server_random_first,
                                       _out, skip + out_len);
        }
 #endif /* CONFIG_TLS_INTERNAL_SERVER */
@@ -455,17 +456,16 @@ int 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)
 {
-       if (context)
-               return -1;
-       return tls_connection_prf(tls_ctx, conn, label, 0, 0, out, out_len);
+       return tls_connection_prf(tls_ctx, conn, label, context, context_len,
+                                 0, 0, out, out_len);
 }
 
 
 int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
                                    u8 *out, size_t out_len)
 {
-       return tls_connection_prf(tls_ctx, conn, "key expansion", 1, 1, out,
-                                 out_len);
+       return tls_connection_prf(tls_ctx, conn, "key expansion", NULL, 0,
+                                 1, 1, out, out_len);
 }
 
 
index 76e19746b02090a6b07a30368d86eb6ec0009886..a147a54a3d10622dfad1dafadaf6f173b0f4d862 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * TLS v1.0/v1.1/v1.2 client (RFC 2246, RFC 4346, RFC 5246)
- * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -514,6 +514,8 @@ int tlsv1_client_established(struct tlsv1_client *conn)
  * tlsv1_client_prf - Use TLS-PRF to derive keying material
  * @conn: TLSv1 client connection data from tlsv1_client_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
  * @server_random_first: seed is 0 = client_random|server_random,
  * 1 = server_random|client_random
  * @out: Buffer for output data from TLS-PRF
@@ -521,13 +523,26 @@ int tlsv1_client_established(struct tlsv1_client *conn)
  * Returns: 0 on success, -1 on failure
  */
 int tlsv1_client_prf(struct tlsv1_client *conn, const char *label,
+                    const u8 *context, size_t context_len,
                     int server_random_first, u8 *out, size_t out_len)
 {
-       u8 seed[2 * TLS_RANDOM_LEN];
+       u8 *seed, *pos;
+       size_t seed_len = 2 * TLS_RANDOM_LEN;
+       int res;
 
        if (conn->state != ESTABLISHED)
                return -1;
 
+       if (context_len > 65535)
+               return -1;
+
+       if (context)
+               seed_len += 2 + context_len;
+
+       seed = os_malloc(seed_len);
+       if (!seed)
+               return -1;
+
        if (server_random_first) {
                os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
                os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random,
@@ -538,9 +553,18 @@ int tlsv1_client_prf(struct tlsv1_client *conn, const char *label,
                          TLS_RANDOM_LEN);
        }
 
-       return tls_prf(conn->rl.tls_version,
-                      conn->master_secret, TLS_MASTER_SECRET_LEN,
-                      label, seed, 2 * TLS_RANDOM_LEN, out, out_len);
+       if (context) {
+               pos = seed + 2 * TLS_RANDOM_LEN;
+               WPA_PUT_BE16(pos, context_len);
+               pos += 2;
+               os_memcpy(pos, context, context_len);
+       }
+
+       res = tls_prf(conn->rl.tls_version,
+                     conn->master_secret, TLS_MASTER_SECRET_LEN,
+                     label, seed, seed_len, out, out_len);
+       os_free(seed);
+       return res;
 }
 
 
index 40fa6c7fbdeeb17f55c2bc369c904e3aadf7d4e2..7fcc256f14aaaa62ce5e22c02d30e3b2f87cb1c1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * TLS v1.0/v1.1/v1.2 client (RFC 2246, RFC 4346, RFC 5246)
- * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -19,6 +19,7 @@ struct tlsv1_client * tlsv1_client_init(void);
 void tlsv1_client_deinit(struct tlsv1_client *conn);
 int tlsv1_client_established(struct tlsv1_client *conn);
 int tlsv1_client_prf(struct tlsv1_client *conn, const char *label,
+                    const u8 *context, size_t context_len,
                     int server_random_first, u8 *out, size_t out_len);
 u8 * tlsv1_client_handshake(struct tlsv1_client *conn,
                            const u8 *in_data, size_t in_len,
index 4759509e53ebbfc34260446ec90d6b71f0727b62..12dcc859a280347c7015485a9cb3262895d5d47e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * TLS v1.0/v1.1/v1.2 server (RFC 2246, RFC 4346, RFC 5246)
- * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -462,6 +462,8 @@ int tlsv1_server_established(struct tlsv1_server *conn)
  * tlsv1_server_prf - Use TLS-PRF to derive keying material
  * @conn: TLSv1 server connection data from tlsv1_server_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
  * @server_random_first: seed is 0 = client_random|server_random,
  * 1 = server_random|client_random
  * @out: Buffer for output data from TLS-PRF
@@ -469,13 +471,26 @@ int tlsv1_server_established(struct tlsv1_server *conn)
  * Returns: 0 on success, -1 on failure
  */
 int tlsv1_server_prf(struct tlsv1_server *conn, const char *label,
+                    const u8 *context, size_t context_len,
                     int server_random_first, u8 *out, size_t out_len)
 {
-       u8 seed[2 * TLS_RANDOM_LEN];
+       u8 *seed, *pos;
+       size_t seed_len = 2 * TLS_RANDOM_LEN;
+       int res;
 
        if (conn->state != ESTABLISHED)
                return -1;
 
+       if (context_len > 65535)
+               return -1;
+
+       if (context)
+               seed_len += 2 + context_len;
+
+       seed = os_malloc(seed_len);
+       if (!seed)
+               return -1;
+
        if (server_random_first) {
                os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
                os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random,
@@ -486,9 +501,18 @@ int tlsv1_server_prf(struct tlsv1_server *conn, const char *label,
                          TLS_RANDOM_LEN);
        }
 
-       return tls_prf(conn->rl.tls_version,
-                      conn->master_secret, TLS_MASTER_SECRET_LEN,
-                      label, seed, 2 * TLS_RANDOM_LEN, out, out_len);
+       if (context) {
+               pos = seed + 2 * TLS_RANDOM_LEN;
+               WPA_PUT_BE16(pos, context_len);
+               pos += 2;
+               os_memcpy(pos, context, context_len);
+       }
+
+       res = tls_prf(conn->rl.tls_version,
+                     conn->master_secret, TLS_MASTER_SECRET_LEN,
+                     label, seed, seed_len, out, out_len);
+       os_free(seed);
+       return res;
 }
 
 
index c3fd37eb0b4b9b96d4bd9aacc8f3bab1915e2aa9..c9c0875ca33082c96a28b2430c28ccfa189d7e3d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * TLS v1.0/v1.1/v1.2 server (RFC 2246, RFC 4346, RFC 5246)
- * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -19,6 +19,7 @@ struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred);
 void tlsv1_server_deinit(struct tlsv1_server *conn);
 int tlsv1_server_established(struct tlsv1_server *conn);
 int tlsv1_server_prf(struct tlsv1_server *conn, const char *label,
+                    const u8 *context, size_t context_len,
                     int server_random_first, u8 *out, size_t out_len);
 u8 * tlsv1_server_handshake(struct tlsv1_server *conn,
                            const u8 *in_data, size_t in_len, size_t *out_len);