[openssl] master update

Richard Levitte levitte at openssl.org
Sat Feb 22 00:14:17 UTC 2020


The branch master has been updated
       via  8e90e3d53665854d76d6d46491b38f0e2a802428 (commit)
       via  e72467d3a4d0b83f478bbd60fee3e788a615238e (commit)
       via  1b6ea3080d86e8c3a249cda92fbd20417e942704 (commit)
       via  ae9e0698df7672977f0c7c88f3b3c2b695c14611 (commit)
       via  f54a4101890665329aedac948d7bce9d6769d568 (commit)
       via  a9127c1d11e95fd7bcbd9df7f8e3ba74a87feafa (commit)
       via  6f4b7663150e2ee264836dbc5b338bd979828312 (commit)
      from  e8d0819d52b2741fcb4ddb79ced4d824c3056918 (commit)


- Log -----------------------------------------------------------------
commit 8e90e3d53665854d76d6d46491b38f0e2a802428
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Jan 30 15:14:37 2020 +0100

    DSA: More conforming names in crypto/dsa/dsa_aid.c
    
    Made macro names that refer to a known base OID, an commented accordingly.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/10557)

commit e72467d3a4d0b83f478bbd60fee3e788a615238e
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Dec 12 09:21:59 2019 +0100

    doc/man3/EVP_PKEY_CTX_ctrl.pod: cleanup
    
    Clean up a manual we've touched, according to conventions found in
    Linux' man-pages(7); function arguments in descriptions should be in
    italics, and types, macros and similar should be in bold, with the
    exception for NULL.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/10557)

commit 1b6ea3080d86e8c3a249cda92fbd20417e942704
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Dec 4 09:54:35 2019 +0100

    PROV: Avoid MDC2 in the RSA signature implementation in the FIPS module
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/10557)

commit ae9e0698df7672977f0c7c88f3b3c2b695c14611
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Dec 3 11:02:58 2019 +0100

    test/recipes/30-test_evp_data/evppkey.txt
    
    Tests that go through provider cannot recognise PKEY_CTRL_INVALID from
    PKEY_CTRL_ERROR any more, because provided implementations' param
    setting functions return 0 or 1.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/10557)

commit f54a4101890665329aedac948d7bce9d6769d568
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Dec 2 11:26:15 2019 +0100

    test/evp_extra_test.c: adapt for RSA signature tests
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/10557)

commit a9127c1d11e95fd7bcbd9df7f8e3ba74a87feafa
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Dec 2 11:25:47 2019 +0100

    rsa_get0_all_params(): Allow zero CRT params
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/10557)

commit 6f4b7663150e2ee264836dbc5b338bd979828312
Author: Richard Levitte <levitte at openssl.org>
Date:   Sun Dec 1 15:01:50 2019 +0100

    PROV: add RSA signature implementation
    
    This includes legacy PSS controls to params conversion, and an attempt
    to generalise the parameter names when they are suitable for more than
    one operation.
    
    Also added crypto/rsa/rsa_aid.c, containing proper AlgorithmIdentifiers
    for known RSA+hash function combinations.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/10557)

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

Summary of changes:
 crypto/dsa/dsa_aid.c                               |   39 +-
 crypto/err/openssl.txt                             |   11 +
 crypto/evp/pmeth_lib.c                             |  118 ++-
 crypto/rsa/build.info                              |    2 +-
 crypto/rsa/rsa_aid.c                               |   98 ++
 crypto/rsa/rsa_ameth.c                             |    8 +-
 crypto/rsa/rsa_lib.c                               |  117 +-
 crypto/rsa/rsa_local.h                             |    4 -
 crypto/rsa/rsa_pmeth.c                             |    1 +
 crypto/rsa/rsa_sign.c                              |   40 +-
 doc/man3/EVP_PKEY_CTX_ctrl.pod                     |  203 ++--
 include/crypto/rsa.h                               |    8 +
 include/openssl/core_names.h                       |   26 +-
 include/openssl/rsa.h                              |   10 +-
 providers/common/include/prov/providercommonerr.h  |   10 +
 providers/common/provider_err.c                    |   19 +
 providers/defltprov.c                              |    1 +
 .../implementations/include/prov/implementations.h |    1 +
 providers/implementations/signature/build.info     |    3 +
 providers/implementations/signature/rsa.c          | 1115 ++++++++++++++++++++
 test/evp_extra_test.c                              |  130 ++-
 test/recipes/30-test_evp_data/evppkey.txt          |    2 +-
 util/libcrypto.num                                 |    2 +
 23 files changed, 1714 insertions(+), 254 deletions(-)
 create mode 100644 crypto/rsa/rsa_aid.c
 create mode 100644 providers/implementations/signature/rsa.c

diff --git a/crypto/dsa/dsa_aid.c b/crypto/dsa/dsa_aid.c
index 759e5c90e1..505e2e2f40 100644
--- a/crypto/dsa/dsa_aid.c
+++ b/crypto/dsa/dsa_aid.c
@@ -15,31 +15,37 @@
 #define ASN1_SEQUENCE 0x30
 #define ASN1_OID 0x06
 
-/* dsaWithSHA OIDs are of the form: (1 3 14 3 2 |n|) */
-#define ENCODE_ALGORITHMIDENTIFIER_SHA(name, n)                         \
+/*
+ * id-dsa-with-sha1 OBJECT IDENTIFIER ::=  {
+ *     iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3
+ * }
+ */
+#define ENCODE_ALGORITHMIDENTIFIER_RFC3279(name, n)                     \
     static const unsigned char algorithmidentifier_##name##_der[] = {   \
-        ASN1_SEQUENCE, 0x07,                                            \
-          ASN1_OID, 0x05, 1 * 40 + 3, 14, 3, 2, n                       \
+        ASN1_SEQUENCE, 0x09,                                            \
+          ASN1_OID, 0x07, 1 * 40 + 2, 134, 72, 206, 56, 4, n            \
 }
 
-ENCODE_ALGORITHMIDENTIFIER_SHA(sha, 13);
-ENCODE_ALGORITHMIDENTIFIER_SHA(sha1, 27);
+ENCODE_ALGORITHMIDENTIFIER_RFC3279(sha1, 3);
 
-/* dsaWithSHA OIDs are of the form: (2 16 840 1 101 3 4 3 |n|) */
-#define ENCODE_ALGORITHMIDENTIFIER_SHAx(name, n)                        \
+/*
+ * dsaWithSHAx OIDs are of the form: (sigAlgs |n|)
+ * where sigAlgs OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 4 3 }
+ */
+#define ENCODE_ALGORITHMIDENTIFIER_SIGALGS(name, n)                     \
     static const unsigned char algorithmidentifier_##name##_der[] = {   \
         ASN1_SEQUENCE, 0x0b,                                            \
           ASN1_OID, 0x09, 2 * 40 + 16, 0x86, 0x48, 1, 101, 3, 4, 3, n   \
 }
 
-ENCODE_ALGORITHMIDENTIFIER_SHAx(sha224, 1);
-ENCODE_ALGORITHMIDENTIFIER_SHAx(sha256, 2);
-ENCODE_ALGORITHMIDENTIFIER_SHAx(sha384, 3);
-ENCODE_ALGORITHMIDENTIFIER_SHAx(sha512, 4);
-ENCODE_ALGORITHMIDENTIFIER_SHAx(sha3_224, 5);
-ENCODE_ALGORITHMIDENTIFIER_SHAx(sha3_256, 6);
-ENCODE_ALGORITHMIDENTIFIER_SHAx(sha3_384, 7);
-ENCODE_ALGORITHMIDENTIFIER_SHAx(sha3_512, 8);
+ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha224, 1);
+ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha256, 2);
+ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha384, 3);
+ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha512, 4);
+ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_224, 5);
+ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_256, 6);
+ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_384, 7);
+ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_512, 8);
 
 #define MD_CASE(name)                                                   \
     case NID_##name:                                                    \
@@ -49,7 +55,6 @@ ENCODE_ALGORITHMIDENTIFIER_SHAx(sha3_512, 8);
 const unsigned char *dsa_algorithmidentifier_encoding(int md_nid, size_t *len)
 {
     switch (md_nid) {
-        MD_CASE(sha);
         MD_CASE(sha1);
         MD_CASE(sha224);
         MD_CASE(sha256);
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index e6a45ac03a..47a20e828f 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -2752,6 +2752,7 @@ PROP_R_PARSE_FAILED:108:parse failed
 PROP_R_STRING_TOO_LONG:109:string too long
 PROP_R_TRAILING_CHARACTERS:110:trailing characters
 PROV_R_AES_KEY_SETUP_FAILED:101:aes key setup failed
+PROV_R_ALGORITHM_MISMATCH:173:algorithm mismatch
 PROV_R_BAD_DECRYPT:100:bad decrypt
 PROV_R_BAD_ENCODING:141:bad encoding
 PROV_R_BAD_LENGTH:142:bad length
@@ -2759,17 +2760,21 @@ PROV_R_BAD_TLS_CLIENT_VERSION:161:bad tls client version
 PROV_R_BN_ERROR:160:bn error
 PROV_R_BOTH_MODE_AND_MODE_INT:127:both mode and mode int
 PROV_R_CIPHER_OPERATION_FAILED:102:cipher operation failed
+PROV_R_DIGEST_NOT_ALLOWED:174:digest not allowed
 PROV_R_FAILED_DURING_DERIVATION:164:failed during derivation
 PROV_R_FAILED_TO_DECRYPT:162:failed to decrypt
 PROV_R_FAILED_TO_GENERATE_KEY:121:failed to generate key
 PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter
 PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter
+PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\
+	illegal or unsupported padding mode
 PROV_R_INAVLID_UKM_LENGTH:146:inavlid ukm length
 PROV_R_INVALID_AAD:108:invalid aad
 PROV_R_INVALID_CONSTANT_LENGTH:157:invalid constant length
 PROV_R_INVALID_CUSTOM_LENGTH:111:invalid custom length
 PROV_R_INVALID_DATA:115:invalid data
 PROV_R_INVALID_DIGEST:122:invalid digest
+PROV_R_INVALID_DIGEST_LENGTH:166:invalid digest length
 PROV_R_INVALID_ITERATION_COUNT:123:invalid iteration count
 PROV_R_INVALID_IVLEN:116:invalid ivlen
 PROV_R_INVALID_IV_LENGTH:109:invalid iv length
@@ -2778,12 +2783,17 @@ PROV_R_INVALID_KEYLEN:117:invalid keylen
 PROV_R_INVALID_KEY_LEN:124:invalid key len
 PROV_R_INVALID_KEY_LENGTH:105:invalid key length
 PROV_R_INVALID_MAC:151:invalid mac
+PROV_R_INVALID_MGF1_MD:167:invalid mgf1 md
 PROV_R_INVALID_MODE:125:invalid mode
 PROV_R_INVALID_MODE_INT:126:invalid mode int
+PROV_R_INVALID_PADDING_MODE:168:invalid padding mode
+PROV_R_INVALID_PSS_SALTLEN:169:invalid pss saltlen
 PROV_R_INVALID_SALT_LENGTH:112:invalid salt length
 PROV_R_INVALID_SEED_LENGTH:154:invalid seed length
 PROV_R_INVALID_TAG:110:invalid tag
 PROV_R_INVALID_TAGLEN:118:invalid taglen
+PROV_R_INVALID_X931_DIGEST:170:invalid x931 digest
+PROV_R_KEY_SIZE_TOO_SMALL:171:key size too small
 PROV_R_MISSING_CEK_ALG:144:missing cek alg
 PROV_R_MISSING_CIPHER:155:missing cipher
 PROV_R_MISSING_CONSTANT:156:missing constant
@@ -2801,6 +2811,7 @@ PROV_R_NOT_SUPPORTED:136:not supported
 PROV_R_NOT_XOF_OR_INVALID_LENGTH:113:not xof or invalid length
 PROV_R_NO_KEY_SET:114:no key set
 PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small
+PROV_R_PSS_SALTLEN_TOO_SMALL:172:pss saltlen too small
 PROV_R_READ_KEY:159:read key
 PROV_R_TAG_NOTSET:119:tag notset
 PROV_R_TAG_NOT_NEEDED:120:tag not needed
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 6be796fafc..cb64b95bf6 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -786,69 +786,73 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
 # ifndef OPENSSL_NO_EC
     if (keytype == EVP_PKEY_EC) {
         switch (cmd) {
-            case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
-                if (p1 == -2) {
-                    return EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx);
-                } else if (p1 < -1 || p1 > 1) {
-                    /* Uses the same return values as EVP_PKEY_CTX_ctrl */
-                    return -2;
-                } else {
-                    return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, p1);
-                }
-            case EVP_PKEY_CTRL_EC_KDF_TYPE:
-                if (p1 == -2) {
-                    return EVP_PKEY_CTX_get_ecdh_kdf_type(ctx);
-                } else {
-                    return EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, p1);
-                }
-            case EVP_PKEY_CTRL_GET_EC_KDF_MD:
-                return EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, p2);
-            case EVP_PKEY_CTRL_EC_KDF_MD:
-                return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, p2);
-            case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
-                return EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, p2);
-            case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
-                return EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, p1);
-            case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
-                return EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p2);
-            case EVP_PKEY_CTRL_EC_KDF_UKM:
-                return EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p2, p1);
+        case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
+            if (p1 == -2) {
+                return EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx);
+            } else if (p1 < -1 || p1 > 1) {
+                /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+                return -2;
+            } else {
+                return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, p1);
+            }
+        case EVP_PKEY_CTRL_EC_KDF_TYPE:
+            if (p1 == -2) {
+                return EVP_PKEY_CTX_get_ecdh_kdf_type(ctx);
+            } else {
+                return EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, p1);
+            }
+        case EVP_PKEY_CTRL_GET_EC_KDF_MD:
+            return EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, p2);
+        case EVP_PKEY_CTRL_EC_KDF_MD:
+            return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, p2);
+        case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
+            return EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, p2);
+        case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
+            return EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, p1);
+        case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
+            return EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p2);
+        case EVP_PKEY_CTRL_EC_KDF_UKM:
+            return EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p2, p1);
         }
     }
 # endif
     if (keytype == -1) {
         switch (cmd) {
-            case EVP_PKEY_CTRL_MD:
-                return EVP_PKEY_CTX_set_signature_md(ctx, p2);
-            case EVP_PKEY_CTRL_GET_MD:
-                return EVP_PKEY_CTX_get_signature_md(ctx, p2);
-            case EVP_PKEY_CTRL_RSA_PADDING:
-                return EVP_PKEY_CTX_set_rsa_padding(ctx, p1);
-            case EVP_PKEY_CTRL_GET_RSA_PADDING:
-                return EVP_PKEY_CTX_get_rsa_padding(ctx, p2);
-            case EVP_PKEY_CTRL_RSA_OAEP_MD:
-                return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2);
-            case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
-                return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2);
-            case EVP_PKEY_CTRL_RSA_MGF1_MD:
-                return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2);
-            case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
-                return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2);
-            case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
-                return EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, p2, p1);
-            case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
-                return EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, (unsigned char **)p2);
-            case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
-            case EVP_PKEY_CTRL_PKCS7_DECRYPT:
+        case EVP_PKEY_CTRL_MD:
+            return EVP_PKEY_CTX_set_signature_md(ctx, p2);
+        case EVP_PKEY_CTRL_GET_MD:
+            return EVP_PKEY_CTX_get_signature_md(ctx, p2);
+        case EVP_PKEY_CTRL_RSA_PADDING:
+            return EVP_PKEY_CTX_set_rsa_padding(ctx, p1);
+        case EVP_PKEY_CTRL_GET_RSA_PADDING:
+            return EVP_PKEY_CTX_get_rsa_padding(ctx, p2);
+        case EVP_PKEY_CTRL_RSA_OAEP_MD:
+            return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2);
+        case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
+            return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2);
+        case EVP_PKEY_CTRL_RSA_MGF1_MD:
+            return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2);
+        case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
+            return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2);
+        case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
+            return EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, p2, p1);
+        case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
+            return EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, (unsigned char **)p2);
+        case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
+            return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, p1);
+        case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
+            return EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, p2);
+        case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
+        case EVP_PKEY_CTRL_PKCS7_DECRYPT:
 # ifndef OPENSSL_NO_CMS
