Updates following review of SSL_export_key_material() changes
[openssl.git] / ssl / tls13_enc.c
index 255bc96ac13efa5c5658c283f4ef99cc0eaeb3cb..55e68c60db1178d517e2023ddeafc5a156bbd846 100644 (file)
@@ -148,6 +148,7 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
                 || EVP_DigestInit_ex(mctx, md, NULL) <= 0
                 || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
             EVP_MD_CTX_free(mctx);
+            EVP_PKEY_CTX_free(pctx);
             return 0;
         }
         EVP_MD_CTX_free(mctx);
@@ -156,8 +157,10 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
         if (!tls13_hkdf_expand(s, md, prevsecret,
                                (unsigned char *)derived_secret_label,
                                sizeof(derived_secret_label) - 1, hash,
-                               preextractsec, mdlen))
+                               preextractsec, mdlen)) {
+            EVP_PKEY_CTX_free(pctx);
             return 0;
+        }
 
         prevsecret = preextractsec;
         prevsecretlen = mdlen;
@@ -321,20 +324,6 @@ static int derive_secret_key_and_iv(SSL *s, int sending, const EVP_MD *md,
         goto err;
     }
 
-#ifdef OPENSSL_SSL_TRACE_CRYPTO
-    if (s->msg_callback) {
-        int wh = sending ? TLS1_RT_CRYPTO_WRITE : 0;
-
-        if (ciph->key_len)
-            s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_KEY,
-                            key, ciph->key_len, s, s->msg_callback_arg);
-
-        wh |= TLS1_RT_CRYPTO_IV;
-        s->msg_callback(2, s->version, wh, iv, ivlen, s,
-                        s->msg_callback_arg);
-    }
-#endif
-
     return 1;
  err:
     OPENSSL_cleanse(key, sizeof(key));
@@ -348,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];
@@ -520,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,
@@ -598,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;
+}