[openssl-commits] [openssl] master update

Dr. Stephen Henson steve at openssl.org
Sun Jan 8 01:52:04 UTC 2017


The branch master has been updated
       via  c82bafc52e4a22c91a0871436727e7a3fd45d75b (commit)
       via  76951372af95091bfc224a308e8cd9fb7b1db769 (commit)
       via  f291138bbe5453858ce0f534f9d3d33902a63929 (commit)
       via  f488976ccff9cc811cf69f1923695bee3e0fdf58 (commit)
       via  c916505092fd92773d481e3fb29d6575f8f66278 (commit)
       via  bc1ea030eff79c592250f1a2eed8dc7879217218 (commit)
       via  b6b885c6b9b4754eace0fe24e4cf2fabd089274e (commit)
       via  285c7d9cdf3fb917be3361df73aae29e9e732298 (commit)
       via  568b9cdc646904f0966767467d6a28adaa5c8f68 (commit)
       via  52ad523c0e7bc159fcc84549bece61bb5c3e44a8 (commit)
       via  d53b1dd4483243a271eea7288915a1fb5293505c (commit)
       via  23d674e802c5fbfaea9c428997eac4ef31a96b7b (commit)
       via  7751098ecdc6598af42c99950ac9554eeb2d60b3 (commit)
       via  1b2146855e303e2834e07f837919ae63998071ea (commit)
       via  0396a447f21ab6f76468f10f6c99378834dadebd (commit)
       via  23b6699ecc337a3f65653bf33e8ffcb481158368 (commit)
       via  635fe50fcd52f92cb2ecd8a23c979a50c70a626b (commit)
       via  f7a21d85b6851bdbdc8db1397285d4c63b2c40be (commit)
       via  08be0331c3632910b937a11e7152207b015265de (commit)
       via  b35b8d116b545656abe14f0dff19aededd7df986 (commit)
       via  186e48cd1bdb3b75b76b5e73c3c9502e46d17197 (commit)
       via  59029ca1134b5eb3b9d56190ff330120f3344e89 (commit)
       via  cb49e7497ac3318b486d08ba7e44394dafbb5776 (commit)
       via  cfd81c6d75a9d04a0e5877ad562524e068d109d2 (commit)
       via  53d2260c4078fed562cd7ce30e62817070fa39d6 (commit)
       via  87ee7b22b6c658a7223098084709bf841cc67cc9 (commit)
       via  a300c7256e14527e3c4804b34824835db42fce54 (commit)
       via  e64b2b5c839efb89403b4894f1ed43d5b8131201 (commit)
       via  ad4b3d0a658a2f5e4028714109d347c2b105dae4 (commit)
       via  410877bad2445796890831d883105cdb982a2d82 (commit)
       via  e5e04ee3983dcf5283c99ce63f3fe37093921747 (commit)
       via  6577e00892fc7b2ce02223e1eff77330e05ea660 (commit)
       via  9503ed8b8b52e58fcecec941452ce3469bb05e97 (commit)
       via  42009ae88249eb5238103d4ff240152e78c52415 (commit)
       via  47e42b3c67ebe0191cad1ca8eaa83cf9abd71524 (commit)
       via  faa02fe25677a7a97160b301e4e7cf5ade039340 (commit)
       via  4e8ba7479df8c5fb23f59742f434ae0e78d1a42f (commit)
       via  ffc6fad56287ef55eb42dc80de29713044717446 (commit)
       via  d771441d9ba5ccb55fa6f7a3b6ec5bac1ebc1d1f (commit)
       via  6745a1ff3268f3e3598df3ec3c34b08b369ed1bf (commit)
      from  3b72dcd5fb4d2c756a830dba1fc34f4a7ae61b73 (commit)


- Log -----------------------------------------------------------------
commit c82bafc52e4a22c91a0871436727e7a3fd45d75b
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sat Jan 7 17:17:30 2017 +0000

    fix a few more style issues
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 76951372af95091bfc224a308e8cd9fb7b1db769
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Fri Jan 6 22:49:01 2017 +0000

    Documentation clarification and fixes.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit f291138bbe5453858ce0f534f9d3d33902a63929
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Fri Jan 6 17:51:28 2017 +0000

    Remove unnecessary frees and style fixes.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit f488976ccff9cc811cf69f1923695bee3e0fdf58
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Fri Jan 6 17:26:11 2017 +0000

    fix typo and remove duplicate macro
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit c916505092fd92773d481e3fb29d6575f8f66278
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Fri Jan 6 14:41:04 2017 +0000

    Add documentation for PSS control operations.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit bc1ea030eff79c592250f1a2eed8dc7879217218
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Fri Jan 6 13:36:37 2017 +0000

    Use more desciptive macro name rsa_pss_restricted()
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit b6b885c6b9b4754eace0fe24e4cf2fabd089274e
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Fri Jan 6 13:12:28 2017 +0000

    style issues
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 285c7d9cdf3fb917be3361df73aae29e9e732298
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Fri Jan 6 13:12:17 2017 +0000

    free str on error
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 568b9cdc646904f0966767467d6a28adaa5c8f68
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Fri Jan 6 13:11:50 2017 +0000

    clarify comment
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 52ad523c0e7bc159fcc84549bece61bb5c3e44a8
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu Jan 5 23:18:28 2017 +0000

    fix various style issues
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit d53b1dd4483243a271eea7288915a1fb5293505c
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu Jan 5 18:52:59 2017 +0000

    make update
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 23d674e802c5fbfaea9c428997eac4ef31a96b7b
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Wed Jan 4 17:32:03 2017 +0000

    add test for invalid key parameters
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 7751098ecdc6598af42c99950ac9554eeb2d60b3
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Wed Jan 4 14:06:44 2017 +0000

    document RSA-PSS algorithm options
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 1b2146855e303e2834e07f837919ae63998071ea
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Jan 3 17:33:31 2017 +0000

    add PSS key tests
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 0396a447f21ab6f76468f10f6c99378834dadebd
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Jan 3 16:07:52 2017 +0000

    print errors in pkey utility
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 23b6699ecc337a3f65653bf33e8ffcb481158368
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Jan 3 16:00:41 2017 +0000

    make errors
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 635fe50fcd52f92cb2ecd8a23c979a50c70a626b
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Jan 3 16:00:04 2017 +0000

    add parameter error
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit f7a21d85b6851bdbdc8db1397285d4c63b2c40be
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Dec 6 14:19:41 2016 +0000

    Set EVP_PKEY_CTX in SignerInfo
    
    If we aren't setting public key parameters make EVP_PKEY_CTX available
    in SignerInfo so PSS mode and parameters are automatically selected.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 08be0331c3632910b937a11e7152207b015265de
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Dec 6 14:17:21 2016 +0000

    Only allow PSS padding for PSS keys.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit b35b8d116b545656abe14f0dff19aededd7df986
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Dec 6 14:01:05 2016 +0000

    Decode parameters properly.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 186e48cd1bdb3b75b76b5e73c3c9502e46d17197
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Dec 6 00:54:19 2016 +0000

    Return errors PKCS#7/CMS enveloped data ctrls and PSS
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 59029ca1134b5eb3b9d56190ff330120f3344e89
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Mon Dec 5 14:55:23 2016 +0000

    Add PSS parameter restrictions.
    
    If a key contains any PSS parameter restrictions set them during
    sign or verification initialisation. Parameters now become the
    default values for sign/verify. Digests are fixed and any attempt
    to change them is an error. The salt length can be modified but
    must not be less than the minimum value.
    
    If the key parameters are invalid then verification or signing
    initialisation returns an error.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit cb49e7497ac3318b486d08ba7e44394dafbb5776
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Mon Dec 5 14:41:32 2016 +0000

    Initial parameter restrictions.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit cfd81c6d75a9d04a0e5877ad562524e068d109d2
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Mon Dec 5 14:00:48 2016 +0000

    Add rsa_pss_get_param.
    
    New function rsa_pss_get_param to extract and sanity check PSS parameters.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 53d2260c4078fed562cd7ce30e62817070fa39d6
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu Dec 1 21:53:58 2016 +0000

    Don't allow PKCS#7/CMS encrypt with PSS.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 87ee7b22b6c658a7223098084709bf841cc67cc9
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu Dec 1 21:46:31 2016 +0000

    Add macros to determine if key or ctx is PSS.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit a300c7256e14527e3c4804b34824835db42fce54
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Wed Nov 30 18:26:10 2016 +0000

    Support pad mode get/set for PSS keys.
    
    Pad mode setting returns an error if the mode is anything other then PSS.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit e64b2b5c839efb89403b4894f1ed43d5b8131201
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Wed Nov 30 16:55:30 2016 +0000

    Key gen param support.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit ad4b3d0a658a2f5e4028714109d347c2b105dae4
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Wed Nov 30 16:23:18 2016 +0000

    Set PSS padding mode for PSS keys.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 410877bad2445796890831d883105cdb982a2d82
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Wed Nov 30 16:21:01 2016 +0000

    Digest string helper function.
    
    New function EVP_PKEY_CTX_md() which takes a string and passes a digest
    to a ctrl.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit e5e04ee3983dcf5283c99ce63f3fe37093921747
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Mon Nov 21 00:44:01 2016 +0000

    Support RSA operations in PSS.
    
    Add support for common operations in PSS by adding a new function
    RSA_pkey_ctx_ctrl() which calls EVP_PKEY_CTX_ctrl if the key type
    is RSA or PSS.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 6577e00892fc7b2ce02223e1eff77330e05ea660
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu Nov 24 21:44:50 2016 +0000

    PSS EVP_PKEY method
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 9503ed8b8b52e58fcecec941452ce3469bb05e97
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu Nov 24 14:22:22 2016 +0000

    RSA-PSS key printing.
    
    Print out RSA-PSS key parameters if present.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 42009ae88249eb5238103d4ff240152e78c52415
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu Nov 24 00:58:33 2016 +0000

    PSS parameter encode and decode.
    
    For RSA PSS keys encode and decode parameters when handling public
    and private keys.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 47e42b3c67ebe0191cad1ca8eaa83cf9abd71524
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Mon Nov 21 01:35:30 2016 +0000

    Split PSS parameter creation.
    
    Split PSS parameter creation. This adds a new function rsa_pss_params_create
    which creates PSS parameters from digest and salt values. This will be
    used for PSS key generation.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit faa02fe25677a7a97160b301e4e7cf5ade039340
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Nov 20 04:17:30 2016 +0000

    Use method key type instead of EVP_PKEY_RSA
    
    Make RSA method more flexible by using the key type from the
    method instead of hard coding EVP_PKEY_RSA: by doing this the
    same code supports both RSA and RSA-PSS.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 4e8ba7479df8c5fb23f59742f434ae0e78d1a42f
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu Nov 24 21:42:49 2016 +0000

    PSS ASN.1 method
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit ffc6fad56287ef55eb42dc80de29713044717446
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu Nov 24 21:50:26 2016 +0000

    add EVP_PKEY_RSA_PSS
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit d771441d9ba5ccb55fa6f7a3b6ec5bac1ebc1d1f
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Mon Nov 21 01:34:56 2016 +0000

    Add pss field to RSA structure and free it.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

commit 6745a1ff3268f3e3598df3ec3c34b08b369ed1bf
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Thu Nov 24 18:51:54 2016 +0000

    Cache maskHash parameter
    
    Store hash algorithm used for MGF1 masks in PSS and OAEP modes in PSS and
    OAEP parameter structure: this avoids the need to decode part of the ASN.1
    structure every time it is used.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/2177)

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

