[openssl] master update

Matt Caswell matt at openssl.org
Thu Sep 3 08:57:12 UTC 2020


The branch master has been updated
       via  0bc193dd05fa0f5580706f34994beb74baf3d531 (commit)
       via  13c9843cff061304275a1723bcba137280e2e97d (commit)
       via  820d87bc98c254bb36c46891f3fe4e55bd47f2e7 (commit)
       via  f27138930528e0429a88c8022276e774caa9dd50 (commit)
       via  e08f86ddb1b4b911da55af6d7f71f00f43529e50 (commit)
       via  2e2084dac34170fe1f9e93975e5b3cdc30360a9c (commit)
       via  3fddbb264e87a8cef2903cbd7b02b8e1a39a2a99 (commit)
      from  b48ca22a56553f285d91da0ac9399fd5efd54589 (commit)


- Log -----------------------------------------------------------------
commit 0bc193dd05fa0f5580706f34994beb74baf3d531
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Aug 31 14:44:17 2020 +0100

    Ensure EVP_MAC_update() passes the length even if it is 0
    
    We leave it up to the EVP_MAC implemenations what to do with an update
    where the data length is 0. In the TLS HMAC implemenation this is still
    signficant.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12732)

commit 13c9843cff061304275a1723bcba137280e2e97d
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Aug 31 14:43:15 2020 +0100

    Convert ssl3_cbc_digest_record() to use EVP_MD_is_a()
    
    Previously it used EVP_MD_type(), which doesn't work when called inside
    the FIPs module.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12732)

commit 820d87bc98c254bb36c46891f3fe4e55bd47f2e7
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Aug 27 12:52:17 2020 +0100

    Update the EVP_PKEY MAC documentation
    
    Include more information about the new HMAC parameter. Also fill in some
    missing documentation about the EVP_PKEY MAC bridge.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12732)

commit f27138930528e0429a88c8022276e774caa9dd50
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Aug 20 15:54:01 2020 +0100

    Enable PKEY MAC bridge signature algs to take ctx params
    
    The underlying MAC implementations may take ctx params. Therefore we allow
    the bridge to pass these through.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12732)

commit e08f86ddb1b4b911da55af6d7f71f00f43529e50
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Aug 20 15:48:05 2020 +0100

    Make ssl3_cbc_digest_record() use the real data_size
    
    Previously we passed it the data plus mac size. Now we just pass it the
    data size. We already know the mac size.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12732)

commit 2e2084dac34170fe1f9e93975e5b3cdc30360a9c
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Jul 30 13:16:39 2020 +0100

    Start using the provider side TLS HMAC implementation
    
    This commit just moves the TLS1 and above implementation to use the TLS
    HMAC implementation in the providers.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12732)

commit 3fddbb264e87a8cef2903cbd7b02b8e1a39a2a99
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Jul 30 12:02:06 2020 +0100

    Add an HMAC implementation that is TLS aware
    
    The TLS HMAC implementation should take care to calculate the MAC in
    constant time in the case of MAC-Then-Encrypt where we have a variable
    amount of padding.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12732)

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

Summary of changes:
 crypto/evp/mac_lib.c                             |  2 -
 crypto/md5/build.info                            |  4 +-
 doc/man3/EVP_DigestVerifyInit.pod                |  2 +-
 doc/man3/EVP_MAC.pod                             | 15 ++++
 doc/man7/EVP_MAC-HMAC.pod                        |  2 +
 doc/man7/EVP_MAC-Siphash.pod                     |  4 +-
 doc/man7/EVP_PKEY-HMAC.pod                       | 10 +--
 doc/man7/EVP_SIGNATURE-HMAC.pod                  | 24 ++++---
 doc/man7/OSSL_PROVIDER-FIPS.pod                  |  6 ++
 doc/man7/OSSL_PROVIDER-default.pod               |  8 +++
 include/openssl/core_names.h                     |  9 +--
 providers/implementations/macs/blake2_mac_impl.c |  3 +
 providers/implementations/macs/gmac_prov.c       |  3 +
 providers/implementations/macs/hmac_prov.c       | 91 +++++++++++++++++++++++-
 providers/implementations/macs/poly1305_prov.c   |  3 +
 providers/implementations/macs/siphash_prov.c    |  3 +
 providers/implementations/signature/mac_legacy.c | 46 ++++++++++++
 ssl/build.info                                   |  1 +
 ssl/record/ssl3_record.c                         | 46 ++++++------
 ssl/s3_cbc.c                                     | 90 ++++++++++++++---------
 ssl/ssl_local.h                                  |  5 +-
 21 files changed, 290 insertions(+), 87 deletions(-)

diff --git a/crypto/evp/mac_lib.c b/crypto/evp/mac_lib.c
index 2198c46680..79dd49ae20 100644
--- a/crypto/evp/mac_lib.c
+++ b/crypto/evp/mac_lib.c
@@ -112,8 +112,6 @@ int EVP_MAC_init(EVP_MAC_CTX *ctx)
 
 int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen)
 {
-    if (datalen == 0)
-        return 1;
     return ctx->meth->update(ctx->data, data, datalen);
 }
 
diff --git a/crypto/md5/build.info b/crypto/md5/build.info
index d4494b274d..afcf7c4426 100644
--- a/crypto/md5/build.info
+++ b/crypto/md5/build.info
@@ -14,7 +14,9 @@ IF[{- !$disabled{asm} -}]
   ENDIF
 ENDIF
 
