[openssl] master update

Richard Levitte levitte at openssl.org
Tue Feb 4 18:34:32 UTC 2020


The branch master has been updated
       via  e3b1ccad694aabfffbde68c56fb8d44c011f98b1 (commit)
       via  8bee651213c4755761ed5dd32d416d782cc5fc3c (commit)
       via  31a796d1cc884c727a226d3dfba6a1ad7a50b865 (commit)
       via  00bc1ad99a69f851ccdea3656445ae2daaf70717 (commit)
       via  972fa31895b38cbe91a87a04875f7dadee387dea (commit)
      from  6d53ad6b5cf726d92860e973d7bc8c1930762086 (commit)


- Log -----------------------------------------------------------------
commit e3b1ccad694aabfffbde68c56fb8d44c011f98b1
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Feb 2 13:09:29 2020 +0100

    EVP_MD_CTX_ctrl(): Remove unnecessary control
    
    A check was present as to what operation is performed with this
    context.  It may have been useful at some point, but isn't any more.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/10947)

commit 8bee651213c4755761ed5dd32d416d782cc5fc3c
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Feb 2 13:09:23 2020 +0100

    PROV: Fix the DSA SIGNATURE implementation for better digests handling
    
    Refactor the DSA SIGNATURE digest setup to be uniform, and to happen
    in two places:
    
    1. when given through the digestsign and digestverify inits
    2. when given through the set_ctx_params function.
    
    When setting up the digest, we also check that the digest is one of
    the officially accepted for DSA.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/10947)

commit 31a796d1cc884c727a226d3dfba6a1ad7a50b865
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Feb 2 13:09:09 2020 +0100

    PROV: Implement padding mode words in the RSA ASYM_CIPHER implementation
    
    Because the libcrypto code has relinquished control of exact words to
    express padding mode choices, we re-implement them in the appropriate
    provider implementation.
    
    For the sake of legacy controls, we maintain support for the numeric
    form of the padding mode, but leave that support otherwise undeclared.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/10947)

commit 00bc1ad99a69f851ccdea3656445ae2daaf70717
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Feb 2 12:55:05 2020 +0100

    Don't pass a digest-size to signature implementations
    
    It turns out this was never necessary, as the implementation should
    always check the default digest size anyway.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/10947)

commit 972fa31895b38cbe91a87a04875f7dadee387dea
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Jan 25 12:27:47 2020 +0100

    Decentralize legacy_ctrl_str_to_param()
    
    This function did a bit too much in terms of central control, actually
    more so than the legacy counterpart, where all the string processing
    is done in the diverse *_pmeth.c.  Furthermore, there was no room
    whatsoever for control keys that libcrypto isn't centrally aware of.
    
    This function is changed to simply translating keys and values to
    OSSL_PARAM form and then sent on their merry way to the provider
    implementations through EVP_PKEY_CTX_set_params().  It translates
    selected well known legacy names to their core name counterpart, and
    that's as far as centralized control should extend.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/10947)

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

Summary of changes:
 crypto/err/openssl.txt                            |   1 +
 crypto/evp/digest.c                               |   5 +-
 crypto/evp/pmeth_lib.c                            |  96 +++-------
 include/openssl/core_names.h                      |   4 +-
 providers/common/include/prov/providercommonerr.h |   3 +-
 providers/common/provider_err.c                   |   4 +-
 providers/fips/fipsprov.c                         |   4 +-
 providers/implementations/asymciphers/rsa_enc.c   |  72 +++++++-
 providers/implementations/signature/dsa.c         | 205 ++++++++++++----------
 test/evp_extra_test.c                             |  21 +--
 10 files changed, 227 insertions(+), 188 deletions(-)

diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index eb8d32dcff..b59c8ba1c6 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -2766,6 +2766,7 @@ PROV_R_TAG_NOTSET:119:tag notset
 PROV_R_TAG_NOT_NEEDED:120:tag not needed
 PROV_R_UNABLE_TO_LOAD_SHA1:143:unable to load sha1
 PROV_R_UNABLE_TO_LOAD_SHA256:147:unable to load sha256