Summary of changes:
 apps/pkey.c                                        |   2 +
 crypto/asn1/standard_methods.h                     |   9 +-
 crypto/cms/cms_sd.c                                |   1 +
 crypto/evp/evp_err.c                               |   1 +
 crypto/evp/pmeth_lib.c                             |  26 +-
 crypto/include/internal/asn1_int.h                 |   1 +
 crypto/include/internal/evp_int.h                  |   1 +
 crypto/rsa/rsa_ameth.c                             | 556 +++++++++++++--------
 crypto/rsa/rsa_asn1.c                              |  30 +-
 crypto/rsa/rsa_err.c                               |   9 +-
 crypto/rsa/rsa_lib.c                               |  13 +
 crypto/rsa/rsa_locl.h                              |  10 +
 crypto/rsa/rsa_pmeth.c                             | 183 ++++++-
 doc/man1/genpkey.pod                               |  25 +
 doc/man1/pkeyutl.pod                               |  26 +
 .../EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md.pod    |  99 ++++
 include/openssl/evp.h                              |   4 +
 include/openssl/rsa.h                              |  62 ++-
 test/evptests.txt                                  | 102 ++++
 util/libcrypto.num                                 |   2 +
 20 files changed, 895 insertions(+), 267 deletions(-)
 create mode 100644 doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md.pod

diff --git a/apps/pkey.c b/apps/pkey.c
index 48bfda8..14896d3 100644
--- a/apps/pkey.c
+++ b/apps/pkey.c
@@ -179,6 +179,8 @@ int pkey_main(int argc, char **argv)
     ret = 0;
 
  end:
+    if (ret != 0)
+        ERR_print_errors(bio_err);
     EVP_PKEY_free(pkey);
     release_engine(e);
     BIO_free_all(out);
diff --git a/crypto/asn1/standard_methods.h b/crypto/asn1/standard_methods.h
index 5b8f9dd..322ba97 100644
--- a/crypto/asn1/standard_methods.h
+++ b/crypto/asn1/standard_methods.h
@@ -7,7 +7,11 @@
  * https://www.openssl.org/source/license.html
  */
 
-/* Keep this sorted in type order !! */
+/*
+ * This table MUST be kept in ascening order of the NID each method
+ * represents (corresponding to the pkey_id field) as OBJ_bsearch
+ * is used to search it.
+ */
 static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
 #ifndef OPENSSL_NO_RSA
     &rsa_asn1_meths[0],
@@ -30,6 +34,9 @@ static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
 #ifndef OPENSSL_NO_CMAC
     &cmac_asn1_meth,
 #endif
+#ifndef OPENSSL_NO_RSA
+    &rsa_pss_asn1_meth,
+#endif
 #ifndef OPENSSL_NO_DH
     &dhx_asn1_meth,
 #endif
diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c
index 76c1f53..a31e849 100644
--- a/crypto/cms/cms_sd.c
+++ b/crypto/cms/cms_sd.c
@@ -656,6 +656,7 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si)
         EVP_MD_CTX_reset(mctx);
         if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0)
             goto err;
+        si->pctx = pctx;
     }
 
     if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index 7fcbdcd..0331c2a 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -50,6 +50,7 @@ static ERR_STRING_DATA EVP_str_functs[] = {
     {ERR_FUNC(EVP_F_EVP_PKEY_CTX_CTRL), "EVP_PKEY_CTX_ctrl"},
     {ERR_FUNC(EVP_F_EVP_PKEY_CTX_CTRL_STR), "EVP_PKEY_CTX_ctrl_str"},
     {ERR_FUNC(EVP_F_EVP_PKEY_CTX_DUP), "EVP_PKEY_CTX_dup"},
+    {ERR_FUNC(EVP_F_EVP_PKEY_CTX_MD), "EVP_PKEY_CTX_md"},
     {ERR_FUNC(EVP_F_EVP_PKEY_DECRYPT), "EVP_PKEY_decrypt"},
     {ERR_FUNC(EVP_F_EVP_PKEY_DECRYPT_INIT), "EVP_PKEY_decrypt_init"},
     {ERR_FUNC(EVP_F_EVP_PKEY_DECRYPT_OLD), "EVP_PKEY_decrypt_old"},
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 169639b..e7845ed 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -38,6 +38,9 @@ static const EVP_PKEY_METHOD *standard_methods[] = {
 #ifndef OPENSSL_NO_CMAC
     &cmac_pkey_meth,
 #endif
+#ifndef OPENSSL_NO_RSA
+    &rsa_pss_pkey_meth,
+#endif
 #ifndef OPENSSL_NO_DH
     &dhx_pkey_meth,
 #endif
@@ -327,14 +330,9 @@ int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
         EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
         return -2;
     }
-    if (strcmp(name, "digest") == 0) {
-        const EVP_MD *md;
-        if (value == NULL || (md = EVP_get_digestbyname(value)) == NULL) {
-            EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_INVALID_DIGEST);
-            return 0;
-        }
-        return EVP_PKEY_CTX_set_signature_md(ctx, md);
-    }
+    if (strcmp(name, "digest") == 0)
+        return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD,
+                               value);
     return ctx->pmeth->ctrl_str(ctx, name, value);
 }
 
@@ -365,6 +363,18 @@ int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex)
     return rv;
 }
 
+/* Pass a message digest to a ctrl */
+int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md)
+{
+    const EVP_MD *m;
+
+    if (md == NULL || (m = EVP_get_digestbyname(md)) == NULL) {
+        EVPerr(EVP_F_EVP_PKEY_CTX_MD, EVP_R_INVALID_DIGEST);
+        return 0;
+    }
+    return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, 0, (void *)m);
+}
+
 int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx)
 {
     return ctx->operation;
diff --git a/crypto/include/internal/asn1_int.h b/crypto/include/internal/asn1_int.h
index f70e3b4..a5fdc0e 100644
--- a/crypto/include/internal/asn1_int.h
+++ b/crypto/include/internal/asn1_int.h
@@ -64,6 +64,7 @@ extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
 extern const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth;
 extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
 extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2];
+extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth;
 
 /*
  * These are used internally in the ASN1_OBJECT to keep track of whether the
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index 0809dc3..121523b 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -84,6 +84,7 @@ extern const EVP_PKEY_METHOD ec_pkey_meth;
 extern const EVP_PKEY_METHOD ecx25519_pkey_meth;
 extern const EVP_PKEY_METHOD hmac_pkey_meth;
 extern const EVP_PKEY_METHOD rsa_pkey_meth;
+extern const EVP_PKEY_METHOD rsa_pss_pkey_meth;
 extern const EVP_PKEY_METHOD tls1_prf_pkey_meth;
 extern const EVP_PKEY_METHOD hkdf_pkey_meth;
 
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 5694140..ae844ea 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -24,15 +24,68 @@ static int rsa_cms_decrypt(CMS_RecipientInfo *ri);
 static int rsa_cms_encrypt(CMS_RecipientInfo *ri);
 #endif
 
+static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg);
+
+/* Set any parameters associated with pkey */
+static int rsa_param_encode(const EVP_PKEY *pkey,
+                            ASN1_STRING **pstr, int *pstrtype)
+{
+    const RSA *rsa = pkey->pkey.rsa;
+
+    *pstr = NULL;
+    /* If RSA it's just NULL type */
+    if (pkey->ameth->pkey_id == EVP_PKEY_RSA) {
+        *pstrtype = V_ASN1_NULL;
+        return 1;
+    }
+    /* If no PSS parameters we omit parameters entirely */
+    if (rsa->pss == NULL) {
+        *pstrtype = V_ASN1_UNDEF;
+        return 1;
+    }
+    /* Encode PSS parameters */
+    if (ASN1_item_pack(rsa->pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), pstr) == NULL)
+        return 0;
+
+    *pstrtype = V_ASN1_SEQUENCE;
+    return 1;
+}
+/* Decode any parameters and set them in RSA structure */
+static int rsa_param_decode(RSA *rsa, const X509_ALGOR *alg)
+{
+    const ASN1_OBJECT *algoid;
+    const void *algp;
+    int algptype;
+
+    X509_ALGOR_get0(&algoid, &algptype, &algp, alg);
+    if (OBJ_obj2nid(algoid) == EVP_PKEY_RSA)
+        return 1;
+    if (algptype == V_ASN1_UNDEF)
+        return 1;
+    if (algptype != V_ASN1_SEQUENCE) {
+        RSAerr(RSA_F_RSA_PARAM_DECODE, RSA_R_INVALID_PSS_PARAMETERS);
+        return 0;
+    }
+    rsa->pss = rsa_pss_decode(alg);
+    if (rsa->pss == NULL)
+        return 0;
+    return 1;
+}
+
 static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
 {
     unsigned char *penc = NULL;
     int penclen;
+    ASN1_STRING *str;
+    int strtype;
+
+    if (!rsa_param_encode(pkey, &str, &strtype))
+        return 0;
     penclen = i2d_RSAPublicKey(pkey->pkey.rsa, &penc);
     if (penclen <= 0)
         return 0;
-    if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_RSA),
-                               V_ASN1_NULL, NULL, penc, penclen))
+    if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
+                               strtype, str, penc, penclen))
         return 1;
 
     OPENSSL_free(penc);
@@ -43,15 +96,20 @@ static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
 {
     const unsigned char *p;
     int pklen;
+    X509_ALGOR *alg;
     RSA *rsa = NULL;
 
-    if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, NULL, pubkey))
+    if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &alg, pubkey))
         return 0;
     if ((rsa = d2i_RSAPublicKey(NULL, &p, pklen)) == NULL) {
         RSAerr(RSA_F_RSA_PUB_DECODE, ERR_R_RSA_LIB);
         return 0;
     }
-    EVP_PKEY_assign_RSA(pkey, rsa);
+    if (!rsa_param_decode(rsa, alg)) {
+        RSA_free(rsa);
+        return 0;
+    }
+    EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
     return 1;
 }
 
@@ -72,7 +130,7 @@ static int old_rsa_priv_decode(EVP_PKEY *pkey,
         RSAerr(RSA_F_OLD_RSA_PRIV_DECODE, ERR_R_RSA_LIB);
         return 0;
     }
-    EVP_PKEY_assign_RSA(pkey, rsa);
+    EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
     return 1;
 }
 
@@ -85,16 +143,23 @@ static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
 {
     unsigned char *rk = NULL;
     int rklen;
+    ASN1_STRING *str;
+    int strtype;
+
+    if (!rsa_param_encode(pkey, &str, &strtype))
+        return 0;
     rklen = i2d_RSAPrivateKey(pkey->pkey.rsa, &rk);
 
     if (rklen <= 0) {
         RSAerr(RSA_F_RSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+        ASN1_STRING_free(str);
         return 0;
     }
 
-    if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_rsaEncryption), 0,
-                         V_ASN1_NULL, NULL, rk, rklen)) {
+    if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
+                         strtype, str, rk, rklen)) {
         RSAerr(RSA_F_RSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+        ASN1_STRING_free(str);
         return 0;
     }
 
@@ -104,10 +169,23 @@ static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
 static int rsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
 {
     const unsigned char *p;
+    RSA *rsa;
     int pklen;
-    if (!PKCS8_pkey_get0(NULL, &p, &pklen, NULL, p8))
+    const X509_ALGOR *alg;
+
+    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &alg, p8))
         return 0;
-    return old_rsa_priv_decode(pkey, &p, pklen);
+    rsa = d2i_RSAPrivateKey(NULL, &p, pklen);
+    if (rsa == NULL) {
+        RSAerr(RSA_F_RSA_PRIV_DECODE, ERR_R_RSA_LIB);
+        return 0;
+    }
+    if (!rsa_param_decode(rsa, alg)) {
+        RSA_free(rsa);
+        return 0;
+    }
+    EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
+    return 1;
 }
 
 static int int_rsa_size(const EVP_PKEY *pkey)
@@ -130,104 +208,40 @@ static void int_rsa_free(EVP_PKEY *pkey)
     RSA_free(pkey->pkey.rsa);
 }
 