-SOURCE[../../libcrypto]=md5_dgst.c md5_one.c md5_sha1.c $MD5ASM
+$COMMON=md5_dgst.c md5_one.c md5_sha1.c $MD5ASM
+SOURCE[../../libcrypto]=$COMMON
+SOURCE[../../providers/libimplementations.a]=$COMMON
 
 # Implementations are now spread across several libraries, so the defines
 # need to be applied to all affected libraries and modules.
diff --git a/doc/man3/EVP_DigestVerifyInit.pod b/doc/man3/EVP_DigestVerifyInit.pod
index f0061f4548..f90fb2754f 100644
--- a/doc/man3/EVP_DigestVerifyInit.pod
+++ b/doc/man3/EVP_DigestVerifyInit.pod
@@ -93,7 +93,7 @@ Support no digests (the digest B<type> must be NULL)
 
 Supports any digest
 
-=item CMAC, Poly1305 and SipHash
+=item CMAC, Poly1305 and Siphash
 
 Will ignore any digest provided.
 
diff --git a/doc/man3/EVP_MAC.pod b/doc/man3/EVP_MAC.pod
index 9e35d57c17..dc90ee5421 100644
--- a/doc/man3/EVP_MAC.pod
+++ b/doc/man3/EVP_MAC.pod
@@ -248,6 +248,21 @@ EVP_MAC_final() should produce.
 The allowed sizes vary between MAC implementations, but must never exceed
 what can be given with a B<size_t>.
 
+=item "tls-data-size" (B<OSSL_MAC_PARAM_TLS_DATA_SIZE>) <unsigned integer>
+
+This parameter is only supported by HMAC. If set then special handling is
+activated for calculating the MAC of a received mac-then-encrypt TLS record
+where variable length record padding has been used (as in the case of CBC mode
+ciphersuites). The value represents the total length of the record that is
+having the MAC calculated including the received MAC and the record padding.
+
+When used EVP_MAC_update must be called precisely twice. The first time with
+the 13 bytes of TLS "header" data, and the second time with the entire record
+including the MAC itself and any padding. The entire record length must equal
+the value passed in the "tls-data-size" parameter. The length passed in the
+B<datalen> parameter to EVP_MAC_update() should be equal to the length of the
+record after the MAC and any padding has been removed.
+
 =back
 
 All these parameters should be used before the calls to any of
diff --git a/doc/man7/EVP_MAC-HMAC.pod b/doc/man7/EVP_MAC-HMAC.pod
index 7f0ec35b43..45ccd17211 100644
--- a/doc/man7/EVP_MAC-HMAC.pod
+++ b/doc/man7/EVP_MAC-HMAC.pod
@@ -36,6 +36,8 @@ The following parameter can be set with EVP_MAC_CTX_set_params():
 
 =item "properties" (B<OSSL_MAC_PARAM_PROPERTIES>) <UTF8 string>
 
+=item "tls-data-size" (B<OSSL_MAC_PARAM_TLS_DATA_SIZE>) <unsigned integer>
+
 =back
 
 The "flags" parameter is passed directly to HMAC_CTX_set_flags().
diff --git a/doc/man7/EVP_MAC-Siphash.pod b/doc/man7/EVP_MAC-Siphash.pod
index d8013b3369..8b610c4383 100644
--- a/doc/man7/EVP_MAC-Siphash.pod
+++ b/doc/man7/EVP_MAC-Siphash.pod
@@ -2,11 +2,11 @@
 
 =head1 NAME
 
-EVP_MAC-Siphash - The SipHash EVP_MAC implementation
+EVP_MAC-Siphash - The Siphash EVP_MAC implementation
 
 =head1 DESCRIPTION
 
-Support for computing SipHash MACs through the B<EVP_MAC> API.
+Support for computing Siphash MACs through the B<EVP_MAC> API.
 
 =head2 Identity
 
diff --git a/doc/man7/EVP_PKEY-HMAC.pod b/doc/man7/EVP_PKEY-HMAC.pod
index 7b6c52bb03..84b647e530 100644
--- a/doc/man7/EVP_PKEY-HMAC.pod
+++ b/doc/man7/EVP_PKEY-HMAC.pod
@@ -2,22 +2,22 @@
 
 =head1 NAME
 
-EVP_PKEY-HMAC, EVP_KEYMGMT-HMAC, EVP_PKEY-SIPHASH, EVP_KEYMGMT-SIPHASH,
-EVP_PKEY-POLY1305, EVP_KEYMGMT-POLY1305, EVP_PKEY-CMAC, EVP_KEYMGMT-CMAC
+EVP_PKEY-HMAC, EVP_KEYMGMT-HMAC, EVP_PKEY-Siphash, EVP_KEYMGMT-Siphash,
+EVP_PKEY-Poly1305, EVP_KEYMGMT-Poly1305, EVP_PKEY-CMAC, EVP_KEYMGMT-CMAC
 - EVP_PKEY legacy MAC keytypes and algorithm support
 
 =head1 DESCRIPTION
 
 The B<HMAC> and B<CMAC> key types are implemented in OpenSSL's default and FIPS
-providers. Additionally the B<SIPHASH> and B<POLY1305> key types are implemented
+providers. Additionally the B<Siphash> and B<Poly1305> key types are implemented
 in the default provider. Performing MAC operations via an EVP_PKEY
 is considered legacy and are only available for backwards compatibility purposes
 and for a restricted set of algorithms. The preferred way of performing MAC
 operations is via the EVP_MAC APIs. See L<EVP_MAC_init(3)>.
 
 For further details on using EVP_PKEY based MAC keys see