-            case EVP_PKEY_CTRL_CMS_DECRYPT:
-            case EVP_PKEY_CTRL_CMS_ENCRYPT:
+        case EVP_PKEY_CTRL_CMS_DECRYPT:
+        case EVP_PKEY_CTRL_CMS_ENCRYPT:
 # endif
-                if (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
-                    return 1;
-                ERR_raise(ERR_LIB_EVP,
-                          EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
-                return -2;
+            if (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
+                return 1;
+            ERR_raise(ERR_LIB_EVP,
+                      EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+            return -2;
         }
     }
     return 0;
@@ -918,6 +922,8 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
         name = OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST;
     else if (strcmp(name, "rsa_oaep_label") == 0)
         name = OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL;
+    else if (strcmp(name, "rsa_pss_saltlen") == 0)
+        name = OSSL_SIGNATURE_PARAM_PSS_SALTLEN;
 # ifndef OPENSSL_NO_DH
     else if (strcmp(name, "dh_pad") == 0)
         name = OSSL_EXCHANGE_PARAM_PAD;
diff --git a/crypto/rsa/build.info b/crypto/rsa/build.info
index 274f376979..ddb4e6fc5a 100644
--- a/crypto/rsa/build.info
+++ b/crypto/rsa/build.info
@@ -1,6 +1,6 @@
 LIBS=../../libcrypto
 
-$COMMON=rsa_ossl.c rsa_gen.c rsa_lib.c rsa_sign.c rsa_pk1.c \
+$COMMON=rsa_ossl.c rsa_gen.c rsa_lib.c rsa_sign.c rsa_aid.c rsa_pk1.c \
         rsa_none.c rsa_oaep.c rsa_chk.c rsa_pss.c rsa_x931.c rsa_crpt.c \
         rsa_x931g.c rsa_sp800_56b_gen.c rsa_sp800_56b_check.c
 
diff --git a/crypto/rsa/rsa_aid.c b/crypto/rsa/rsa_aid.c
new file mode 100644
index 0000000000..4b4d3a62f1
--- /dev/null
+++ b/crypto/rsa/rsa_aid.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+
+#include <openssl/objects.h>
+#include "crypto/rsa.h"
+
+#define ASN1_SEQUENCE 0x30
+#define ASN1_OID 0x06
+
+/*
+ * -- RFC 2313
+ * pkcs-1 OBJECT IDENTIFIER ::= {
+ *     iso(1) member-body(2) US(840) rsadsi(113549) pkcs(1) 1
+ * }
+ */
+
+/*
+ * -- RFC 3279
+ * md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
+ * md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
+ * sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
+ */
+#define ENCODE_ALGORITHMIDENTIFIER_PKCS1(name, n)                       \
+    static const unsigned char algorithmidentifier_##name##_der[] = {   \
+        ASN1_SEQUENCE, 0x0b,                                            \
+          ASN1_OID, 0x09, 1 * 40 + 2,  134, 72, 134, 247, 13, 1, 1, n   \
+}
+#ifndef FIPS_MODE
+ENCODE_ALGORITHMIDENTIFIER_PKCS1(md2, 2);
+ENCODE_ALGORITHMIDENTIFIER_PKCS1(md5, 4);
+#endif
+ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha1, 5);
+
+/*
+ * -- RFC 4055
+ * sha224WithRSAEncryption  OBJECT IDENTIFIER  ::=  { pkcs-1 14 }
+ * sha256WithRSAEncryption  OBJECT IDENTIFIER  ::=  { pkcs-1 11 }
+ * sha384WithRSAEncryption  OBJECT IDENTIFIER  ::=  { pkcs-1 12 }
+ * sha512WithRSAEncryption  OBJECT IDENTIFIER  ::=  { pkcs-1 13 }
+ */
+ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha224, 14);
+ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha256, 11);
+ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha384, 12);
+ENCODE_ALGORITHMIDENTIFIER_PKCS1(sha512, 13);
+
+/*
+ * -- https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
+ *
+ * sigAlgs OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 4 3 }
+ *
+ * id-rsassa-pkcs1-v1_5-with-sha3-224 ::= { sigAlgs 13 }
+ * id-rsassa-pkcs1-v1_5-with-sha3-256 ::= { sigAlgs 14 }
+ * id-rsassa-pkcs1-v1_5-with-sha3-384 ::= { sigAlgs 15 }
+ * id-rsassa-pkcs1-v1_5-with-sha3-512 ::= { sigAlgs 16 }
+ */
+#define ENCODE_ALGORITHMIDENTIFIER_SIGALGS(name, n)                     \
+    static const unsigned char algorithmidentifier_##name##_der[] = {   \
+        ASN1_SEQUENCE, 0x0c,                                            \
+          ASN1_OID, 0x0a, 1 * 40 + 2,  16, 134, 72, 1, 101, 3, 4, 3, n  \
+}
+ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_224, 13);
+ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_256, 14);
+ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_384, 15);
+ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_512, 16);
+
+#define MD_CASE(name)                                                   \
+    case NID_##name:                                                    \
+        *len = sizeof(algorithmidentifier_##name##_der);                \
+        return algorithmidentifier_##name##_der
+
+const unsigned char *rsa_algorithmidentifier_encoding(int md_nid, size_t *len)
+{
+    switch (md_nid) {
+#ifndef FIPS_MODE
+        MD_CASE(md2);
+        MD_CASE(md5);
+#endif
+        MD_CASE(sha1);
+        MD_CASE(sha224);
+        MD_CASE(sha256);
+        MD_CASE(sha384);
+        MD_CASE(sha512);
+        MD_CASE(sha3_224);
+        MD_CASE(sha3_256);
+        MD_CASE(sha3_384);
+        MD_CASE(sha3_512);
+    default:
+        return NULL;
+    }
+}
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 71aa435bd7..f34eacf552 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -1120,7 +1120,13 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
         numexps = sk_BIGNUM_const_num(exps);
         numcoeffs = sk_BIGNUM_const_num(coeffs);
 
-        if (numprimes < 2 || numexps < 2 || numcoeffs < 1)
+        /*
+         * It's permisssible to have zero primes, i.e. no CRT params.
+         * Otherwise, there must be at least two, as many exponents,
+         * and one coefficient less.
+         */
+        if (numprimes != 0
+            && (numprimes < 2 || numexps < 2 || numcoeffs < 1))
             goto err;
 
         /* assert that an OSSL_PARAM_BLD has enough space. */
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c
index c43c9fdd48..08ce8b4ef8 100644
--- a/crypto/rsa/rsa_lib.c
+++ b/crypto/rsa/rsa_lib.c
@@ -780,6 +780,10 @@ int rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes,
     if (r == NULL)
         return 0;
 
+    /* If |p| is NULL, there are no CRT parameters */
+    if (RSA_get0_p(r) == NULL)
+        return 1;
+
     sk_BIGNUM_const_push(primes, RSA_get0_p(r));
     sk_BIGNUM_const_push(primes, RSA_get0_q(r));
     sk_BIGNUM_const_push(exps, RSA_get0_dmp1(r));
@@ -817,12 +821,14 @@ int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad_mode)
         return -1;
 
     /* TODO(3.0): Remove this eventually when no more legacy */
-    if (!EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
-            || ctx->op.ciph.ciphprovctx == NULL)
+    if ((!EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
+         || ctx->op.ciph.ciphprovctx == NULL)
+        && (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
+            || ctx->op.sig.sigprovctx == NULL))
         return EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_RSA_PADDING,
                                  pad_mode, NULL);
 
-    *p++ = OSSL_PARAM_construct_int(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, &pad_mode);
+    *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_PAD_MODE, &pad_mode);
     *p++ = OSSL_PARAM_construct_end();
 
     return EVP_PKEY_CTX_set_params(ctx, pad_params);
@@ -845,12 +851,14 @@ int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad_mode)
         return -1;
 
     /* TODO(3.0): Remove this eventually when no more legacy */
-    if (!EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
-            || ctx->op.ciph.ciphprovctx == NULL)
+    if ((!EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
+         || ctx->op.ciph.ciphprovctx == NULL)
+        && (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
+            || ctx->op.sig.sigprovctx == NULL))
         return EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, 0,
                                  pad_mode);
 
-    *p++ = OSSL_PARAM_construct_int(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, pad_mode);
+    *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_PAD_MODE, pad_mode);
     *p++ = OSSL_PARAM_construct_end();
 
     if (!EVP_PKEY_CTX_get_params(ctx, pad_params))
@@ -1026,20 +1034,20 @@ int EVP_PKEY_CTX_set_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, const char *mdname,
             && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
         return -1;
 
-    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST,
+    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MGF1_DIGEST,
                                             /*
-                                             * Cast away the const. This is read
-                                             * only so should be safe
+                                             * Cast away the const. This is
+                                             * read only so should be safe
                                              */
                                             (char *)mdname, 0);
     if (mdprops != NULL) {
-        *p++ = OSSL_PARAM_construct_utf8_string(
-                    OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS,
-                    /*
-                     * Cast away the const. This is read
-                     * only so should be safe
-                     */
-                    (char *)mdprops, 0);
+        *p++ =
+            OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MGF1_PROPERTIES,
+                                             /*
+                                              * Cast away the const. This is
+                                              * read only so should be safe
+                                              */
+                                             (char *)mdprops, 0);
     }
     *p++ = OSSL_PARAM_construct_end();
 
@@ -1065,7 +1073,7 @@ int EVP_PKEY_CTX_get_rsa_mgf1_md_name(EVP_PKEY_CTX *ctx, char *name,
             && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
         return -1;
 
-    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST,
+    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MGF1_DIGEST,
                                             name, namelen);
     *p++ = OSSL_PARAM_construct_end();
 
@@ -1133,12 +1141,12 @@ int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label, int llen)
                                  (void *)label);
 
     *p++ = OSSL_PARAM_construct_octet_string(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL,
-                                            /*
-                                             * Cast away the const. This is read
-                                             * only so should be safe
-                                             */
-                                            (void *)label,
-                                            (size_t)llen);
+                                             /*
+                                              * Cast away the const. This is
+                                              * read only so should be safe
+                                              */
+                                             (void *)label,
+                                             (size_t)llen);
     *p++ = OSSL_PARAM_construct_end();
 
     if (!EVP_PKEY_CTX_set_params(ctx, rsa_params))
@@ -1183,4 +1191,67 @@ int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx, unsigned char **label)
 
     return (int)labellen;
 }
+
+int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int saltlen)
+{
+    OSSL_PARAM pad_params[2], *p = pad_params;
+
+    if (ctx == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    /* If key type not RSA or RSA-PSS return error */
+    if (ctx->pmeth != NULL
+            && ctx->pmeth->pkey_id != EVP_PKEY_RSA
+            && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
+        return -1;
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
+        || ctx->op.sig.sigprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_RSA_PSS_SALTLEN,
+                                 saltlen, NULL);
+
+    *p++ =
+        OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, &saltlen);
+    *p++ = OSSL_PARAM_construct_end();
+
+    return EVP_PKEY_CTX_set_params(ctx, pad_params);
+}
+
+int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen)
+{
+    OSSL_PARAM pad_params[2], *p = pad_params;
+
+    if (ctx == NULL || saltlen == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    /* If key type not RSA or RSA-PSS return error */
+    if (ctx->pmeth != NULL
+            && ctx->pmeth->pkey_id != EVP_PKEY_RSA
+            && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
+        return -1;
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
+        || ctx->op.sig.sigprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, -1, -1,
+                                 EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN,
+                                 0, saltlen);
+
+    *p++ =
+        OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, saltlen);
+    *p++ = OSSL_PARAM_construct_end();
+
+    if (!EVP_PKEY_CTX_get_params(ctx, pad_params))
+        return 0;
+
+    return 1;
+
+}
 #endif
diff --git a/crypto/rsa/rsa_local.h b/crypto/rsa/rsa_local.h
index e15c1ae3d5..11d7635c35 100644
--- a/crypto/rsa/rsa_local.h
+++ b/crypto/rsa/rsa_local.h
@@ -122,10 +122,6 @@ struct rsa_meth_st {
                                    BIGNUM *e, BN_GENCB *cb);
 };
 