-static int do_rsa_print(BIO *bp, const RSA *x, int off, int priv)
-{
-    char *str;
-    const char *s;
-    int ret = 0, mod_len = 0;
-
-    if (x->n != NULL)
-        mod_len = BN_num_bits(x->n);
-
-    if (!BIO_indent(bp, off, 128))
-        goto err;
-
-    if (priv && x->d) {
-        if (BIO_printf(bp, "Private-Key: (%d bit)\n", mod_len) <= 0)
-            goto err;
-        str = "modulus:";
-        s = "publicExponent:";
-    } else {
-        if (BIO_printf(bp, "Public-Key: (%d bit)\n", mod_len) <= 0)
-            goto err;
-        str = "Modulus:";
-        s = "Exponent:";
-    }
-    if (!ASN1_bn_print(bp, str, x->n, NULL, off))
-        goto err;
-    if (!ASN1_bn_print(bp, s, x->e, NULL, off))
-        goto err;
-    if (priv) {
-        if (!ASN1_bn_print(bp, "privateExponent:", x->d, NULL, off))
-            goto err;
-        if (!ASN1_bn_print(bp, "prime1:", x->p, NULL, off))
-            goto err;
-        if (!ASN1_bn_print(bp, "prime2:", x->q, NULL, off))
-            goto err;
-        if (!ASN1_bn_print(bp, "exponent1:", x->dmp1, NULL, off))
-            goto err;
-        if (!ASN1_bn_print(bp, "exponent2:", x->dmq1, NULL, off))
-            goto err;
-        if (!ASN1_bn_print(bp, "coefficient:", x->iqmp, NULL, off))
-            goto err;
-    }
-    ret = 1;
- err:
-    return (ret);
-}
-
-static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
-                         ASN1_PCTX *ctx)
-{
-    return do_rsa_print(bp, pkey->pkey.rsa, indent, 0);
-}
-
-static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
-                          ASN1_PCTX *ctx)
-{
-    return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
-}
-
-/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */
 static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg)
 {
-    if (alg == NULL)
-        return NULL;
     if (OBJ_obj2nid(alg->algorithm) != NID_mgf1)
         return NULL;
     return ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR),
                                      alg->parameter);
 }
 
-static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
-                                      X509_ALGOR **pmaskHash)
-{
-    RSA_PSS_PARAMS *pss;
-
-    *pmaskHash = NULL;
-
-    pss = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_PSS_PARAMS),
-                                    alg->parameter);
-
-    if (!pss)
-        return NULL;
-
-    *pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
-
-    return pss;
-}
-
-static int rsa_pss_param_print(BIO *bp, RSA_PSS_PARAMS *pss,
-                               X509_ALGOR *maskHash, int indent)
+static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss,
+                               int indent)
 {
     int rv = 0;
-    if (!pss) {
-        if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0)
+    X509_ALGOR *maskHash = NULL;
+
+    if (!BIO_indent(bp, indent, 128))
+        goto err;
+    if (pss_key) {
+        if (pss == NULL) {
+            if (BIO_puts(bp, "No PSS parameter restrictions\n") <= 0)
+                return 0;
+            return 1;
+        } else {
+            if (BIO_puts(bp, "PSS parameter restrictions:") <= 0)
+                return 0;
+        }
+    } else if (pss == NULL) {
+        if (BIO_puts(bp,"(INVALID PSS PARAMETERS)\n") <= 0)
             return 0;
         return 1;
     }
     if (BIO_puts(bp, "\n") <= 0)
         goto err;
+    if (pss_key)
+        indent += 2;
     if (!BIO_indent(bp, indent, 128))
         goto err;
     if (BIO_puts(bp, "Hash Algorithm: ") <= 0)
@@ -252,7 +266,8 @@ static int rsa_pss_param_print(BIO *bp, RSA_PSS_PARAMS *pss,
             goto err;
         if (BIO_puts(bp, " with ") <= 0)
             goto err;
-        if (maskHash) {
+        maskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
+        if (maskHash != NULL) {
             if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0)
                 goto err;
         } else if (BIO_puts(bp, "INVALID") <= 0)
@@ -263,7 +278,7 @@ static int rsa_pss_param_print(BIO *bp, RSA_PSS_PARAMS *pss,
 
     if (!BIO_indent(bp, indent, 128))
         goto err;
-    if (BIO_puts(bp, "Salt Length: 0x") <= 0)
+    if (BIO_printf(bp, "%s Salt Length: 0x", pss_key ? "Minimum" : "") <= 0)
         goto err;
     if (pss->saltLength) {
         if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0)
@@ -286,25 +301,110 @@ static int rsa_pss_param_print(BIO *bp, RSA_PSS_PARAMS *pss,
     rv = 1;
 
  err:
+    X509_ALGOR_free(maskHash);
     return rv;
 
 }
 
+static int pkey_rsa_print(BIO *bp, const EVP_PKEY *pkey, int off, int priv)
+{
+    const RSA *x = pkey->pkey.rsa;
+    char *str;
+    const char *s;
+    int ret = 0, mod_len = 0;
+
+    if (x->n != NULL)
+        mod_len = BN_num_bits(x->n);
+
+    if (!BIO_indent(bp, off, 128))
+        goto err;
+
+    if (BIO_printf(bp, "%s ", pkey_is_pss(pkey) ?  "RSA-PSS" : "RSA") <= 0)
+        goto err;
+
+    if (priv && x->d) {
+        if (BIO_printf(bp, "Private-Key: (%d bit)\n", mod_len) <= 0)
+            goto err;
+        str = "modulus:";
+        s = "publicExponent:";
+    } else {
+        if (BIO_printf(bp, "Public-Key: (%d bit)\n", mod_len) <= 0)
+            goto err;
+        str = "Modulus:";
+        s = "Exponent:";
+    }
+    if (!ASN1_bn_print(bp, str, x->n, NULL, off))
+        goto err;
+    if (!ASN1_bn_print(bp, s, x->e, NULL, off))
+        goto err;
+    if (priv) {
+        if (!ASN1_bn_print(bp, "privateExponent:", x->d, NULL, off))
+            goto err;
+        if (!ASN1_bn_print(bp, "prime1:", x->p, NULL, off))
+            goto err;
+        if (!ASN1_bn_print(bp, "prime2:", x->q, NULL, off))
+            goto err;
+        if (!ASN1_bn_print(bp, "exponent1:", x->dmp1, NULL, off))
+            goto err;
+        if (!ASN1_bn_print(bp, "exponent2:", x->dmq1, NULL, off))
+            goto err;
+        if (!ASN1_bn_print(bp, "coefficient:", x->iqmp, NULL, off))
+            goto err;
+    }
+    if (pkey_is_pss(pkey) && !rsa_pss_param_print(bp, 1, x->pss, off))
+        goto err;
+    ret = 1;
+ err:
+    return ret;
+}
+
+static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+                         ASN1_PCTX *ctx)
+{
+    return pkey_rsa_print(bp, pkey, indent, 0);
+}
+
+static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+                          ASN1_PCTX *ctx)
+{
+    return pkey_rsa_print(bp, pkey, indent, 1);
+}
+
+static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg)
+{
+    RSA_PSS_PARAMS *pss;
+
+    pss = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_PSS_PARAMS),
+                                    alg->parameter);
+
+    if (pss == NULL)
+        return NULL;
+
+    if (pss->maskGenAlgorithm != NULL) {
+        pss->maskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
+        if (pss->maskHash == NULL) {
+            RSA_PSS_PARAMS_free(pss);
+            return NULL;
+        }
+    }
+
+    return pss;
+}
+
 static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
                          const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx)
 {
-    if (OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss) {
+    if (OBJ_obj2nid(sigalg->algorithm) == EVP_PKEY_RSA_PSS) {
         int rv;
-        RSA_PSS_PARAMS *pss;
-        X509_ALGOR *maskHash;
-        pss = rsa_pss_decode(sigalg, &maskHash);
-        rv = rsa_pss_param_print(bp, pss, maskHash, indent);
+        RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg);
+
+        rv = rsa_pss_param_print(bp, 0, pss, indent);
         RSA_PSS_PARAMS_free(pss);
-        X509_ALGOR_free(maskHash);
         if (!rv)
             return 0;
-    } else if (!sig && BIO_puts(bp, "\n") <= 0)
+    } else if (!sig && BIO_puts(bp, "\n") <= 0) {
         return 0;
+    }
     if (sig)
         return X509_signature_dump(bp, sig, indent);
     return 1;
@@ -313,6 +413,7 @@ static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
 static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
 {
     X509_ALGOR *alg = NULL;
+
     switch (op) {
 
     case ASN1_PKEY_CTRL_PKCS7_SIGN:
@@ -321,6 +422,8 @@ static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
         break;
 
     case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
+        if (pkey_is_pss(pkey))
+            return -2;
         if (arg1 == 0)
             PKCS7_RECIP_INFO_get0_alg(arg2, &alg);
         break;
@@ -333,6 +436,8 @@ static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
         break;
 
     case ASN1_PKEY_CTRL_CMS_ENVELOPE:
+        if (pkey_is_pss(pkey))
+            return -2;
         if (arg1 == 0)
             return rsa_cms_encrypt(arg2);
         else if (arg1 == 1)
@@ -340,6 +445,8 @@ static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
         break;
 
     case ASN1_PKEY_CTRL_CMS_RI_TYPE:
+        if (pkey_is_pss(pkey))
+            return -2;
         *(int *)arg2 = CMS_RECIPINFO_TRANS;
         return 1;
 #endif
@@ -363,7 +470,7 @@ static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
 /* allocate and set algorithm ID from EVP_MD, default SHA1 */
 static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md)
 {
-    if (EVP_MD_type(md) == NID_sha1)
+    if (md == NULL || EVP_MD_type(md) == NID_sha1)
         return 1;
     *palg = X509_ALGOR_new();
     if (*palg == NULL)
@@ -377,13 +484,14 @@ static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md)
 {
     X509_ALGOR *algtmp = NULL;
     ASN1_STRING *stmp = NULL;
+
     *palg = NULL;
-    if (EVP_MD_type(mgf1md) == NID_sha1)
+    if (mgf1md == NULL || EVP_MD_type(mgf1md) == NID_sha1)
         return 1;
     /* need to embed algorithm ID inside another */
     if (!rsa_md_to_algor(&algtmp, mgf1md))
         goto err;
-    if (!ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp))
+    if (ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp) == NULL)
          goto err;
     *palg = X509_ALGOR_new();
     if (*palg == NULL)
@@ -402,6 +510,7 @@ static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md)
 static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg)
 {
     const EVP_MD *md;
+
     if (!alg)
         return EVP_sha1();
     md = EVP_get_digestbyobj(alg->algorithm);
@@ -410,47 +519,23 @@ static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg)
     return md;
 }
 
-/* convert MGF1 algorithm ID to EVP_MD, default SHA1 */
-static const EVP_MD *rsa_mgf1_to_md(X509_ALGOR *alg, X509_ALGOR *maskHash)
-{
-    const EVP_MD *md;
-    if (!alg)
-        return EVP_sha1();
-    /* Check mask and lookup mask hash algorithm */
-    if (OBJ_obj2nid(alg->algorithm) != NID_mgf1) {
-        RSAerr(RSA_F_RSA_MGF1_TO_MD, RSA_R_UNSUPPORTED_MASK_ALGORITHM);
-        return NULL;
-    }
-    if (!maskHash) {
-        RSAerr(RSA_F_RSA_MGF1_TO_MD, RSA_R_UNSUPPORTED_MASK_PARAMETER);
-        return NULL;
-    }
-    md = EVP_get_digestbyobj(maskHash->algorithm);
-    if (md == NULL) {
-        RSAerr(RSA_F_RSA_MGF1_TO_MD, RSA_R_UNKNOWN_MASK_DIGEST);
-        return NULL;
-    }
-    return md;
-}
-
 /*
- * Convert EVP_PKEY_CTX is PSS mode into corresponding algorithm parameter,
+ * Convert EVP_PKEY_CTX in PSS mode into corresponding algorithm parameter,
  * suitable for setting an AlgorithmIdentifier.
  */
 