-L<EVP_SIGNATURE-HMAC(7)>, L<EVP_SIGNATURE-SIPHASH(7)>,
-L<EVP_SIGNATURE-POLY1305(7)> or L<EVP_SIGNATURE-CMAC(7)>.
+L<EVP_SIGNATURE-HMAC(7)>, L<EVP_SIGNATURE-Siphash(7)>,
+L<EVP_SIGNATURE-Poly1305(7)> or L<EVP_SIGNATURE-CMAC(7)>.
 
 =head2 Common MAC parameters
 
diff --git a/doc/man7/EVP_SIGNATURE-HMAC.pod b/doc/man7/EVP_SIGNATURE-HMAC.pod
index dd74fae88c..6628d9ebc2 100644
--- a/doc/man7/EVP_SIGNATURE-HMAC.pod
+++ b/doc/man7/EVP_SIGNATURE-HMAC.pod
@@ -2,7 +2,7 @@
 
 =head1 NAME
 
-EVP_SIGNATURE-HMAC, EVP_SIGNATURE-SIPHASH, EVP_SIGNATURE-POLY1305,
+EVP_SIGNATURE-HMAC, EVP_SIGNATURE-Siphash, EVP_SIGNATURE-Poly1305,
 EVP_SIGNATURE-CMAC
 - The legacy B<EVP_PKEY> MAC signature implementations
 
@@ -12,21 +12,29 @@ The algorithms described here have legacy support for creating MACs using
 L<EVP_DigestSignInit(3)> and related functions. This is not the preferred way of
 creating MACs. Instead you should use the newer L<EVP_MAC_init(3)> functions.
 This mechanism is provided for backwards compatibility with older versions of
-OpenSSL. 
+OpenSSL.
 
-There are no parameters supported by the legacy EVP_PKEY MAC signature
-algorithms. See L<EVP_PKEY-HMAC(7)>, L<EVP_PKEY-SIPHASH(7)>,
-L<EVP_PKEY-POLY1305(7)> or L<EVP_PKEY-CMAC(7)> for details about parameters that
-are supported during the creation of an EVP_PKEY.
+The same signature parameters can be set using EVP_PKEY_CTX_set_params() as can
+be set via EVP_MAC_CTX_set_params() for the underlying EVP_MAC. See
+L<EVP_MAC-HMAC(7)>, L<EVP_MAC-Siphash(7)>, L<EVP_MAC-Poly1305(7)> and
+L<EVP_MAC-CMAC(7)> for details.
+
+ See L<EVP_PKEY-HMAC(7)>, L<EVP_PKEY-Siphash(7)>, L<EVP_PKEY-Poly1305(7)> or
+ L<EVP_PKEY-CMAC(7)> for details about parameters that are supported during the
+ creation of an EVP_PKEY.
 
 =head1 SEE ALSO
 
 L<EVP_MAC_init(3)>,
 L<EVP_DigestSignInit(3)>,
 L<EVP_PKEY-HMAC(7)>,
-L<EVP_PKEY-SIPHASH(7)>,
-L<EVP_PKEY-POLY1305(7)>,
+L<EVP_PKEY-Siphash(7)>,
+L<EVP_PKEY-Poly1305(7)>,
 L<EVP_PKEY-CMAC(7)>,
+L<EVP_MAC-HMAC(7)>,
+L<EVP_MAC-Siphash(7)>,
+L<EVP_MAC-Poly1305(7)>,
+L<EVP_MAC-CMAC(7)>,
 L<provider-signature(7)>,
 
 =head1 COPYRIGHT
diff --git a/doc/man7/OSSL_PROVIDER-FIPS.pod b/doc/man7/OSSL_PROVIDER-FIPS.pod
index fc9c191855..d404716b23 100644
--- a/doc/man7/OSSL_PROVIDER-FIPS.pod
+++ b/doc/man7/OSSL_PROVIDER-FIPS.pod
@@ -120,6 +120,12 @@ This has the property "provider=fips,fips=no"
 
 =item DSA, see L<EVP_KEYEXCH-DSA(7)>
 
+=item RSA, see L<EVP_SIGNATURE-RSA(7)>
+
+=item HMAC, see L<EVP_SIGNATURE-HMAC(7)>
+
+=item CMAC, see L<EVP_SIGNATURE-CMAC(7)>
+
 =back
 
 =head2 Asymmetric Cipher
diff --git a/doc/man7/OSSL_PROVIDER-default.pod b/doc/man7/OSSL_PROVIDER-default.pod
index 0b477b56c1..a88c0be6e6 100644
--- a/doc/man7/OSSL_PROVIDER-default.pod
+++ b/doc/man7/OSSL_PROVIDER-default.pod
@@ -164,6 +164,14 @@ The OpenSSL default provider supports these operations and algorithms:
 
 =item RSA, see L<EVP_SIGNATURE-RSA(7)>
 