-extern int int_rsa_verify(int dtype, const unsigned char *m,
-                          unsigned int m_len, unsigned char *rm,
-                          size_t *prm_len, const unsigned char *sigbuf,
-                          size_t siglen, RSA *rsa);
 /* Macros to test if a pkey or ctx is for a PSS key */
 #define pkey_is_pss(pkey) (pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS)
 #define pkey_ctx_is_pss(ctx) (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS)
diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c
index 174271874a..7a298d5d93 100644
--- a/crypto/rsa/rsa_pmeth.c
+++ b/crypto/rsa/rsa_pmeth.c
@@ -25,6 +25,7 @@
 #include <openssl/x509v3.h>
 #include <openssl/cms.h>
 #include "crypto/evp.h"
+#include "crypto/rsa.h"
 #include "rsa_local.h"
 
 /* RSA pkey context structure */
diff --git a/crypto/rsa/rsa_sign.c b/crypto/rsa/rsa_sign.c
index 31b8ed11fa..e9c4c55398 100644
--- a/crypto/rsa/rsa_sign.c
+++ b/crypto/rsa/rsa_sign.c
@@ -23,13 +23,20 @@
 #ifndef OPENSSL_NO_MD2
 # include <openssl/md2.h> /* uses MD2_DIGEST_LENGTH */
 #endif
+#ifndef OPENSSL_NO_MD4
+# include <openssl/md4.h> /* uses MD4_DIGEST_LENGTH */
+#endif
 #ifndef OPENSSL_NO_MD5
 # include <openssl/md5.h> /* uses MD5_DIGEST_LENGTH */
 #endif
 #ifndef OPENSSL_NO_MDC2
 # include <openssl/mdc2.h> /* uses MDC2_DIGEST_LENGTH */
 #endif
+#ifndef OPENSSL_NO_RMD160
+# include <openssl/ripemd.h> /* uses RIPEMD160_DIGEST_LENGTH */
+#endif
 #include <openssl/sha.h> /* uses SHA???_DIGEST_LENGTH */
+#include "crypto/rsa.h"
 #include "rsa_local.h"
 
 /*
@@ -76,7 +83,7 @@ static const unsigned char digestinfo_##name##_der[] = {                       \
       ASN1_OCTET_STRING, sz                                                    \
 };
 
-/* MD2 and MD5 OIDs are of the form: (1 2 840 113549 2 |n|) */
+/* MD2, MD4 and MD5 OIDs are of the form: (1 2 840 113549 2 |n|) */
 #define ENCODE_DIGESTINFO_MD(name, n, sz)                                      \
 static const unsigned char digestinfo_##name##_der[] = {                       \
     ASN1_SEQUENCE, 0x10 + sz,                                                  \
@@ -90,6 +97,9 @@ static const unsigned char digestinfo_##name##_der[] = {                       \
 # ifndef OPENSSL_NO_MD2
 ENCODE_DIGESTINFO_MD(md2, 0x02, MD2_DIGEST_LENGTH)
 # endif
+# ifndef OPENSSL_NO_MD4
+ENCODE_DIGESTINFO_MD(md4, 0x03, MD4_DIGEST_LENGTH)
+# endif
 # ifndef OPENSSL_NO_MD5
 ENCODE_DIGESTINFO_MD(md5, 0x05, MD5_DIGEST_LENGTH)
 # endif
@@ -103,6 +113,18 @@ static const unsigned char digestinfo_mdc2_der[] = {
       ASN1_OCTET_STRING, MDC2_DIGEST_LENGTH
 };
 # endif
+# ifndef OPENSSL_NO_RMD160
+/* RIPEMD160 (1 3 36 3 3 1 2) */
+static const unsigned char digestinfo_ripemd160_der[] = {
+    ASN1_SEQUENCE, 0x0c + RIPEMD160_DIGEST_LENGTH,
+      ASN1_SEQUENCE, 0x08,
+        ASN1_OID, 0x04, 1 * 40 + 3, 36, 3, 3, 1, 2,
+        ASN1_NULL, 0x00,
+      ASN1_OCTET_STRING, RIPEMD160_DIGEST_LENGTH
+};
+# endif
+#endif /* FIPS_MODE */
+
 /* SHA-1 (1 3 14 3 2 26) */
 static const unsigned char digestinfo_sha1_der[] = {
     ASN1_SEQUENCE, 0x0d + SHA_DIGEST_LENGTH,
@@ -112,8 +134,6 @@ static const unsigned char digestinfo_sha1_der[] = {
       ASN1_OCTET_STRING, SHA_DIGEST_LENGTH
 };
 
-#endif /* FIPS_MODE */
-
 ENCODE_DIGESTINFO_SHA(sha256, 0x01, SHA256_DIGEST_LENGTH)
 ENCODE_DIGESTINFO_SHA(sha384, 0x02, SHA384_DIGEST_LENGTH)
 ENCODE_DIGESTINFO_SHA(sha512, 0x03, SHA512_DIGEST_LENGTH)
@@ -130,9 +150,9 @@ ENCODE_DIGESTINFO_SHA(sha3_512, 0x0a, SHA512_DIGEST_LENGTH)
         *len = sizeof(digestinfo_##name##_der);                                \
         return digestinfo_##name##_der;
 
-static const unsigned char *digestinfo_encoding(int nid, size_t *len)
+const unsigned char *rsa_digestinfo_encoding(int md_nid, size_t *len)
 {
-    switch (nid) {
+    switch (md_nid) {
 #ifndef FIPS_MODE
 # ifndef OPENSSL_NO_MDC2
     MD_CASE(mdc2)
@@ -140,11 +160,17 @@ static const unsigned char *digestinfo_encoding(int nid, size_t *len)
 # ifndef OPENSSL_NO_MD2
     MD_CASE(md2)
 # endif
+# ifndef OPENSSL_NO_MD4
+    MD_CASE(md4)
+# endif
 # ifndef OPENSSL_NO_MD5
     MD_CASE(md5)
 # endif
-    MD_CASE(sha1)
+# ifndef OPENSSL_NO_RMD160
+    MD_CASE(ripemd160)
+# endif
 #endif /* FIPS_MODE */
+    MD_CASE(sha1)
     MD_CASE(sha224)
     MD_CASE(sha256)
     MD_CASE(sha384)
@@ -183,7 +209,7 @@ static int encode_pkcs1(unsigned char **out, size_t *out_len, int type,
         RSAerr(RSA_F_ENCODE_PKCS1, RSA_R_UNKNOWN_ALGORITHM_TYPE);
         return 0;
     }
-    di_prefix = digestinfo_encoding(type, &di_prefix_len);
+    di_prefix = rsa_digestinfo_encoding(type, &di_prefix_len);
     if (di_prefix == NULL) {
         RSAerr(RSA_F_ENCODE_PKCS1,
                RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod
index 8334cfc110..ca1b1fa8b9 100644
--- a/doc/man3/EVP_PKEY_CTX_ctrl.pod
+++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod
@@ -94,8 +94,8 @@ EVP_PKEY_CTX_set1_id, EVP_PKEY_CTX_get1_id, EVP_PKEY_CTX_get1_id_len
 
  int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad);
  int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad);
- int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int len);
- int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *len);
+ int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int saltlen);
+ int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen);
  int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int mbits);
  int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *pubexp);
  int EVP_PKEY_CTX_set_rsa_keygen_primes(EVP_PKEY_CTX *ctx, int primes);
@@ -178,7 +178,7 @@ The parameters currently supported by the default provider are:
 
 Sets the DH padding mode.
 If B<OSSL_EXCHANGE_PARAM_PAD> is 1 then the  shared secret is padded with zeros
-up to the size of the DH prime B<p>.
+up to the size of the DH prime I<p>.
 If B<OSSL_EXCHANGE_PARAM_PAD> is zero (the default) then no padding is
 performed.
 
@@ -206,29 +206,29 @@ These functions must only be called after the EVP_PKEY_CTX has been initialised
 for use in an operation.
 
 The function EVP_PKEY_CTX_ctrl() sends a control operation to the context
-B<ctx>. The key type used must match B<keytype> if it is not -1. The parameter
-B<optype> is a mask indicating which operations the control can be applied to.
-The control command is indicated in B<cmd> and any additional arguments in
-B<p1> and B<p2>.
+I<ctx>. The key type used must match I<keytype> if it is not -1. The parameter
+I<optype> is a mask indicating which operations the control can be applied to.
+The control command is indicated in I<cmd> and any additional arguments in
+I<p1> and I<p2>.
 
-For B<cmd> = B<EVP_PKEY_CTRL_SET_MAC_KEY>, B<p1> is the length of the MAC key,
-and B<p2> is MAC key. This is used by Poly1305, SipHash, HMAC and CMAC.
+For I<cmd> = B<EVP_PKEY_CTRL_SET_MAC_KEY>, I<p1> is the length of the MAC key,
+and I<p2> is the MAC key. This is used by Poly1305, SipHash, HMAC and CMAC.
 
 Applications will not normally call EVP_PKEY_CTX_ctrl() directly but will
 instead call one of the algorithm specific macros below.
 
 The function EVP_PKEY_CTX_ctrl_uint64() is a wrapper that directly passes a
-uint64 value as B<p2> to EVP_PKEY_CTX_ctrl().
+uint64 value as I<p2> to EVP_PKEY_CTX_ctrl().
 
 The function EVP_PKEY_CTX_ctrl_str() allows an application to send an algorithm
-specific control operation to a context B<ctx> in string form. This is
+specific control operation to a context I<ctx> in string form. This is
 intended to be used for options specified on the command line or in text
 files. The commands supported are documented in the openssl utility
-command line pages for the option B<-pkeyopt> which is supported by the
-B<pkeyutl>, B<genpkey> and B<req> commands.
+command line pages for the option I<-pkeyopt> which is supported by the
+I<pkeyutl>, I<genpkey> and I<req> commands.
 
 The function EVP_PKEY_CTX_md() sends a message digest control operation
-to the context B<ctx>. The message digest is specified by its name B<md>.
+to the context I<ctx>. The message digest is specified by its name I<md>.
 
 The EVP_PKEY_CTX_set_signature_md() function sets the message digest type used
 in a signature. It can be used in the RSA, DSA and ECDSA algorithms.
@@ -251,8 +251,8 @@ supported by the L<EVP_PKEY_new_raw_private_key(3)> function.
 
 =head2 RSA parameters
 