-static ASN1_STRING *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
+static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
 {
     const EVP_MD *sigmd, *mgf1md;
-    RSA_PSS_PARAMS *pss = NULL;
-    ASN1_STRING *os = NULL;
     EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
-    int saltlen, rv = 0;
+    int saltlen;
+
     if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0)
-        goto err;
+        return NULL;
     if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
-        goto err;
+        return NULL;
     if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen))
-        goto err;
+        return NULL;
     if (saltlen == -1)
         saltlen = EVP_MD_size(sigmd);
     else if (saltlen == -2) {
@@ -458,7 +543,15 @@ static ASN1_STRING *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
         if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0)
             saltlen--;
     }
-    pss = RSA_PSS_PARAMS_new();
+
+    return rsa_pss_params_create(sigmd, mgf1md, saltlen);
+}
+
+RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd,
+                                      const EVP_MD *mgf1md, int saltlen)
+{
+    RSA_PSS_PARAMS *pss = RSA_PSS_PARAMS_new();
+
     if (pss == NULL)
         goto err;
     if (saltlen != 20) {
@@ -470,20 +563,29 @@ static ASN1_STRING *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
     }
     if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd))
         goto err;
+    if (mgf1md == NULL)
+        mgf1md = sigmd;
     if (!rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md))
         goto err;
-    /* Finally create string with pss parameter encoding. */
-    if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os))
-         goto err;
-    rv = 1;
+    return pss;
  err:
     RSA_PSS_PARAMS_free(pss);
-    if (rv)
-        return os;
-    ASN1_STRING_free(os);
     return NULL;
 }
 
+static ASN1_STRING *rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx)
+{
+    RSA_PSS_PARAMS *pss = rsa_ctx_to_pss(pkctx);
+    ASN1_STRING *os;
+
+    if (pss == NULL)
+        return NULL;
+
+    os = ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), NULL);
+    RSA_PSS_PARAMS_free(pss);
+    return os;
+}
+
 /*
  * From PSS AlgorithmIdentifier set public key parameters. If pkey isn't NULL
  * then the EVP_MD_CTX is setup and initialised. If it is NULL parameters are
@@ -497,51 +599,21 @@ static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
     int saltlen;
     const EVP_MD *mgf1md = NULL, *md = NULL;
     RSA_PSS_PARAMS *pss;
-    X509_ALGOR *maskHash;
+
     /* Sanity check: make sure it is PSS */
-    if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
+    if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) {
         RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
         return -1;
     }
     /* Decode PSS parameters */
-    pss = rsa_pss_decode(sigalg, &maskHash);
+    pss = rsa_pss_decode(sigalg);
 
-    if (pss == NULL) {
+    if (!rsa_pss_get_param(pss, &md, &mgf1md, &saltlen)) {
         RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_PSS_PARAMETERS);
         goto err;
     }
-    mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash);
-    if (!mgf1md)
-        goto err;
-    md = rsa_algor_to_md(pss->hashAlgorithm);
-    if (!md)
-        goto err;
-
-    if (pss->saltLength) {
-        saltlen = ASN1_INTEGER_get(pss->saltLength);
-
-        /*
-         * Could perform more salt length sanity checks but the main RSA
-         * routines will trap other invalid values anyway.
-         */
-        if (saltlen < 0) {
-            RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_SALT_LENGTH);
-            goto err;
-        }
-    } else
-        saltlen = 20;
-
-    /*
-     * low-level routines support only trailer field 0xbc (value 1) and
-     * PKCS#1 says we should reject any other value anyway.
-     */
-    if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) {
-        RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_TRAILER);
-        goto err;
-    }
 
     /* We have all parameters now set up context */
-
     if (pkey) {
         if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey))
             goto err;
@@ -568,22 +640,60 @@ static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
 
  err:
     RSA_PSS_PARAMS_free(pss);
-    X509_ALGOR_free(maskHash);
     return rv;
 }
 
+int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
+                      const EVP_MD **pmgf1md, int *psaltlen)
+{
+    if (pss == NULL)
+        return 0;
+    *pmd = rsa_algor_to_md(pss->hashAlgorithm);
+    if (*pmd == NULL)
+        return 0;
+    *pmgf1md = rsa_algor_to_md(pss->maskHash);
+    if (*pmgf1md == NULL)
+        return 0;
+    if (pss->saltLength) {
+        *psaltlen = ASN1_INTEGER_get(pss->saltLength);
+        if (*psaltlen < 0) {
+            RSAerr(RSA_F_RSA_PSS_GET_PARAM, RSA_R_INVALID_SALT_LENGTH);
+            return 0;
+        }
+    } else {
+        *psaltlen = 20;
+    }
+
+    /*
+     * low-level routines support only trailer field 0xbc (value 1) and
+     * PKCS#1 says we should reject any other value anyway.
+     */
+    if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) {
+        RSAerr(RSA_F_RSA_PSS_GET_PARAM, RSA_R_INVALID_TRAILER);
+        return 0;
+    }
+
+    return 1;
+}
+
 #ifndef OPENSSL_NO_CMS
 static int rsa_cms_verify(CMS_SignerInfo *si)
 {
     int nid, nid2;
     X509_ALGOR *alg;
     EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
+
     CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
     nid = OBJ_obj2nid(alg->algorithm);
+    if (nid == EVP_PKEY_RSA_PSS)
+        return rsa_pss_to_ctx(NULL, pkctx, alg, NULL);
+    /* Only PSS allowed for PSS keys */
+    if (pkey_ctx_is_pss(pkctx)) {
+        RSAerr(RSA_F_RSA_CMS_VERIFY, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
+        return 0;
+    }
     if (nid == NID_rsaEncryption)
         return 1;
-    if (nid == NID_rsassaPss)
-        return rsa_pss_to_ctx(NULL, pkctx, alg, NULL);
     /* Workaround for some implementation that use a signature OID */
     if (OBJ_find_sigid_algs(nid, NULL, &nid2)) {
         if (nid2 == NID_rsaEncryption)
@@ -603,7 +713,7 @@ static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
                            EVP_PKEY *pkey)
 {
     /* Sanity check: make sure it is PSS */
-    if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
+    if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) {
         RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
         return -1;
     }
@@ -621,6 +731,7 @@ static int rsa_cms_sign(CMS_SignerInfo *si)
     X509_ALGOR *alg;
     EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
     ASN1_STRING *os = NULL;
+
     CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
     if (pkctx) {
         if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
@@ -633,10 +744,10 @@ static int rsa_cms_sign(CMS_SignerInfo *si)
     /* We don't support it */
     if (pad_mode != RSA_PKCS1_PSS_PADDING)
         return 0;
-    os = rsa_ctx_to_pss(pkctx);
+    os = rsa_ctx_to_pss_string(pkctx);
     if (!os)
         return 0;
-    X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os);
+    X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_PKEY_RSA_PSS), V_ASN1_SEQUENCE, os);
     return 1;
 }
 #endif
@@ -647,13 +758,14 @@ static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
 {
     int pad_mode;
     EVP_PKEY_CTX *pkctx = EVP_MD_CTX_pkey_ctx(ctx);
+
     if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
         return 0;
     if (pad_mode == RSA_PKCS1_PADDING)
         return 2;
     if (pad_mode == RSA_PKCS1_PSS_PADDING) {
         ASN1_STRING *os1 = NULL;
-        os1 = rsa_ctx_to_pss(pkctx);
+        os1 = rsa_ctx_to_pss_string(pkctx);
         if (!os1)
             return 0;
         /* Duplicate parameters if we have to */
@@ -663,10 +775,10 @@ static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
                 ASN1_STRING_free(os1);
                 return 0;
             }
-            X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_rsassaPss),
+            X509_ALGOR_set0(alg2, OBJ_nid2obj(EVP_PKEY_RSA_PSS),
                             V_ASN1_SEQUENCE, os2);
         }
-        X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_rsassaPss),
+        X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_RSA_PSS),
                         V_ASN1_SEQUENCE, os1);
         return 3;
     }
@@ -674,22 +786,24 @@ static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
 }
 
 #ifndef OPENSSL_NO_CMS
-static RSA_OAEP_PARAMS *rsa_oaep_decode(const X509_ALGOR *alg,
-                                        X509_ALGOR **pmaskHash)
+static RSA_OAEP_PARAMS *rsa_oaep_decode(const X509_ALGOR *alg)
 {
-    RSA_OAEP_PARAMS *pss;
-
-    *pmaskHash = NULL;
+    RSA_OAEP_PARAMS *oaep;
 
-    pss = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_OAEP_PARAMS),
-                                    alg->parameter);
+    oaep = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_OAEP_PARAMS),
+                                     alg->parameter);
 
-    if (!pss)
+    if (oaep == NULL)
         return NULL;
 
-    *pmaskHash = rsa_mgf1_decode(pss->maskGenFunc);
-
-    return pss;
+    if (oaep->maskGenFunc != NULL) {
+        oaep->maskHash = rsa_mgf1_decode(oaep->maskGenFunc);
+        if (oaep->maskHash == NULL) {
+            RSA_OAEP_PARAMS_free(oaep);
+            return NULL;
+        }
+    }
+    return oaep;
 }
 
 static int rsa_cms_decrypt(CMS_RecipientInfo *ri)
@@ -702,9 +816,9 @@ static int rsa_cms_decrypt(CMS_RecipientInfo *ri)
     int labellen = 0;
     const EVP_MD *mgf1md = NULL, *md = NULL;
     RSA_OAEP_PARAMS *oaep;
-    X509_ALGOR *maskHash;
+
     pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
-    if (!pkctx)
+    if (pkctx == NULL)
         return 0;
     if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg))
         return -1;
@@ -716,22 +830,23 @@ static int rsa_cms_decrypt(CMS_RecipientInfo *ri)
         return -1;
     }
     /* Decode OAEP parameters */
-    oaep = rsa_oaep_decode(cmsalg, &maskHash);
+    oaep = rsa_oaep_decode(cmsalg);
 
     if (oaep == NULL) {
         RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_OAEP_PARAMETERS);
         goto err;
     }
 
-    mgf1md = rsa_mgf1_to_md(oaep->maskGenFunc, maskHash);
-    if (!mgf1md)
+    mgf1md = rsa_algor_to_md(oaep->maskHash);
+    if (mgf1md == NULL)
         goto err;
     md = rsa_algor_to_md(oaep->hashFunc);
-    if (!md)
+    if (md == NULL)
         goto err;
 
-    if (oaep->pSourceFunc) {
+    if (oaep->pSourceFunc != NULL) {
         X509_ALGOR *plab = oaep->pSourceFunc;
+
         if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) {
             RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_LABEL_SOURCE);
             goto err;
@@ -760,7 +875,6 @@ static int rsa_cms_decrypt(CMS_RecipientInfo *ri)
 
  err:
     RSA_OAEP_PARAMS_free(oaep);
-    X509_ALGOR_free(maskHash);
     return rv;
 }
 
@@ -773,6 +887,7 @@ static int rsa_cms_encrypt(CMS_RecipientInfo *ri)
     EVP_PKEY_CTX *pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
     int pad_mode = RSA_PKCS1_PADDING, rv = 0, labellen;
     unsigned char *label;
+
     CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg);
     if (pkctx) {
         if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
@@ -864,3 +979,34 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
      EVP_PKEY_RSA,
      ASN1_PKEY_ALIAS}
 };