+=item HMAC, see L<EVP_SIGNATURE-HMAC(7)>
+
+=item SIPHASH, see L<EVP_SIGNATURE-Siphash(7)>
+
+=item POLY1305, see L<EVP_SIGNATURE-Poly1305(7)>
+
+=item CMAC, see L<EVP_SIGNATURE-CMAC(7)>
+
 =back
 
 =head2 Asymmetric Cipher
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
index 3be69d5774..fc8d2cea02 100644
--- a/include/openssl/core_names.h
+++ b/include/openssl/core_names.h
@@ -153,10 +153,11 @@ extern "C" {
  * If "engine" or "properties" are specified, they should always be paired
  * with "cipher" or "digest".
  */
-#define OSSL_MAC_PARAM_CIPHER       OSSL_ALG_PARAM_CIPHER     /* utf8 string */
-#define OSSL_MAC_PARAM_DIGEST       OSSL_ALG_PARAM_DIGEST     /* utf8 string */
-#define OSSL_MAC_PARAM_PROPERTIES   OSSL_ALG_PARAM_PROPERTIES /* utf8 string */
-#define OSSL_MAC_PARAM_SIZE         "size"       /* size_t */
+#define OSSL_MAC_PARAM_CIPHER           OSSL_ALG_PARAM_CIPHER     /* utf8 string */
+#define OSSL_MAC_PARAM_DIGEST           OSSL_ALG_PARAM_DIGEST     /* utf8 string */
+#define OSSL_MAC_PARAM_PROPERTIES       OSSL_ALG_PARAM_PROPERTIES /* utf8 string */
+#define OSSL_MAC_PARAM_SIZE             "size"                    /* size_t */
+#define OSSL_MAC_PARAM_TLS_DATA_SIZE    "tls-data-size"           /* size_t */
 
 /* Known MAC names */
 #define OSSL_MAC_NAME_BLAKE2BMAC    "BLAKE2BMAC"
diff --git a/providers/implementations/macs/blake2_mac_impl.c b/providers/implementations/macs/blake2_mac_impl.c
index b567369f58..c2f292f9bb 100644
--- a/providers/implementations/macs/blake2_mac_impl.c
+++ b/providers/implementations/macs/blake2_mac_impl.c
@@ -92,6 +92,9 @@ static int blake2_mac_update(void *vmacctx,
 {
     struct blake2_mac_data_st *macctx = vmacctx;
 
+    if (datalen == 0)
+        return 1;
+
     return BLAKE2_UPDATE(&macctx->ctx, data, datalen);
 }
 
diff --git a/providers/implementations/macs/gmac_prov.c b/providers/implementations/macs/gmac_prov.c
index f0c152d48f..c44dea3ec1 100644
--- a/providers/implementations/macs/gmac_prov.c
+++ b/providers/implementations/macs/gmac_prov.c
@@ -99,6 +99,9 @@ static int gmac_update(void *vmacctx, const unsigned char *data,
     EVP_CIPHER_CTX *ctx = macctx->ctx;
     int outlen;
 
+    if (datalen == 0)
+        return 1;
+
     while (datalen > INT_MAX) {
         if (!EVP_EncryptUpdate(ctx, NULL, &outlen, data, INT_MAX))
             return 0;
diff --git a/providers/implementations/macs/hmac_prov.c b/providers/implementations/macs/hmac_prov.c
index b30de6c4a3..f6cb544f64 100644
--- a/providers/implementations/macs/hmac_prov.c
+++ b/providers/implementations/macs/hmac_prov.c
@@ -13,6 +13,8 @@
  */
 #include "internal/deprecated.h"
 
+#include <string.h>
+
 #include <openssl/core_dispatch.h>
 #include <openssl/core_names.h>
 #include <openssl/params.h>
@@ -47,8 +49,27 @@ struct hmac_data_st {
     void *provctx;
     HMAC_CTX *ctx;               /* HMAC context */
     PROV_DIGEST digest;
+    unsigned char *key;
+    size_t keylen;
+    /* Length of full TLS record including the MAC and any padding */
+    size_t tls_data_size;
+    unsigned char tls_header[13];
+    int tls_header_set;
+    unsigned char tls_mac_out[EVP_MAX_MD_SIZE];
+    size_t tls_mac_out_size;
 };
 
+/* Defined in ssl/s3_cbc.c */
+int ssl3_cbc_digest_record(const EVP_MD *md,
+                           unsigned char *md_out,
+                           size_t *md_out_size,
+                           const unsigned char header[13],
+                           const unsigned char *data,
+                           size_t data_size,
+                           size_t data_plus_mac_plus_padding_size,
+                           const unsigned char *mac_secret,
+                           size_t mac_secret_length, char is_sslv3);
+
 static size_t hmac_size(void *vmacctx);
 
 static void *hmac_new(void *provctx)
@@ -73,6 +94,7 @@ static void hmac_free(void *vmacctx)
     if (macctx != NULL) {
         HMAC_CTX_free(macctx->ctx);
         ossl_prov_digest_reset(&macctx->digest);
+        OPENSSL_secure_clear_free(macctx->key, macctx->keylen);
         OPENSSL_free(macctx);
     }
 }
@@ -81,15 +103,30 @@ static void *hmac_dup(void *vsrc)
 {
     struct hmac_data_st *src = vsrc;
     struct hmac_data_st *dst = hmac_new(src->provctx);
+    HMAC_CTX *ctx;
 
     if (dst == NULL)
         return NULL;
 
+    ctx = dst->ctx;
+    *dst = *src;
+    dst->ctx = ctx;
+    dst->key = NULL;
+
     if (!HMAC_CTX_copy(dst->ctx, src->ctx)
         || !ossl_prov_digest_copy(&dst->digest, &src->digest)) {
         hmac_free(dst);
         return NULL;
     }
+    if (src->key != NULL) {
+        /* There is no "secure" OPENSSL_memdup */
+        dst->key = OPENSSL_secure_malloc(src->keylen);
+        if (dst->key == NULL) {
+            hmac_free(dst);
+            return 0;
+        }
+        memcpy(dst->key, src->key, src->keylen);
+    }
     return dst;
 }
 
@@ -107,10 +144,10 @@ static int hmac_init(void *vmacctx)
     int rv = 1;
 
     /* HMAC_Init_ex doesn't tolerate all zero params, so we must be careful */
-    if (digest != NULL)
+    if (macctx->tls_data_size == 0 && digest != NULL)
         rv = HMAC_Init_ex(macctx->ctx, NULL, 0, digest,
                           ossl_prov_digest_engine(&macctx->digest));
-    ossl_prov_digest_reset(&macctx->digest);
+
     return rv;
 }
 
@@ -119,6 +156,32 @@ static int hmac_update(void *vmacctx, const unsigned char *data,
 {
     struct hmac_data_st *macctx = vmacctx;
 
+    if (macctx->tls_data_size > 0) {
+        /* We're doing a TLS HMAC */
+        if (!macctx->tls_header_set) {
+            /* We expect the first update call to contain the TLS header */
+            if (datalen != sizeof(macctx->tls_header))
+                return 0;
+            memcpy(macctx->tls_header, data, datalen);
+            macctx->tls_header_set = 1;
+            return 1;
+        }
+        /* macctx->tls_data_size is datalen plus the padding length */
+        if (macctx->tls_data_size < datalen)
+            return 0;
+
+        return ssl3_cbc_digest_record(ossl_prov_digest_md(&macctx->digest),
+                                      macctx->tls_mac_out,
+                                      &macctx->tls_mac_out_size,
+                                      macctx->tls_header,
+                                      data,
+                                      datalen,
+                                      macctx->tls_data_size,
+                                      macctx->key,
+                                      macctx->keylen,
+                                      0);
+    }
+
     return HMAC_Update(macctx->ctx, data, datalen);
 }
 
@@ -128,6 +191,14 @@ static int hmac_final(void *vmacctx, unsigned char *out, size_t *outl,
     unsigned int hlen;
     struct hmac_data_st *macctx = vmacctx;
 
+    if (macctx->tls_data_size > 0) {
+        if (macctx->tls_mac_out_size == 0)
+            return 0;
+        if (outl != NULL)
+            *outl = macctx->tls_mac_out_size;
+        memcpy(out, macctx->tls_mac_out, macctx->tls_mac_out_size);
+        return 1;
+    }
     if (!HMAC_Final(macctx->ctx, out, &hlen))
         return 0;
     *outl = hlen;
@@ -158,6 +229,7 @@ static const OSSL_PARAM known_settable_ctx_params[] = {
     OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0),
     OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
     OSSL_PARAM_int(OSSL_MAC_PARAM_FLAGS, NULL),
+    OSSL_PARAM_size_t(OSSL_MAC_PARAM_TLS_DATA_SIZE, NULL),
     OSSL_PARAM_END
 };
 static const OSSL_PARAM *hmac_settable_ctx_params(ossl_unused void *provctx)
@@ -190,12 +262,25 @@ static int hmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
         if (p->data_type != OSSL_PARAM_OCTET_STRING)
             return 0;
 
+        if (macctx->keylen > 0)
+            OPENSSL_secure_clear_free(macctx->key, macctx->keylen);
+        /* Keep a copy of the key if we need it for TLS HMAC */
+        macctx->key = OPENSSL_secure_malloc(p->data_size);
+        if (macctx->key == NULL)
+            return 0;
+        memcpy(macctx->key, p->data, p->data_size);
+        macctx->keylen = p->data_size;
+
         if (!HMAC_Init_ex(macctx->ctx, p->data, p->data_size,
                           ossl_prov_digest_md(&macctx->digest),
                           NULL /* ENGINE */))
             return 0;
 
-        ossl_prov_digest_reset(&macctx->digest);
+    }
+    if ((p = OSSL_PARAM_locate_const(params,
+                                     OSSL_MAC_PARAM_TLS_DATA_SIZE)) != NULL) {
+        if (!OSSL_PARAM_get_size_t(p, &macctx->tls_data_size))
+            return 0;
     }
     return 1;
 }
diff --git a/providers/implementations/macs/poly1305_prov.c b/providers/implementations/macs/poly1305_prov.c
index 08eb81ee0d..36546eb95d 100644
--- a/providers/implementations/macs/poly1305_prov.c
+++ b/providers/implementations/macs/poly1305_prov.c
@@ -83,6 +83,9 @@ static int poly1305_update(void *vmacctx, const unsigned char *data,
 {
     struct poly1305_data_st *ctx = vmacctx;
 
+    if (datalen == 0)
+        return 1;
+
     /* poly1305 has nothing to return in its update function */
     Poly1305_Update(&ctx->poly1305, data, datalen);
     return 1;
diff --git a/providers/implementations/macs/siphash_prov.c b/providers/implementations/macs/siphash_prov.c
index 8797241e33..1bea7a2787 100644
--- a/providers/implementations/macs/siphash_prov.c
+++ b/providers/implementations/macs/siphash_prov.c
@@ -91,6 +91,9 @@ static int siphash_update(void *vmacctx, const unsigned char *data,
 {
     struct siphash_data_st *ctx = vmacctx;
 
+    if (datalen == 0)
+        return 1;
+
     SipHash_Update(&ctx->siphash, data, datalen);
     return 1;
 }
diff --git a/providers/implementations/signature/mac_legacy.c b/providers/implementations/signature/mac_legacy.c
index 2b8edcad9d..3c6366756d 100644
--- a/providers/implementations/signature/mac_legacy.c
+++ b/providers/implementations/signature/mac_legacy.c
@@ -21,11 +21,19 @@
 #include "prov/macsignature.h"
 
 static OSSL_FUNC_signature_newctx_fn mac_hmac_newctx;
+static OSSL_FUNC_signature_newctx_fn mac_siphash_newctx;
+static OSSL_FUNC_signature_newctx_fn mac_poly1305_newctx;
+static OSSL_FUNC_signature_newctx_fn mac_cmac_newctx;
 static OSSL_FUNC_signature_digest_sign_init_fn mac_digest_sign_init;
 static OSSL_FUNC_signature_digest_sign_update_fn mac_digest_sign_update;
 static OSSL_FUNC_signature_digest_sign_final_fn mac_digest_sign_final;
 static OSSL_FUNC_signature_freectx_fn mac_freectx;
 static OSSL_FUNC_signature_dupctx_fn mac_dupctx;
+static OSSL_FUNC_signature_set_ctx_params_fn mac_set_ctx_params;
+static OSSL_FUNC_signature_settable_ctx_params_fn mac_hmac_settable_ctx_params;
+static OSSL_FUNC_signature_settable_ctx_params_fn mac_siphash_settable_ctx_params;
+static OSSL_FUNC_signature_settable_ctx_params_fn mac_poly1305_settable_ctx_params;
+static OSSL_FUNC_signature_settable_ctx_params_fn mac_cmac_settable_ctx_params;
 
 typedef struct {
     OPENSSL_CTX *libctx;
@@ -171,6 +179,40 @@ static void *mac_dupctx(void *vpmacctx)
     return NULL;
 }
 
+static int mac_set_ctx_params(void *vpmacctx, const OSSL_PARAM params[])
+{
+    PROV_MAC_CTX *ctx = (PROV_MAC_CTX *)vpmacctx;
+
+    return EVP_MAC_CTX_set_params(ctx->macctx, params);
+}
+
+static const OSSL_PARAM *mac_settable_ctx_params(void *provctx,
+                                                 const char *macname)
+{
+    EVP_MAC *mac = EVP_MAC_fetch(PROV_LIBRARY_CONTEXT_OF(provctx), macname,
+                                 NULL);
+    const OSSL_PARAM *params;
+
+    if (mac == NULL)
+        return NULL;
+
+    params = EVP_MAC_settable_ctx_params(mac);
+    EVP_MAC_free(mac);
+
+    return params;
+}
+
+#define MAC_SETTABLE_CTX_PARAMS(funcname, macname) \
+    static const OSSL_PARAM *mac_##funcname##_settable_ctx_params(void *provctx) \
+    { \
+        return mac_settable_ctx_params(provctx, macname); \
+    }
+
+MAC_SETTABLE_CTX_PARAMS(hmac, "HMAC")
+MAC_SETTABLE_CTX_PARAMS(siphash, "SIPHASH")
+MAC_SETTABLE_CTX_PARAMS(poly1305, "POLY1305")
+MAC_SETTABLE_CTX_PARAMS(cmac, "CMAC")
+
 #define MAC_SIGNATURE_FUNCTIONS(funcname) \
     const OSSL_DISPATCH mac_legacy_##funcname##_signature_functions[] = { \
         { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))mac_##funcname##_newctx }, \
@@ -182,6 +224,10 @@ static void *mac_dupctx(void *vpmacctx)
         (void (*)(void))mac_digest_sign_final }, \
         { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))mac_freectx }, \
         { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))mac_dupctx }, \