-The EVP_PKEY_CTX_set_rsa_padding() function sets the RSA padding mode for B<ctx>.
-The B<pad> parameter can take the value B<RSA_PKCS1_PADDING> for PKCS#1
+The EVP_PKEY_CTX_set_rsa_padding() function sets the RSA padding mode for I<ctx>.
+The I<pad> parameter can take the value B<RSA_PKCS1_PADDING> for PKCS#1
 padding, B<RSA_SSLV23_PADDING> for SSLv23 padding, B<RSA_NO_PADDING> for
 no padding, B<RSA_PKCS1_OAEP_PADDING> for OAEP padding (encrypt and
 decrypt only), B<RSA_X931_PADDING> for X9.31 padding (signature operations
@@ -270,45 +270,61 @@ padding for RSA the algorithm identifier byte is added or checked and removed
 if this control is called. If it is not called then the first byte of the plaintext
 buffer is expected to be the algorithm identifier byte.
 
-The EVP_PKEY_CTX_get_rsa_padding() function gets the RSA padding mode for B<ctx>.
+The EVP_PKEY_CTX_get_rsa_padding() function gets the RSA padding mode for I<ctx>.
 
-The EVP_PKEY_CTX_set_rsa_pss_saltlen() macro sets the RSA PSS salt length to
-B<len>. As its name implies it is only supported for PSS padding. Three special
-values are supported: B<RSA_PSS_SALTLEN_DIGEST> sets the salt length to the
-digest length, B<RSA_PSS_SALTLEN_MAX> sets the salt length to the maximum
-permissible value. When verifying B<RSA_PSS_SALTLEN_AUTO> causes the salt length
-to be automatically determined based on the B<PSS> block structure. If this
-macro is not called maximum salt length is used when signing and auto detection
-when verifying is used by default.
+The EVP_PKEY_CTX_set_rsa_pss_saltlen() function sets the RSA PSS salt
+length to I<saltlen>. As its name implies it is only supported for PSS
+padding. If this function is not called then the maximum salt length
+is used when signing and auto detection when verifying. Three special
+values are supported:
 
-The EVP_PKEY_CTX_get_rsa_pss_saltlen() macro gets the RSA PSS salt length
-for B<ctx>. The padding mode must have been set to B<RSA_PKCS1_PSS_PADDING>.
+=over 4
+
+=item B<RSA_PSS_SALTLEN_DIGEST>
+
+sets the salt length to the digest length.
+
+=item B<RSA_PSS_SALTLEN_MAX>
+
+sets the salt length to the maximum permissible value.
+
+=item B<RSA_PSS_SALTLEN_AUTO>
+
+causes the salt length to be automatically determined based on the
+B<PSS> block structure when verifying.  When signing, it has the same
+meaning as B<RSA_PSS_SALTLEN_MAX>.
+
+=back
+
+The EVP_PKEY_CTX_get_rsa_pss_saltlen() function gets the RSA PSS salt length
+for I<ctx>. The padding mode must already have been set to
+B<RSA_PKCS1_PSS_PADDING>.
 
 The EVP_PKEY_CTX_set_rsa_keygen_bits() macro sets the RSA key length for
-RSA key generation to B<bits>. If not specified 1024 bits is used.
+RSA key generation to I<bits>. If not specified 2048 bits is used.
 
 The EVP_PKEY_CTX_set_rsa_keygen_pubexp() macro sets the public exponent value
-for RSA key generation to B<pubexp>. Currently it should be an odd integer. The
-B<pubexp> pointer is used internally by this function so it should not be
+for RSA key generation to I<pubexp>. Currently it should be an odd integer. The
+I<pubexp> pointer is used internally by this function so it should not be
 modified or freed after the call. If not specified 65537 is used.
 
 The EVP_PKEY_CTX_set_rsa_keygen_primes() macro sets the number of primes for
-RSA key generation to B<primes>. If not specified 2 is used.
+RSA key generation to I<primes>. If not specified 2 is used.
 
 The EVP_PKEY_CTX_set_rsa_mgf1_md_name() function sets the MGF1 digest for RSA
-padding schemes to the digest named B<mdname>. If the RSA algorithm
+padding schemes to the digest named I<mdname>. If the RSA algorithm
 implementation for the selected provider supports it then the digest will be
-fetched using the properties B<mdprops>. If not explicitly set the signing
+fetched using the properties I<mdprops>. If not explicitly set the signing
 digest is used. The padding mode must have been set to B<RSA_PKCS1_OAEP_PADDING>
 or B<RSA_PKCS1_PSS_PADDING>.
 
 The EVP_PKEY_CTX_set_rsa_mgf1_md() function does the same as
 EVP_PKEY_CTX_set_rsa_mgf1_md_name() except that the name of the digest is
-inferred from the supplied B<md> and it is not possible to specify any
+inferred from the supplied I<md> and it is not possible to specify any
 properties.
 
 The EVP_PKEY_CTX_get_rsa_mgf1_md_name() function gets the name of the MGF1
-digest algorithm for B<ctx>. If not explicitly set the signing digest is used.
+digest algorithm for I<ctx>. If not explicitly set the signing digest is used.
 The padding mode must have been set to B<RSA_PKCS1_OAEP_PADDING> or
 B<RSA_PKCS1_PSS_PADDING>.
 
@@ -319,19 +335,19 @@ returned. The EVP_MD object may be NULL if the digest is not one of these (such
 as a digest only implemented in a third party provider).
 
 The EVP_PKEY_CTX_set_rsa_oaep_md_name() function sets the message digest type
-used in RSA OAEP to the digest named B<mdname>.  If the RSA algorithm
+used in RSA OAEP to the digest named I<mdname>.  If the RSA algorithm
 implementation for the selected provider supports it then the digest will be
-fetched using the properties B<mdprops>. The padding mode must have been set to
+fetched using the properties I<mdprops>. The padding mode must have been set to
 B<RSA_PKCS1_OAEP_PADDING>.
 
 The EVP_PKEY_CTX_set_rsa_oaep_md() function does the same as
 EVP_PKEY_CTX_set_rsa_oaep_md_name() except that the name of the digest is
-inferred from the supplied B<md> and it is not possible to specify any
+inferred from the supplied I<md> and it is not possible to specify any
 properties.
 
 The EVP_PKEY_CTX_get_rsa_oaep_md_name() function gets the message digest
-algorithm name used in RSA OAEP and stores it in the buffer B<name> which is of
-size B<namelen>. The padding mode must have been set to
+algorithm name used in RSA OAEP and stores it in the buffer I<name> which is of
+size I<namelen>. The padding mode must have been set to
 B<RSA_PKCS1_OAEP_PADDING>. The buffer should be sufficiently large for any
 expected digest algorithm names or the function will fail.
 
@@ -342,13 +358,13 @@ returned. The EVP_MD object may be NULL if the digest is not one of these (such
 as a digest only implemented in a third party provider).
 
 The EVP_PKEY_CTX_set0_rsa_oaep_label() function sets the RSA OAEP label to
-B<label> and its length to B<len>. If B<label> is NULL or B<len> is 0,
+I<label> and its length to I<len>. If I<label> is NULL or I<len> is 0,
 the label is cleared. The library takes ownership of the label so the
-caller should not free the original memory pointed to by B<label>.
+caller should not free the original memory pointed to by I<label>.
 The padding mode must have been set to B<RSA_PKCS1_OAEP_PADDING>.
 
 The EVP_PKEY_CTX_get0_rsa_oaep_label() function gets the RSA OAEP label to
-B<label>. The return value is the label length. The padding mode
+I<label>. The return value is the label length. The padding mode
 must have been set to B<RSA_PKCS1_OAEP_PADDING>. The resulting pointer is owned
 by the library and should not be freed by the caller.
 
@@ -374,31 +390,31 @@ negotiated protocol version. Otherwise it should be left unset.
 =head2 DSA parameters
 
 The EVP_PKEY_CTX_set_dsa_paramgen_bits() macro sets the number of bits used
-for DSA parameter generation to B<nbits>. If not specified, 1024 is used.
+for DSA parameter generation to I<nbits>. If not specified, 2048 is used.
 
 The EVP_PKEY_CTX_set_dsa_paramgen_q_bits() macro sets the number of bits in the
-subprime parameter B<q> for DSA parameter generation to B<qbits>. If not
-specified, 160 is used. If a digest function is specified below, this parameter
-is ignored and instead, the number of bits in B<q> matches the size of the
+subprime parameter I<q> for DSA parameter generation to I<qbits>. If not
+specified, 224 is used. If a digest function is specified below, this parameter
+is ignored and instead, the number of bits in I<q> matches the size of the
 digest.
 
 The EVP_PKEY_CTX_set_dsa_paramgen_md() macro sets the digest function used for
-DSA parameter generation to B<md>. If not specified, one of SHA-1, SHA-224, or
-SHA-256 is selected to match the bit length of B<q> above.
+DSA parameter generation to I<md>. If not specified, one of SHA-1, SHA-224, or
+SHA-256 is selected to match the bit length of I<q> above.
 
 =head2 DH parameters
 
 The EVP_PKEY_CTX_set_dh_paramgen_prime_len() macro sets the length of the DH
-prime parameter B<p> for DH parameter generation. If this macro is not called
+prime parameter I<p> for DH parameter generation. If this macro is not called
 then 2048 is used. Only accepts lengths greater than or equal to 256.
 
 The EVP_PKEY_CTX_set_dh_paramgen_subprime_len() macro sets the length of the DH
-optional subprime parameter B<q> for DH parameter generation. The default is
+optional subprime parameter I<q> for DH parameter generation. The default is
 256 if the prime is at least 2048 bits long or 160 otherwise. The DH
 paramgen type must have been set to B<DH_PARAMGEN_TYPE_FIPS_186_2> or
 B<DH_PARAMGEN_TYPE_FIPS_186_4>.
 
-The EVP_PKEY_CTX_set_dh_paramgen_generator() macro sets DH generator to B<gen>
+The EVP_PKEY_CTX_set_dh_paramgen_generator() macro sets DH generator to I<gen>
 for DH parameter generation. If not specified 2 is used.
 
 The EVP_PKEY_CTX_set_dh_paramgen_type() macro sets the key type for DH
@@ -423,12 +439,12 @@ FIPS186-4 FFC parameter generator.
 The default is B<DH_PARAMGEN_TYPE_GENERATOR>.
 
 The EVP_PKEY_CTX_set_dh_pad() function sets the DH padding mode.
-If B<pad> is 1 the shared secret is padded with zeros up to the size of the DH
-prime B<p>.
-If B<pad> is zero (the default) then no padding is performed.
+If I<pad> is 1 the shared secret is padded with zeros up to the size of the DH
+prime I<p>.
+If I<pad> is zero (the default) then no padding is performed.
 
 EVP_PKEY_CTX_set_dh_nid() sets the DH parameters to values corresponding to
-B<nid> as defined in RFC7919 or RFC3526. The B<nid> parameter must be
+I<nid> as defined in RFC7919 or RFC3526. The I<nid> parameter must be
 B<NID_ffdhe2048>, B<NID_ffdhe3072>, B<NID_ffdhe4096>, B<NID_ffdhe6144>,
 B<NID_ffdhe8192>, B<NID_modp_1536>, B<NID_modp_2048>, B<NID_modp_3072>,
 B<NID_modp_4096>, B<NID_modp_6144>, B<NID_modp_8192> or B<NID_undef> to clear
@@ -437,74 +453,74 @@ The nid parameter and the rfc5114 parameter are mutually exclusive.
 
 The EVP_PKEY_CTX_set_dh_rfc5114() and EVP_PKEY_CTX_set_dhx_rfc5114() macros are
 synonymous. They set the DH parameters to the values defined in RFC5114. The
-B<rfc5114> parameter must be 1, 2 or 3 corresponding to RFC5114 sections
+I<rfc5114> parameter must be 1, 2 or 3 corresponding to RFC5114 sections
 2.1, 2.2 and 2.3. or 0 to clear the stored value. This macro can be called
-during parameter generation. The B<ctx> must have a key type of
+during parameter generation. The I<ctx> must have a key type of
 B<EVP_PKEY_DHX>.
 The rfc5114 parameter and the nid parameter are mutually exclusive.
 
 =head2 DH key derivation function parameters
 
-Note that all of the following functions require that the B<ctx> parameter has
+Note that all of the following functions require that the I<ctx> parameter has
 a private key type of B<EVP_PKEY_DHX>. When using key derivation, the output of
 EVP_PKEY_derive() is the output of the KDF instead of the DH shared secret.
 The KDF output is typically used as a Key Encryption Key (KEK) that in turn
 encrypts a Content Encryption Key (CEK).
 
 The EVP_PKEY_CTX_set_dh_kdf_type() macro sets the key derivation function type
-to B<kdf> for DH key derivation. Possible values are B<EVP_PKEY_DH_KDF_NONE>
+to I<kdf> for DH key derivation. Possible values are B<EVP_PKEY_DH_KDF_NONE>
 and B<EVP_PKEY_DH_KDF_X9_42> which uses the key derivation specified in RFC2631
 (based on the keying algorithm described in X9.42). When using key derivation,
-the B<kdf_oid>, B<kdf_md> and B<kdf_outlen> parameters must also be specified.
+the I<kdf_oid>, I<kdf_md> and I<kdf_outlen> parameters must also be specified.
 
 The EVP_PKEY_CTX_get_dh_kdf_type() macro gets the key derivation function type
-for B<ctx> used for DH key derivation. Possible values are B<EVP_PKEY_DH_KDF_NONE>
+for I<ctx> used for DH key derivation. Possible values are B<EVP_PKEY_DH_KDF_NONE>
 and B<EVP_PKEY_DH_KDF_X9_42>.
 
 The EVP_PKEY_CTX_set0_dh_kdf_oid() macro sets the key derivation function
-object identifier to B<oid> for DH key derivation. This OID should identify
+object identifier to I<oid> for DH key derivation. This OID should identify
 the algorithm to be used with the Content Encryption Key.
 The library takes ownership of the object identifier so the caller should not
-free the original memory pointed to by B<oid>.
+free the original memory pointed to by I<oid>.
 
 The EVP_PKEY_CTX_get0_dh_kdf_oid() macro gets the key derivation function oid
-for B<ctx> used for DH key derivation. The resulting pointer is owned by the
+for I<ctx> used for DH key derivation. The resulting pointer is owned by the
 library and should not be freed by the caller.
 
 The EVP_PKEY_CTX_set_dh_kdf_md() macro sets the key derivation function
-message digest to B<md> for DH key derivation. Note that RFC2631 specifies
+message digest to I<md> for DH key derivation. Note that RFC2631 specifies
 that this digest should be SHA1 but OpenSSL tolerates other digests.
 
 The EVP_PKEY_CTX_get_dh_kdf_md() macro gets the key derivation function
-message digest for B<ctx> used for DH key derivation.
+message digest for I<ctx> used for DH key derivation.
 
 The EVP_PKEY_CTX_set_dh_kdf_outlen() macro sets the key derivation function
-output length to B<len> for DH key derivation.
+output length to I<len> for DH key derivation.
 
 The EVP_PKEY_CTX_get_dh_kdf_outlen() macro gets the key derivation function
-output length for B<ctx> used for DH key derivation.
+output length for I<ctx> used for DH key derivation.
 
 The EVP_PKEY_CTX_set0_dh_kdf_ukm() macro sets the user key material to
-B<ukm> and its length to B<len> for DH key derivation. This parameter is optional
+I<ukm> and its length to I<len> for DH key derivation. This parameter is optional
 and corresponds to the partyAInfo field in RFC2631 terms. The specification
 requires that it is 512 bits long but this is not enforced by OpenSSL.
 The library takes ownership of the user key material so the caller should not
-free the original memory pointed to by B<ukm>.
+free the original memory pointed to by I<ukm>.
 
-The EVP_PKEY_CTX_get0_dh_kdf_ukm() macro gets the user key material for B<ctx>.
+The EVP_PKEY_CTX_get0_dh_kdf_ukm() macro gets the user key material for I<ctx>.
 The return value is the user key material length. The resulting pointer is owned
 by the library and should not be freed by the caller.
 
 =head2 EC parameters
 
 The EVP_PKEY_CTX_set_ec_paramgen_curve_nid() sets the EC curve for EC parameter
-generation to B<nid>. For EC parameter generation this macro must be called
+generation to I<nid>. For EC parameter generation this macro must be called
 or an error occurs because there is no default curve.
 This function can also be called to set the curve explicitly when
 generating an EC key.
 
 The EVP_PKEY_CTX_set_ec_param_enc() macro sets the EC parameter encoding to
-B<param_enc> when generating EC parameters or an EC key. The encoding can be
+I<param_enc> when generating EC parameters or an EC key. The encoding can be
 B<OPENSSL_EC_EXPLICIT_CURVE> for explicit parameters (the default in versions
 of OpenSSL before 1.1.0) or B<OPENSSL_EC_NAMED_CURVE> to use named curve form.
 For maximum compatibility the named curve form should be used. Note: the
@@ -514,45 +530,45 @@ versions should use 0 instead.
 =head2 ECDH parameters
 
 The EVP_PKEY_CTX_set_ecdh_cofactor_mode() macro sets the cofactor mode to
-B<cofactor_mode> for ECDH key derivation. Possible values are 1 to enable
+I<cofactor_mode> for ECDH key derivation. Possible values are 1 to enable
 cofactor key derivation, 0 to disable it and -1 to clear the stored cofactor
 mode and fallback to the private key cofactor mode.
 
 The EVP_PKEY_CTX_get_ecdh_cofactor_mode() macro returns the cofactor mode for
-B<ctx> used for ECDH key derivation. Possible values are 1 when cofactor key
+I<ctx> used for ECDH key derivation. Possible values are 1 when cofactor key
 derivation is enabled and 0 otherwise.
 
 =head2 ECDH key derivation function parameters
 
 The EVP_PKEY_CTX_set_ecdh_kdf_type() macro sets the key derivation function type
-to B<kdf> for ECDH key derivation. Possible values are B<EVP_PKEY_ECDH_KDF_NONE>
+to I<kdf> for ECDH key derivation. Possible values are B<EVP_PKEY_ECDH_KDF_NONE>
 and B<EVP_PKEY_ECDH_KDF_X9_63> which uses the key derivation specified in X9.63.
-When using key derivation, the B<kdf_md> and B<kdf_outlen> parameters must
+When using key derivation, the I<kdf_md> and I<kdf_outlen> parameters must
 also be specified.
 
 The EVP_PKEY_CTX_get_ecdh_kdf_type() macro returns the key derivation function
-type for B<ctx> used for ECDH key derivation. Possible values are
+type for I<ctx> used for ECDH key derivation. Possible values are
 B<EVP_PKEY_ECDH_KDF_NONE> and B<EVP_PKEY_ECDH_KDF_X9_63>.
 
 The EVP_PKEY_CTX_set_ecdh_kdf_md() macro sets the key derivation function
-message digest to B<md> for ECDH key derivation. Note that X9.63 specifies
+message digest to I<md> for ECDH key derivation. Note that X9.63 specifies
 that this digest should be SHA1 but OpenSSL tolerates other digests.
 
 The EVP_PKEY_CTX_get_ecdh_kdf_md() macro gets the key derivation function
-message digest for B<ctx> used for ECDH key derivation.
+message digest for I<ctx> used for ECDH key derivation.
 
 The EVP_PKEY_CTX_set_ecdh_kdf_outlen() macro sets the key derivation function
-output length to B<len> for ECDH key derivation.
+output length to I<len> for ECDH key derivation.
 
 The EVP_PKEY_CTX_get_ecdh_kdf_outlen() macro gets the key derivation function
-output length for B<ctx> used for ECDH key derivation.
+output length for I<ctx> used for ECDH key derivation.
 
-The EVP_PKEY_CTX_set0_ecdh_kdf_ukm() macro sets the user key material to B<ukm>
+The EVP_PKEY_CTX_set0_ecdh_kdf_ukm() macro sets the user key material to I<ukm>
 for ECDH key derivation. This parameter is optional and corresponds to the
 shared info in X9.63 terms. The library takes ownership of the user key material
-so the caller should not free the original memory pointed to by B<ukm>.
+so the caller should not free the original memory pointed to by I<ukm>.
 
-The EVP_PKEY_CTX_get0_ecdh_kdf_ukm() macro gets the user key material for B<ctx>.
+The EVP_PKEY_CTX_get0_ecdh_kdf_ukm() macro gets the user key material for I<ctx>.
 The return value is the user key material length. The resulting pointer is owned
 by the library and should not be freed by the caller.
 
@@ -560,14 +576,14 @@ by the library and should not be freed by the caller.
 
 The EVP_PKEY_CTX_set1_id(), EVP_PKEY_CTX_get1_id() and EVP_PKEY_CTX_get1_id_len()
 macros are used to manipulate the special identifier field for specific signature
-algorithms such as SM2. The EVP_PKEY_CTX_set1_id() sets an ID pointed by B<id> with
-the length B<id_len> to the library. The library takes a copy of the id so that
-the caller can safely free the original memory pointed to by B<id>. The
+algorithms such as SM2. The EVP_PKEY_CTX_set1_id() sets an ID pointed by I<id> with
+the length I<id_len> to the library. The library takes a copy of the id so that
+the caller can safely free the original memory pointed to by I<id>. The
 EVP_PKEY_CTX_get1_id_len() macro returns the length of the ID set via a previous
 call to EVP_PKEY_CTX_set1_id(). The length is usually used to allocate adequate
 memory for further calls to EVP_PKEY_CTX_get1_id(). The EVP_PKEY_CTX_get1_id()
-macro returns the previously set ID value to caller in B<id>. The caller should
-allocate adequate memory space for the B<id> before calling EVP_PKEY_CTX_get1_id().
+macro returns the previously set ID value to caller in I<id>. The caller should
+allocate adequate memory space for the I<id> before calling EVP_PKEY_CTX_get1_id().
 
 =head1 RETURN VALUES
 
@@ -598,8 +614,9 @@ EVP_PKEY_CTX_set_dh_pad(), EVP_PKEY_CTX_set_rsa_padding(),
 EVP_PKEY_CTX_get_rsa_padding(), EVP_PKEY_CTX_get_rsa_mgf1_md(),
 EVP_PKEY_CTX_set_rsa_mgf1_md(), EVP_PKEY_CTX_set_rsa_oaep_md(),
 EVP_PKEY_CTX_get_rsa_oaep_md(), EVP_PKEY_CTX_set0_rsa_oaep_label(),
-EVP_PKEY_CTX_get0_rsa_oaep_label() were macros in OpenSSL 1.1.1 and below. From
-OpenSSL 3.0 they are functions.
+EVP_PKEY_CTX_get0_rsa_oaep_label(), EVP_PKEY_CTX_set_rsa_pss_saltlen(),
+EVP_PKEY_CTX_get_rsa_pss_saltlen(), were macros in OpenSSL 1.1.1 and below.
+From OpenSSL 3.0 they are functions.
 
 EVP_PKEY_CTX_get_rsa_oaep_md_name(), EVP_PKEY_CTX_get_rsa_mgf1_md_name(),
 EVP_PKEY_CTX_set_rsa_mgf1_md_name() and EVP_PKEY_CTX_set_rsa_oaep_md_name() were
diff --git a/include/crypto/rsa.h b/include/crypto/rsa.h
index 97fd0f7aad..51ac0148af 100644
--- a/include/crypto/rsa.h
+++ b/include/crypto/rsa.h
@@ -29,4 +29,12 @@ int rsa_validate_public(const RSA *key);
 int rsa_validate_private(const RSA *key);
 int rsa_validate_pairwise(const RSA *key);
 
+int int_rsa_verify(int dtype, const unsigned char *m,
+                   unsigned int m_len, unsigned char *rm,
+                   size_t *prm_len, const unsigned char *sigbuf,
+                   size_t siglen, RSA *rsa);
+
+const unsigned char *rsa_digestinfo_encoding(int md_nid, size_t *len);
+const unsigned char *rsa_algorithmidentifier_encoding(int md_nid, size_t *len);
+
 #endif
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
index b2befd8bb5..5e3a13a34b 100644
--- a/include/openssl/core_names.h
+++ b/include/openssl/core_names.h
@@ -88,11 +88,16 @@ extern "C" {
 
 /* Known DIGEST names (not a complete list) */
 #define OSSL_DIGEST_NAME_MD5            "MD5"
+#define OSSL_DIGEST_NAME_MD5_SHA1       "MD5-SHA1"
 #define OSSL_DIGEST_NAME_SHA1           "SHA1"
 #define OSSL_DIGEST_NAME_SHA2_224       "SHA2-224"
 #define OSSL_DIGEST_NAME_SHA2_256       "SHA2-256"
 #define OSSL_DIGEST_NAME_SHA2_384       "SHA2-384"
 #define OSSL_DIGEST_NAME_SHA2_512       "SHA2-512"
+#define OSSL_DIGEST_NAME_MD2            "MD2"
+#define OSSL_DIGEST_NAME_MD4            "MD4"
+#define OSSL_DIGEST_NAME_MDC2           "MDC2"
+#define OSSL_DIGEST_NAME_RIPEMD160      "RIPEMD160"
 #define OSSL_DIGEST_NAME_SHA3_224       "SHA3-224"
 #define OSSL_DIGEST_NAME_SHA3_256       "SHA3-256"
 #define OSSL_DIGEST_NAME_SHA3_384       "SHA3-384"
@@ -171,6 +176,14 @@ extern "C" {
 #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 */
+#define OSSL_PKEY_PARAM_PAD_MODE            "pad-mode"
+#define OSSL_PKEY_PARAM_DIGEST              OSSL_ALG_PARAM_DIGEST
+#define OSSL_PKEY_PARAM_PROPERTIES          OSSL_ALG_PARAM_PROPERTIES
+#define OSSL_PKEY_PARAM_DIGEST_SIZE         "digest-size"
+#define OSSL_PKEY_PARAM_MGF1_DIGEST         "mgf1-digest"
+#define OSSL_PKEY_PARAM_MGF1_PROPERTIES     "mgf1-properties"
+
+/* Diffie-Hellman/DSA public/private key */
 #define OSSL_PKEY_PARAM_PUB_KEY             "pub"
 #define OSSL_PKEY_PARAM_PRIV_KEY            "priv"
 
@@ -234,15 +247,22 @@ extern "C" {
 
 /* Signature parameters */
 #define OSSL_SIGNATURE_PARAM_ALGORITHM_ID       "algorithm-id"
+#define OSSL_SIGNATURE_PARAM_PAD_MODE           OSSL_PKEY_PARAM_PAD_MODE
 #define OSSL_SIGNATURE_PARAM_DIGEST             OSSL_PKEY_PARAM_DIGEST
 #define OSSL_SIGNATURE_PARAM_PROPERTIES         OSSL_PKEY_PARAM_PROPERTIES
+#define OSSL_SIGNATURE_PARAM_PSS_SALTLEN        "pss-saltlen"
+#define OSSL_SIGNATURE_PARAM_MGF1_DIGEST        OSSL_PKEY_PARAM_MGF1_DIGEST
+#define OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES    \
+    OSSL_PKEY_PARAM_MGF1_PROPERTIES
 
 /* Asym cipher parameters */
-#define OSSL_ASYM_CIPHER_PARAM_PAD_MODE                 "pad-mode"
+#define OSSL_ASYM_CIPHER_PARAM_PAD_MODE                 OSSL_PKEY_PARAM_PAD_MODE
+#define OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST              \
+    OSSL_PKEY_PARAM_MGF1_DIGEST
+#define OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS        \
+    OSSL_PKEY_PARAM_MGF1_PROPERTIES
 #define OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST              OSSL_ALG_PARAM_DIGEST
 #define OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS        "digest-props"
-#define OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST              "mgf1-digest"
-#define OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS        "mgf1-digest-props"
 #define OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL               "oaep-label"
 #define OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL_LEN           "oaep-label-len"
 #define OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION       "tls-client-version"
diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h
index 12ee01192e..1f0687df24 100644
--- a/include/openssl/rsa.h
+++ b/include/openssl/rsa.h
@@ -108,9 +108,9 @@ extern "C" {
 int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int pad_mode);
 int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad_mode);
 
-#  define EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, len) \
-        RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \
-                          EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL)
+int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int saltlen);
+int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *saltlen);
+
 /* Salt length matches digest */
 #  define RSA_PSS_SALTLEN_DIGEST -1
 /* Verify only: auto detect salt length */