+PROV_R_UNKNOWN_PADDING_TYPE:163:unknown padding type
 PROV_R_UNSUPPORTED_CEK_ALG:145:unsupported cek alg
 PROV_R_UNSUPPORTED_KEY_SIZE:153:unsupported key size
 PROV_R_UNSUPPORTED_MAC_TYPE:137:unsupported mac type
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index adde3e13ab..be6fcb58f1 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -662,10 +662,7 @@ int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
         return 0;
     }
 
-    if (ctx->digest->prov == NULL
-        && (ctx->pctx == NULL
-            || (ctx->pctx->operation != EVP_PKEY_OP_VERIFYCTX
-                && ctx->pctx->operation != EVP_PKEY_OP_SIGNCTX)))
+    if (ctx->digest->prov == NULL)
         goto legacy;
 
     switch (cmd) {
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 075e87fe1c..2cbd3ff284 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -679,8 +679,7 @@ int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md)
 
 int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
 {
-    OSSL_PARAM sig_md_params[3], *p = sig_md_params;
-    size_t mdsize;
+    OSSL_PARAM sig_md_params[2], *p = sig_md_params;
     const char *name;
 
     if (ctx == NULL || !EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
@@ -696,9 +695,7 @@ int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
 
     if (md == NULL) {
         name = "";
-        mdsize = 0;
     } else {
-        mdsize = EVP_MD_size(md);
         name = EVP_MD_name(md);
     }
 
@@ -709,8 +706,6 @@ int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
                                              */
                                             (char *)name,
                                             strlen(name) + 1);
-    *p++ = OSSL_PARAM_construct_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE,
-                                       &mdsize);
     *p++ = OSSL_PARAM_construct_end();
 
     return EVP_PKEY_CTX_set_params(ctx, sig_md_params);
@@ -815,76 +810,37 @@ int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype,
 static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
                                     const char *value)
 {
+    if (strcmp(name, "rsa_padding_mode") == 0)
+        name = OSSL_ASYM_CIPHER_PARAM_PAD_MODE;
+    else if (strcmp(name, "rsa_mgf1_md") == 0)
+        name = OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST;
+    else if (strcmp(name, "rsa_oaep_md") == 0)
+        name = OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST;
+    else if (strcmp(name, "rsa_oaep_label") == 0)
+        name = OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL;
 # ifndef OPENSSL_NO_DH
-    if (strcmp(name, "dh_pad") == 0) {
-        int pad;
-
-        pad = atoi(value);
-        return EVP_PKEY_CTX_set_dh_pad(ctx, pad);
-    }
+    else if (strcmp(name, "dh_pad") == 0)
+        name = OSSL_EXCHANGE_PARAM_PAD;
 # endif
-    if (strcmp(name, "digest") == 0) {
-        int ret;
-        EVP_MD *md;
-
-        if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) || ctx->op.sig.signature == NULL)
-            return 0;
-        md = EVP_MD_fetch(ossl_provider_library_context(ctx->op.sig.signature->prov),
-                          value, NULL);
-        if (md == NULL)
-            return 0;
-        ret = EVP_PKEY_CTX_set_signature_md(ctx, md);
-        EVP_MD_free(md);
-        return ret;
-    }
-
-    if (strcmp(name, "rsa_padding_mode") == 0) {
-        int pm;
-
-        if (strcmp(value, "pkcs1") == 0) {
-            pm = RSA_PKCS1_PADDING;
-        } else if (strcmp(value, "sslv23") == 0) {
-            pm = RSA_SSLV23_PADDING;
-        } else if (strcmp(value, "none") == 0) {
-            pm = RSA_NO_PADDING;
-        } else if (strcmp(value, "oeap") == 0) {
-            pm = RSA_PKCS1_OAEP_PADDING;
-        } else if (strcmp(value, "oaep") == 0) {
-            pm = RSA_PKCS1_OAEP_PADDING;
-        } else if (strcmp(value, "x931") == 0) {
-            pm = RSA_X931_PADDING;
-        } else if (strcmp(value, "pss") == 0) {
-            pm = RSA_PKCS1_PSS_PADDING;
-        } else {
-            ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_PADDING_TYPE);
-            return -2;
-        }
-        return EVP_PKEY_CTX_set_rsa_padding(ctx, pm);
-    }
-
-    if (strcmp(name, "rsa_mgf1_md") == 0)
-        return EVP_PKEY_CTX_set_rsa_mgf1_md_name(ctx, value, NULL);
-
-    if (strcmp(name, "rsa_oaep_md") == 0)
-        return EVP_PKEY_CTX_set_rsa_oaep_md_name(ctx, value, NULL);
 
