[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Thu Jun 29 09:20:31 UTC 2017


The branch master has been updated
       via  a599574be17579496877bcdcc5e1eeaf5b014cf3 (commit)
       via  e88c40af4572a422be5fcab732bd46c55df136f8 (commit)
       via  2197d1dfbe787902fb5fa8f5bd8f67a15b83923f (commit)
       via  0ca8d1ecf26b4a564222fc17e0e48053f2fd0843 (commit)
      from  519a5d1ef2ca3ba0adf0bc1d7dff984e8523d813 (commit)


- Log -----------------------------------------------------------------
commit a599574be17579496877bcdcc5e1eeaf5b014cf3
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Jun 28 17:18:27 2017 +0100

    Updates following review of SSL_export_key_material() changes
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/3782)

commit e88c40af4572a422be5fcab732bd46c55df136f8
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jun 27 16:32:40 2017 +0100

    Update the SSL_export_keying_material() documentation for TLSv1.3
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/3782)

commit 2197d1dfbe787902fb5fa8f5bd8f67a15b83923f
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jun 27 16:28:25 2017 +0100

    Add an SSL_export_keying_material() test
    
    There aren't any test vectors for this, so all we do is test that both
    sides of the communication create the same result for different protocol
    versions.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/3782)

commit 0ca8d1ecf26b4a564222fc17e0e48053f2fd0843
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Jun 27 14:57:15 2017 +0100

    Update SSL_export_keying_material() for TLSv1.3
    
    Fixes #3680
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/3782)

-----------------------------------------------------------------------

Summary of changes:
 doc/man3/SSL_export_keying_material.pod |   9 ++-
 ssl/ssl_locl.h                          |   5 ++
 ssl/t1_lib.c                            |   2 +-
 ssl/tls13_enc.c                         |  45 +++++++++++
 test/sslapitest.c                       | 127 ++++++++++++++++++++++++++++++++
 5 files changed, 184 insertions(+), 4 deletions(-)

diff --git a/doc/man3/SSL_export_keying_material.pod b/doc/man3/SSL_export_keying_material.pod
index ccb99ec..532b144 100644
--- a/doc/man3/SSL_export_keying_material.pod
+++ b/doc/man3/SSL_export_keying_material.pod
@@ -18,7 +18,8 @@ SSL_export_keying_material - obtain keying material for application use
 During the creation of a TLS or DTLS connection shared keying material is
 established between the two endpoints. The function SSL_export_keying_material()
 enables an application to use some of this keying material for its own purposes
-in accordance with RFC5705.
+in accordance with RFC5705 (for TLSv1.2 and below) or RFCXXXX (for TLSv1.3).
+TODO(TLS1.3): Update the RFC number when the RFC is published.
 
 An application may need to securely establish the context within which this
 keying material will be used. For example this may include identifiers for the
@@ -32,8 +33,10 @@ pointed to by B<context> and should be B<contextlen> bytes long. Provision of
 a context is optional. If the context should be omitted entirely then
 B<use_context> should be set to 0. Otherwise it should be any other value. If
 B<use_context> is 0 then the values of B<context> and B<contextlen> are ignored.
-Note that a zero length context is treated differently to no context at all, and
-will result in different keying material being returned.
+Note that in TLSv1.2 and below a zero length context is treated differently from
+no context at all, and will result in different keying material being returned.
+In TLSv1.3 a zero length context is that same as no context at all and will
+result in the same keying material being returned.
 
 An application specific label should be provided in the location pointed to by
 B<label> and should be B<llen> bytes long. Typically this will be a value from
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 7889ab5..1105416 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1073,6 +1073,7 @@ struct ssl_st {
     unsigned char handshake_traffic_hash[EVP_MAX_MD_SIZE];
     unsigned char client_app_traffic_secret[EVP_MAX_MD_SIZE];
     unsigned char server_app_traffic_secret[EVP_MAX_MD_SIZE];
+    unsigned char exporter_master_secret[EVP_MAX_MD_SIZE];
     EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */
     unsigned char read_iv[EVP_MAX_IV_LENGTH]; /* TLSv1.3 static read IV */
     EVP_MD_CTX *read_hash;      /* used for mac generation */
@@ -2288,6 +2289,10 @@ __owur int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
                                        const char *label, size_t llen,
                                        const unsigned char *p, size_t plen,
                                        int use_context);