+
+const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth = {
+     EVP_PKEY_RSA_PSS,
+     EVP_PKEY_RSA_PSS,
+     ASN1_PKEY_SIGPARAM_NULL,
+
+     "RSA-PSS",
+     "OpenSSL RSA-PSS method",
+
+     rsa_pub_decode,
+     rsa_pub_encode,
+     rsa_pub_cmp,
+     rsa_pub_print,
+
+     rsa_priv_decode,
+     rsa_priv_encode,
+     rsa_priv_print,
+
+     int_rsa_size,
+     rsa_bits,
+     rsa_security_bits,
+
+     0, 0, 0, 0, 0, 0,
+
+     rsa_sig_print,
+     int_rsa_free,
+     rsa_pkey_ctrl,
+     0, 0,
+     rsa_item_verify,
+     rsa_item_sign,
+};
diff --git a/crypto/rsa/rsa_asn1.c b/crypto/rsa/rsa_asn1.c
index 20f8ebf..626a479 100644
--- a/crypto/rsa/rsa_asn1.c
+++ b/crypto/rsa/rsa_asn1.c
@@ -49,20 +49,42 @@ ASN1_SEQUENCE_cb(RSAPublicKey, rsa_cb) = {
         ASN1_SIMPLE(RSA, e, BIGNUM),
 } ASN1_SEQUENCE_END_cb(RSA, RSAPublicKey)
 
-ASN1_SEQUENCE(RSA_PSS_PARAMS) = {
+/* Free up maskHash */
+static int rsa_pss_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+                      void *exarg)
+{
+    if (operation == ASN1_OP_FREE_PRE) {
+        RSA_PSS_PARAMS *pss = (RSA_PSS_PARAMS *)*pval;
+        X509_ALGOR_free(pss->maskHash);
+    }
+    return 1;
+}
+
+ASN1_SEQUENCE_cb(RSA_PSS_PARAMS, rsa_pss_cb) = {
         ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
         ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1),
         ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2),
         ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3)
-} ASN1_SEQUENCE_END(RSA_PSS_PARAMS)
+} ASN1_SEQUENCE_END_cb(RSA_PSS_PARAMS, RSA_PSS_PARAMS)
 
 IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
 
-ASN1_SEQUENCE(RSA_OAEP_PARAMS) = {
+/* Free up maskHash */
+static int rsa_oaep_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+                       void *exarg)
+{
+    if (operation == ASN1_OP_FREE_PRE) {
+        RSA_OAEP_PARAMS *oaep = (RSA_OAEP_PARAMS *)*pval;
+        X509_ALGOR_free(oaep->maskHash);
+    }
+    return 1;
+}
+
+ASN1_SEQUENCE_cb(RSA_OAEP_PARAMS, rsa_oaep_cb) = {
         ASN1_EXP_OPT(RSA_OAEP_PARAMS, hashFunc, X509_ALGOR, 0),
         ASN1_EXP_OPT(RSA_OAEP_PARAMS, maskGenFunc, X509_ALGOR, 1),
         ASN1_EXP_OPT(RSA_OAEP_PARAMS, pSourceFunc, X509_ALGOR, 2),
-} ASN1_SEQUENCE_END(RSA_OAEP_PARAMS)
+} ASN1_SEQUENCE_END_cb(RSA_OAEP_PARAMS, RSA_OAEP_PARAMS)
 
 IMPLEMENT_ASN1_FUNCTIONS(RSA_OAEP_PARAMS)
 
diff --git a/crypto/rsa/rsa_err.c b/crypto/rsa/rsa_err.c
index bf54095..45fd4ca 100644
--- a/crypto/rsa/rsa_err.c
+++ b/crypto/rsa/rsa_err.c
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -33,6 +33,7 @@ static ERR_STRING_DATA RSA_str_functs[] = {
     {ERR_FUNC(RSA_F_RSA_CHECK_KEY), "RSA_check_key"},
     {ERR_FUNC(RSA_F_RSA_CHECK_KEY_EX), "RSA_check_key_ex"},
     {ERR_FUNC(RSA_F_RSA_CMS_DECRYPT), "rsa_cms_decrypt"},
+    {ERR_FUNC(RSA_F_RSA_CMS_VERIFY), "rsa_cms_verify"},
     {ERR_FUNC(RSA_F_RSA_ITEM_VERIFY), "rsa_item_verify"},
     {ERR_FUNC(RSA_F_RSA_METH_DUP), "RSA_meth_dup"},
     {ERR_FUNC(RSA_F_RSA_METH_NEW), "RSA_meth_new"},
@@ -73,9 +74,12 @@ static ERR_STRING_DATA RSA_str_functs[] = {
      "RSA_padding_check_PKCS1_type_2"},
     {ERR_FUNC(RSA_F_RSA_PADDING_CHECK_SSLV23), "RSA_padding_check_SSLv23"},
     {ERR_FUNC(RSA_F_RSA_PADDING_CHECK_X931), "RSA_padding_check_X931"},
+    {ERR_FUNC(RSA_F_RSA_PARAM_DECODE), "rsa_param_decode"},
     {ERR_FUNC(RSA_F_RSA_PRINT), "RSA_print"},
     {ERR_FUNC(RSA_F_RSA_PRINT_FP), "RSA_print_fp"},
+    {ERR_FUNC(RSA_F_RSA_PRIV_DECODE), "rsa_priv_decode"},
     {ERR_FUNC(RSA_F_RSA_PRIV_ENCODE), "rsa_priv_encode"},
+    {ERR_FUNC(RSA_F_RSA_PSS_GET_PARAM), "rsa_pss_get_param"},
     {ERR_FUNC(RSA_F_RSA_PSS_TO_CTX), "rsa_pss_to_ctx"},
     {ERR_FUNC(RSA_F_RSA_PUB_DECODE), "rsa_pub_decode"},
     {ERR_FUNC(RSA_F_RSA_SETUP_BLINDING), "RSA_setup_blinding"},
@@ -108,6 +112,7 @@ static ERR_STRING_DATA RSA_str_reasons[] = {
     {ERR_REASON(RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE),
      "data too small for key size"},
     {ERR_REASON(RSA_R_DIGEST_DOES_NOT_MATCH), "digest does not match"},
+    {ERR_REASON(RSA_R_DIGEST_NOT_ALLOWED), "digest not allowed"},
     {ERR_REASON(RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY),
      "digest too big for rsa key"},
     {ERR_REASON(RSA_R_DMP1_NOT_CONGRUENT_TO_D), "dmp1 not congruent to d"},
@@ -133,6 +138,7 @@ static ERR_STRING_DATA RSA_str_reasons[] = {
     {ERR_REASON(RSA_R_IQMP_NOT_INVERSE_OF_Q), "iqmp not inverse of q"},
     {ERR_REASON(RSA_R_KEY_SIZE_TOO_SMALL), "key size too small"},
     {ERR_REASON(RSA_R_LAST_OCTET_INVALID), "last octet invalid"},
+    {ERR_REASON(RSA_R_MGF1_DIGEST_NOT_ALLOWED), "mgf1 digest not allowed"},
     {ERR_REASON(RSA_R_MODULUS_TOO_LARGE), "modulus too large"},
     {ERR_REASON(RSA_R_NO_PUBLIC_EXPONENT), "no public exponent"},
     {ERR_REASON(RSA_R_NULL_BEFORE_BLOCK_MISSING),
@@ -143,6 +149,7 @@ static ERR_STRING_DATA RSA_str_reasons[] = {
      "operation not supported for this keytype"},
     {ERR_REASON(RSA_R_PADDING_CHECK_FAILED), "padding check failed"},
     {ERR_REASON(RSA_R_PKCS_DECODING_ERROR), "pkcs decoding error"},
+    {ERR_REASON(RSA_R_PSS_SALTLEN_TOO_SMALL), "pss saltlen too small"},
     {ERR_REASON(RSA_R_P_NOT_PRIME), "p not prime"},
     {ERR_REASON(RSA_R_Q_NOT_PRIME), "q not prime"},
     {ERR_REASON(RSA_R_RSA_OPERATIONS_NOT_SUPPORTED),
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c
index e41644b..0fbda9a 100644
--- a/crypto/rsa/rsa_lib.c
+++ b/crypto/rsa/rsa_lib.c
@@ -13,6 +13,8 @@
 #include <openssl/lhash.h>
 #include "internal/bn_int.h"
 #include <openssl/engine.h>
+#include <openssl/evp.h>
+#include "internal/evp_int.h"
 #include "rsa_locl.h"
 
 static const RSA_METHOD *default_RSA_meth = NULL;
@@ -152,6 +154,7 @@ void RSA_free(RSA *r)
     BN_clear_free(r->dmp1);
     BN_clear_free(r->dmq1);
     BN_clear_free(r->iqmp);
+    RSA_PSS_PARAMS_free(r->pss);
     BN_BLINDING_free(r->blinding);
     BN_BLINDING_free(r->mt_blinding);
     OPENSSL_free(r->bignum_data);
@@ -308,3 +311,13 @@ ENGINE *RSA_get0_engine(const RSA *r)
 {
     return r->engine;
 }
+
+int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2)
+{
+    /* If key type not RSA or RSA-PSS return error */
+    if (ctx != NULL && ctx->pmeth != NULL
+        && ctx->pmeth->pkey_id != EVP_PKEY_RSA
+        && ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
+        return -1;
+     return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, p1, p2);
+}
diff --git a/crypto/rsa/rsa_locl.h b/crypto/rsa/rsa_locl.h
index e342ca8..f2681f9 100644
--- a/crypto/rsa/rsa_locl.h
+++ b/crypto/rsa/rsa_locl.h
@@ -28,6 +28,8 @@ struct rsa_st {
     BIGNUM *dmp1;
     BIGNUM *dmq1;
     BIGNUM *iqmp;
+    /* If a PSS only key this contains the parameter restrictions */
+    RSA_PSS_PARAMS *pss;
     /* be careful using this if the RSA structure is shared */
     CRYPTO_EX_DATA ex_data;
     CRYPTO_REF_COUNT references;
@@ -95,3 +97,11 @@ 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)
+
+RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd,
+                                      const EVP_MD *mgf1md, int saltlen);
+int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
+                      const EVP_MD **pmgf1md, int *psaltlen);
diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c
index db4fb0f..d55fb21 100644
--- a/crypto/rsa/rsa_pmeth.c
+++ b/crypto/rsa/rsa_pmeth.c
@@ -35,6 +35,8 @@ typedef struct {
     const EVP_MD *mgf1md;
     /* PSS salt length */
     int saltlen;
+    /* Minimum salt length or -1 if no PSS parameter restriction */
+    int min_saltlen;
     /* Temp buffer */
     unsigned char *tbuf;
     /* OAEP label */
@@ -42,15 +44,22 @@ typedef struct {
     size_t oaep_labellen;
 } RSA_PKEY_CTX;
 
+/* True if PSS parameters are restricted */
+#define rsa_pss_restricted(rctx) (rctx->min_saltlen != -1)
+
 static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
 {
-    RSA_PKEY_CTX *rctx;
-    rctx = OPENSSL_zalloc(sizeof(*rctx));
+    RSA_PKEY_CTX *rctx = OPENSSL_zalloc(sizeof(*rctx));
+
     if (rctx == NULL)
         return 0;
     rctx->nbits = 1024;
-    rctx->pad_mode = RSA_PKCS1_PADDING;
+    if (pkey_ctx_is_pss(ctx))
+        rctx->pad_mode = RSA_PKCS1_PSS_PADDING;
+    else
+        rctx->pad_mode = RSA_PKCS1_PADDING;
     rctx->saltlen = -2;
+    rctx->min_saltlen = -1;
     ctx->data = rctx;
     ctx->keygen_info = rctx->gentmp;
     ctx->keygen_info_count = 2;
@@ -61,6 +70,7 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
 static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
 {
     RSA_PKEY_CTX *dctx, *sctx;
+
     if (!pkey_rsa_init(dst))
         return 0;
     sctx = src->data;
@@ -86,7 +96,7 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
 
 static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk)
 {
-    if (ctx->tbuf)
+    if (ctx->tbuf != NULL)
         return 1;
     ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey));
     if (ctx->tbuf == NULL)
@@ -225,6 +235,7 @@ static int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
     RSA_PKEY_CTX *rctx = ctx->data;
     RSA *rsa = ctx->pkey->pkey.rsa;
     size_t rslen;
+
     if (rctx->md) {
         if (rctx->pad_mode == RSA_PKCS1_PADDING)
             return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen,
@@ -274,6 +285,7 @@ static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx,
 {
     int ret;
     RSA_PKEY_CTX *rctx = ctx->data;
+
     if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
         int klen = RSA_size(ctx->pkey->pkey.rsa);
         if (!setup_tbuf(rctx, ctx))
@@ -301,6 +313,7 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
 {
     int ret;
     RSA_PKEY_CTX *rctx = ctx->data;
+
     if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
         int i;
         if (!setup_tbuf(rctx, ctx))
@@ -330,6 +343,7 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
 static int check_padding_md(const EVP_MD *md, int padding)
 {
     int mdnid;
+
     if (!md)
         return 1;
 
@@ -374,6 +388,7 @@ static int check_padding_md(const EVP_MD *md, int padding)
 static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
 {
     RSA_PKEY_CTX *rctx = ctx->data;
+
     switch (type) {
     case EVP_PKEY_CTRL_RSA_PADDING:
         if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_PKCS1_PSS_PADDING)) {
@@ -385,6 +400,8 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                     goto bad_pad;
                 if (!rctx->md)
                     rctx->md = EVP_sha1();
+            } else if (pkey_ctx_is_pss(ctx)) {
+                goto bad_pad;
             }
             if (p1 == RSA_PKCS1_OAEP_PADDING) {
                 if (!(ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))
@@ -410,11 +427,15 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
             RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN);
             return -2;
         }
-        if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN)
+        if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) {
             *(int *)p2 = rctx->saltlen;
-        else {
+        } else {
             if (p1 < -2)
                 return -2;
+            if (rsa_pss_restricted(rctx) && p1 < rctx->min_saltlen) {
+                RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_PSS_SALTLEN_TOO_SMALL);
+                return 0;
+            }
             rctx->saltlen = p1;
         }
         return 1;
@@ -451,6 +472,12 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
     case EVP_PKEY_CTRL_MD:
         if (!check_padding_md(p2, rctx->pad_mode))
             return 0;
+        if (rsa_pss_restricted(rctx)) {
+            if (EVP_MD_type(rctx->md) == EVP_MD_type(p2))
+                return 1;
+            RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_DIGEST_NOT_ALLOWED);
+            return 0;
+        }
         rctx->md = p2;
         return 1;
 
@@ -470,8 +497,15 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
                 *(const EVP_MD **)p2 = rctx->mgf1md;
             else
                 *(const EVP_MD **)p2 = rctx->md;
-        } else
+        } else {
+            if (rsa_pss_restricted(rctx)) {
+                if (EVP_MD_type(rctx->md) == EVP_MD_type(p2))
+                    return 1;
+                RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_MGF1_DIGEST_NOT_ALLOWED);
+                return 0;
+            }
             rctx->mgf1md = p2;
+        }
         return 1;
 
     case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