-    if (strcmp(name, "rsa_oaep_label") == 0) {
-        unsigned char *lab;
-        long lablen;
-        int ret;
+    {
+        /*
+         * TODO(3.0) reduce the code above to only translate known legacy
+         * string to the corresponding core name (see core_names.h), but
+         * otherwise leave it to this code block to do the actual work.
+         */
+        const OSSL_PARAM *settable = EVP_PKEY_CTX_settable_params(ctx);
+        OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+        int rv = 0;
 
-        lab = OPENSSL_hexstr2buf(value, &lablen);
-        if (lab == NULL)
+        if (!OSSL_PARAM_allocate_from_text(&params[0], settable, name, value,
+                                           strlen(value)))
             return 0;
-        ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen);
-        if (ret <= 0)
-            OPENSSL_free(lab);
-        return ret;
+        if (EVP_PKEY_CTX_set_params(ctx, params))
+            rv = 1;
+        OPENSSL_free(params[0].data);
+        return rv;
     }
-
-
-
-    return 0;
 }
 
 int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
index cd701ab937..c17eee42a5 100644
--- a/include/openssl/core_names.h
+++ b/include/openssl/core_names.h
@@ -168,7 +168,7 @@ extern "C" {
 #define OSSL_PKEY_PARAM_MAX_SIZE            "max-size" /* integer */
 #define OSSL_PKEY_PARAM_SECURITY_BITS       "security-bits" /* integer */
 #define OSSL_PKEY_PARAM_DIGEST              OSSL_ALG_PARAM_DIGEST
-#define OSSL_PKEY_PARAM_DIGEST_SIZE         "digest-size"
+#define OSSL_PKEY_PARAM_PROPERTIES          OSSL_ALG_PARAM_PROPERTIES
 #define OSSL_PKEY_PARAM_DEFAULT_DIGEST      "default-digest" /* utf8 string */
 #define OSSL_PKEY_PARAM_MANDATORY_DIGEST    "mandatory-digest" /* utf8 string */
 
@@ -213,7 +213,7 @@ extern "C" {
 /* Signature parameters */
 #define OSSL_SIGNATURE_PARAM_ALGORITHM_ID       "algorithm-id"
 #define OSSL_SIGNATURE_PARAM_DIGEST             OSSL_PKEY_PARAM_DIGEST
-#define OSSL_SIGNATURE_PARAM_DIGEST_SIZE        OSSL_PKEY_PARAM_DIGEST_SIZE
+#define OSSL_SIGNATURE_PARAM_PROPERTIES         OSSL_PKEY_PARAM_PROPERTIES
 
 /* Asym cipher parameters */
 #define OSSL_ASYM_CIPHER_PARAM_PAD_MODE                 "pad-mode"
diff --git a/providers/common/include/prov/providercommonerr.h b/providers/common/include/prov/providercommonerr.h
index d97b735ca9..21d7f54a57 100644
--- a/providers/common/include/prov/providercommonerr.h
+++ b/providers/common/include/prov/providercommonerr.h
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -103,6 +103,7 @@ int ERR_load_PROV_strings(void);
 # define PROV_R_TAG_NOT_NEEDED                            120
 # define PROV_R_UNABLE_TO_LOAD_SHA1                       143
 # define PROV_R_UNABLE_TO_LOAD_SHA256                     147
+# define PROV_R_UNKNOWN_PADDING_TYPE                      163
 # define PROV_R_UNSUPPORTED_CEK_ALG                       145
 # define PROV_R_UNSUPPORTED_KEY_SIZE                      153
 # define PROV_R_UNSUPPORTED_MAC_TYPE                      137
diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c
index eba3dbef5f..fcb0722070 100644
--- a/providers/common/provider_err.c
+++ b/providers/common/provider_err.c
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -88,6 +88,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
     "unable to load sha1"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_LOAD_SHA256),
     "unable to load sha256"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNKNOWN_PADDING_TYPE),