+__owur int tls13_export_keying_material(SSL *s, unsigned char *out, size_t olen,
+                                        const char *label, size_t llen,
+                                        const unsigned char *context,
+                                        size_t contextlen, int use_context);
 __owur int tls1_alert_code(int code);
 __owur int tls13_alert_code(int code);
 __owur int ssl3_alert_code(int code);
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 4f28818..95b9b8b 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -82,7 +82,7 @@ SSL3_ENC_METHOD const TLSv1_3_enc_data = {
     TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
     TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
     tls13_alert_code,
-    tls1_export_keying_material,
+    tls13_export_keying_material,
     SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF,
     ssl3_set_handshake_header,
     tls_close_construct_packet,
diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c
index bc1995e..55e68c6 100644
--- a/ssl/tls13_enc.c
+++ b/ssl/tls13_enc.c
@@ -337,6 +337,7 @@ int tls13_change_cipher_state(SSL *s, int which)
     static const unsigned char client_application_traffic[] = "c ap traffic";
     static const unsigned char server_handshake_traffic[] = "s hs traffic";
     static const unsigned char server_application_traffic[] = "s ap traffic";
+    static const unsigned char exporter_master_secret[] = "exp master";
     static const unsigned char resumption_master_secret[] = "res master";
     unsigned char *iv;
     unsigned char secret[EVP_MAX_MD_SIZE];
@@ -509,6 +510,15 @@ int tls13_change_cipher_state(SSL *s, int which)
             goto err;
         }
         s->session->master_key_length = hashlen;
+
+        /* Now we create the exporter master secret */
+        if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret,
+                               exporter_master_secret,
+                               sizeof(exporter_master_secret) - 1,
+                               hash, s->exporter_master_secret, hashlen)) {
+            SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+            goto err;
+        }
     }
 
     if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher,
@@ -587,3 +597,38 @@ int tls13_alert_code(int code)
 
     return tls1_alert_code(code);
 }
+
+int tls13_export_keying_material(SSL *s, unsigned char *out, size_t olen,
+                                 const char *label, size_t llen,
+                                 const unsigned char *context,
+                                 size_t contextlen, int use_context)
+{
+    unsigned char exportsecret[EVP_MAX_MD_SIZE];
+    static const unsigned char exporterlabel[] = "exporter";
+    unsigned char hash[EVP_MAX_MD_SIZE];
+    const EVP_MD *md = ssl_handshake_md(s);
+    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+    unsigned int hashsize;
+    int ret = 0;
+
+    if (ctx == NULL || !SSL_is_init_finished(s))
+        goto err;
+
+    if (!use_context)
+        contextlen = 0;
+
+    if (EVP_DigestInit_ex(ctx, md, NULL) <= 0
+            || EVP_DigestUpdate(ctx, context, contextlen) <= 0
+            || EVP_DigestFinal_ex(ctx, hash, &hashsize) <= 0
+            || !tls13_hkdf_expand(s, md, s->exporter_master_secret,
+                                  (const unsigned char *)label, llen, NULL,
+                                  exportsecret, 0)
+            || !tls13_hkdf_expand(s, md, exportsecret, exporterlabel,
+                                  sizeof(exporterlabel) - 1, hash, out, olen))
+        goto err;
+
+    ret = 1;
+ err:
+    EVP_MD_CTX_free(ctx);
+    return ret;
+}
diff --git a/test/sslapitest.c b/test/sslapitest.c
index 215035a..ae5c4c0 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -2486,6 +2486,132 @@ static int test_serverinfo(int tst)
     return testresult;
 }
 