@@ -124,10 +124,6 @@ int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *pad_mode);
         EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \
                           EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL)
 
-#  define EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, plen) \
-        RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \
-                          EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, plen)
-
 #  define EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) \
         RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
                           EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL)
diff --git a/providers/common/include/prov/providercommonerr.h b/providers/common/include/prov/providercommonerr.h
index 6586d65626..19ecab1f0f 100644
--- a/providers/common/include/prov/providercommonerr.h
+++ b/providers/common/include/prov/providercommonerr.h
@@ -50,6 +50,7 @@ int ERR_load_PROV_strings(void);
  * PROV reason codes.
  */
 # define PROV_R_AES_KEY_SETUP_FAILED                      101
+# define PROV_R_ALGORITHM_MISMATCH                        173
 # define PROV_R_BAD_DECRYPT                               100
 # define PROV_R_BAD_ENCODING                              141
 # define PROV_R_BAD_LENGTH                                142
@@ -57,17 +58,20 @@ int ERR_load_PROV_strings(void);
 # define PROV_R_BN_ERROR                                  160
 # define PROV_R_BOTH_MODE_AND_MODE_INT                    127
 # define PROV_R_CIPHER_OPERATION_FAILED                   102
+# define PROV_R_DIGEST_NOT_ALLOWED                        174
 # define PROV_R_FAILED_DURING_DERIVATION                  164
 # define PROV_R_FAILED_TO_DECRYPT                         162
 # define PROV_R_FAILED_TO_GENERATE_KEY                    121
 # define PROV_R_FAILED_TO_GET_PARAMETER                   103
 # define PROV_R_FAILED_TO_SET_PARAMETER                   104
+# define PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE       165
 # define PROV_R_INAVLID_UKM_LENGTH                        146
 # define PROV_R_INVALID_AAD                               108
 # define PROV_R_INVALID_CONSTANT_LENGTH                   157
 # define PROV_R_INVALID_CUSTOM_LENGTH                     111
 # define PROV_R_INVALID_DATA                              115
 # define PROV_R_INVALID_DIGEST                            122
+# define PROV_R_INVALID_DIGEST_LENGTH                     166
 # define PROV_R_INVALID_ITERATION_COUNT                   123
 # define PROV_R_INVALID_IVLEN                             116
 # define PROV_R_INVALID_IV_LENGTH                         109
@@ -76,12 +80,17 @@ int ERR_load_PROV_strings(void);
 # define PROV_R_INVALID_KEY_LEN                           124
 # define PROV_R_INVALID_KEY_LENGTH                        105
 # define PROV_R_INVALID_MAC                               151
+# define PROV_R_INVALID_MGF1_MD                           167
 # define PROV_R_INVALID_MODE                              125
 # define PROV_R_INVALID_MODE_INT                          126
+# define PROV_R_INVALID_PADDING_MODE                      168
+# define PROV_R_INVALID_PSS_SALTLEN                       169
 # define PROV_R_INVALID_SALT_LENGTH                       112
 # define PROV_R_INVALID_SEED_LENGTH                       154
 # define PROV_R_INVALID_TAG                               110
 # define PROV_R_INVALID_TAGLEN                            118
+# define PROV_R_INVALID_X931_DIGEST                       170
+# define PROV_R_KEY_SIZE_TOO_SMALL                        171
 # define PROV_R_MISSING_CEK_ALG                           144
 # define PROV_R_MISSING_CIPHER                            155
 # define PROV_R_MISSING_CONSTANT                          156