+        { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, \
+          (void (*)(void))mac_set_ctx_params }, \
+        { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, \
+          (void (*)(void))mac_##funcname##_settable_ctx_params }, \
         { 0, NULL } \
     };
 
diff --git a/ssl/build.info b/ssl/build.info
index cfcb2b1737..e5b7befbaa 100644
--- a/ssl/build.info
+++ b/ssl/build.info
@@ -37,3 +37,4 @@ SOURCE[../libssl]=\
 DEFINE[../libssl]=$AESDEF
 
 SOURCE[../providers/libcommon.a]=record/tls_pad.c
+SOURCE[../providers/libimplementations.a]=s3_cbc.c
diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c
index 634052d342..baa4f239bf 100644
--- a/ssl/record/ssl3_record.c
+++ b/ssl/record/ssl3_record.c
@@ -1362,10 +1362,10 @@ int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
         header[j++] = (unsigned char)(rec->length & 0xff);
 
         /* Final param == is SSLv3 */
-        if (ssl3_cbc_digest_record(ssl, hash,
+        if (ssl3_cbc_digest_record(EVP_MD_CTX_md(hash),
                                    md, &md_size,
                                    header, rec->input,
-                                   rec->length + md_size, rec->orig_len,
+                                   rec->length, rec->orig_len,
                                    mac_sec, md_size, 1) <= 0)
             return 0;
     } else {
@@ -1465,31 +1465,25 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
     header[12] = (unsigned char)(rec->length & 0xff);
 
     if (!sending && !SSL_READ_ETM(ssl) &&
-        EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
-        ssl3_cbc_record_digest_supported(mac_ctx)) {
-        /*
-         * This is a CBC-encrypted record. We must avoid leaking any
-         * timing-side channel information about how many blocks of data we
-         * are hashing because that gives an attacker a timing-oracle.
-         */
-        /* Final param == not SSLv3 */
-        if (ssl3_cbc_digest_record(ssl, mac_ctx,
-                                   md, &md_size,
-                                   header, rec->input,
-                                   rec->length + md_size, rec->orig_len,
-                                   ssl->s3.read_mac_secret,
-                                   ssl->s3.read_mac_secret_size, 0) <= 0) {
-            EVP_MD_CTX_free(hmac);
-            return 0;
-        }
-    } else {
-        /* TODO(size_t): Convert these calls */
-        if (EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)) <= 0
-            || EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length) <= 0
-            || EVP_DigestSignFinal(mac_ctx, md, &md_size) <= 0) {
-            EVP_MD_CTX_free(hmac);
+            EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
+            ssl3_cbc_record_digest_supported(mac_ctx)) {
+        OSSL_PARAM tls_hmac_params[2], *p = tls_hmac_params;
+
+        *p++ = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_TLS_DATA_SIZE,
+                                           &rec->orig_len);
+        *p++ = OSSL_PARAM_construct_end();
+
+        if (!EVP_PKEY_CTX_set_params(EVP_MD_CTX_pkey_ctx(mac_ctx),
+                                     tls_hmac_params))
             return 0;
