Support calling EVP_DigestUpdate instead of EVP_Digest[Sign|Verify]Update
authorMatt Caswell <matt@openssl.org>
Mon, 7 Oct 2019 16:47:04 +0000 (17:47 +0100)
committerMatt Caswell <matt@openssl.org>
Fri, 11 Oct 2019 10:42:43 +0000 (11:42 +0100)
Prior to OpenSSL 3.0 EVP_Digest[Sign|Verify|Update were just macros for
EVP_DigestUpdate. They are now separate functions. Unfortunately some
code assumes that EVP_Digest[Sign|Verify]Update is interchangeable with
EVP_DigestUpdate. For example the dgst app uses an MD bio which always
calls EVP_DigestUpdate(). However the dgst app supports signing instead
of digesting and may initialise with EVP_DigestSignInit_ex() instead of
just EVP_DigestInit().

We now detect these differences and redirect to the correct function
where appropriate.

Fixes #10114

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10116)

crypto/evp/build.info
crypto/evp/digest.c
crypto/evp/m_sigver.c

index 94f033bbc189a8aa7b7ea4d88171bc0749958e40..aef0031d3dcb841890df9254d8904f4effaffa96 100644 (file)
@@ -1,6 +1,7 @@
 LIBS=../../libcrypto
 $COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c evp_utils.c \
-        mac_lib.c mac_meth.c keymgmt_meth.c keymgmt_lib.c kdf_lib.c kdf_meth.c
+        mac_lib.c mac_meth.c keymgmt_meth.c keymgmt_lib.c kdf_lib.c kdf_meth.c \
+        m_sigver.c
 SOURCE[../../libcrypto]=$COMMON\
         encode.c evp_key.c evp_cnf.c \
         e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\
@@ -13,7 +14,7 @@ SOURCE[../../libcrypto]=$COMMON\
         c_allc.c c_alld.c bio_ok.c \
         evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
         pkey_kdf.c \
-        e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
+        e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c \
         e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
         e_chacha20_poly1305.c \
         pkey_mac.c exchange.c \
index fa1dfa7303a0b65538704dd532c60c442b4c1c9b..5ff43fdd6433c0d1ed04d9dca455ac3d331d8e90 100644 (file)
@@ -285,6 +285,24 @@ int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
     if (count == 0)
         return 1;
 
+    if (ctx->pctx != NULL
+            && EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx->pctx)
+            && ctx->pctx->op.sig.sigprovctx != NULL) {
+        /*
+         * Prior to OpenSSL 3.0 EVP_DigestSignUpdate() and
+         * EVP_DigestVerifyUpdate() were just macros for EVP_DigestUpdate().
+         * Some code calls EVP_DigestUpdate() directly even when initialised
+         * with EVP_DigestSignInit_ex() or EVP_DigestVerifyInit_ex(), so we
+         * detect that and redirect to the correct EVP_Digest*Update() function
+         */
+        if (ctx->pctx->operation == EVP_PKEY_OP_SIGNCTX)
+            return EVP_DigestSignUpdate(ctx, data, count);
+        if (ctx->pctx->operation == EVP_PKEY_OP_VERIFYCTX)
+            return EVP_DigestVerifyUpdate(ctx, data, count);
+        EVPerr(EVP_F_EVP_DIGESTUPDATE, EVP_R_UPDATE_ERROR);
+        return 0;
+    }
+
     if (ctx->digest == NULL || ctx->digest->prov == NULL)
         goto legacy;
 
index 85272c9516f24e1756731eb6bc6787e664fac9e7..7912c8dd5917422d2e23ad7fb32094b4b762baac 100644 (file)
@@ -16,6 +16,8 @@
 #include "internal/provider.h"
 #include "evp_local.h"
 
+#ifndef FIPS_MODE
+
 static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen)
 {
     EVPerr(EVP_F_UPDATE, EVP_R_ONLY_ONESHOT_SUPPORTED);
@@ -220,6 +222,7 @@ int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
 {
     return do_sigver_init(ctx, pctx, type, NULL, NULL, e, pkey, NULL, 1);
 }
+#endif /* FIPS_MDOE */
 
 int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
 {
@@ -255,7 +258,7 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
     return EVP_DigestUpdate(ctx, data, dsize);
 }
 
-
+#ifndef FIPS_MODE
 int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
                         size_t *siglen)
 {
@@ -397,3 +400,4 @@ int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
         return -1;
     return EVP_DigestVerifyFinal(ctx, sigret, siglen);
 }
+#endif /* FIPS_MODE */