@@ -99,6 +108,7 @@ int ERR_load_PROV_strings(void);
 # define PROV_R_NOT_XOF_OR_INVALID_LENGTH                 113
 # define PROV_R_NO_KEY_SET                                114
 # define PROV_R_OUTPUT_BUFFER_TOO_SMALL                   106
+# define PROV_R_PSS_SALTLEN_TOO_SMALL                     172
 # define PROV_R_READ_KEY                                  159
 # define PROV_R_TAG_NOTSET                                119
 # define PROV_R_TAG_NOT_NEEDED                            120
diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c
index 792697c810..f73f82351f 100644
--- a/providers/common/provider_err.c
+++ b/providers/common/provider_err.c
@@ -16,6 +16,8 @@
 static const ERR_STRING_DATA PROV_str_reasons[] = {
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_AES_KEY_SETUP_FAILED),
     "aes key setup failed"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ALGORITHM_MISMATCH),
+    "algorithm mismatch"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_DECRYPT), "bad decrypt"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_ENCODING), "bad encoding"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_LENGTH), "bad length"},
@@ -26,6 +28,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
     "both mode and mode int"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_CIPHER_OPERATION_FAILED),
     "cipher operation failed"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_DIGEST_NOT_ALLOWED),
+    "digest not allowed"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_DURING_DERIVATION),
     "failed during derivation"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_DECRYPT), "failed to decrypt"},
@@ -35,6 +39,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
     "failed to get parameter"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SET_PARAMETER),
     "failed to set parameter"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE),
+    "illegal or unsupported padding mode"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INAVLID_UKM_LENGTH),
     "inavlid ukm length"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_AAD), "invalid aad"},
@@ -44,6 +50,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
     "invalid custom length"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DATA), "invalid data"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST), "invalid digest"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST_LENGTH),
+    "invalid digest length"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_ITERATION_COUNT),
     "invalid iteration count"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_IVLEN), "invalid ivlen"},
@@ -54,14 +62,23 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY_LENGTH),
     "invalid key length"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MAC), "invalid mac"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MGF1_MD), "invalid mgf1 md"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MODE), "invalid mode"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MODE_INT), "invalid mode int"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_PADDING_MODE),
+    "invalid padding mode"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_PSS_SALTLEN),
+    "invalid pss saltlen"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_SALT_LENGTH),
     "invalid salt length"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_SEED_LENGTH),
     "invalid seed length"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAG), "invalid tag"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAGLEN), "invalid taglen"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_X931_DIGEST),
+    "invalid x931 digest"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_KEY_SIZE_TOO_SMALL),
+    "key size too small"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CEK_ALG), "missing cek alg"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CIPHER), "missing cipher"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CONSTANT), "missing constant"},
@@ -83,6 +100,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NO_KEY_SET), "no key set"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_OUTPUT_BUFFER_TOO_SMALL),
     "output buffer too small"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PSS_SALTLEN_TOO_SMALL),
+    "pss saltlen too small"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_READ_KEY), "read key"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOTSET), "tag notset"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOT_NEEDED), "tag not needed"},
diff --git a/providers/defltprov.c b/providers/defltprov.c
index 0b2390a291..5bebf6665d 100644
--- a/providers/defltprov.c
+++ b/providers/defltprov.c
@@ -384,6 +384,7 @@ static const OSSL_ALGORITHM deflt_signature[] = {
 #ifndef OPENSSL_NO_DSA
     { "DSA:dsaEncryption", "provider=default", dsa_signature_functions },
 #endif
+    { "RSA:rsaEncryption", "default=yes", rsa_signature_functions },
     { NULL, NULL, NULL }
 };
 
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h
index ec0507d86b..6d6a26d1e0 100644
--- a/providers/implementations/include/prov/implementations.h
+++ b/providers/implementations/include/prov/implementations.h
@@ -269,6 +269,7 @@ extern const OSSL_DISPATCH ecdh_keyexch_functions[];
 
 /* Signature */
 extern const OSSL_DISPATCH dsa_signature_functions[];
+extern const OSSL_DISPATCH rsa_signature_functions[];
 
 /* Asym Cipher */
 extern const OSSL_DISPATCH rsa_asym_cipher_functions[];
diff --git a/providers/implementations/signature/build.info b/providers/implementations/signature/build.info
index a9687fc929..22b55dcf54 100644
--- a/providers/implementations/signature/build.info
+++ b/providers/implementations/signature/build.info
@@ -2,9 +2,12 @@
 # switch each to the Legacy provider when needed.
 
 $DSA_GOAL=../../libimplementations.a
+$RSA_GOAL=../../libimplementations.a
 
 IF[{- !$disabled{dsa} -}]
   SOURCE[$DSA_GOAL]=dsa.c
 ENDIF
 
+SOURCE[$RSA_GOAL]=rsa.c
+
 