-        }
+    }
+
+    /* TODO(size_t): Convert these calls */
+    if (EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)) <= 0
+        || EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length) <= 0
+        || EVP_DigestSignFinal(mac_ctx, md, &md_size) <= 0) {
+        EVP_MD_CTX_free(hmac);
+        return 0;
     }
 
     EVP_MD_CTX_free(hmac);
diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c
index ec1f3cf83b..4895f43568 100644
--- a/ssl/s3_cbc.c
+++ b/ssl/s3_cbc.c
@@ -7,6 +7,16 @@
  * https://www.openssl.org/source/license.html
  */
 
+/*
+ * This file has no dependencies on the rest of libssl because it is shared
+ * with the providers. It contains functions for low level MAC calculations.
+ * Responsibility for this lies with the HMAC implementation in the
+ * providers. However there are legacy code paths in libssl which also need to
+ * do this. In time those legacy code paths can be removed and this file can be
+ * moved out of libssl.
+ */
+
+
 /*
  * MD5 and SHA-1 low level APIs are deprecated for public use, but still ok for
  * internal use.
@@ -14,12 +24,44 @@
 #include "internal/deprecated.h"
 
 #include "internal/constant_time.h"
-#include "ssl_local.h"
 #include "internal/cryptlib.h"
 
+#include <openssl/evp.h>
 #include <openssl/md5.h>
 #include <openssl/sha.h>
 
+char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx);
+int ssl3_cbc_digest_record(const EVP_MD *md,
+                           unsigned char *md_out,
+                           size_t *md_out_size,
+                           const unsigned char header[13],
+                           const unsigned char *data,
+                           size_t data_size,
+                           size_t data_plus_mac_plus_padding_size,
+                           const unsigned char *mac_secret,
+                           size_t mac_secret_length, char is_sslv3);
+
+# define l2n(l,c)        (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+                         *((c)++)=(unsigned char)(((l)    )&0xff))
+
+# define l2n6(l,c)       (*((c)++)=(unsigned char)(((l)>>40)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>32)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>24)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+                         *((c)++)=(unsigned char)(((l)    )&0xff))
+
+# define l2n8(l,c)       (*((c)++)=(unsigned char)(((l)>>56)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>48)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>40)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>32)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>24)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+                         *((c)++)=(unsigned char)(((l)    )&0xff))
+
 /*
  * MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's
  * length field. (SHA-384/512 have 128-bit length.)
@@ -119,25 +161,21 @@ char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
  *   md_out_size: if non-NULL, the number of output bytes is written here.
  *   header: the 13-byte, TLS record header.
  *   data: the record data itself, less any preceding explicit IV.
- *   data_plus_mac_size: the secret, reported length of the data and MAC
- *     once the padding has been removed.
+ *   data_size: the secret, reported length of the data once the MAC and padding
+ *              has been removed.
  *   data_plus_mac_plus_padding_size: the public length of the whole
- *     record, including padding.
+ *     record, including MAC and padding.
  *   is_sslv3: non-zero if we are to use SSLv3. Otherwise, TLS.
  *
- * On entry: by virtue of having been through one of the remove_padding
- * functions, above, we know that data_plus_mac_size is large enough to contain
- * a padding byte and MAC. (If the padding was invalid, it might contain the
- * padding too. )
+ * On entry: we know that data is data_plus_mac_plus_padding_size in length
  * Returns 1 on success or 0 on error
  */