+    "unknown padding type"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNSUPPORTED_CEK_ALG),
     "unsupported cek alg"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNSUPPORTED_KEY_SIZE),
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index 288168cb81..c89fa64264 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -276,9 +276,7 @@ static int dsa_key_signature_test(OPENSSL_CTX *libctx)
     /* set signature parameters */
     ossl_param_bld_init(&bld);
     if (!ossl_param_bld_push_utf8_string(&bld, OSSL_SIGNATURE_PARAM_DIGEST,
-                                         SN_sha256,strlen(SN_sha256) + 1)
-        || !ossl_param_bld_push_size_t(&bld, OSSL_SIGNATURE_PARAM_DIGEST_SIZE,
-                                       SHA256_DIGEST_LENGTH))
+                                         SN_sha256,strlen(SN_sha256) + 1))
         goto err;
     params_sig = ossl_param_bld_to_param(&bld);
     if (EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0)
diff --git a/providers/implementations/asymciphers/rsa_enc.c b/providers/implementations/asymciphers/rsa_enc.c
index 77f807e7ef..c72571d6bb 100644
--- a/providers/implementations/asymciphers/rsa_enc.c
+++ b/providers/implementations/asymciphers/rsa_enc.c
@@ -37,6 +37,16 @@ static OSSL_OP_asym_cipher_gettable_ctx_params_fn rsa_gettable_ctx_params;
 static OSSL_OP_asym_cipher_set_ctx_params_fn rsa_set_ctx_params;
 static OSSL_OP_asym_cipher_settable_ctx_params_fn rsa_settable_ctx_params;
 
+static OSSL_ITEM padding_item[] = {
+    { RSA_PKCS1_PADDING,        "pkcs1"  },
+    { RSA_SSLV23_PADDING,       "sslv23" },
+    { RSA_NO_PADDING,           "none"   },
+    { RSA_PKCS1_OAEP_PADDING,   "oaep"   }, /* Correct spelling first */
+    { RSA_PKCS1_OAEP_PADDING,   "oeap"   },
+    { RSA_X931_PADDING,         "x931"   },
+    { RSA_PKCS1_PSS_PADDING,    "pss"    },
+    { 0,                        NULL     }
+};
 
 /*
  * What's passed as an actual key is defined by the KEYMGMT interface.
@@ -263,8 +273,35 @@ static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
         return 0;
 
     p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE);
-    if (p != NULL && !OSSL_PARAM_set_int(p, prsactx->pad_mode))
-        return 0;
+    if (p != NULL)
+        switch (p->data_type) {
+        case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
+            if (!OSSL_PARAM_set_int(p, prsactx->pad_mode))
+                return 0;
+            break;
+        case OSSL_PARAM_UTF8_STRING:
+            {
+                int i;
+                const char *word = NULL;
+
+                for (i = 0; padding_item[i].id != 0; i++) {
+                    if (prsactx->pad_mode == (int)padding_item[i].id) {
+                        word = padding_item[i].ptr;
+                        break;
+                    }
+                }
+
+                if (word != NULL) {
+                    if (!OSSL_PARAM_set_utf8_string(p, word))
+                        return 0;
+                } else {
+                    ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
+                }
+            }
+            break;
+        default:
+            return 0;
+        }
 
     p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST);
     if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->oaep_md == NULL
@@ -304,7 +341,7 @@ static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
 
 static const OSSL_PARAM known_gettable_ctx_params[] = {
     OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, NULL, 0),
-    OSSL_PARAM_int(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL),
+    OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL, 0),
     OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, NULL, 0),
     OSSL_PARAM_DEFN(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, OSSL_PARAM_OCTET_PTR,
                     NULL, 0),
@@ -326,7 +363,6 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
     char mdname[OSSL_MAX_NAME_SIZE];
     char mdprops[OSSL_MAX_PROPQUERY_SIZE] = { '\0' };
     char *str = mdname;
-    int pad_mode;
 
     if (prsactx == NULL || params == NULL)
         return 0;
@@ -353,8 +389,32 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
 
     p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_PAD_MODE);
     if (p != NULL) {
-        if (!OSSL_PARAM_get_int(p, &pad_mode))
+        int pad_mode = 0;
+
+        switch (p->data_type) {
+        case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
+            if (!OSSL_PARAM_get_int(p, &pad_mode))
+                return 0;
+            break;
+        case OSSL_PARAM_UTF8_STRING:
+            {
+                int i;
+
+                if (p->data == NULL)
+                    return 0;
+
+                for (i = 0; padding_item[i].id != 0; i++) {
+                    if (strcmp(p->data, padding_item[i].ptr) == 0) {
+                        pad_mode = padding_item[i].id;
+                        break;
+                    }
+                }
+            }
+            break;
+        default:
             return 0;
+        }
+
         /*
          * PSS padding is for signatures only so is not compatible with
          * asymmetric cipher use.
@@ -426,7 +486,7 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
 
 static const OSSL_PARAM known_settable_ctx_params[] = {
     OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST, NULL, 0),
-    OSSL_PARAM_int(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL),
+    OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, NULL, 0),
     OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST, NULL, 0),
     OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS, NULL, 0),
     OSSL_PARAM_octet_string(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, NULL, 0),
diff --git a/providers/implementations/signature/dsa.c b/providers/implementations/signature/dsa.c
index e8d9cd0b81..b2309ef510 100644
--- a/providers/implementations/signature/dsa.c
+++ b/providers/implementations/signature/dsa.c
@@ -16,10 +16,12 @@
 #include <openssl/dsa.h>
 #include <openssl/params.h>
 #include <openssl/evp.h>
+#include <openssl/err.h>
 #include "internal/nelem.h"
 #include "internal/sizes.h"
 #include "prov/providercommonerr.h"
 #include "prov/implementations.h"
+#include "prov/providercommonerr.h"
 #include "prov/provider_ctx.h"
 #include "crypto/dsa.h"
 
@@ -54,7 +56,15 @@ static OSSL_OP_signature_settable_ctx_md_params_fn dsa_settable_ctx_md_params;
 typedef struct {
     OPENSSL_CTX *libctx;
     DSA *dsa;
-    size_t mdsize;
+
+    /*
+     * Flag to determine if the hash function can be changed (1) or not (0)
+     * Because it's dangerous to change during a DigestSign or DigestVerify
+     * operation, this flag is cleared by their Init function, and set again
+     * by their Final function.
+     */
+    unsigned int flag_allow_md : 1;
+
     char mdname[OSSL_MAX_NAME_SIZE];
 
     /* The Algorithm Identifier of the combined signature agorithm */