diff --git a/providers/implementations/signature/rsa.c b/providers/implementations/signature/rsa.c
new file mode 100644
index 0000000000..6b0f55a19a
--- /dev/null
+++ b/providers/implementations/signature/rsa.c
@@ -0,0 +1,1115 @@
+/*
+ * Copyright 2019 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#include "internal/cryptlib.h"
+#include "internal/nelem.h"
+#include "internal/sizes.h"
+#include "crypto/rsa.h"
+#include "prov/providercommonerr.h"
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+
+static OSSL_OP_signature_newctx_fn rsa_newctx;
+static OSSL_OP_signature_sign_init_fn rsa_signature_init;
+static OSSL_OP_signature_verify_init_fn rsa_signature_init;
+static OSSL_OP_signature_verify_recover_init_fn rsa_signature_init;
+static OSSL_OP_signature_sign_fn rsa_sign;
+static OSSL_OP_signature_verify_fn rsa_verify;
+static OSSL_OP_signature_verify_recover_fn rsa_verify_recover;
+static OSSL_OP_signature_digest_sign_init_fn rsa_digest_signverify_init;
+static OSSL_OP_signature_digest_sign_update_fn rsa_digest_signverify_update;
+static OSSL_OP_signature_digest_sign_final_fn rsa_digest_sign_final;
+static OSSL_OP_signature_digest_verify_init_fn rsa_digest_signverify_init;
+static OSSL_OP_signature_digest_verify_update_fn rsa_digest_signverify_update;
+static OSSL_OP_signature_digest_verify_final_fn rsa_digest_verify_final;
+static OSSL_OP_signature_freectx_fn rsa_freectx;
+static OSSL_OP_signature_dupctx_fn rsa_dupctx;
+static OSSL_OP_signature_get_ctx_params_fn rsa_get_ctx_params;
+static OSSL_OP_signature_gettable_ctx_params_fn rsa_gettable_ctx_params;
+static OSSL_OP_signature_set_ctx_params_fn rsa_set_ctx_params;
+static OSSL_OP_signature_settable_ctx_params_fn rsa_settable_ctx_params;
+static OSSL_OP_signature_get_ctx_md_params_fn rsa_get_ctx_md_params;
+static OSSL_OP_signature_gettable_ctx_md_params_fn rsa_gettable_ctx_md_params;
+static OSSL_OP_signature_set_ctx_md_params_fn rsa_set_ctx_md_params;
+static OSSL_OP_signature_settable_ctx_md_params_fn rsa_settable_ctx_md_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.
+ * We happen to know that our KEYMGMT simply passes RSA structures, so
+ * we use that here too.
+ */
+
+typedef struct {
+    OPENSSL_CTX *libctx;
+    RSA *rsa;
+
+    /*
+     * 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;
+
+    /* The Algorithm Identifier of the combined signature agorithm */
+    unsigned char aid[128];
+    size_t  aid_len;
+
+    /* main digest */
+    EVP_MD *md;
+    EVP_MD_CTX *mdctx;
+    int mdnid;
+    char mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */
+
+    /* RSA padding mode */
+    int pad_mode;
+    /* message digest for MGF1 */
+    EVP_MD *mgf1_md;
+    char mgf1_mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */
+    /* PSS salt length */
+    int saltlen;
+    /* Minimum salt length or -1 if no PSS parameter restriction */
+    int min_saltlen;
+
+    /* Temp buffer */
+    unsigned char *tbuf;
+
+} PROV_RSA_CTX;
+
+static size_t rsa_get_md_size(const PROV_RSA_CTX *prsactx)
+{
+    if (prsactx->md != NULL)
+        return EVP_MD_size(prsactx->md);
+    return 0;
+}
+
+static int rsa_get_md_nid(const EVP_MD *md)
+{
+    /*
+     * Because the RSA 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_md5,       OSSL_DIGEST_NAME_MD5       },
+        { NID_md5_sha1,  OSSL_DIGEST_NAME_MD5_SHA1  },
+        { NID_md2,       OSSL_DIGEST_NAME_MD2       },
+        { NID_md4,       OSSL_DIGEST_NAME_MD4       },
+        { NID_mdc2,      OSSL_DIGEST_NAME_MDC2      },
+        { NID_ripemd160, OSSL_DIGEST_NAME_RIPEMD160 },
+        { 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 rsa_check_padding(int mdnid, int padding)
+{
+    if (padding == RSA_NO_PADDING) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE);
+        return 0;
+    }
+
+    if (padding == RSA_X931_PADDING) {
+        if (RSA_X931_hash_id(mdnid) == -1) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_X931_DIGEST);
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+static void *rsa_newctx(void *provctx)
+{
+    PROV_RSA_CTX *prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX));
+
+    if (prsactx == NULL)
+        return NULL;
+
+    prsactx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
+    prsactx->flag_allow_md = 1;
+    return prsactx;
+}
+
+/* True if PSS parameters are restricted */
+#define rsa_pss_restricted(prsactx) (prsactx->min_saltlen != -1)
+
+static int rsa_signature_init(void *vprsactx, void *vrsa)
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+    if (prsactx == NULL || vrsa == NULL || !RSA_up_ref(vrsa))
+        return 0;
+
+    RSA_free(prsactx->rsa);
+    prsactx->rsa = vrsa;
+    if (RSA_get0_pss_params(prsactx->rsa) != NULL)
+        prsactx->pad_mode = RSA_PKCS1_PSS_PADDING;
+    else
+        prsactx->pad_mode = RSA_PKCS1_PADDING;
+    /* Maximum for sign, auto for verify */
+    prsactx->saltlen = RSA_PSS_SALTLEN_AUTO;
+    prsactx->min_saltlen = -1;
+
+    return 1;
+}
+
+static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname,
+                        const char *mdprops)
+{
+    if (mdname != NULL) {
+        EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
+        int md_nid = rsa_get_md_nid(md);
+        size_t algorithmidentifier_len = 0;
+        const unsigned char *algorithmidentifier = NULL;
+
+        if (md == NULL)
+            return 0;
+
+        if (!rsa_check_padding(md_nid, ctx->pad_mode)) {
+            EVP_MD_free(md);
+            return 0;
+        }
+
+        EVP_MD_CTX_free(ctx->mdctx);
+        EVP_MD_free(ctx->md);
+        ctx->md = NULL;
+        ctx->mdctx = NULL;
+        ctx->mdname[0] = '\0';
+        ctx->aid[0] = '\0';
+        ctx->aid_len = 0;
+
+        algorithmidentifier =
+            rsa_algorithmidentifier_encoding(md_nid, &algorithmidentifier_len);
+
+        ctx->md = md;
+        ctx->mdnid = md_nid;
+        OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname));
+        if (algorithmidentifier != NULL) {
+            memcpy(ctx->aid, algorithmidentifier, algorithmidentifier_len);
+            ctx->aid_len = algorithmidentifier_len;
+        }
+    }
+
+    return 1;
+}
+
+static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname,
+                             const char *props)
+{
+    if (ctx->mgf1_mdname[0] != '\0')
+        EVP_MD_free(ctx->mgf1_md);
+
+    if ((ctx->mgf1_md = EVP_MD_fetch(ctx->libctx, mdname, props)) == NULL)
+        return 0;
+    OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname));
+
+    return 1;
+}
+
+static int setup_tbuf(PROV_RSA_CTX *ctx)
+{
+    if (ctx->tbuf != NULL)
+        return 1;
+    if ((ctx->tbuf = OPENSSL_malloc(RSA_size(ctx->rsa))) == NULL) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    return 1;
+}
+
+static void clean_tbuf(PROV_RSA_CTX *ctx)
+{
+    if (ctx->tbuf != NULL)
+        OPENSSL_cleanse(ctx->tbuf, RSA_size(ctx->rsa));
+}
+
+static void free_tbuf(PROV_RSA_CTX *ctx)
+{
+    OPENSSL_clear_free(ctx->tbuf, RSA_size(ctx->rsa));
+    ctx->tbuf = NULL;
+}
+
+static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen,
+                    size_t sigsize, const unsigned char *tbs, size_t tbslen)
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+    int ret;
+    size_t rsasize = RSA_size(prsactx->rsa);
+    size_t mdsize = rsa_get_md_size(prsactx);
+
+    if (sig == NULL) {
+        *siglen = rsasize;
+        return 1;
+    }
+
+    if (sigsize < (size_t)rsasize)
+        return 0;
+
+    if (mdsize != 0) {
+        if (tbslen != mdsize) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
+            return 0;
+        }
+
+#ifndef FIPS_MODE
+        if (EVP_MD_is_a(prsactx->md, OSSL_DIGEST_NAME_MDC2)) {
+            unsigned int sltmp;
+
+            if (prsactx->pad_mode != RSA_PKCS1_PADDING) {
+                ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
+                               "only PKCS#1 padding supported with MDC2");
+                return 0;
+            }
+            ret = RSA_sign_ASN1_OCTET_STRING(0, tbs, tbslen, sig, &sltmp,
+                                             prsactx->rsa);
+
+            if (ret <= 0) {
+                ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
+                return 0;
+            }
+            ret = sltmp;
+            goto end;
+        }
+#endif
+
+        switch (prsactx->pad_mode) {
+        case RSA_X931_PADDING:
+            if ((size_t)RSA_size(prsactx->rsa) < tbslen + 1) {
+                ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL);
+                return 0;
+            }
+            if (!setup_tbuf(prsactx)) {
+                ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+                return 0;
+            }
+            memcpy(prsactx->tbuf, tbs, tbslen);
+            prsactx->tbuf[tbslen] = RSA_X931_hash_id(prsactx->mdnid);
+            ret = RSA_private_encrypt(tbslen + 1, prsactx->tbuf,
+                                      sig, prsactx->rsa, RSA_X931_PADDING);
+            clean_tbuf(prsactx);
+            break;
+
+        case RSA_PKCS1_PADDING:
+            {
+                unsigned int sltmp;
+
+                ret = RSA_sign(prsactx->mdnid, tbs, tbslen, sig, &sltmp,
+                               prsactx->rsa);
+                if (ret <= 0) {
+                    ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
+                    return 0;
+                }
+                ret = sltmp;
+            }
+            break;
+
+        case RSA_PKCS1_PSS_PADDING:
+            /* Check PSS restrictions */
+            if (rsa_pss_restricted(prsactx)) {
+                switch (prsactx->saltlen) {
+                case RSA_PSS_SALTLEN_DIGEST:
+                    if (prsactx->min_saltlen > EVP_MD_size(prsactx->md)) {
+                        ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL);
+                        return 0;
+                    }
+                    /* FALLTHRU */
+                default:
+                    if (prsactx->saltlen >= 0
+                        && prsactx->saltlen < prsactx->min_saltlen) {
+                        ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL);
+                        return 0;
+                    }
+                    break;
+                }
+            }
+            if (!setup_tbuf(prsactx))
+                return 0;
+            if (!RSA_padding_add_PKCS1_PSS_mgf1(prsactx->rsa,
+                                                prsactx->tbuf, tbs,
+                                                prsactx->md, prsactx->mgf1_md,
+                                                prsactx->saltlen)) {
+                ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
+                return 0;
+            }
+            ret = RSA_private_encrypt(RSA_size(prsactx->rsa), prsactx->tbuf,
+                                      sig, prsactx->rsa, RSA_NO_PADDING);
+            clean_tbuf(prsactx);
+            break;
+
+        default:
+            ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
+                           "Only X.931, PKCS#1 v1.5 or PSS padding allowed");
+            return 0;
+        }
+    } else {
+        ret = RSA_private_encrypt(tbslen, tbs, sig, prsactx->rsa,
+                                  prsactx->pad_mode);
+    }
+
+#ifndef FIPS_MODE
+ end:
+#endif
+    if (ret <= 0) {
+        ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
+        return 0;
+    }
+
+    *siglen = ret;
+    return 1;
+}
+
+static int rsa_verify_recover(void *vprsactx,
+                              unsigned char *rout,
+                              size_t *routlen,
+                              size_t routsize,
+                              const unsigned char *sig,
+                              size_t siglen)
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+    int ret;
+
+    if (rout == NULL) {
+        *routlen = RSA_size(prsactx->rsa);
+        return 1;
+    }
+
+    if (prsactx->md != NULL) {
+        switch (prsactx->pad_mode) {
+        case RSA_X931_PADDING:
+            if (!setup_tbuf(prsactx))
+                return 0;
+            ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa,
+                                     RSA_X931_PADDING);
+            if (ret < 1) {
+                ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
+                return 0;
+            }
+            ret--;
+            if (prsactx->tbuf[ret] != RSA_X931_hash_id(prsactx->mdnid)) {
+                ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
+                return 0;
+            }
+            if (ret != EVP_MD_size(prsactx->md)) {
+                ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH,
+                               "Should be %d, but got %d",
+                               EVP_MD_size(prsactx->md), ret);
+                return 0;
+            }
+
+            *routlen = ret;
+            if (routsize < (size_t)ret) {
+                ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+                return 0;
+            }
+            memcpy(rout, prsactx->tbuf, ret);
+            break;
+
+        case RSA_PKCS1_PADDING:
+            {
+                size_t sltmp;
+
+                ret = int_rsa_verify(prsactx->mdnid, NULL, 0, rout, &sltmp,
+                                     sig, siglen, prsactx->rsa);
+                if (ret <= 0) {
+                    ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
+                    return 0;
+                }
+                ret = sltmp;
+            }
+            break;
+
+        default:
+            ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
+                           "Only X.931 or PKCS#1 v1.5 padding allowed");
+            return 0;
+        }
+    } else {
+        ret = RSA_public_decrypt(siglen, sig, rout, prsactx->rsa,
+                                 prsactx->pad_mode);
+        if (ret < 0) {
+            ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
+            return 0;
+        }
+    }
+    *routlen = ret;
+    return 1;
+}
+
+static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen,
+                      const unsigned char *tbs, size_t tbslen)
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+    size_t rslen;
+
+    if (prsactx->md != NULL) {
+        switch (prsactx->pad_mode) {
+        case RSA_PKCS1_PADDING:
+            if (!RSA_verify(prsactx->mdnid, tbs, tbslen, sig, siglen,
+                            prsactx->rsa)) {
+                ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
+                return 0;
+            }
+            return 1;
+        case RSA_X931_PADDING:
+            if (rsa_verify_recover(prsactx, NULL, &rslen, 0, sig, siglen) <= 0)
+                return 0;
+            break;
+        case RSA_PKCS1_PSS_PADDING:
+            {
+                int ret;
+                size_t mdsize;
+
+                /* Check PSS restrictions */
+                if (rsa_pss_restricted(prsactx)) {
+                    switch (prsactx->saltlen) {
+                    case RSA_PSS_SALTLEN_AUTO:
+                        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PSS_SALTLEN);
+                        return 0;
+                    case RSA_PSS_SALTLEN_DIGEST:
+                        if (prsactx->min_saltlen > EVP_MD_size(prsactx->md)) {
+                            ERR_raise(ERR_LIB_PROV,
+                                      PROV_R_PSS_SALTLEN_TOO_SMALL);
+                            return 0;
+                        }
+                        /* FALLTHRU */
+                    default:
+                        if (prsactx->saltlen >= 0
+                            && prsactx->saltlen < prsactx->min_saltlen) {
+                            ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL);
+                            return 0;
+                        }
+                        break;
+                    }
+                }
+
+                /*
+                 * We need to check this for the RSA_verify_PKCS1_PSS_mgf1()
+                 * call
+                 */
+                mdsize = rsa_get_md_size(prsactx);
+                if (tbslen != mdsize) {
+                    ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH,
+                                   "Should be %d, but got %d",
+                                   mdsize, tbslen);
+                    return 0;
+                }
+
+                if (!setup_tbuf(prsactx))
+                    return 0;
+                ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf,
+                                         prsactx->rsa, RSA_NO_PADDING);
+                if (ret <= 0) {
+                    ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
+                    return 0;
+                }
+                ret = RSA_verify_PKCS1_PSS_mgf1(prsactx->rsa, tbs,
+                                                prsactx->md, prsactx->mgf1_md,
+                                                prsactx->tbuf,
+                                                prsactx->saltlen);
+                if (ret <= 0) {
+                    ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
+                    return 0;
+                }
+                return 1;
+            }
+        default:
+            ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
+                           "Only X.931, PKCS#1 v1.5 or PSS padding allowed");
+            return 0;
+        }
+    } else {
+        if (!setup_tbuf(prsactx))
+            return 0;
+        rslen = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa,
+                                   prsactx->pad_mode);
+        if (rslen == 0) {
+            ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
+            return 0;
+        }
+    }
+
+    if ((rslen != tbslen) || memcmp(tbs, prsactx->tbuf, rslen))
+        return 0;
+
+    return 1;
+}
+
+static int rsa_digest_signverify_init(void *vprsactx, const char *mdname,
+                                      const char *props, void *vrsa)
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+    prsactx->flag_allow_md = 0;
+    if (!rsa_signature_init(vprsactx, vrsa)
+        || !rsa_setup_md(prsactx, mdname, props))
+        return 0;
+
+    prsactx->mdctx = EVP_MD_CTX_new();
+    if (prsactx->mdctx == NULL)
+        goto error;
+
+    if (!EVP_DigestInit_ex(prsactx->mdctx, prsactx->md, NULL))
+        goto error;
+
+    return 1;
+
+ error:
+    EVP_MD_CTX_free(prsactx->mdctx);
+    EVP_MD_free(prsactx->md);
+    prsactx->mdctx = NULL;
+    prsactx->md = NULL;
+    return 0;
+}
+
+int rsa_digest_signverify_update(void *vprsactx, const unsigned char *data,
+                                 size_t datalen)
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+    if (prsactx == NULL || prsactx->mdctx == NULL)
+        return 0;
+
+    return EVP_DigestUpdate(prsactx->mdctx, data, datalen);
+}
+
+int rsa_digest_sign_final(void *vprsactx, unsigned char *sig, size_t *siglen,
+                          size_t sigsize)
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+    unsigned char digest[EVP_MAX_MD_SIZE];
+    unsigned int dlen = 0;
+
+    prsactx->flag_allow_md = 1;
+    if (prsactx == NULL || prsactx->mdctx == NULL)
+        return 0;
+
+    /*
+     * If sig is NULL then we're just finding out the sig size. Other fields
+     * are ignored. Defer to rsa_sign.
+     */
+    if (sig != NULL) {
+        /*
+         * TODO(3.0): There is the possibility that some externally provided
+         * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow -
+         * but that problem is much larger than just in RSA.
+         */
+        if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
+            return 0;
+    }
+
+    return rsa_sign(vprsactx, sig, siglen, sigsize, digest, (size_t)dlen);
+}
+
+
+int rsa_digest_verify_final(void *vprsactx, const unsigned char *sig,
+                            size_t siglen)
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+    unsigned char digest[EVP_MAX_MD_SIZE];
+    unsigned int dlen = 0;
+
+    prsactx->flag_allow_md = 1;
+    if (prsactx == NULL || prsactx->mdctx == NULL)
+        return 0;
+
+    /*
+     * TODO(3.0): There is the possibility that some externally provided
+     * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow -
+     * but that problem is much larger than just in RSA.
+     */
+    if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
+        return 0;
+
+    return rsa_verify(vprsactx, sig, siglen, digest, (size_t)dlen);
+}
+
+static void rsa_freectx(void *vprsactx)
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+    if (prsactx == NULL)
+        return;
+
+    RSA_free(prsactx->rsa);
+    EVP_MD_CTX_free(prsactx->mdctx);
+    EVP_MD_free(prsactx->md);
+    EVP_MD_free(prsactx->mgf1_md);
+    free_tbuf(prsactx);
+
+    OPENSSL_clear_free(prsactx, sizeof(prsactx));
+}
+
+static void *rsa_dupctx(void *vprsactx)
+{
+    PROV_RSA_CTX *srcctx = (PROV_RSA_CTX *)vprsactx;
+    PROV_RSA_CTX *dstctx;
+
+    dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+    if (dstctx == NULL)
+        return NULL;
+
+    *dstctx = *srcctx;
+    dstctx->rsa = NULL;
+    dstctx->md = NULL;
+    dstctx->mdctx = NULL;
+    dstctx->tbuf = NULL;
+
+    if (srcctx->rsa != NULL && !RSA_up_ref(srcctx->rsa))
+        goto err;
+    dstctx->rsa = srcctx->rsa;
+
+    if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
+        goto err;
+    dstctx->md = srcctx->md;
+
+    if (srcctx->mgf1_md != NULL && !EVP_MD_up_ref(srcctx->mgf1_md))
+        goto err;
+    dstctx->mgf1_md = srcctx->mgf1_md;
+
+    if (srcctx->mdctx != NULL) {
+        dstctx->mdctx = EVP_MD_CTX_new();
+        if (dstctx->mdctx == NULL
+                || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))
+            goto err;
+    }
+
+    return dstctx;
+ err:
+    rsa_freectx(dstctx);
+    return NULL;
+}
+
+static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+    OSSL_PARAM *p;
+
+    if (prsactx == NULL || params == NULL)
+        return 0;
+
+    p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
+    if (p != NULL
+        && !OSSL_PARAM_set_octet_string(p, prsactx->aid, prsactx->aid_len))
+        return 0;
+
+    p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
+    if (p != NULL)
+        switch (p->data_type) {
+        case OSSL_PARAM_INTEGER:
+            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_SIGNATURE_PARAM_DIGEST);
+    if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mdname))
+        return 0;
+
+    p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST);
+    if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mgf1_mdname))
+        return 0;
+
+    p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN);
+    if (p != NULL) {
+        if (p->data_type == OSSL_PARAM_INTEGER) {
+            if (!OSSL_PARAM_set_int(p, prsactx->saltlen))
+                return 0;
+        } else if (p->data_type == OSSL_PARAM_UTF8_STRING) {
+            switch (prsactx->saltlen) {
+            case RSA_PSS_SALTLEN_DIGEST:
+                if (!OSSL_PARAM_set_utf8_string(p, "digest"))
+                    return 0;
+                break;
+            case RSA_PSS_SALTLEN_MAX:
+                if (!OSSL_PARAM_set_utf8_string(p, "max"))
+                    return 0;
+                break;
+            case RSA_PSS_SALTLEN_AUTO:
+                if (!OSSL_PARAM_set_utf8_string(p, "auto"))
+                    return 0;
+                break;
+            default:
+                if (BIO_snprintf(p->data, p->data_size, "%d", prsactx->saltlen)
+                    <= 0)
+                    return 0;
+                break;
+            }
+        }
+    }
+
+    return 1;
+}
+
+static const OSSL_PARAM known_gettable_ctx_params[] = {
+    OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
+    OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
+    OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
+    OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
+    OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
+    OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *rsa_gettable_ctx_params(void)
+{
+    return known_gettable_ctx_params;
+}
+
+static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+    const OSSL_PARAM *p;
+
+    if (prsactx == NULL || params == NULL)
+        return 0;
+
+    p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
+    /* Not allowed during certain operations */
+    if (p != NULL && !prsactx->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;
+
+        /* TODO(3.0) PSS check needs more work */
+        if (rsa_pss_restricted(prsactx)) {
+            /* TODO(3.0) figure out what to do for prsactx->md == NULL */
+            if (prsactx->md == NULL || EVP_MD_is_a(prsactx->md, mdname))
+                return 1;
+            ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
+            return 0;
+        }
+
+        /* non-PSS code follows */
+        if (!rsa_setup_md(prsactx, mdname, mdprops))
+            return 0;
+    }
+
+    p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
+    if (p != NULL) {
+        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;
+        }
+
+        switch (pad_mode) {
+        case RSA_PKCS1_OAEP_PADDING:
+            /*
+             * OAEP padding is for asymmetric cipher only so is not compatible
+             * with signature use.
+             */
+            ERR_raise_data(ERR_LIB_PROV,
+                           PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE,
+                           "OAEP padding not allowed for signing / verifying");
+            return 0;
+        case RSA_PKCS1_PSS_PADDING:
+            if (prsactx->mdname[0] == '\0')
+                rsa_setup_md(prsactx, "SHA1", "");
+            goto cont;
+        case RSA_PKCS1_PADDING:
+        case RSA_SSLV23_PADDING:
+        case RSA_NO_PADDING:
+        case RSA_X931_PADDING:
+            if (RSA_get0_pss_params(prsactx->rsa) != NULL) {
+                ERR_raise_data(ERR_LIB_PROV,
+                               PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE,
+                               "X.931 padding not allowed with RSA-PSS");
+                return 0;
+            }
+        cont:
+            if (!rsa_check_padding(prsactx->mdnid, pad_mode))
+                return 0;
+            break;
+        default:
+            return 0;
+        }
+        prsactx->pad_mode = pad_mode;
+    }
+
+    p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN);
+    if (p != NULL) {
+        int saltlen;
+
+        if (prsactx->pad_mode != RSA_PKCS1_PSS_PADDING) {
+            ERR_raise_data(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED,
+                           "PSS saltlen can only be specified if "
+                           "PSS padding has been specified first");
+            return 0;
+        }
+
+        switch (p->data_type) {
+        case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
+            if (!OSSL_PARAM_get_int(p, &saltlen))
+                return 0;
+            break;
+        case OSSL_PARAM_UTF8_STRING:
+            if (strcmp(p->data, "digest") == 0)
+                saltlen = RSA_PSS_SALTLEN_DIGEST;
+            else if (strcmp(p->data, "max") == 0)
+                saltlen = RSA_PSS_SALTLEN_MAX;
+            else if (strcmp(p->data, "auto") == 0)
+                saltlen = RSA_PSS_SALTLEN_AUTO;
+            else
+                saltlen = atoi(p->data);
+            break;
+        default:
+            return 0;
+        }
+
+        /*
+         * RSA_PSS_SALTLEN_MAX seems curiously named in this check.
+         * Contrary to what it's name suggests, it's the currently
+         * lowest saltlen number possible.
+         */
+        if (saltlen < RSA_PSS_SALTLEN_MAX) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PSS_SALTLEN);
+            return 0;
+        }
+
+        prsactx->saltlen = saltlen;
+    }
+
+    p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST);
+    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_MGF1_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 (prsactx->pad_mode != RSA_PKCS1_PSS_PADDING) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MGF1_MD);
+            return  0;
+        }
+
+        /* TODO(3.0) PSS check needs more work */
+        if (rsa_pss_restricted(prsactx)) {
+            /* TODO(3.0) figure out what to do for prsactx->md == NULL */
+            if (prsactx->mgf1_md == NULL
+                || EVP_MD_is_a(prsactx->mgf1_md, mdname))
+                return 1;
+            ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
+            return 0;
+        }
+
+        /* non-PSS code follows */
+        if (!rsa_setup_mgf1_md(prsactx, mdname, mdprops))
+            return 0;
+    }
+
+    return 1;
+}
+
+static const OSSL_PARAM known_settable_ctx_params[] = {
+    OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
+    OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
+    OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0),
+    OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
+    OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0),
+    OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
+    OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *rsa_settable_ctx_params(void)
+{
+    /*
+     * TODO(3.0): Should this function return a different set of settable ctx
+     * params if the ctx is being used for a DigestSign/DigestVerify? In that
+     * case it is not allowed to set the digest size/digest name because the
+     * digest is explicitly set as part of the init.
+     */
+    return known_settable_ctx_params;
+}
+
+static int rsa_get_ctx_md_params(void *vprsactx, OSSL_PARAM *params)
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+    if (prsactx->mdctx == NULL)
+        return 0;
+
+    return EVP_MD_CTX_get_params(prsactx->mdctx, params);
+}
+
+static const OSSL_PARAM *rsa_gettable_ctx_md_params(void *vprsactx)
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+    if (prsactx->md == NULL)
+        return 0;
+
+    return EVP_MD_gettable_ctx_params(prsactx->md);
+}
+
+static int rsa_set_ctx_md_params(void *vprsactx, const OSSL_PARAM params[])
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+    if (prsactx->mdctx == NULL)
+        return 0;
+
+    return EVP_MD_CTX_set_params(prsactx->mdctx, params);
+}
+
+static const OSSL_PARAM *rsa_settable_ctx_md_params(void *vprsactx)
+{
+    PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
+
+    if (prsactx->md == NULL)
+        return 0;
+
+    return EVP_MD_settable_ctx_params(prsactx->md);
+}
+
+const OSSL_DISPATCH rsa_signature_functions[] = {
+    { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))rsa_newctx },
+    { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))rsa_signature_init },
+    { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))rsa_sign },
+    { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))rsa_signature_init },
+    { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))rsa_verify },
+    { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT, (void (*)(void))rsa_signature_init },
+    { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER, (void (*)(void))rsa_verify_recover },
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
+      (void (*)(void))rsa_digest_signverify_init },
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
+      (void (*)(void))rsa_digest_signverify_update },
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
+      (void (*)(void))rsa_digest_sign_final },
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
+      (void (*)(void))rsa_digest_signverify_init },
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
+      (void (*)(void))rsa_digest_signverify_update },
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
+      (void (*)(void))rsa_digest_verify_final },
+    { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))rsa_freectx },
+    { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))rsa_dupctx },
+    { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))rsa_get_ctx_params },
+    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
+      (void (*)(void))rsa_gettable_ctx_params },
+    { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))rsa_set_ctx_params },
+    { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
+      (void (*)(void))rsa_settable_ctx_params },
+    { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
+      (void (*)(void))rsa_get_ctx_md_params },
+    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
+      (void (*)(void))rsa_gettable_ctx_md_params },
+    { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
+      (void (*)(void))rsa_set_ctx_md_params },
+    { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
+      (void (*)(void))rsa_settable_ctx_md_params },
+    { 0, NULL }
+};
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index 5d3847e92f..68eb5ffdd3 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -21,6 +21,7 @@
 #include <openssl/kdf.h>
 #include <openssl/provider.h>
 #include <openssl/core_names.h>