-int ssl3_cbc_digest_record(SSL *s,
-                           const EVP_MD_CTX *ctx,
+int ssl3_cbc_digest_record(const EVP_MD *md,
                            unsigned char *md_out,
                            size_t *md_out_size,
                            const unsigned char header[13],
                            const unsigned char *data,
-                           size_t data_plus_mac_size,
+                           size_t data_size,
                            size_t data_plus_mac_plus_padding_size,
                            const unsigned char *mac_secret,
                            size_t mac_secret_length, char is_sslv3)
@@ -168,7 +206,6 @@ int ssl3_cbc_digest_record(SSL *s,
     size_t md_length_size = 8;
     char length_is_big_endian = 1;
     int ret = 0;
-    const EVP_MD *md = NULL;
 
     /*
      * This is a, hopefully redundant, check that allows us to forget about
@@ -177,8 +214,7 @@ int ssl3_cbc_digest_record(SSL *s,
     if (!ossl_assert(data_plus_mac_plus_padding_size < 1024 * 1024))
         return 0;
 
-    switch (EVP_MD_CTX_type(ctx)) {
-    case NID_md5:
+    if (EVP_MD_is_a(md, "MD5")) {
         if (MD5_Init((MD5_CTX *)md_state.c) <= 0)
             return 0;
         md_final_raw = tls1_md5_final_raw;
@@ -187,32 +223,28 @@ int ssl3_cbc_digest_record(SSL *s,
         md_size = 16;
         sslv3_pad_length = 48;
         length_is_big_endian = 0;
-        break;
-    case NID_sha1:
+    } else if (EVP_MD_is_a(md, "SHA1")) {
         if (SHA1_Init((SHA_CTX *)md_state.c) <= 0)
             return 0;
         md_final_raw = tls1_sha1_final_raw;
         md_transform =
             (void (*)(void *ctx, const unsigned char *block))SHA1_Transform;
         md_size = 20;
-        break;
-    case NID_sha224:
+    } else if (EVP_MD_is_a(md, "SHA2-224")) {
         if (SHA224_Init((SHA256_CTX *)md_state.c) <= 0)
             return 0;
         md_final_raw = tls1_sha256_final_raw;
         md_transform =
             (void (*)(void *ctx, const unsigned char *block))SHA256_Transform;
         md_size = 224 / 8;
-        break;
-    case NID_sha256:
+     } else if (EVP_MD_is_a(md, "SHA2-256")) {
         if (SHA256_Init((SHA256_CTX *)md_state.c) <= 0)
             return 0;
         md_final_raw = tls1_sha256_final_raw;
         md_transform =
             (void (*)(void *ctx, const unsigned char *block))SHA256_Transform;
         md_size = 32;
-        break;
-    case NID_sha384:
+     } else if (EVP_MD_is_a(md, "SHA2-384")) {
         if (SHA384_Init((SHA512_CTX *)md_state.c) <= 0)
             return 0;
         md_final_raw = tls1_sha512_final_raw;
@@ -221,8 +253,7 @@ int ssl3_cbc_digest_record(SSL *s,
         md_size = 384 / 8;
         md_block_size = 128;
         md_length_size = 16;
-        break;
-    case NID_sha512:
+    } else if (EVP_MD_is_a(md, "SHA2-512")) {
         if (SHA512_Init((SHA512_CTX *)md_state.c) <= 0)
             return 0;
         md_final_raw = tls1_sha512_final_raw;
@@ -231,8 +262,7 @@ int ssl3_cbc_digest_record(SSL *s,
         md_size = 64;
         md_block_size = 128;
         md_length_size = 16;
-        break;
-    default:
+    } else {
         /*
          * ssl3_cbc_record_digest_supported should have been called first to
          * check that the hash function is supported.
@@ -303,7 +333,7 @@ int ssl3_cbc_digest_record(SSL *s,
     /*
      * mac_end_offset is the index just past the end of the data to be MACed.
      */
-    mac_end_offset = data_plus_mac_size + header_length - md_size;
+    mac_end_offset = data_size + header_length;
     /*
      * c is the index of the 0x80 byte in the final hash block that contains
      * application data.
@@ -463,10 +493,7 @@ int ssl3_cbc_digest_record(SSL *s,
     md_ctx = EVP_MD_CTX_new();
     if (md_ctx == NULL)
         goto err;
-    md = ssl_evp_md_fetch(s->ctx->libctx, EVP_MD_type(EVP_MD_CTX_md(ctx)),
-                          s->ctx->propq);
-    if (md == NULL)
-        goto err;
+
     if (EVP_DigestInit_ex(md_ctx, md, NULL /* engine */ ) <= 0)
         goto err;
     if (is_sslv3) {
@@ -494,6 +521,5 @@ int ssl3_cbc_digest_record(SSL *s,
     ret = 1;
  err:
     EVP_MD_CTX_free(md_ctx);
-    ssl_evp_md_free(md);
     return ret;
 }
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
index f74f833312..49d24e6a96 100644
--- a/ssl/ssl_local.h
+++ b/ssl/ssl_local.h
@@ -2761,13 +2761,12 @@ int ktls_configure_crypto(const SSL *s, const EVP_CIPHER *c, EVP_CIPHER_CTX *dd,
 
 /* s3_cbc.c */
 __owur char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx);
-__owur int ssl3_cbc_digest_record(SSL *s,
-                                  const EVP_MD_CTX *ctx,
+__owur int ssl3_cbc_digest_record(const EVP_MD *md,
                                   unsigned char *md_out,
                                   size_t *md_out_size,
                                   const unsigned char header[13],
                                   const unsigned char *data,
-                                  size_t data_plus_mac_size,
+                                  size_t data_size,
                                   size_t data_plus_mac_plus_padding_size,
                                   const unsigned char *mac_secret,
                                   size_t mac_secret_length, char is_sslv3);


More information about the openssl-commits mailing list