@@ -64,8 +74,54 @@ typedef struct {
     /* main digest */
     EVP_MD *md;
     EVP_MD_CTX *mdctx;
+    size_t mdsize;
 } PROV_DSA_CTX;
 
+static size_t dsa_get_md_size(const PROV_DSA_CTX *pdsactx)
+{
+    if (pdsactx->md != NULL)
+        return EVP_MD_size(pdsactx->md);
+    return 0;
+}
+
+static int dsa_get_md_nid(const EVP_MD *md)
+{
+    /*
+     * Because the DSA library deals with NIDs, we need to translate.
+     * We do so using EVP_MD_is_a(), and therefore need a name to NID
+     * map.
+     */
+    static const OSSL_ITEM name_to_nid[] = {
+        { NID_sha1,   OSSL_DIGEST_NAME_SHA1   },
+        { NID_sha224, OSSL_DIGEST_NAME_SHA2_224 },
+        { NID_sha256, OSSL_DIGEST_NAME_SHA2_256 },
+        { NID_sha384, OSSL_DIGEST_NAME_SHA2_384 },
+        { NID_sha512, OSSL_DIGEST_NAME_SHA2_512 },
+        { NID_sha3_224, OSSL_DIGEST_NAME_SHA3_224 },
+        { NID_sha3_256, OSSL_DIGEST_NAME_SHA3_256 },
+        { NID_sha3_384, OSSL_DIGEST_NAME_SHA3_384 },
+        { NID_sha3_512, OSSL_DIGEST_NAME_SHA3_512 },
+    };
+    size_t i;
+    int mdnid = NID_undef;
+
+    if (md == NULL)
+        goto end;
+
+    for (i = 0; i < OSSL_NELEM(name_to_nid); i++) {
+        if (EVP_MD_is_a(md, name_to_nid[i].ptr)) {
+            mdnid = (int)name_to_nid[i].id;
+            break;
+        }
+    }
+
+    if (mdnid == NID_undef)
+        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
+
+ end:
+    return mdnid;
+}
+
 static void *dsa_newctx(void *provctx)
 {
     PROV_DSA_CTX *pdsactx = OPENSSL_zalloc(sizeof(PROV_DSA_CTX));
@@ -74,9 +130,37 @@ static void *dsa_newctx(void *provctx)
         return NULL;
 
     pdsactx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
+    pdsactx->flag_allow_md = 1;
     return pdsactx;
 }
 
