Use a fetched cipher for the TLSv1.3 early secret
[openssl.git] / ssl / tls13_enc.c
index 181f3920a185f62f70947d94fe618621cee1bd3d..fba12fe5e4bb47fc5a06605f66c802f936d3e45e 100644 (file)
@@ -36,7 +36,8 @@ int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret,
 #else
     static const unsigned char label_prefix[] = "tls13 ";
 #endif
-    EVP_KDF *kdf = EVP_KDF_fetch(NULL, OSSL_KDF_NAME_HKDF, NULL);
+    EVP_KDF *kdf = EVP_KDF_fetch(s->ctx->libctx, OSSL_KDF_NAME_HKDF,
+                                 s->ctx->propq);
     EVP_KDF_CTX *kctx;
     OSSL_PARAM params[5], *p = params;
     int mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
@@ -194,7 +195,7 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
 #endif
     unsigned char preextractsec[EVP_MAX_MD_SIZE];
 
-    kdf = EVP_KDF_fetch(NULL, OSSL_KDF_NAME_HKDF, NULL);
+    kdf = EVP_KDF_fetch(s->ctx->libctx, OSSL_KDF_NAME_HKDF, s->ctx->propq);
     kctx = EVP_KDF_CTX_new(kdf);
     EVP_KDF_free(kdf);
     if (kctx == NULL) {
@@ -311,11 +312,27 @@ int tls13_generate_master_secret(SSL *s, unsigned char *out,
 size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
                              unsigned char *out)
 {
-    const EVP_MD *md = ssl_handshake_md(s);
+    const char *mdname = EVP_MD_name(ssl_handshake_md(s));
+    EVP_MAC *hmac = EVP_MAC_fetch(s->ctx->libctx, "HMAC", s->ctx->propq);
     unsigned char hash[EVP_MAX_MD_SIZE];
+    unsigned char finsecret[EVP_MAX_MD_SIZE];
     size_t hashlen, ret = 0;
-    EVP_PKEY *key = NULL;
-    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+    EVP_MAC_CTX *ctx = NULL;
+    OSSL_PARAM params[4], *p = params;
+
+    if (hmac == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_FINAL_FINISH_MAC,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+
+    /* Safe to cast away const here since we're not "getting" any data */
+    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_DIGEST,
+                                            (char *)mdname, 0);
+    if (s->ctx->propq != NULL)
+        *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_PROPERTIES,
+                                                (char *)s->ctx->propq,
+                                                0);
 
     if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
         /* SSLfatal() already called */
@@ -323,29 +340,31 @@ size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
     }
 
     if (str == s->method->ssl3_enc->server_finished_label) {
-        key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
-                                           s->server_finished_secret, hashlen);
+        *p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+                                                 s->server_finished_secret,
+                                                 hashlen);
     } else if (SSL_IS_FIRST_HANDSHAKE(s)) {
-        key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
-                                           s->client_finished_secret, hashlen);
+        *p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+                                                 s->client_finished_secret,
+                                                 hashlen);
     } else {
-        unsigned char finsecret[EVP_MAX_MD_SIZE];
-
         if (!tls13_derive_finishedkey(s, ssl_handshake_md(s),
                                       s->client_app_traffic_secret,
                                       finsecret, hashlen))
             goto err;
 
-        key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finsecret,
-                                           hashlen);
-        OPENSSL_cleanse(finsecret, sizeof(finsecret));
+        *p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, finsecret,
+                                                 hashlen);
     }
+    *p++ = OSSL_PARAM_construct_end();
 
-    if (key == NULL
-            || ctx == NULL
-            || EVP_DigestSignInit(ctx, NULL, md, NULL, key) <= 0
-            || EVP_DigestSignUpdate(ctx, hash, hashlen) <= 0
-            || EVP_DigestSignFinal(ctx, out, &hashlen) <= 0) {
+    ctx = EVP_MAC_CTX_new(hmac);
+    if (ctx == NULL
+            || !EVP_MAC_CTX_set_params(ctx, params)
+            || !EVP_MAC_init(ctx)
+            || !EVP_MAC_update(ctx, hash, hashlen)
+               /* outsize as per sizeof(peer_finish_md) */
+            || !EVP_MAC_final(ctx, out, &hashlen, EVP_MAX_MD_SIZE * 2)) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_FINAL_FINISH_MAC,
                  ERR_R_INTERNAL_ERROR);
         goto err;
@@ -353,8 +372,9 @@ size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
 
     ret = hashlen;
  err:
-    EVP_PKEY_free(key);
-    EVP_MD_CTX_free(ctx);
+    OPENSSL_cleanse(finsecret, sizeof(finsecret));
+    EVP_MAC_CTX_free(ctx);
+    EVP_MAC_free(hmac);
     return ret;
 }
 
@@ -368,13 +388,16 @@ int tls13_setup_key_block(SSL *s)
     const EVP_MD *hash;
 
     s->session->cipher = s->s3.tmp.new_cipher;
-    if (!ssl_cipher_get_evp(s->session, &c, &hash, NULL, NULL, NULL, 0)) {
+    if (!ssl_cipher_get_evp(s->ctx, s->session, &c, &hash, NULL, NULL, NULL,
+                            0)) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_SETUP_KEY_BLOCK,
                  SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
         return 0;
     }
 
+    ssl_evp_cipher_free(s->s3.tmp.new_sym_enc);
     s->s3.tmp.new_sym_enc = c;
+    ssl_evp_md_free(s->s3.tmp.new_hash);
     s->s3.tmp.new_hash = hash;
 
     return 1;
@@ -576,8 +599,19 @@ int tls13_change_cipher_state(SSL *s, int which)
                          SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
-            cipher = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(sslcipher));
-            md = ssl_md(sslcipher->algorithm2);
+
+            /*
+             * This ups the ref count on cipher so we better make sure we free
+             * it again
+             */
+            if (!ssl_cipher_get_evp_cipher(s->ctx, sslcipher, &cipher)) {
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS13_CHANGE_CIPHER_STATE,
+                         SSL_R_ALGORITHM_FETCH_FAILED);
+                goto err;
+            }
+
+            md = ssl_md(s->ctx, sslcipher->algorithm2);
             if (md == NULL || !EVP_DigestInit_ex(mdctx, md, NULL)
                     || !EVP_DigestUpdate(mdctx, hdata, handlen)
                     || !EVP_DigestFinal_ex(mdctx, hashval, &hashlenui)) {
@@ -732,6 +766,10 @@ int tls13_change_cipher_state(SSL *s, int which)
         s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
     ret = 1;
  err:
+    if ((which & SSL3_CC_EARLY) != 0) {
+        /* We up-refed this so now we need to down ref */
+        ssl_evp_cipher_free(cipher);
+    }
     OPENSSL_cleanse(secret, sizeof(secret));
     return ret;
 }
@@ -862,7 +900,7 @@ int tls13_export_keying_material_early(SSL *s, unsigned char *out, size_t olen,
     else
         sslcipher = SSL_SESSION_get0_cipher(s->session);
 
-    md = ssl_md(sslcipher->algorithm2);
+    md = ssl_md(s->ctx, sslcipher->algorithm2);
 
     /*
      * Calculate the hash value and store it in |data|. The reason why