+/*
+ * Test that SSL_export_keying_material() produces expected results. There are
+ * no test vectors so all we do is test that both sides of the communication
+ * produce the same results for different protocol versions.
+ */
+static int test_export_key_mat(int tst)
+{
+    int testresult = 0;
+    SSL_CTX *cctx = NULL, *sctx = NULL, *sctx2 = NULL;
+    SSL *clientssl = NULL, *serverssl = NULL;
+    const char label[] = "test label";
+    const unsigned char context[] = "context";
+    const unsigned char *emptycontext = NULL;
+    unsigned char ckeymat1[80], ckeymat2[80], ckeymat3[80];
+    unsigned char skeymat1[80], skeymat2[80], skeymat3[80];
+    const int protocols[] = {
+        TLS1_VERSION,
+        TLS1_1_VERSION,
+        TLS1_2_VERSION,
+        TLS1_3_VERSION
+    };
+
+#ifdef OPENSSL_NO_TLS1
+    if (tst == 0)
+        return 1;
+#endif
+#ifdef OPENSSL_NO_TLS1_1
+    if (tst == 1)
+        return 1;
+#endif
+#ifdef OPENSSL_NO_TLS1_2
+    if (tst == 2)
+        return 1;
+#endif
+#ifdef OPENSSL_NO_TLS1_3
+    if (tst == 3)
+        return 1;
+#endif
+    if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
+                                       TLS_client_method(), &sctx,
+                                       &cctx, cert, privkey)))
+        goto end;
+
+    OPENSSL_assert(tst >= 0 && (size_t)tst < OSSL_NELEM(protocols));
+    SSL_CTX_set_max_proto_version(cctx, protocols[tst]);
+    SSL_CTX_set_min_proto_version(cctx, protocols[tst]);
+
+    if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL,
+                                      NULL))
+            || !TEST_true(create_ssl_connection(serverssl, clientssl,
+                                                SSL_ERROR_NONE)))
+        goto end;
+
+    if (!TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat1,
+                                                sizeof(ckeymat1), label,
+                                                sizeof(label) - 1, context,
+                                                sizeof(context) - 1, 1), 1)
+            || !TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat2,
+                                                       sizeof(ckeymat2), label,
+                                                       sizeof(label) - 1,
+                                                       emptycontext,
+                                                       0, 1), 1)
+            || !TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat3,
+                                                       sizeof(ckeymat3), label,
+                                                       sizeof(label) - 1,
+                                                       NULL, 0, 0), 1)
+            || !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat1,
+                                                       sizeof(skeymat1), label,
+                                                       sizeof(label) - 1,
+                                                       context,
+                                                       sizeof(context) -1, 1),
+                            1)
+            || !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat2,
+                                                       sizeof(skeymat2), label,
+                                                       sizeof(label) - 1,
+                                                       emptycontext,
+                                                       0, 1), 1)
+            || !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat3,
+                                                       sizeof(skeymat3), label,
+                                                       sizeof(label) - 1,
+                                                       NULL, 0, 0), 1)
+               /*
+                * Check that both sides created the same key material with the
+                * same context.
+                */
+            || !TEST_mem_eq(ckeymat1, sizeof(ckeymat1), skeymat1,
+                            sizeof(skeymat1))
+               /*
+                * Check that both sides created the same key material with an
+                * empty context.
+                */
+            || !TEST_mem_eq(ckeymat2, sizeof(ckeymat2), skeymat2,
+                            sizeof(skeymat2))
+               /*
+                * Check that both sides created the same key material without a
+                * context.
+                */
+            || !TEST_mem_eq(ckeymat3, sizeof(ckeymat3), skeymat3,
+                            sizeof(skeymat3))
+               /* Different contexts should produce different results */
+            || !TEST_mem_ne(ckeymat1, sizeof(ckeymat1), ckeymat2,
+                            sizeof(ckeymat2)))
+        goto end;
+
+    /*
+     * Check that an empty context and no context produce different results in
+     * protocols less than TLSv1.3. In TLSv1.3 they should be the same.
+     */
+    if ((tst != 3 && !TEST_mem_ne(ckeymat2, sizeof(ckeymat2), ckeymat3,
+                                  sizeof(ckeymat3)))
+            || (tst ==3 && !TEST_mem_eq(ckeymat2, sizeof(ckeymat2), ckeymat3,
+                                        sizeof(ckeymat3))))
+        goto end;
+
+    testresult = 1;
+
+ end:
+    SSL_free(serverssl);
+    SSL_free(clientssl);
+    SSL_CTX_free(sctx2);
+    SSL_CTX_free(sctx);
+    SSL_CTX_free(cctx);
+
+    return testresult;
+}
+
 int test_main(int argc, char *argv[])
 {
     int testresult = 1;
@@ -2539,6 +2665,7 @@ int test_main(int argc, char *argv[])
     ADD_ALL_TESTS(test_custom_exts, 3);
 #endif
     ADD_ALL_TESTS(test_serverinfo, 8);
+    ADD_ALL_TESTS(test_export_key_mat, 4);
 
     testresult = run_tests(argv[0]);
 


More information about the openssl-commits mailing list