+static int dsa_setup_md(PROV_DSA_CTX *ctx,
+                        const char *mdname, const char *mdprops)
+{
+    if (mdname != NULL) {
+        EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
+        int md_nid = dsa_get_md_nid(md);
+        size_t algorithmidentifier_len = 0;
+        const unsigned char *algorithmidentifier;
+
+        EVP_MD_free(ctx->md);
+        ctx->md = NULL;
+        ctx->mdname[0] = '\0';
+
+        algorithmidentifier =
+            dsa_algorithmidentifier_encoding(md_nid, &algorithmidentifier_len);
+
+        if (algorithmidentifier == NULL) {
+            EVP_MD_free(md);
+            return 0;
+        }
+
+        ctx->md = md;
+        OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname));
+    }
+    return 1;
+}
+
 static int dsa_signature_init(void *vpdsactx, void *vdsa)
 {
     PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
@@ -95,6 +179,7 @@ static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen,
     int ret;
     unsigned int sltmp;
     size_t dsasize = DSA_size(pdsactx->dsa);
+    size_t mdsize = dsa_get_md_size(pdsactx);
 
     if (sig == NULL) {
         *siglen = dsasize;
@@ -104,7 +189,7 @@ static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen,
     if (sigsize < (size_t)dsasize)
         return 0;
 
-    if (pdsactx->mdsize != 0 && tbslen != pdsactx->mdsize)
+    if (mdsize != 0 && tbslen != mdsize)
         return 0;
 
     ret = dsa_sign_int(pdsactx->libctx, 0, tbs, tbslen, sig, &sltmp,
@@ -120,83 +205,30 @@ static int dsa_verify(void *vpdsactx, const unsigned char *sig, size_t siglen,
                       const unsigned char *tbs, size_t tbslen)
 {
     PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
+    size_t mdsize = dsa_get_md_size(pdsactx);
 
-    if (pdsactx->mdsize != 0 && tbslen != pdsactx->mdsize)
+    if (mdsize != 0 && tbslen != mdsize)
         return 0;
 
     return DSA_verify(0, tbs, tbslen, sig, siglen, pdsactx->dsa);
 }
 
-static int get_md_nid(const EVP_MD *md)
-{
-    /*
-     * Because the DSA library deals with NIDs, we need to translate.
-     * We do so using EVP_MD_is_a(), and therefore need a name to NID
-     * map.
-     */
-    static const OSSL_ITEM name_to_nid[] = {
-        { NID_sha1,   OSSL_DIGEST_NAME_SHA1   },
-        { NID_sha224, OSSL_DIGEST_NAME_SHA2_224 },
-        { NID_sha256, OSSL_DIGEST_NAME_SHA2_256 },
-        { NID_sha384, OSSL_DIGEST_NAME_SHA2_384 },
-        { NID_sha512, OSSL_DIGEST_NAME_SHA2_512 },
-        { NID_sha3_224, OSSL_DIGEST_NAME_SHA3_224 },
-        { NID_sha3_256, OSSL_DIGEST_NAME_SHA3_256 },
-        { NID_sha3_384, OSSL_DIGEST_NAME_SHA3_384 },
-        { NID_sha3_512, OSSL_DIGEST_NAME_SHA3_512 },
-    };
-    size_t i;
-    int mdnid = NID_undef;
-
-    if (md == NULL)
-        goto end;
-
-    for (i = 0; i < OSSL_NELEM(name_to_nid); i++) {
-        if (EVP_MD_is_a(md, name_to_nid[i].ptr)) {
-            mdnid = (int)name_to_nid[i].id;
-            break;
-        }
-    }
-
-    if (mdnid == NID_undef)
-        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
-
- end:
-    return mdnid;
-}
-
 static int dsa_digest_signverify_init(void *vpdsactx, const char *mdname,
                                       const char *props, void *vdsa)
 {
     PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
-    size_t algorithmidentifier_len = 0;
-    const unsigned char *algorithmidentifier;
-
-    EVP_MD_CTX_free(pdsactx->mdctx);
-    EVP_MD_free(pdsactx->md);
-    pdsactx->mdctx = NULL;
-    pdsactx->mdsize = 0;
-    pdsactx->md = NULL;
 
+    pdsactx->flag_allow_md = 0;
     if (!dsa_signature_init(vpdsactx, vdsa))
         return 0;
 
-    pdsactx->md = EVP_MD_fetch(pdsactx->libctx, mdname, props);
-    algorithmidentifier =
-        dsa_algorithmidentifier_encoding(get_md_nid(pdsactx->md),
-                                         &algorithmidentifier_len);
-
-    if (algorithmidentifier == NULL)
-        goto error;
+    if (!dsa_setup_md(pdsactx, mdname, props))
+        return 0;
 
-    pdsactx->mdsize = EVP_MD_size(pdsactx->md);
     pdsactx->mdctx = EVP_MD_CTX_new();
     if (pdsactx->mdctx == NULL)
         goto error;
 
-    memcpy(pdsactx->aid, algorithmidentifier, algorithmidentifier_len);
-    pdsactx->aid_len = algorithmidentifier_len;
-
     if (!EVP_DigestInit_ex(pdsactx->mdctx, pdsactx->md, NULL))
         goto error;
 
@@ -206,7 +238,6 @@ static int dsa_digest_signverify_init(void *vpdsactx, const char *mdname,
     EVP_MD_CTX_free(pdsactx->mdctx);
     EVP_MD_free(pdsactx->md);
     pdsactx->mdctx = NULL;
-    pdsactx->mdsize = 0;
     pdsactx->md = NULL;
     return 0;
 }
@@ -246,6 +277,8 @@ int dsa_digest_sign_final(void *vpdsactx, unsigned char *sig, size_t *siglen,
             return 0;
     }
 
+    pdsactx->flag_allow_md = 1;
+
     return dsa_sign(vpdsactx, sig, siglen, sigsize, digest, (size_t)dlen);
 }
 
@@ -268,6 +301,8 @@ int dsa_digest_verify_final(void *vpdsactx, const unsigned char *sig,
     if (!EVP_DigestFinal_ex(pdsactx->mdctx, digest, &dlen))
         return 0;
 
+    pdsactx->flag_allow_md = 1;
+
     return dsa_verify(vpdsactx, sig, siglen, digest, (size_t)dlen);
 }
 
@@ -330,14 +365,8 @@ static int dsa_get_ctx_params(void *vpdsactx, OSSL_PARAM *params)
         && !OSSL_PARAM_set_octet_string(p, pdsactx->aid, pdsactx->aid_len))
         return 0;
 
-    p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, pdsactx->mdsize))
-        return 0;
-
     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