@@ -498,14 +532,18 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
         return rctx->oaep_labellen;
 
     case EVP_PKEY_CTRL_DIGESTINIT:
+    case EVP_PKEY_CTRL_PKCS7_SIGN:
+#ifndef OPENSSL_NO_CMS
+    case EVP_PKEY_CTRL_CMS_SIGN:
+#endif
+    return 1;
+
     case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
     case EVP_PKEY_CTRL_PKCS7_DECRYPT:
-    case EVP_PKEY_CTRL_PKCS7_SIGN:
-        return 1;
 #ifndef OPENSSL_NO_CMS
     case EVP_PKEY_CTRL_CMS_DECRYPT:
     case EVP_PKEY_CTRL_CMS_ENCRYPT:
-    case EVP_PKEY_CTRL_CMS_SIGN:
+    if (!pkey_ctx_is_pss(ctx))
         return 1;
 #endif
     case EVP_PKEY_CTRL_PEER_KEY:
@@ -522,7 +560,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
 static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
                              const char *type, const char *value)
 {
-    if (!value) {
+    if (value == NULL) {
         RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_VALUE_MISSING);
         return 0;
     }
@@ -572,23 +610,32 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
         return ret;
     }
 
-    if (strcmp(type, "rsa_mgf1_md") == 0) {
-        const EVP_MD *md;
-        if ((md = EVP_get_digestbyname(value)) == NULL) {
-            RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_INVALID_DIGEST);
-            return 0;
-        }
-        return EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md);
-    }
+    if (strcmp(type, "rsa_mgf1_md") == 0)
+        return EVP_PKEY_CTX_md(ctx,
+                               EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
+                               EVP_PKEY_CTRL_RSA_MGF1_MD, value);
 
-    if (strcmp(type, "rsa_oaep_md") == 0) {
-        const EVP_MD *md;
-        if ((md = EVP_get_digestbyname(value)) == NULL) {
-            RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_INVALID_DIGEST);
-            return 0;
+    if (pkey_ctx_is_pss(ctx)) {
+
+        if (strcmp(type, "rsa_pss_keygen_mgf1_md") == 0)
+            return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN,
+                                   EVP_PKEY_CTRL_RSA_MGF1_MD, value);
+
+        if (strcmp(type, "rsa_pss_keygen_md") == 0)
+            return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN,
+                                   EVP_PKEY_CTRL_MD, value);
+
+        if (strcmp(type, "rsa_pss_keygen_saltlen") == 0) {
+            int saltlen = atoi(value);
+
+            return EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, saltlen);
         }
-        return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md);
     }
+
+    if (strcmp(type, "rsa_oaep_md") == 0)
+        return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_CRYPT,
+                               EVP_PKEY_CTRL_RSA_OAEP_MD, value);
+
     if (strcmp(type, "rsa_oaep_label") == 0) {
         unsigned char *lab;
         long lablen;
@@ -605,12 +652,30 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
     return -2;
 }
 
+/* Set PSS parameters when generating a key, if necessary */
+static int rsa_set_pss_param(RSA *rsa, EVP_PKEY_CTX *ctx)
+{
+    RSA_PKEY_CTX *rctx = ctx->data;
+
+    if (!pkey_ctx_is_pss(ctx))
+        return 1;
+    /* If all parameters are default values don't set pss */
+    if (rctx->md == NULL && rctx->mgf1md == NULL && rctx->saltlen == -2)
+        return 1;
+    rsa->pss = rsa_pss_params_create(rctx->md, rctx->mgf1md,
+                                     rctx->saltlen == -2 ? 0 : rctx->saltlen);
+    if (rsa->pss == NULL)
+        return 0;
+    return 1;
+}
+
 static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
 {
     RSA *rsa = NULL;
     RSA_PKEY_CTX *rctx = ctx->data;
     BN_GENCB *pcb;
     int ret;
+
     if (rctx->pub_exp == NULL) {
         rctx->pub_exp = BN_new();
         if (rctx->pub_exp == NULL || !BN_set_word(rctx->pub_exp, RSA_F4))
@@ -630,8 +695,12 @@ static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
         pcb = NULL;
     ret = RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, pcb);
     BN_GENCB_free(pcb);
+    if (ret > 0 && !rsa_set_pss_param(rsa, ctx)) {
+        RSA_free(rsa);
+        return 0;
+    }
     if (ret > 0)
-        EVP_PKEY_assign_RSA(pkey, rsa);
+        EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, rsa);
     else
         RSA_free(rsa);
     return ret;
@@ -671,3 +740,65 @@ const EVP_PKEY_METHOD rsa_pkey_meth = {
     pkey_rsa_ctrl,
     pkey_rsa_ctrl_str
 };
+
+/*
+ * Called for PSS sign or verify initialisation: checks PSS parameter
+ * sanity and sets any restrictions on key usage.
+ */
+
+static int pkey_pss_init(EVP_PKEY_CTX *ctx)
+{
+    RSA *rsa;
+    RSA_PKEY_CTX *rctx = ctx->data;
+    const EVP_MD *md;
+    const EVP_MD *mgf1md;
+    int min_saltlen;
+
+    /* Should never happen */
+    if (!pkey_ctx_is_pss(ctx))
+        return 0;
+    rsa = ctx->pkey->pkey.rsa;
+    /* If no restrictions just return */
+    if (rsa->pss == NULL)
+        return 1;
+    /* Get and check parameters */
+    if (!rsa_pss_get_param(rsa->pss, &md, &mgf1md, &min_saltlen))
+        return 0;
+
+    rctx->min_saltlen = min_saltlen;
+
+    /*
+     * Set PSS restrictions as defaults: we can then block any attempt to
+     * use invalid values in pkey_rsa_ctrl
+     */
+
+    rctx->md = md;
+    rctx->mgf1md = mgf1md;
+    rctx->saltlen = min_saltlen;
+
+    return 1;
+}
+
+const EVP_PKEY_METHOD rsa_pss_pkey_meth = {
+    EVP_PKEY_RSA_PSS,
+    EVP_PKEY_FLAG_AUTOARGLEN,
+    pkey_rsa_init,
+    pkey_rsa_copy,
+    pkey_rsa_cleanup,
+
+    0, 0,
+
+    0,
+    pkey_rsa_keygen,
+
+    pkey_pss_init,
+    pkey_rsa_sign,
+
+    pkey_pss_init,
+    pkey_rsa_verify,
+
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+    pkey_rsa_ctrl,
+    pkey_rsa_ctrl_str
+};
diff --git a/doc/man1/genpkey.pod b/doc/man1/genpkey.pod
index e77fc7e..8df0905 100644
--- a/doc/man1/genpkey.pod
+++ b/doc/man1/genpkey.pod
@@ -111,6 +111,31 @@ hexadecimal value if preceded by B<0x>. Default value is 65537.
 
 =back
 
+=head1 RSA-PSS KEY GENERATION OPTIONS
+
+Note: by default an B<RSA-PSS> key has no parameter restrictions.
+
+=over 4
+
+=item B<rsa_keygen_bits:numbits>, B<rsa_keygen_pubexp:value>
+
+These options have the same meaning as the B<RSA> algorithm.
+
+=item B<rsa_pss_keygen_md:digest>
+
+If set the key is restricted and can only use B<digest> for signing.
+
+=item B<rsa_pss_keygen_mgf1_md:digest>
+
+If set the key is restricted and can only use B<digest> as it's MGF1
+parameter.
+
+=item B<rsa_pss_keygen_saltlen:len>
+
+If set the key is restricted and B<len> specifies the minimum salt length.
+
+=back
+
 =head1 DSA PARAMETER GENERATION OPTIONS
 
 =over 4
diff --git a/doc/man1/pkeyutl.pod b/doc/man1/pkeyutl.pod
index ceb9de3..6fc0325 100644
--- a/doc/man1/pkeyutl.pod
+++ b/doc/man1/pkeyutl.pod
@@ -221,6 +221,32 @@ sets the salt length to the maximum permissible value. When verifying -2 causes
 the salt length to be automatically determined based on the B<PSS> block
 structure.
 
+=item B<rsa_mgf1_md:digest>
+
+For PSS and OAEP padding sets the MGF1 digest. If the MGF1 digest is not
+explicitly set in PSS mode then the signing digest is used.
+
+=back
+
+=head1 RSA-PSS ALGORITHM
+
+The RSA-PSS algorithm is a restricted version of the RSA algorithm which only
+supports the sign and verify operations with PSS padding. The following
+additional B<pkeyopt> values are supported:
+
+=over 4
+
+=item B<rsa_padding_mode:mode>, B<rsa_pss_saltlen:len>, B<rsa_mgf1_md:digest>
+
+These have the same meaning as the B<RSA> algorithm with some additional
+restrictions. The padding mode can only be set to B<pss> which is the
+default value.
+
+If the key has parameter restrictions than the digest, MGF1
+digest and salt length are set to the values specified in the parameters.
+The digest and MG cannot be changed and the salt length cannot be set to a
+value less than the minimum restriction.
+
 =back
 
 =head1 DSA ALGORITHM
