Update SSL_export_keying_material() for TLSv1.3
authorMatt Caswell <matt@openssl.org>
Tue, 27 Jun 2017 13:57:15 +0000 (14:57 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 29 Jun 2017 09:15:49 +0000 (10:15 +0100)
Fixes #3680

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3782)

ssl/ssl_locl.h
ssl/t1_lib.c
ssl/tls13_enc.c

index 7889ab5b0e2bde4b6707786513eae22eb4de59e3..1105416d96e3e50b4cd8c1af3a1f09386af2f632 100644 (file)
@@ -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);
index 4f28818c33bb7fa780f6ba7afb0868ce581765ee..95b9b8b4d0749cb24617f943702d84926193f0b4 100644 (file)
@@ -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,
index bc1995e21f392c5382b2dbabb98b98d3213bc49b..67ae0a35415ca2fe11feb36b2ff4f1f1762f27b5 100644 (file)
@@ -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,41 @@ 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)
+        goto err;
+
+    if (!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;
+}