-    if (p != NULL && !OSSL_PARAM_set_utf8_string(p, pdsactx->md == NULL
-                                                    ? pdsactx->mdname
-                                                    : EVP_MD_name(pdsactx->md)))
+    if (p != NULL && !OSSL_PARAM_set_utf8_string(p, pdsactx->mdname))
         return 0;
 
     return 1;
@@ -345,7 +374,6 @@ static int dsa_get_ctx_params(void *vpdsactx, OSSL_PARAM *params)
 
 static const OSSL_PARAM known_gettable_ctx_params[] = {
     OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
-    OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
     OSSL_PARAM_END
 };
@@ -359,39 +387,34 @@ static int dsa_set_ctx_params(void *vpdsactx, const OSSL_PARAM params[])
 {
     PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
     const OSSL_PARAM *p;
-    char *mdname;
 
     if (pdsactx == NULL || params == NULL)
         return 0;
 
-    if (pdsactx->md != NULL) {
-        /*
-         * You cannot set the digest name/size when doing a DigestSign or
-         * DigestVerify.
-         */
-        return 1;
-    }
-
-    p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
-    if (p != NULL && !OSSL_PARAM_get_size_t(p, &pdsactx->mdsize))
-        return 0;
-
-    /*
-     * We never actually use the mdname, but we do support getting it later.
-     * This can be useful for applications that want to know the MD that they
-     * previously set.
-     */
     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
-    mdname = pdsactx->mdname;
-    if (p != NULL
-            && !OSSL_PARAM_get_utf8_string(p, &mdname, sizeof(pdsactx->mdname)))
+    /* Not allowed during certain operations */
+    if (p != NULL && !pdsactx->flag_allow_md)
         return 0;
+    if (p != NULL) {
+        char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname;
+        char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = mdprops;
+        const OSSL_PARAM *propsp =
+            OSSL_PARAM_locate_const(params,
+                                    OSSL_SIGNATURE_PARAM_PROPERTIES);
+
+        if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
+            return 0;
+        if (propsp != NULL
+            && !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops)))
+            return 0;
+        if (!dsa_setup_md(pdsactx, mdname, mdprops))
+            return 0;
+    }
 
     return 1;
 }
 
 static const OSSL_PARAM known_settable_ctx_params[] = {
-    OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
     OSSL_PARAM_END
 };
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index 4dfcd26c28..024ef6ad17 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -25,6 +25,7 @@
 #include <openssl/dh.h>
 #include "testutil.h"
 #include "internal/nelem.h"