diff --git a/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md.pod b/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md.pod
new file mode 100644
index 0000000..eb7dfd8
--- /dev/null
+++ b/doc/man3/EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md.pod
@@ -0,0 +1,99 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_CTX_set_rsa_pss_keygen_md, EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md,
+EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen - RSA PSS signature algorithm
+
+=head1 SYNOPSIS
+
+ #include <openssl/rsa.h>
+
+ int EVP_PKEY_CTX_set_rsa_pss_keygen_md(EVP_PKEY_CTX *pctx,
+                                        const EVP_MD *md);
+ int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *pctx,
+                                             const EVP_MD *md);
+ int EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(EVP_PKEY_CTX *pctx,
+                                             int saltlen);
+
+=head1 DESCRIPTION
+
+The B<EVP_PKEY_RSA_PSS> algorithm implements the RSA PSS signature algorithm.
+It is a restricted version of the RSA algorithm which only supports signing,
+verification and key generation using PSS padding modes with optional
+parameter restrictions.
+
+It has associated private key and public key formats.
+
+This algorithm shares several control operations with the B<RSA> algorithm
+but with some restrictions described below.
+
+=head1 SIGNING AND VERIFICATION
+
+Siging and verification is similar to the B<RSA> algorithm except the
+padding mode is always PSS. If the key in use has parameter restrictions then
+the corresponding signature parameters are set to the restrictions:
+for example, if the key can only be used with digest SHA256, MGF1 SHA256
+and minimum salt length 32 then the digest, MGF1 digest and salt length
+will be set to SHA256, SHA256 and 32 respectively.
+
+The macro EVP_PKEY_CTX_set_rsa_padding() is supported but an error is
+returned if an attempt is made to set the padding mode to anything other
+than B<PSS>. It is otherwise similar to the B<RSA> version.
+
+The EVP_PKEY_CTX_set_rsa_pss_saltlen() macro is used to set the salt length.
+If the key has usage restrictionsthen an error is returned if an attempt is
+made to set the salt length below the minimum value. It is otherwise similar
+to the B<RSA> operation except special negative values are not supported.
+
+The EVP_PKEY_CTX_set_signature_md() and EVP_PKEY_CTX_set_rsa_mgf1_md() macros
+are used to set the digest and MGF1 algorithms respectively. If the key has
+usage restrictions then an error is returned if an attempt is made to set the
+digest to anything other than the restricted value. Otherwise these are
+similar to the B<RSA> versions.
+
+=head1 KEY GENERATION
+
+As with RSA key generation the EVP_PKEY_CTX_set_rsa_rsa_keygen_bits()
+and EVP_PKEY_CTX_set_rsa_keygen_pubexp() macros are supported for RSA PSS:
+they have exactly the same meaning as for the RSA algorithm.
+
+Optional parameter restrictions can be specified when generating a PSS key. By
+default no parameter restrictions are placed on the generated key. If any
+restrictions are set (using the macros described below) then B<all> parameters
+are restricted. For example, setting a minimum salt length also restricts the
+digest and MGF1 algorithms. If any restrictions are in place then they are
+reflected in the corresponding parameters of the public key when (for example)
+a certificate request is signed.
+
+EVP_PKEY_CTX_set_rsa_pss_keygen_md() restricts the digest algorithm the
+generated key can use to B<md>.
+
+EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md() restricts the MGF1 algorithm the
+generated key can use to B<md>.
+
+EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen() restricts the minimum salt length
+to B<saltlen>.
+
+=head1 RETURN VALUES
+
+All these functions return 1 for success and 0 or a negative value for failure.
+In particular a return value of -2 indicates the operation is not supported by
+the public key algorithm.
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>,
+L<EVP_PKEY_CTX_ctrl_str(3)>,
+L<EVP_PKEY_derive(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the OpenSSL license (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
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 8216a8f..00c3a3d 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -40,6 +40,7 @@
 # define EVP_PKEY_NONE   NID_undef
 # define EVP_PKEY_RSA    NID_rsaEncryption
 # define EVP_PKEY_RSA2   NID_rsa
+# define EVP_PKEY_RSA_PSS NID_rsassaPss
 # define EVP_PKEY_DSA    NID_dsa
 # define EVP_PKEY_DSA1   NID_dsa_2
 # define EVP_PKEY_DSA2   NID_dsaWithSHA
@@ -1204,6 +1205,8 @@ int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
 int EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str);
 int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex);
 
+int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md);
+
 int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx);
 void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen);
 
@@ -1483,6 +1486,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_F_EVP_PKEY_CTX_CTRL                          137
 # define EVP_F_EVP_PKEY_CTX_CTRL_STR                      150
 # define EVP_F_EVP_PKEY_CTX_DUP                           156
+# define EVP_F_EVP_PKEY_CTX_MD                            168
 # define EVP_F_EVP_PKEY_DECRYPT                           104
 # define EVP_F_EVP_PKEY_DECRYPT_INIT                      138
 # define EVP_F_EVP_PKEY_DECRYPT_OLD                       151
diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h
index d97d6e0..95639cb 100644
--- a/include/openssl/rsa.h
+++ b/include/openssl/rsa.h
@@ -86,46 +86,46 @@ extern "C" {
 # endif
 
 # define EVP_PKEY_CTX_set_rsa_padding(ctx, pad) \
-        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, \
-                                pad, NULL)
+        RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_RSA_PADDING, pad, NULL)
 
 # define EVP_PKEY_CTX_get_rsa_padding(ctx, ppad) \
-        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, \
-                                EVP_PKEY_CTRL_GET_RSA_PADDING, 0, ppad)
+        RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, 0, ppad)
 
 # define EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, len) \
-        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, \
-                                (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \
-                                EVP_PKEY_CTRL_RSA_PSS_SALTLEN, \
-                                len, NULL)
+        RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \
+                          EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL)
+
+# define EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, len) \
+        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) \
-        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, \
-                                (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \
-                                EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, \
-                                0, 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) \
-        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, \
-                                EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL)
+        RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
+                          EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL)
 
 # define EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp) \
-        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, \
-                                EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp)
+        RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \
+                          EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp)
 
 # define  EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md)  \
-                EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, \
-                        EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \
-                                EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)md)
+        RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \
+                          EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)md)
+
+# define  EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(ctx, md)  \
+        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \
+                          EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)md)
 
 # define  EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md)  \
                 EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,  \
                                 EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)md)
 
 # define  EVP_PKEY_CTX_get_rsa_mgf1_md(ctx, pmd) \
-                EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, \
-                        EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \
-                                EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)pmd)
+        RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \
+                          EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)pmd)
 
 # define  EVP_PKEY_CTX_get_rsa_oaep_md(ctx, pmd) \
                 EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,  \
@@ -139,6 +139,11 @@ extern "C" {
                 EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,  \
                                 EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, (void *)l)
 
+# define  EVP_PKEY_CTX_rsa_pss_keygen_md(ctx, md)  \
+                EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, \
+                                  EVP_PKEY_OP_TYPE_KEYGEN, EVP_PKEY_CTRL_MD, \
+                                  0, (void *)md)
+
 # define EVP_PKEY_CTRL_RSA_PADDING       (EVP_PKEY_ALG_CTRL + 1)
 # define EVP_PKEY_CTRL_RSA_PSS_SALTLEN   (EVP_PKEY_ALG_CTRL + 2)
 
@@ -231,6 +236,8 @@ const RSA_METHOD *RSA_PKCS1_OpenSSL(void);
 
 const RSA_METHOD *RSA_null_method(void);
 
+int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2);
+
 DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey)
 DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey)
 
@@ -239,6 +246,8 @@ typedef struct rsa_pss_params_st {
     X509_ALGOR *maskGenAlgorithm;
     ASN1_INTEGER *saltLength;
     ASN1_INTEGER *trailerField;
+    /* Decoded hash algorithm from maskGenAlgorithm */
+    X509_ALGOR *maskHash;
 } RSA_PSS_PARAMS;
 
 DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
@@ -247,6 +256,8 @@ typedef struct rsa_oaep_params_st {
     X509_ALGOR *hashFunc;
     X509_ALGOR *maskGenFunc;
     X509_ALGOR *pSourceFunc;
+    /* Decoded hash algorithm from maskGenFunc */
+    X509_ALGOR *maskHash;
 } RSA_OAEP_PARAMS;
 
 DECLARE_ASN1_FUNCTIONS(RSA_OAEP_PARAMS)
@@ -475,6 +486,7 @@ int ERR_load_RSA_strings(void);
 # define RSA_F_RSA_CHECK_KEY                              123
 # define RSA_F_RSA_CHECK_KEY_EX                           160
 # define RSA_F_RSA_CMS_DECRYPT                            159
+# define RSA_F_RSA_CMS_VERIFY                             158
 # define RSA_F_RSA_ITEM_VERIFY                            148
 # define RSA_F_RSA_METH_DUP                               161
 # define RSA_F_RSA_METH_NEW                               162
@@ -506,9 +518,12 @@ int ERR_load_RSA_strings(void);
 # define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2             113
 # define RSA_F_RSA_PADDING_CHECK_SSLV23                   114
 # define RSA_F_RSA_PADDING_CHECK_X931                     128
+# define RSA_F_RSA_PARAM_DECODE                           164
 # define RSA_F_RSA_PRINT                                  115
 # define RSA_F_RSA_PRINT_FP                               116
+# define RSA_F_RSA_PRIV_DECODE                            150
 # define RSA_F_RSA_PRIV_ENCODE                            138
+# define RSA_F_RSA_PSS_GET_PARAM                          151
 # define RSA_F_RSA_PSS_TO_CTX                             155
 # define RSA_F_RSA_PUB_DECODE                             139
 # define RSA_F_RSA_SETUP_BLINDING                         136
@@ -533,6 +548,7 @@ int ERR_load_RSA_strings(void);
 # define RSA_R_DATA_TOO_SMALL                             111
 # define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE                122
 # define RSA_R_DIGEST_DOES_NOT_MATCH                      158
+# define RSA_R_DIGEST_NOT_ALLOWED                         145
 # define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY                 112
 # define RSA_R_DMP1_NOT_CONGRUENT_TO_D                    124
 # define RSA_R_DMQ1_NOT_CONGRUENT_TO_D                    125
@@ -556,6 +572,7 @@ int ERR_load_RSA_strings(void);
 # define RSA_R_IQMP_NOT_INVERSE_OF_Q                      126
 # define RSA_R_KEY_SIZE_TOO_SMALL                         120
 # define RSA_R_LAST_OCTET_INVALID                         134
+# define RSA_R_MGF1_DIGEST_NOT_ALLOWED                    152
 # define RSA_R_MODULUS_TOO_LARGE                          105
 # define RSA_R_NO_PUBLIC_EXPONENT                         140
 # define RSA_R_NULL_BEFORE_BLOCK_MISSING                  113
@@ -564,6 +581,7 @@ int ERR_load_RSA_strings(void);
 # define RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE   148
 # define RSA_R_PADDING_CHECK_FAILED                       114
 # define RSA_R_PKCS_DECODING_ERROR                        159
+# define RSA_R_PSS_SALTLEN_TOO_SMALL                      164
 # define RSA_R_P_NOT_PRIME                                128
 # define RSA_R_Q_NOT_PRIME                                129
 # define RSA_R_RSA_OPERATIONS_NOT_SUPPORTED               130
diff --git a/test/evptests.txt b/test/evptests.txt
index 413de2c..095aced 100644
--- a/test/evptests.txt
+++ b/test/evptests.txt
@@ -2968,6 +2968,108 @@ Input="0123456789ABCDEF0123456789ABCDEF"
 Output=4DE433D5844043EF08D354DA03CB29068780D52706D7D1E4D50EFB7D58C9D547D83A747DDD0635A96B28F854E50145518482CB49E963054621B53C60C498D07C16E9C2789C893CF38D4D86900DE71BDE463BD2761D1271E358C7480A1AC0BAB930DDF39602AD1BC165B5D7436B516B7A7858E8EB7AB1C420EEB482F4D207F0E462B1724959320A084E13848D11D10FB593E66BF680BF6D3F345FC3E9C3DE60ABBAC37E1C6EC80A268C8D9FC49626C679097AA690BC1AA662B95EB8DB70390861AA0898229F9349B4B5FDD030D4928C47084708A933144BE23BD3C6E661B85B2C0EF9ED36D498D5B7320E8194D363D4AD478C059BAE804181965E0B81B663158A
 Result = VERIFY_ERROR
 