+#include <openssl/params.h>
 #include <openssl/dsa.h>
 #include <openssl/dh.h>
 #include "testutil.h"
@@ -1232,53 +1233,18 @@ done:
 }
 #endif /* OPENSSL_NO_EC */
 
-#ifndef OPENSSL_NO_DSA
 /* Test getting and setting parameters on an EVP_PKEY_CTX */
-static int test_EVP_PKEY_CTX_get_set_params(void)
+static int test_EVP_PKEY_CTX_get_set_params(EVP_PKEY *pkey)
 {
     EVP_MD_CTX *mdctx = NULL;
     EVP_PKEY_CTX *ctx = NULL;
-    EVP_SIGNATURE *dsaimpl = NULL;
     const OSSL_PARAM *params;
     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;
     char mdname[OSSL_MAX_NAME_SIZE];
     char ssl3ms[48];
 
-    /*
-     * Setup the parameters for our DSA object. For our purposes they don't
-     * have to actually be *valid* parameters. We just need to set something.
-     */
-    dsa = DSA_new();
-    p = BN_new();
-    q = BN_new();
-    g = BN_new();
-    pub = BN_new();
-    priv = BN_new();
-    if (!TEST_ptr(dsa)
-            || !TEST_ptr(p)
-            || !TEST_ptr(q)
-            || !TEST_ptr(g)
-            || !DSA_set0_pqg(dsa, p, q, g))
-        goto err;
-    p = q = g = NULL;
-    if (!TEST_ptr(pub)
-            || !TEST_ptr(priv)
-            || !DSA_set0_key(dsa, pub, priv))
-        goto err;
-    pub = priv = NULL;
-
-    pkey = EVP_PKEY_new();
-    if (!TEST_ptr(pkey)
-            || !TEST_true(EVP_PKEY_assign_DSA(pkey, dsa)))
-        goto err;
-
-    dsa = NULL;
-
     /* Initialise a sign operation */
     ctx = EVP_PKEY_CTX_new(pkey, NULL);
     if (!TEST_ptr(ctx)
@@ -1286,9 +1252,7 @@ static int test_EVP_PKEY_CTX_get_set_params(void)
         goto err;
 
     /*
-     * We should be able to query the parameters now. The default DSA
-     * implementation supports exactly one parameter - so we expect to see that
-     * returned and no more.
+     * We should be able to query the parameters now.
      */
     params = EVP_PKEY_CTX_settable_params(ctx);
     if (!TEST_ptr(params)
@@ -1366,7 +1330,48 @@ static int test_EVP_PKEY_CTX_get_set_params(void)
  err:
     EVP_MD_CTX_free(mdctx);
     EVP_PKEY_CTX_free(ctx);
-    EVP_SIGNATURE_free(dsaimpl);
+
+    return ret;
+}
+
+#ifndef OPENSSL_NO_DSA
+static int test_DSA_get_set_params(void)
+{
+    DSA *dsa = NULL;
+    BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub = NULL, *priv = NULL;
+    EVP_PKEY *pkey = NULL;
+    int ret = 0;
+
+    /*
+     * Setup the parameters for our DSA object. For our purposes they don't
+     * have to actually be *valid* parameters. We just need to set something.
+     */
+    dsa = DSA_new();
+    p = BN_new();
+    q = BN_new();
+    g = BN_new();
+    pub = BN_new();
+    priv = BN_new();
+    if (!TEST_ptr(dsa)
+            || !TEST_ptr(p)
+            || !TEST_ptr(q)
+            || !TEST_ptr(g)
+            || !TEST_ptr(pub)
+            || !DSA_set0_pqg(dsa, p, q, g)
+        || !DSA_set0_key(dsa, pub, priv))
+        goto err;
+    p = q = g = pub = priv = NULL;
+
+    pkey = EVP_PKEY_new();
+    if (!TEST_ptr(pkey)
+            || !TEST_true(EVP_PKEY_assign_DSA(pkey, dsa)))
+        goto err;
+
+    dsa = NULL;
+
+    ret = test_EVP_PKEY_CTX_get_set_params(pkey);
+
+ err:
     EVP_PKEY_free(pkey);
     DSA_free(dsa);
     BN_free(p);
@@ -1379,6 +1384,48 @@ static int test_EVP_PKEY_CTX_get_set_params(void)
 }
 #endif
 
+static int test_RSA_get_set_params(void)
+{
+    RSA *rsa = NULL;
+    BIGNUM *n = NULL, *e = NULL, *d = NULL;
+    EVP_PKEY *pkey = NULL;
+    int ret = 0;
+
+    /*
+     * Setup the parameters for our RSA object. For our purposes they don't
+     * have to actually be *valid* parameters. We just need to set something.
+     */
+    rsa = RSA_new();
+    n = BN_new();
+    e = BN_new();
+    d = BN_new();
+    if (!TEST_ptr(rsa)
+            || !TEST_ptr(n)
+            || !TEST_ptr(e)
+            || !TEST_ptr(d)
+        || !RSA_set0_key(rsa, n, e, d))
+        goto err;
+    n = e = d = NULL;
+
+    pkey = EVP_PKEY_new();
+    if (!TEST_ptr(pkey)
+            || !TEST_true(EVP_PKEY_assign_RSA(pkey, rsa)))
+        goto err;
+
+    rsa = NULL;
+
+    ret = test_EVP_PKEY_CTX_get_set_params(pkey);
+
+ err:
+    EVP_PKEY_free(pkey);
+    RSA_free(rsa);
+    BN_free(n);
+    BN_free(e);
+    BN_free(d);
+
+    return ret;
+}
+
 #if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
 static int test_decrypt_null_chunks(void)
 {
@@ -1522,8 +1569,9 @@ int setup_tests(void)
                   OSSL_NELEM(ec_der_pub_keys));
 #endif
 #ifndef OPENSSL_NO_DSA
-    ADD_TEST(test_EVP_PKEY_CTX_get_set_params);
+    ADD_TEST(test_DSA_get_set_params);
 #endif
+    ADD_TEST(test_RSA_get_set_params);
 #if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
     ADD_TEST(test_decrypt_null_chunks);
 #endif
diff --git a/test/recipes/30-test_evp_data/evppkey.txt b/test/recipes/30-test_evp_data/evppkey.txt
index 1ca16572c4..e649e92c3f 100644
--- a/test/recipes/30-test_evp_data/evppkey.txt
+++ b/test/recipes/30-test_evp_data/evppkey.txt
@@ -414,7 +414,7 @@ Reason = operation not supported for this keytype
 Sign = RSA-2048
 Availablein = default
 Ctrl = rsa_mgf1_md:sha1
-Result = PKEY_CTRL_INVALID
+Result = PKEY_CTRL_ERROR
 Reason = invalid mgf1 md
 
 # RSA PSS key tests
diff --git a/util/libcrypto.num b/util/libcrypto.num
index db4532f0e4..6c8487e20b 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4945,3 +4945,5 @@ EVP_PKEY_CTX_set_ecdh_kdf_outlen        ?	3_0_0	EXIST::FUNCTION:EC
 EVP_PKEY_CTX_get_ecdh_kdf_outlen        ?	3_0_0	EXIST::FUNCTION:EC
 EVP_PKEY_CTX_set0_ecdh_kdf_ukm          ?	3_0_0	EXIST::FUNCTION:EC
 EVP_PKEY_CTX_get0_ecdh_kdf_ukm          ?	3_0_0	EXIST::FUNCTION:EC
+EVP_PKEY_CTX_set_rsa_pss_saltlen        ?	3_0_0	EXIST::FUNCTION:RSA
+EVP_PKEY_CTX_get_rsa_pss_saltlen        ?	3_0_0	EXIST::FUNCTION:RSA


More information about the openssl-commits mailing list