+#include "internal/sizes.h"
 #include "crypto/evp.h"
 
 /*
@@ -1239,13 +1240,13 @@ static int test_EVP_PKEY_CTX_get_set_params(void)
     EVP_PKEY_CTX *ctx = NULL;
     EVP_SIGNATURE *dsaimpl = NULL;
     const OSSL_PARAM *params;
-    OSSL_PARAM ourparams[2], *param = ourparams;
+    OSSL_PARAM ourparams[2], *param = ourparams, *param_md;
     DSA *dsa = NULL;
     BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub = NULL, *priv = NULL;
     EVP_PKEY *pkey = NULL;
     int ret = 0;
     const EVP_MD *md;
-    size_t mdsize = SHA512_DIGEST_LENGTH;
+    char mdname[OSSL_MAX_NAME_SIZE];
     char ssl3ms[48];
 
     /*
@@ -1288,8 +1289,6 @@ static int test_EVP_PKEY_CTX_get_set_params(void)
      */
     params = EVP_PKEY_CTX_settable_params(ctx);
     if (!TEST_ptr(params)
-        || !TEST_ptr(OSSL_PARAM_locate_const(params,
-                                             OSSL_SIGNATURE_PARAM_DIGEST_SIZE))
         || !TEST_ptr(OSSL_PARAM_locate_const(params,
                                              OSSL_SIGNATURE_PARAM_DIGEST)))
         goto err;
@@ -1298,8 +1297,6 @@ static int test_EVP_PKEY_CTX_get_set_params(void)
     if (!TEST_ptr(params)
         || !TEST_ptr(OSSL_PARAM_locate_const(params,
                                              OSSL_SIGNATURE_PARAM_ALGORITHM_ID))
-        || !TEST_ptr(OSSL_PARAM_locate_const(params,
-                                             OSSL_SIGNATURE_PARAM_DIGEST_SIZE))
         || !TEST_ptr(OSSL_PARAM_locate_const(params,
                                              OSSL_SIGNATURE_PARAM_DIGEST)))
         goto err;
@@ -1308,16 +1305,20 @@ static int test_EVP_PKEY_CTX_get_set_params(void)
      * Test getting and setting params via EVP_PKEY_CTX_set_params() and
      * EVP_PKEY_CTX_get_params()
      */
-    *param++ = OSSL_PARAM_construct_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE,
-                                           &mdsize);
+    strcpy(mdname, "SHA512");
+    param_md = param;
+    *param++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST,
+                                                mdname, 0);
     *param++ = OSSL_PARAM_construct_end();
 
     if (!TEST_true(EVP_PKEY_CTX_set_params(ctx, ourparams)))
         goto err;
 
-    mdsize = 0;
+    mdname[0] = '\0';
+    *param_md = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST,
+                                                 mdname, sizeof(mdname));
     if (!TEST_true(EVP_PKEY_CTX_get_params(ctx, ourparams))
-            || !TEST_size_t_eq(mdsize, SHA512_DIGEST_LENGTH))
+            || !TEST_str_eq(mdname, "SHA512"))
         goto err;
 
     /*


More information about the openssl-commits mailing list