+# RSA PSS key tests
+
+# PSS only key, no parameter restrictions
+PrivateKey = RSA-PSS
+-----BEGIN PRIVATE KEY-----
+MIIEugIBADALBgkqhkiG9w0BAQoEggSmMIIEogIBAAKCAQEAzQCB6nsq4eoG1Z98
+c9n/uUoJYVwuS6fGNs7wjdNTPsMYVSWwFcdpuZp31nJb+cNTKptuX2Yn1fuFFgdo
+092py9NZdFEXF9w9MJ0vxH7kH5fjKtt/ndhkocR2emZuzXG8Gqz151F/SzhZT+qb
+BeQtWtqZEgCAE+RTFqTZu47QhriNKHWLrK+SLUaoaLSF0jnJuusOK2RZJxD0Ky0e
+oKS0gCwL7Ksyj4posAc721Rv7qmAnShJkSs5DBUyvH4px2WPgXX65G80My/4e8qz
+5AZJuYV3hp2g6nGDU/ByJ1SIaRNkh2DRIr5nbg/Eg90g/8Mb2pajGWbJqi51rQPe
+R+HETwIDAQABAoIBAGApeseZGxZ6BtayR1i4y+IIvrmy2eyXOL2A+QouNQBd184p
+LZ4puohb0xb+8fIJE7wKyQ1rCAiyQU2CEERB2GJKM84CM8j3gKSLN1r/AtdnEiKK
+cCSE2z+evszPu+4XCduhgoANlJ6eQhbgv/NVg4j4vZDaNzodgnQ+w/vdFCf9FoJa
+ZXoxaRLoaVNlEXyi+EXJCUBfysVfiV/BXSA4bCbueMnpkHUCmheKbB5M8MIA6KnP
+sn6dFW+G5sKtwisahKHNXKWyeQh115QHyEs1I5XLgcw/7VuwQ7ae3gwHIEVQAlzu
+jF9EAXC2Egu0jg90e82PUiEQhQ3wQ8Qo39GHBTECgYEA9vlhtHy8A1067evH3oUK
+lWtl7Nuc9gdkBj8VqkhVPFjZcv5mdQVuNd39w3vzufL2Iu4nEzclaEnJvvIXb+j3
+w/i7kbo3TdU7rz3sgU0r3sEMH9yIzdFodvJrHt+j8JQZft9NQv8fspcRA7iYyoWc
+QnKHCGqEKrQQu2nPLTWva+MCgYEA1H5ySn/0EEiycMJSSkEBh4tzFZu3PT28GHsi
+DmNbNTT5biQ6GE2T+GC2v7trccHtmh4fRYWDAjwwHpamksGgi1PQ7JypEBANgEUe
+O33GoBusSuzvjfeYhGvCNaCMu6LPTAaATMESGelWCMcU4/FDDUkfrbujKldRoE+X
+dFg0yaUCgYAh8kUrubld/QKMkUv3mfHKd+ialdUNPBbThPhFX4vXr56z36PVkdmE
+Le8jX3YwqOSMCI/2ZC4QF5RTWpM+HpdvqFCfxyiy2gxKGgjX/PN6uq4f8wAayh3B
+u7Bdnf+6oaCff7Hu84I32evMxyK5M4Q23ecRkRJ5jCaAnBqN7EMgYQKBgB91EKpi
+wtjeSjxTKCeB9B4C0Oi0Aq54Qy5EnEgRAWGhFAPwLQGICo3Mk4FS15chpHEaYHrE
+Rx6/lkgQ+VvkekXmBJnin0yXc8g3c0BPYGY3cowtA1G7A8MmyLtzpyHn+lRA6iFy
+u6FGX8ww3LDZ+Jkw6BWqH3+XKahX4A4DON1ZAoGATR8NdW/nfgEJmmUvUKiLe2hd
+xb8AmB1dI3b9DG/inNW2OHNEeTBac608FZnTnq47rgNfvW/tB8KN5wWTOHmgbkjm
+pgNobtjiVgpfavHywk+vSqlg44IYbxXu3OmiSRrnMGgN1M93i3D6qGgmqzIjR3zJ
+E3exmm1aLq6iGXYL7tU=
+-----END PRIVATE KEY-----
+
+# PSS public key default parameters
+PublicKey = RSA-PSS-DEFAULT
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQowAAOCAQ8AMIIBCgKCAQEAzQCB6nsq4eoG1Z98c9n/
+uUoJYVwuS6fGNs7wjdNTPsMYVSWwFcdpuZp31nJb+cNTKptuX2Yn1fuFFgdo092p
+y9NZdFEXF9w9MJ0vxH7kH5fjKtt/ndhkocR2emZuzXG8Gqz151F/SzhZT+qbBeQt
+WtqZEgCAE+RTFqTZu47QhriNKHWLrK+SLUaoaLSF0jnJuusOK2RZJxD0Ky0eoKS0
+gCwL7Ksyj4posAc721Rv7qmAnShJkSs5DBUyvH4px2WPgXX65G80My/4e8qz5AZJ
+uYV3hp2g6nGDU/ByJ1SIaRNkh2DRIr5nbg/Eg90g/8Mb2pajGWbJqi51rQPeR+HE
+TwIDAQAB
+-----END PUBLIC KEY-----
+# Key with invalid negative minimum salt length
+PublicKey = RSA-PSS-BAD
+-----BEGIN PUBLIC KEY-----
+MIIBJzASBgkqhkiG9w0BAQowBaIDAgH/A4IBDwAwggEKAoIBAQDNAIHqeyrh6gbV
+n3xz2f+5SglhXC5Lp8Y2zvCN01M+wxhVJbAVx2m5mnfWclv5w1Mqm25fZifV+4UW
+B2jT3anL01l0URcX3D0wnS/EfuQfl+Mq23+d2GShxHZ6Zm7NcbwarPXnUX9LOFlP
+6psF5C1a2pkSAIAT5FMWpNm7jtCGuI0odYusr5ItRqhotIXSOcm66w4rZFknEPQr
+LR6gpLSALAvsqzKPimiwBzvbVG/uqYCdKEmRKzkMFTK8finHZY+BdfrkbzQzL/h7
+yrPkBkm5hXeGnaDqcYNT8HInVIhpE2SHYNEivmduD8SD3SD/wxvalqMZZsmqLnWt
+A95H4cRPAgMBAAE=
+-----END PUBLIC KEY-----
+
+# Verify using default parameters
+Verify = RSA-PSS-DEFAULT
+Input="0123456789ABCDEF0123"
+Output = 3EFE09D88509027D837BFA5F8471CF7B69E6DF395DD999BB9CA42021F15722D9AC76670507C6BCFB73F64FB2211B611B8F140E76EBDB064BD762FDBA89D019E304A0D6B274E1C2FE1DF50005598A0306AF805416094E2A5BA60BC72BDE38CE061E853ED40F14967A8B9CA4DC739B462F89558F12FDF2D8D19FBEF16AD66FE2DDDA8BEE983ECBD873064244849D8D94B5B33F45E076871A47ED653E73257A2BE2DB3C0878094B0D2B6B682C8007DFD989425FB39A1FEEC9EED5876414601A49176EC344F5E3EDEE81CA2DDD29B7364F4638112CB3A547E2BC170E28CB66BDABE863754BE8AD5BA230567B575266F4B6B4CF81F28310ABF05351CC9E2DB85D00BF
+
+# Verify using default parameters, explicitly setting parameters
+Verify = RSA-PSS-DEFAULT
+Ctrl = rsa_padding_mode:pss
+Ctrl = rsa_pss_saltlen:20
+Ctrl = digest:sha1
+Input="0123456789ABCDEF0123"
+Output = 3EFE09D88509027D837BFA5F8471CF7B69E6DF395DD999BB9CA42021F15722D9AC76670507C6BCFB73F64FB2211B611B8F140E76EBDB064BD762FDBA89D019E304A0D6B274E1C2FE1DF50005598A0306AF805416094E2A5BA60BC72BDE38CE061E853ED40F14967A8B9CA4DC739B462F89558F12FDF2D8D19FBEF16AD66FE2DDDA8BEE983ECBD873064244849D8D94B5B33F45E076871A47ED653E73257A2BE2DB3C0878094B0D2B6B682C8007DFD989425FB39A1FEEC9EED5876414601A49176EC344F5E3EDEE81CA2DDD29B7364F4638112CB3A547E2BC170E28CB66BDABE863754BE8AD5BA230567B575266F4B6B4CF81F28310ABF05351CC9E2DB85D00BF
+
+# Verify using salt length larger than minimum
+Verify = RSA-PSS-DEFAULT
+Ctrl = rsa_pss_saltlen:30
+Input="0123456789ABCDEF0123"
+Output = 6BF7EDC63A0BA184EEEC7F3020FEC8F5EBF38C2B76481881F48BCCE5796E7AB294548BA9AE810457C7723CABD1BDE94CF59CF7C0FC7461B22760C8ED703DD98E97BFDD61FA8D1181C411F6DEE5FF159F4850746D78EDEE385A363DC28E2CB373D5CAD7953F3BD5E639BE345732C03A1BDEA268814DA036EB1891C82D4012F3B903D86636055F87B96FC98806AD1B217685A4D754046A5DE0B0D7870664BE07902153EC85BA457BE7D7F89D7FE0F626D02A9CBBB2BB479DDA1A5CAE75247FB7BF6BFB15C1D3FD9E6B1573CCDBC72011C3B97716058BB11C7EA2E4E56ADAFE1F5DE6A7FD405AC5890100F9C3408EFFB5C73BF73F48177FF743B4B819D0699D507B
+
+# Attempt to change salt length below minimum
+Verify = RSA-PSS-DEFAULT
+Ctrl = rsa_pss_saltlen:0
+Result = PKEY_CTRL_ERROR
+
+# Attempt to change padding mode
+Verify = RSA-PSS-DEFAULT
+Ctrl = rsa_padding_mode:pkcs1
+Result = PKEY_CTRL_INVALID
+
+# Attempt to change digest
+Verify = RSA-PSS-DEFAULT
+Ctrl = digest:sha256
+Result = PKEY_CTRL_ERROR
+
+# Illegal decrypt
+Decrypt = RSA-PSS
+Result = KEYOP_INIT_ERROR
+Function = EVP_PKEY_decrypt_init
+Reason = operation not supported for this keytype
+
+# Invalid key: rejected when we try to init
+Verify = RSA-PSS-BAD
+Result = KEYOP_INIT_ERROR
+Function = rsa_pss_get_param
+Reason = invalid salt length
+
 # scrypt tests from draft-josefsson-scrypt-kdf-03
 PBE = scrypt
 Password = ""
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 27d530a..ffd03b5 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4222,3 +4222,5 @@ CT_POLICY_EVAL_CTX_get_time             4172	1_1_0d	EXIST::FUNCTION:CT
 CT_POLICY_EVAL_CTX_set_time             4173	1_1_0d	EXIST::FUNCTION:CT
 X509_VERIFY_PARAM_set_inh_flags         4174	1_1_0d	EXIST::FUNCTION:
 X509_VERIFY_PARAM_get_inh_flags         4175	1_1_0d	EXIST::FUNCTION:
+EVP_PKEY_CTX_md                         4176	1_1_1	EXIST::FUNCTION:
+RSA_pkey_ctx_ctrl                       4177	1_1_1	EXIST::FUNCTION:RSA


More information about the openssl-commits mailing list