[openssl] master update

Richard Levitte levitte at openssl.org
Fri Aug 7 02:13:34 UTC 2020


The branch master has been updated
       via  a7922e208ddfbdcff44d1b3fa5839f96510d04bd (commit)
       via  dca51418b0186c1d829b04ce89990148fbedbf9c (commit)
       via  37d398c180cd30f69a9d122af4734852309b55a5 (commit)
       via  fb89000897cddee45abb2949c0697a3f8ec090b2 (commit)
       via  413835f5d158acb14147e9f1c4f85b9c518b1fa6 (commit)
      from  6ce6ad39fe85cf8b5c84ded9885329bf703ee649 (commit)


- Log -----------------------------------------------------------------
commit a7922e208ddfbdcff44d1b3fa5839f96510d04bd
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Aug 3 21:10:19 2020 +0200

    TEST: Adjust the serdes test to include MSBLOB and PVK
    
    Because PVK uses RC4, we must ensure that default + legacy providers
    are active.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12574)

commit dca51418b0186c1d829b04ce89990148fbedbf9c
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Aug 3 21:09:26 2020 +0200

    PEM: Fix i2b_PvK to use EVP_Encrypt calls consistently
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12574)

commit 37d398c180cd30f69a9d122af4734852309b55a5
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Aug 3 21:08:40 2020 +0200

    PROV: Add MSBLOB and PVK to DSA and RSA deserializers
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12574)

commit fb89000897cddee45abb2949c0697a3f8ec090b2
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Aug 3 21:04:05 2020 +0200

    DESERIALIZER: Adjust to allow the use several deserializers with same name
    
    A key type may be deserialized from one of several sources, which
    means that more than one deserializer with the same name should be
    possible to add to the stack of deserializers to try, in the
    OSSL_DESERIALIZER_CTX collection.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12574)

commit 413835f5d158acb14147e9f1c4f85b9c518b1fa6
Author: Richard Levitte <levitte at openssl.org>
Date:   Mon Aug 3 21:01:35 2020 +0200

    PEM: Make general MSBLOB reader functions exposed internally
    
    Fly-by fix is to move crypto/include/internal/pem_int.h to
    include/internal/pem.h.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12574)

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

Summary of changes:
 crypto/pem/pvkfmt.c                                |  55 ++---
 crypto/serializer/deserializer_pkey.c              |  67 +++---
 crypto/store/loader_file.c                         |   2 +-
 .../internal/pem_int.h => include/internal/pem.h   |  12 +-
 providers/deserializers.inc                        |  11 +
 .../implementations/include/prov/implementations.h |   4 +
 providers/implementations/serializers/build.info   |   6 +-
 .../serializers/deserialize_common.c               |  58 ++++-
 ...{deserialize_der2key.c => deserialize_ms2key.c} | 182 ++++++++--------
 .../implementations/serializers/serializer_local.h |   8 +
 test/recipes/04-test_serializer_deserializer.t     |  12 +-
 test/serdes_test.c                                 | 239 ++++++++++++++++++++-
 12 files changed, 503 insertions(+), 153 deletions(-)
 rename crypto/include/internal/pem_int.h => include/internal/pem.h (75%)
 copy providers/implementations/serializers/{deserialize_der2key.c => deserialize_ms2key.c} (54%)

diff --git a/crypto/pem/pvkfmt.c b/crypto/pem/pvkfmt.c
index 6d85a8a4e1..95d1ff5a94 100644
--- a/crypto/pem/pvkfmt.c
+++ b/crypto/pem/pvkfmt.c
@@ -20,7 +20,7 @@
 
 #include "internal/cryptlib.h"
 #include <openssl/pem.h>
-#include "internal/pem_int.h"
+#include "internal/pem.h"
 #include <openssl/rand.h>
 #include <openssl/bn.h>
 #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
@@ -186,28 +186,27 @@ static unsigned int blob_length(unsigned bitlen, int isdss, int ispub)
 
 }
 
-static EVP_PKEY *do_b2i(const unsigned char **in, unsigned int length,
-                        int ispub)
+EVP_PKEY *ossl_b2i(const unsigned char **in, unsigned int length, int *ispub)
 {
     const unsigned char *p = *in;
     unsigned int bitlen, magic;
     int isdss;
-    if (ossl_do_blob_header(&p, length, &magic, &bitlen, &isdss, &ispub) <= 0) {
-        PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_HEADER_PARSE_ERROR);
+    if (ossl_do_blob_header(&p, length, &magic, &bitlen, &isdss, ispub) <= 0) {
+        PEMerr(0, PEM_R_KEYBLOB_HEADER_PARSE_ERROR);
         return NULL;
     }
     length -= 16;
-    if (length < blob_length(bitlen, isdss, ispub)) {
-        PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_TOO_SHORT);
+    if (length < blob_length(bitlen, isdss, *ispub)) {
+        PEMerr(0, PEM_R_KEYBLOB_TOO_SHORT);
         return NULL;
     }
     if (isdss)
-        return b2i_dss(&p, bitlen, ispub);
+        return b2i_dss(&p, bitlen, *ispub);
     else
-        return b2i_rsa(&p, bitlen, ispub);
+        return b2i_rsa(&p, bitlen, *ispub);
 }
 
-static EVP_PKEY *do_b2i_bio(BIO *in, int ispub)
+EVP_PKEY *ossl_b2i_bio(BIO *in, int *ispub)
 {
     const unsigned char *p;
     unsigned char hdr_buf[16], *buf = NULL;
@@ -215,33 +214,33 @@ static EVP_PKEY *do_b2i_bio(BIO *in, int ispub)
     int isdss;
     EVP_PKEY *ret = NULL;
     if (BIO_read(in, hdr_buf, 16) != 16) {
-        PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT);
+        PEMerr(0, PEM_R_KEYBLOB_TOO_SHORT);
         return NULL;
     }
     p = hdr_buf;
-    if (ossl_do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) <= 0)
+    if (ossl_do_blob_header(&p, 16, &magic, &bitlen, &isdss, ispub) <= 0)
         return NULL;
 
-    length = blob_length(bitlen, isdss, ispub);
+    length = blob_length(bitlen, isdss, *ispub);
     if (length > BLOB_MAX_LENGTH) {
-        PEMerr(PEM_F_DO_B2I_BIO, PEM_R_HEADER_TOO_LONG);
+        PEMerr(0, PEM_R_HEADER_TOO_LONG);
         return NULL;
     }
     buf = OPENSSL_malloc(length);
     if (buf == NULL) {
-        PEMerr(PEM_F_DO_B2I_BIO, ERR_R_MALLOC_FAILURE);
+        PEMerr(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     p = buf;
     if (BIO_read(in, buf, length) != (int)length) {
-        PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT);
+        PEMerr(0, PEM_R_KEYBLOB_TOO_SHORT);
         goto err;
     }
 
     if (isdss)
-        ret = b2i_dss(&p, bitlen, ispub);
+        ret = b2i_dss(&p, bitlen, *ispub);
     else
-        ret = b2i_rsa(&p, bitlen, ispub);
+        ret = b2i_rsa(&p, bitlen, *ispub);
 
  err:
     OPENSSL_free(buf);
@@ -391,22 +390,30 @@ static EVP_PKEY *b2i_rsa(const unsigned char **in,
 
 EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length)
 {
-    return do_b2i(in, length, 0);
+    int ispub = 0;
+
+    return ossl_b2i(in, length, &ispub);
 }
 
 EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length)
 {
-    return do_b2i(in, length, 1);
+    int ispub = 1;
+
+    return ossl_b2i(in, length, &ispub);
 }
 
 EVP_PKEY *b2i_PrivateKey_bio(BIO *in)
 {
-    return do_b2i_bio(in, 0);
+    int ispub = 0;
+
+    return ossl_b2i_bio(in, &ispub);
 }
 
 EVP_PKEY *b2i_PublicKey_bio(BIO *in)
 {
-    return do_b2i_bio(in, 1);
+    int ispub = 1;
+
+    return ossl_b2i_bio(in, &ispub);
 }
 
 static void write_ledword(unsigned char **out, unsigned int dw)
@@ -852,9 +859,9 @@ static int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel,
         if (!EVP_EncryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
             goto error;
         OPENSSL_cleanse(keybuf, 20);
-        if (!EVP_DecryptUpdate(cctx, p, &enctmplen, p, pklen - 8))
+        if (!EVP_EncryptUpdate(cctx, p, &enctmplen, p, pklen - 8))
             goto error;
-        if (!EVP_DecryptFinal_ex(cctx, p + enctmplen, &enctmplen))
+        if (!EVP_EncryptFinal_ex(cctx, p + enctmplen, &enctmplen))
             goto error;
     }
 
diff --git a/crypto/serializer/deserializer_pkey.c b/crypto/serializer/deserializer_pkey.c
index 44e7eb56ee..6375a29e36 100644
--- a/crypto/serializer/deserializer_pkey.c
+++ b/crypto/serializer/deserializer_pkey.c
@@ -241,6 +241,7 @@ DEFINE_STACK_OF_CSTRING()
 struct collected_data_st {
     struct deser_EVP_PKEY_data_st *process_data;
     STACK_OF(OPENSSL_CSTRING) *names;
+    OSSL_DESERIALIZER_CTX *ctx;
 
     unsigned int error_occured:1;
 };
@@ -279,6 +280,28 @@ static void collect_name(const char *name, void *arg)
     data->error_occured = 0;         /* All is good now */
 }
 
+static void collect_deserializer(OSSL_DESERIALIZER *deser, void *arg)
+{
+    struct collected_data_st *data = arg;
+    size_t i, end_i;
+
+    if (data->error_occured)
+        return;
+
+    data->error_occured = 1;         /* Assume the worst */
+
+    end_i = sk_OPENSSL_CSTRING_num(data->names);
+    for (i = 0; i < end_i; i++) {
+        const char *name = sk_OPENSSL_CSTRING_value(data->names, i);
+
+        if (!OSSL_DESERIALIZER_is_a(deser, name))
+            continue;
+        (void)OSSL_DESERIALIZER_CTX_add_deserializer(data->ctx, deser);
+    }
+
+    data->error_occured = 0;         /* All is good now */
+}
+
 OSSL_DESERIALIZER_CTX *
 OSSL_DESERIALIZER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
                                       const char *input_type,
@@ -300,6 +323,7 @@ OSSL_DESERIALIZER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
         goto err;
     }
     data->process_data->object = (void **)pkey;
+    data->ctx = ctx;
     OSSL_DESERIALIZER_CTX_set_input_type(ctx, input_type);
 
     /* First, find all keymgmts to form goals */
@@ -308,49 +332,30 @@ OSSL_DESERIALIZER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
     if (data->error_occured)
         goto err;
 
-    /*
-     * Then, use the names of those keymgmts to find the first set of
-     * derializers.
-     */
-    ERR_set_mark();
+    /* Then, we collect all the keymgmt names */
     end_i = sk_EVP_KEYMGMT_num(data->process_data->keymgmts);
     for (i = 0; i < end_i; i++) {
         EVP_KEYMGMT *keymgmt =
             sk_EVP_KEYMGMT_value(data->process_data->keymgmts, i);
-        size_t j;
-        OSSL_DESERIALIZER *deser = NULL;
 
         EVP_KEYMGMT_names_do_all(keymgmt, collect_name, data);
 
-        for (j = sk_OPENSSL_CSTRING_num(data->names);
-             j-- > 0 && deser == NULL;) {
-            const char *name = sk_OPENSSL_CSTRING_pop(data->names);
+        if (data->error_occured)
+            goto err;
+    }
 
-            ERR_set_mark();
-            deser = OSSL_DESERIALIZER_fetch(libctx, name, propquery);
-            ERR_pop_to_mark();
-        }
+    /*
+     * Finally, find all deserializers that have any keymgmt of the collected
+     * keymgmt names
+     */
+    OSSL_DESERIALIZER_do_all_provided(libctx, collect_deserializer, data);
 
-        /*
-         * The names in |data->names| aren't allocated for the stack,
-         * so we can simply clear it and let it be re-used.
-         */
-        sk_OPENSSL_CSTRING_zero(data->names);
+    if (data->error_occured)
+        goto err;
 
-        /*
-         * If we found a matching serializer, try to add it to the context.
-         */
-        if (deser != NULL) {
-            (void)OSSL_DESERIALIZER_CTX_add_deserializer(ctx, deser);
-            OSSL_DESERIALIZER_free(deser);
-        }
-    }
     /* If we found no deserializers to match the keymgmts, we err */
-    if (OSSL_DESERIALIZER_CTX_num_deserializers(ctx) == 0) {
-        ERR_clear_last_mark();
+    if (OSSL_DESERIALIZER_CTX_num_deserializers(ctx) == 0)
         goto err;
-    }
-    ERR_pop_to_mark();
 
     /* Finally, collect extra deserializers based on what we already have */
     (void)OSSL_DESERIALIZER_CTX_add_extra(ctx, libctx, propquery);
diff --git a/crypto/store/loader_file.c b/crypto/store/loader_file.c
index 5ff93e33ab..da4e96b989 100644
--- a/crypto/store/loader_file.c
+++ b/crypto/store/loader_file.c
@@ -21,7 +21,7 @@
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/pem.h>
-#include "internal/pem_int.h"
+#include "internal/pem.h"
 #include <openssl/pkcs12.h>      /* For the PKCS8 stuff o.O */
 #include <openssl/rsa.h>         /* For d2i_RSAPrivateKey */
 #include <openssl/safestack.h>
diff --git a/crypto/include/internal/pem_int.h b/include/internal/pem.h
similarity index 75%
rename from crypto/include/internal/pem_int.h
rename to include/internal/pem.h
index c8f90528c3..b6a10241f3 100644
--- a/crypto/include/internal/pem_int.h
+++ b/include/internal/pem.h
@@ -7,17 +7,25 @@
  * https://www.openssl.org/source/license.html
  */
 
-#ifndef HEADER_PEM_INT_H
-# define HEADER_PEM_INT_H
+#ifndef OSSL_INTERNAL_PEM_H
+# define OSSL_INTERNAL_PEM_H
 
 # include <openssl/pem.h>
 
+# ifndef OPENSSL_NO_DSA
 /* Found in crypto/pem/pvkfmt.c */
 int ossl_do_blob_header(const unsigned char **in, unsigned int length,
                         unsigned int *pmagic, unsigned int *pbitlen,
                         int *pisdss, int *pispub);
+#  ifndef OPENSSL_NO_RC4
 int ossl_do_PVK_header(const unsigned char **in, unsigned int length,
                        int skip_magic,
                        unsigned int *psaltlen, unsigned int *pkeylen);
+#  endif
+
+EVP_PKEY *ossl_b2i(const unsigned char **in, unsigned int length, int *ispub);
+EVP_PKEY *ossl_b2i_bio(BIO *in, int *ispub);
+
+# endif
 
 #endif
diff --git a/providers/deserializers.inc b/providers/deserializers.inc
index ead1c67878..e11056ee9e 100644
--- a/providers/deserializers.inc
+++ b/providers/deserializers.inc
@@ -16,6 +16,10 @@
 #endif
 #ifndef OPENSSL_NO_DSA
     DESER("DSA", "yes", "der", der_to_dsa_deserializer_functions),
+    DESER("DSA", "yes", "mblob", msblob_to_dsa_deserializer_functions),
+# ifndef OPENSSL_NO_RC4
+    DESER("DSA", "yes", "pvk", pvk_to_dsa_deserializer_functions),
+# endif
 #endif
 #ifndef OPENSSL_NO_EC
     DESER("EC", "yes", "der", der_to_ec_deserializer_functions),
@@ -26,5 +30,12 @@
 #endif
     DESER("RSA", "yes", "der", der_to_rsa_deserializer_functions),
     DESER("RSA-PSS", "yes", "der", der_to_rsapss_deserializer_functions),
+#ifndef OPENSSL_NO_DSA
+    DESER("RSA", "yes", "mblob", msblob_to_rsa_deserializer_functions),
+# ifndef OPENSSL_NO_RC4
+    DESER("RSA", "yes", "pvk", pvk_to_rsa_deserializer_functions),
+# endif
+#endif
 
     DESER("DER", "yes", "pem", pem_to_der_deserializer_functions),
+
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h
index 73d4a0225e..7e470044cd 100644
--- a/providers/implementations/include/prov/implementations.h
+++ b/providers/implementations/include/prov/implementations.h
@@ -361,6 +361,8 @@ extern const OSSL_DISPATCH ec_param_pem_serializer_functions[];
 
 extern const OSSL_DISPATCH der_to_dh_deserializer_functions[];
 extern const OSSL_DISPATCH der_to_dsa_deserializer_functions[];
+extern const OSSL_DISPATCH msblob_to_dsa_deserializer_functions[];
+extern const OSSL_DISPATCH pvk_to_dsa_deserializer_functions[];
 extern const OSSL_DISPATCH der_to_ec_deserializer_functions[];
 extern const OSSL_DISPATCH der_to_x25519_deserializer_functions[];
 extern const OSSL_DISPATCH der_to_x448_deserializer_functions[];
@@ -368,4 +370,6 @@ extern const OSSL_DISPATCH der_to_ed25519_deserializer_functions[];
 extern const OSSL_DISPATCH der_to_ed448_deserializer_functions[];
 extern const OSSL_DISPATCH der_to_rsa_deserializer_functions[];
 extern const OSSL_DISPATCH der_to_rsapss_deserializer_functions[];
+extern const OSSL_DISPATCH msblob_to_rsa_deserializer_functions[];
+extern const OSSL_DISPATCH pvk_to_rsa_deserializer_functions[];
 extern const OSSL_DISPATCH pem_to_der_deserializer_functions[];
diff --git a/providers/implementations/serializers/build.info b/providers/implementations/serializers/build.info
index d660385163..04f230b334 100644
--- a/providers/implementations/serializers/build.info
+++ b/providers/implementations/serializers/build.info
@@ -12,7 +12,11 @@ $EC_GOAL=../../libimplementations.a
 
 SOURCE[$SERIALIZER_GOAL]=serializer_common.c deserialize_common.c
 
-SOURCE[$RSA_GOAL]=deserialize_der2key.c deserialize_pem2der.c
+SOURCE[$DESERIALIZER_GOAL]=deserialize_der2key.c deserialize_pem2der.c
+IF[{- !$disabled{dsa} -}]
+  SOURCE[$DESERIALIZER_GOAL]=deserialize_ms2key.c
+ENDIF
+
 SOURCE[$RSA_GOAL]=serializer_rsa.c serializer_rsa_priv.c serializer_rsa_pub.c
 DEPEND[serializer_rsa.o]=../../common/include/prov/der_rsa.h
 
diff --git a/providers/implementations/serializers/deserialize_common.c b/providers/implementations/serializers/deserialize_common.c
index 1a9d3d4a77..54c63347fd 100644
--- a/providers/implementations/serializers/deserialize_common.c
+++ b/providers/implementations/serializers/deserialize_common.c
@@ -7,11 +7,13 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include <openssl/core_names.h>
 #include <openssl/bio.h>
 #include <openssl/err.h>
 #include <openssl/buffer.h>
-#include <openssl/pem.h>
+#include <openssl/pem.h>         /* For public PEM and PVK functions */
 #include <openssl/pkcs12.h>
+#include "internal/pem.h"        /* For internal PVK and "blob" functions */
 #include "internal/cryptlib.h"
 #include "crypto/asn1.h"
 #include "prov/bio.h"               /* ossl_prov_bio_printf() */
@@ -45,6 +47,60 @@ int ossl_prov_read_pem(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
     return ok;
 }
 
+#ifndef OPENSSL_NO_DSA
+EVP_PKEY *ossl_prov_read_msblob(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
+                                int *ispub)
+{
+    BIO *in = bio_new_from_core_bio(provctx, cin);
+    EVP_PKEY *pkey = ossl_b2i_bio(in, ispub);
+
+    BIO_free(in);
+    return pkey;
+}
+
+struct pwdata_st {
+    OSSL_PASSPHRASE_CALLBACK *pw_cb;
+    void *pw_cbarg;
+};
+
+pem_password_cb pw_pem_password_to_ossl_passhrase;
+int pw_pem_password_to_ossl_passhrase(char *buf, int size, int rwflag,
+                                      void *userdata)
+{
+    struct pwdata_st *data = userdata;
+    size_t pw_len = 0;
+    static char prompt_info[] = "pass phrase";
+    OSSL_PARAM params[] = {
+        OSSL_PARAM_utf8_string(OSSL_PASSPHRASE_PARAM_INFO, prompt_info,
+                               sizeof(prompt_info) - 1),
+        OSSL_PARAM_END
+    };
+    int ok = data->pw_cb(buf, (size_t)size, &pw_len, params, data->pw_cbarg);
+
+    if (ok)
+        return (int)pw_len;
+    else
+        return -1;
+}
+
+# ifndef OPENSSL_NO_RC4
+EVP_PKEY *ossl_prov_read_pvk(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
+                             OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+{
+    BIO *in = bio_new_from_core_bio(provctx, cin);
+    EVP_PKEY *pkey = NULL;
+    struct pwdata_st pwdata;
+
+    pwdata.pw_cb = pw_cb;
+    pwdata.pw_cbarg = pw_cbarg;
+    pkey = b2i_PVK_bio(in, pw_pem_password_to_ossl_passhrase, &pwdata);
+
+    BIO_free(in);
+    return pkey;
+}
+# endif
+#endif
+
 int ossl_prov_der_from_p8(unsigned char **new_der, long *new_der_len,
                           unsigned char *input_der, long input_der_len,
                           OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
diff --git a/providers/implementations/serializers/deserialize_der2key.c b/providers/implementations/serializers/deserialize_ms2key.c
similarity index 54%
copy from providers/implementations/serializers/deserialize_der2key.c
copy to providers/implementations/serializers/deserialize_ms2key.c
index d765ad8fab..73d462e41e 100644
--- a/providers/implementations/serializers/deserialize_der2key.c
+++ b/providers/implementations/serializers/deserialize_ms2key.c
@@ -18,17 +18,22 @@
 #include <openssl/crypto.h>
 #include <openssl/params.h>
 #include <openssl/x509.h>
+#include "internal/pem.h"        /* For PVK and "blob" PEM headers */
 #include "prov/bio.h"
 #include "prov/implementations.h"
 #include "serializer_local.h"
 
-static OSSL_FUNC_deserializer_newctx_fn der2rsa_newctx;
-
-static OSSL_FUNC_deserializer_freectx_fn der2key_freectx;
-static OSSL_FUNC_deserializer_gettable_params_fn der2key_gettable_params;
-static OSSL_FUNC_deserializer_get_params_fn der2key_get_params;
-static OSSL_FUNC_deserializer_deserialize_fn der2key_deserialize;
-static OSSL_FUNC_deserializer_export_object_fn der2key_export_object;
+static OSSL_FUNC_deserializer_freectx_fn ms2key_freectx;
+static OSSL_FUNC_deserializer_gettable_params_fn ms2key_gettable_params;
+static OSSL_FUNC_deserializer_get_params_fn msblob2key_get_params;
+#ifndef OPENSSL_NO_RC4
+static OSSL_FUNC_deserializer_get_params_fn pvk2key_get_params;
+#endif
+static OSSL_FUNC_deserializer_deserialize_fn msblob2key_deserialize;
+#ifndef OPENSSL_NO_RC4
+static OSSL_FUNC_deserializer_deserialize_fn pvk2key_deserialize;
+#endif
+static OSSL_FUNC_deserializer_export_object_fn ms2key_export_object;
 
 typedef void *(extract_key_fn)(EVP_PKEY *);
 typedef void (free_key_fn)(void *);
@@ -48,15 +53,15 @@ struct keytype_desc_st {
 /*
  * Context used for DER to key deserialization.
  */
-struct der2key_ctx_st {
+struct ms2key_ctx_st {
     PROV_CTX *provctx;
     const struct keytype_desc_st *desc;
 };
 
-static struct der2key_ctx_st *
-der2key_newctx(void *provctx, const struct keytype_desc_st *desc)
+static struct ms2key_ctx_st *
+ms2key_newctx(void *provctx, const struct keytype_desc_st *desc)
 {
-    struct der2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
+    struct ms2key_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
 
     if (ctx != NULL) {
         ctx->provctx = provctx;
@@ -65,14 +70,14 @@ der2key_newctx(void *provctx, const struct keytype_desc_st *desc)
     return ctx;
 }
 
-static void der2key_freectx(void *vctx)
+static void ms2key_freectx(void *vctx)
 {
-    struct der2key_ctx_st *ctx = vctx;
+    struct ms2key_ctx_st *ctx = vctx;
 
     OPENSSL_free(ctx);
 }
 
-static const OSSL_PARAM *der2key_gettable_params(void *provctx)
+static const OSSL_PARAM *ms2key_gettable_params(void)
 {
     static const OSSL_PARAM gettables[] = {
         { OSSL_DESERIALIZER_PARAM_INPUT_TYPE, OSSL_PARAM_UTF8_PTR, NULL, 0, 0 },
@@ -82,58 +87,35 @@ static const OSSL_PARAM *der2key_gettable_params(void *provctx)
     return gettables;
 }
 
-static int der2key_get_params(OSSL_PARAM params[])
+static int msblob2key_get_params(OSSL_PARAM params[])
 {
     OSSL_PARAM *p;
 
     p = OSSL_PARAM_locate(params, OSSL_DESERIALIZER_PARAM_INPUT_TYPE);
-    if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "DER"))
+    if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "MSBLOB"))
         return 0;
 
     return 1;
 }
 
-static int der2key_deserialize(void *vctx, OSSL_CORE_BIO *cin,
-                               OSSL_CALLBACK *data_cb, void *data_cbarg,
-                               OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
+#ifndef OPENSSL_NO_RC4
+static int pvk2key_get_params(OSSL_PARAM params[])
 {
-    struct der2key_ctx_st *ctx = vctx;
-    void *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
-    unsigned char *der = NULL;
-    const unsigned char *derp;
-    long der_len = 0;
-    unsigned char *new_der = NULL;
-    long new_der_len;
-    EVP_PKEY *pkey = NULL;
-    void *key = NULL;
-    int ok = 0;
+    OSSL_PARAM *p;
 
-    if (!ossl_prov_read_der(ctx->provctx, cin, &der, &der_len))
+    p = OSSL_PARAM_locate(params, OSSL_DESERIALIZER_PARAM_INPUT_TYPE);
+    if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "PVK"))
         return 0;
 
-    /*
-     * Opportunistic attempt to decrypt.  If it doesn't work, we try to
-     * decode our input unencrypted.
-     */
-    if (ossl_prov_der_from_p8(&new_der, &new_der_len, der, der_len,
-                              pw_cb, pw_cbarg)) {
-        OPENSSL_free(der);
-        der = new_der;
-        der_len = new_der_len;
-    }
-
-    derp = der;
-    pkey = d2i_PrivateKey_ex(ctx->desc->type, NULL, &derp, der_len,
-                             libctx, NULL);
-    if (pkey == NULL) {
-        derp = der;
-        pkey = d2i_PUBKEY(NULL, &derp, der_len);
-    }
+    return 1;
+}
+#endif
 
-    if (pkey == NULL) {
-        derp = der;
-        pkey = d2i_KeyParams(ctx->desc->type, NULL, &derp, der_len);
-    }
+static int ms2key_post(struct ms2key_ctx_st *ctx, EVP_PKEY *pkey,
+                       OSSL_CALLBACK *data_cb, void *data_cbarg)
+{
+    void *key = NULL;
+    int ok = 0;
 
     if (pkey != NULL) {
         /*
@@ -146,16 +128,8 @@ static int der2key_deserialize(void *vctx, OSSL_CORE_BIO *cin,
          */
         if (EVP_PKEY_id(pkey) == ctx->desc->type)
             key = ctx->desc->extract_key(pkey);
-
-        /*
-         * ctx->desc->extract_key() is expected to have incremented |key|'s
-         * reference count, so it should be safe to free |pkey| now.
-         */
-        EVP_PKEY_free(pkey);
     }
 
-    OPENSSL_free(der);
-
     if (key != NULL) {
         OSSL_PARAM params[3];
 
@@ -175,11 +149,40 @@ static int der2key_deserialize(void *vctx, OSSL_CORE_BIO *cin,
     return ok;
 }
 
-static int der2key_export_object(void *vctx,
+static int msblob2key_deserialize(void *vctx, OSSL_CORE_BIO *cin,
+                                  OSSL_CALLBACK *data_cb, void *data_cbarg,
+                                  OSSL_PASSPHRASE_CALLBACK *pw_cb,
+                                  void *pw_cbarg)
+{
+    struct ms2key_ctx_st *ctx = vctx;
+    int ispub = -1;
+    EVP_PKEY *pkey = ossl_prov_read_msblob(ctx->provctx, cin, &ispub);
+    int ok = ms2key_post(ctx, pkey, data_cb, data_cbarg);
+
+    EVP_PKEY_free(pkey);
+    return ok;
+}
+
+#ifndef OPENSSL_NO_RC4
+static int pvk2key_deserialize(void *vctx, OSSL_CORE_BIO *cin,
+                               OSSL_CALLBACK *data_cb, void *data_cbarg,
+                               OSSL_PASSPHRASE_CALLBACK *pw_cb,
+                               void *pw_cbarg)
+{
+    struct ms2key_ctx_st *ctx = vctx;
+    EVP_PKEY *pkey = ossl_prov_read_pvk(ctx->provctx, cin, pw_cb, pw_cbarg);
+    int ok = ms2key_post(ctx, pkey, data_cb, data_cbarg);
+
+    EVP_PKEY_free(pkey);
+    return ok;
+}
+#endif
+
+static int ms2key_export_object(void *vctx,
                                  const void *reference, size_t reference_sz,
                                  OSSL_CALLBACK *export_cb, void *export_cbarg)
 {
-    struct der2key_ctx_st *ctx = vctx;
+    struct ms2key_ctx_st *ctx = vctx;
     OSSL_FUNC_keymgmt_export_fn *export =
         ossl_prov_get_keymgmt_export(ctx->desc->fns);
     void *keydata;
@@ -194,46 +197,45 @@ static int der2key_export_object(void *vctx,
     return 0;
 }
 
-#define IMPLEMENT_NEWCTX(KEYTYPEstr, KEYTYPE, keytype, extract, free)   \
+#define IMPLEMENT_TYPE(KEYTYPEstr, KEYTYPE, keytype, extract, free)     \
+    static const struct keytype_desc_st keytype##_desc;                 \
+    static OSSL_FUNC_deserializer_newctx_fn ms2##keytype##_newctx;      \
+    static void *ms2##keytype##_newctx(void *provctx)                   \
+    {                                                                   \
+        return ms2key_newctx(provctx, &keytype##_desc);                 \
+    }                                                                   \
     static const struct keytype_desc_st keytype##_desc =                \
         { EVP_PKEY_##KEYTYPE, KEYTYPEstr, keytype##_keymgmt_functions,  \
           (extract_key_fn *)extract,                                    \
-          (free_key_fn *)free };                                        \
-    static void *der2##keytype##_newctx(void *provctx)                  \
-    {                                                                   \
-        return der2key_newctx(provctx, &keytype##_desc);                \
-    }                                                                   \
-    const OSSL_DISPATCH der_to_##keytype##_deserializer_functions[] = { \
+          (free_key_fn *)free }
+
+#define IMPLEMENT_MS(mstype, keytype)                                   \
+    const OSSL_DISPATCH                                                 \
+    mstype##_to_##keytype##_deserializer_functions[] = {                \
         { OSSL_FUNC_DESERIALIZER_NEWCTX,                                \
-          (void (*)(void))der2##keytype##_newctx },                     \
+          (void (*)(void))ms2##keytype##_newctx },                      \
         { OSSL_FUNC_DESERIALIZER_FREECTX,                               \
-          (void (*)(void))der2key_freectx },                            \
+          (void (*)(void))ms2key_freectx },                             \
         { OSSL_FUNC_DESERIALIZER_GETTABLE_PARAMS,                       \
-          (void (*)(void))der2key_gettable_params },                    \
+          (void (*)(void))ms2key_gettable_params },                     \
         { OSSL_FUNC_DESERIALIZER_GET_PARAMS,                            \
-          (void (*)(void))der2key_get_params },                         \
+          (void (*)(void))mstype##2key_get_params },                    \
         { OSSL_FUNC_DESERIALIZER_DESERIALIZE,                           \
-          (void (*)(void))der2key_deserialize },                        \
+          (void (*)(void))mstype##2key_deserialize },                   \
         { OSSL_FUNC_DESERIALIZER_EXPORT_OBJECT,                         \
-          (void (*)(void))der2key_export_object },                      \
+          (void (*)(void))ms2key_export_object },                       \
         { 0, NULL }                                                     \
     }
 
-#ifndef OPENSSL_NO_DH
-IMPLEMENT_NEWCTX("DH", DH, dh, EVP_PKEY_get1_DH, DH_free);
-#endif
 #ifndef OPENSSL_NO_DSA
-IMPLEMENT_NEWCTX("DSA", DSA, dsa, EVP_PKEY_get1_DSA, DSA_free);
+IMPLEMENT_TYPE("DSA", DSA, dsa, EVP_PKEY_get1_DSA, DSA_free);
+IMPLEMENT_MS(msblob, dsa);
+# ifndef OPENSSL_NO_RC4
+IMPLEMENT_MS(pvk, dsa);
+# endif
 #endif
-#ifndef OPENSSL_NO_EC
-IMPLEMENT_NEWCTX("EC", EC, ec, EVP_PKEY_get1_EC_KEY, EC_KEY_free);
-IMPLEMENT_NEWCTX("X25519", X25519, x25519,
-                 EVP_PKEY_get1_X25519, ecx_key_free);
-IMPLEMENT_NEWCTX("X448", X448, x448,
-                 EVP_PKEY_get1_X448, ecx_key_free);
-IMPLEMENT_NEWCTX("ED25519", ED25519, ed25519,
-                 EVP_PKEY_get1_ED25519, ecx_key_free);
-IMPLEMENT_NEWCTX("ED448", ED448, ed448, EVP_PKEY_get1_ED448, ecx_key_free);
+IMPLEMENT_TYPE("RSA", RSA, rsa, EVP_PKEY_get1_RSA, RSA_free);
+IMPLEMENT_MS(msblob, rsa);
+#ifndef OPENSSL_NO_RC4
+IMPLEMENT_MS(pvk, rsa);
 #endif
-IMPLEMENT_NEWCTX("RSA", RSA, rsa, EVP_PKEY_get1_RSA, RSA_free);
-IMPLEMENT_NEWCTX("RSA-PSS", RSA_PSS, rsapss, EVP_PKEY_get1_RSA, RSA_free);
diff --git a/providers/implementations/serializers/serializer_local.h b/providers/implementations/serializers/serializer_local.h
index d1359f7f4d..49ec8882c6 100644
--- a/providers/implementations/serializers/serializer_local.h
+++ b/providers/implementations/serializers/serializer_local.h
@@ -167,6 +167,14 @@ int ossl_prov_read_der(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
 int ossl_prov_read_pem(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
                        char **pem_name, char **pem_header,
                        unsigned char **data, long *len);
+#ifndef OPENSSL_NO_DSA
+EVP_PKEY *ossl_prov_read_msblob(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
+                                int *ispub);
+# ifndef OPENSSL_NO_RC4
+EVP_PKEY *ossl_prov_read_pvk(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
+                             OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg);
+# endif
+#endif
 
 int ossl_prov_der_from_p8(unsigned char **new_der, long *new_der_len,
                           unsigned char *input_der, long input_der_len,
diff --git a/test/recipes/04-test_serializer_deserializer.t b/test/recipes/04-test_serializer_deserializer.t
index 8da6ffb09f..905fc3fccc 100644
--- a/test/recipes/04-test_serializer_deserializer.t
+++ b/test/recipes/04-test_serializer_deserializer.t
@@ -10,6 +10,14 @@ use strict;
 use warnings;
 
 use OpenSSL::Test::Simple;
-use OpenSSL::Test;
+use OpenSSL::Test qw/:DEFAULT srctop_file bldtop_dir/;
+use Cwd qw(abs_path);
 
-simple_test("test_serializer_deserializer", "serdes_test");
+setup("test_serializer_deserializer");
+
+plan tests => 1;
+
+$ENV{OPENSSL_MODULES} = abs_path(bldtop_dir("providers"));
+$ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "default-and-legacy.cnf"));
+
+ok(run(test(["serdes_test"])));
diff --git a/test/serdes_test.c b/test/serdes_test.c
index 85165523ca..43d64155f5 100644
--- a/test/serdes_test.c
+++ b/test/serdes_test.c
@@ -16,6 +16,7 @@
 #include <openssl/serializer.h>
 #include <openssl/deserializer.h>
 
+#include "internal/pem.h"        /* For PVK and "blob" PEM headers */
 #include "internal/cryptlib.h"   /* ossl_assert */
 
 #include "testutil.h"
@@ -255,6 +256,102 @@ static int serialize_EVP_PKEY_legacy_PEM(void **serialized,
     return ok;
 }
 
+#ifndef OPENSSL_NO_DSA
+static int serialize_EVP_PKEY_MSBLOB(void **serialized,
+                                     long *serialized_len,
+                                     void *object,
+                                     ossl_unused const char *pass,
+                                     ossl_unused const char *pcipher,
+                                     ossl_unused const char *ser_propq)
+{
+    EVP_PKEY *pkey = object;
+    BIO *mem_ser = NULL;
+    BUF_MEM *mem_buf = NULL;
+    int ok = 0;
+
+    if (!TEST_ptr(mem_ser = BIO_new(BIO_s_mem()))
+        || !TEST_int_ge(i2b_PrivateKey_bio(mem_ser, pkey), 0)
+        || !TEST_true(BIO_get_mem_ptr(mem_ser, &mem_buf) > 0)
+        || !TEST_ptr(*serialized = mem_buf->data)
+        || !TEST_long_gt(*serialized_len = mem_buf->length, 0))
+        goto end;
+
+    /* Detach the serialized output */
+    mem_buf->data = NULL;
+    mem_buf->length = 0;
+    ok = 1;
+ end:
+    BIO_free(mem_ser);
+    return ok;
+}
+
+static int serialize_public_EVP_PKEY_MSBLOB(void **serialized,
+                                            long *serialized_len,
+                                            void *object,
+                                            ossl_unused const char *pass,
+                                            ossl_unused const char *pcipher,
+                                            ossl_unused const char *ser_propq)
+{
+    EVP_PKEY *pkey = object;
+    BIO *mem_ser = NULL;
+    BUF_MEM *mem_buf = NULL;
+    int ok = 0;
+
+    if (!TEST_ptr(mem_ser = BIO_new(BIO_s_mem()))
+        || !TEST_int_ge(i2b_PublicKey_bio(mem_ser, pkey), 0)
+        || !TEST_true(BIO_get_mem_ptr(mem_ser, &mem_buf) > 0)
+        || !TEST_ptr(*serialized = mem_buf->data)
+        || !TEST_long_gt(*serialized_len = mem_buf->length, 0))
+        goto end;
+
+    /* Detach the serialized output */
+    mem_buf->data = NULL;
+    mem_buf->length = 0;
+    ok = 1;
+ end:
+    BIO_free(mem_ser);
+    return ok;
+}
+
+# ifndef OPENSSL_NO_RC4
+static pem_password_cb pass_pw;
+static int pass_pw(char *buf, int size, int rwflag, void *userdata)
+{
+    OPENSSL_strlcpy(buf, userdata, size);
+    return strlen(userdata);
+}
+
+static int serialize_EVP_PKEY_PVK(void **serialized, long *serialized_len,
+                                  void *object,
+                                  const char *pass,
+                                  ossl_unused const char *pcipher,
+                                  ossl_unused const char *ser_propq)
+{
+    EVP_PKEY *pkey = object;
+    BIO *mem_ser = NULL;
+    BUF_MEM *mem_buf = NULL;
+    int enc = (pass != NULL);
+    int ok = 0;
+
+    if (!TEST_ptr(mem_ser = BIO_new(BIO_s_mem()))
+        || !TEST_int_ge(i2b_PVK_bio(mem_ser, pkey, enc,
+                                    pass_pw, (void *)pass), 0)
+        || !TEST_true(BIO_get_mem_ptr(mem_ser, &mem_buf) > 0)
+        || !TEST_ptr(*serialized = mem_buf->data)
+        || !TEST_long_gt(*serialized_len = mem_buf->length, 0))
+        goto end;
+
+    /* Detach the serialized output */
+    mem_buf->data = NULL;
+    mem_buf->length = 0;
+    ok = 1;
+ end:
+    BIO_free(mem_ser);
+    return ok;
+}
+# endif
+#endif
+
 static int test_text(const void *data1, size_t data1_len,
                      const void *data2, size_t data2_len)
 {
@@ -348,6 +445,49 @@ static int test_unprotected_via_legacy_PEM(const char *type, EVP_PKEY *key)
                                       NULL, 1);
 }
 
+#ifndef OPENSSL_NO_DSA
+static int check_MSBLOB(const char *type, const void *data, size_t data_len)
+{
+    const unsigned char *datap = data;
+    EVP_PKEY *pkey = b2i_PrivateKey(&datap, data_len);
+    int ok = TEST_ptr(pkey);
+
+    EVP_PKEY_free(pkey);
+    return ok;
+}
+
+static int test_unprotected_via_MSBLOB(const char *type, EVP_PKEY *key)
+{
+    return test_serialize_deserialize(type, key, NULL, NULL,
+                                      serialize_EVP_PKEY_MSBLOB,
+                                      deserialize_EVP_PKEY_prov,
+                                      test_mem,
+                                      check_MSBLOB, dump_der,
+                                      NULL, 0);
+}
+
+# ifndef OPENSSL_NO_RC4
+static int check_PVK(const char *type, const void *data, size_t data_len)
+{
+    const unsigned char *in = data;
+    unsigned int saltlen = 0, keylen = 0;
+    int ok = ossl_do_PVK_header(&in, data_len, 0, &saltlen, &keylen);
+
+    return ok;
+}
+
+static int test_unprotected_via_PVK(const char *type, EVP_PKEY *key)
+{
+    return test_serialize_deserialize(type, key, NULL, NULL,
+                                      serialize_EVP_PKEY_PVK,
+                                      deserialize_EVP_PKEY_prov,
+                                      test_mem,
+                                      check_PVK, dump_der,
+                                      NULL, 0);
+}
+# endif
+#endif
+
 static const char *pass_cipher = "AES-256-CBC";
 static const char *pass = "the holy handgrenade of antioch";
 
@@ -414,6 +554,18 @@ static int test_protected_via_legacy_PEM(const char *type, EVP_PKEY *key)
                                       NULL, 1);
 }
 
+#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4)
+static int test_protected_via_PVK(const char *type, EVP_PKEY *key)
+{
+    return test_serialize_deserialize(type, key, pass, NULL,
+                                      serialize_EVP_PKEY_PVK,
+                                      deserialize_EVP_PKEY_prov,
+                                      test_mem,
+                                      check_PVK, dump_der,
+                                      NULL, 0);
+}
+#endif
+
 static int check_public_DER(const char *type, const void *data, size_t data_len)
 {
     const unsigned char *datap = data;
@@ -454,6 +606,29 @@ static int test_public_via_PEM(const char *type, EVP_PKEY *key)
                                       0);
 }
 
+#ifndef OPENSSL_NO_DSA
+static int check_public_MSBLOB(const char *type,
+                               const void *data, size_t data_len)
+{
+    const unsigned char *datap = data;
+    EVP_PKEY *pkey = b2i_PublicKey(&datap, data_len);
+    int ok = TEST_ptr(pkey);
+
+    EVP_PKEY_free(pkey);
+    return ok;
+}
+
+static int test_public_via_MSBLOB(const char *type, EVP_PKEY *key)
+{
+    return test_serialize_deserialize(type, key, NULL, NULL,
+                                      serialize_public_EVP_PKEY_MSBLOB,
+                                      deserialize_EVP_PKEY_prov,
+                                      test_mem,
+                                      check_public_MSBLOB, dump_der,
+                                      NULL, 0);
+}
+#endif
+
 #define KEYS(KEYTYPE)                           \
     static EVP_PKEY *key_##KEYTYPE = NULL;      \
     static EVP_PKEY *legacy_key_##KEYTYPE = NULL
@@ -530,6 +705,38 @@ static int test_public_via_PEM(const char *type, EVP_PKEY *key)
     ADD_TEST(test_public_##KEYTYPE##_via_DER);                  \
     ADD_TEST(test_public_##KEYTYPE##_via_PEM)
 
+#ifndef OPENSSL_NO_DSA
+# define IMPLEMENT_TEST_SUITE_MSBLOB(KEYTYPE, KEYTYPEstr)               \
+    static int test_unprotected_##KEYTYPE##_via_MSBLOB(void)            \
+    {                                                                   \
+        return test_unprotected_via_MSBLOB(KEYTYPEstr, key_##KEYTYPE);  \
+    }                                                                   \
+    static int test_public_##KEYTYPE##_via_MSBLOB(void)                 \
+    {                                                                   \
+        return test_public_via_MSBLOB(KEYTYPEstr, key_##KEYTYPE);       \
+    }
+
+# define ADD_TEST_SUITE_MSBLOB(KEYTYPE)                         \
+    ADD_TEST(test_unprotected_##KEYTYPE##_via_MSBLOB);          \
+    ADD_TEST(test_public_##KEYTYPE##_via_MSBLOB)
+
+# ifndef OPENSSL_NO_RC4
+#  define IMPLEMENT_TEST_SUITE_PVK(KEYTYPE, KEYTYPEstr)                 \
+    static int test_unprotected_##KEYTYPE##_via_PVK(void)               \
+    {                                                                   \
+        return test_unprotected_via_PVK(KEYTYPEstr, key_##KEYTYPE);     \
+    }                                                                   \
+    static int test_protected_##KEYTYPE##_via_PVK(void)                 \
+    {                                                                   \
+        return test_protected_via_PVK(KEYTYPEstr, key_##KEYTYPE);       \
+    }
+
+#  define ADD_TEST_SUITE_PVK(KEYTYPE)                           \
+    ADD_TEST(test_unprotected_##KEYTYPE##_via_PVK);             \
+    ADD_TEST(test_protected_##KEYTYPE##_via_PVK)
+# endif
+#endif
+
 #ifndef OPENSSL_NO_DH
 DOMAIN_KEYS(DH);
 IMPLEMENT_TEST_SUITE(DH, "DH")
@@ -537,6 +744,10 @@ IMPLEMENT_TEST_SUITE(DH, "DH")
 #ifndef OPENSSL_NO_DSA
 DOMAIN_KEYS(DSA);
 IMPLEMENT_TEST_SUITE(DSA, "DSA")
+IMPLEMENT_TEST_SUITE_MSBLOB(DSA, "DSA")
+# ifndef OPENSSL_NO_RC4
+IMPLEMENT_TEST_SUITE_PVK(DSA, "DSA")
+# endif
 #endif
 #ifndef OPENSSL_NO_EC
 DOMAIN_KEYS(EC);
@@ -554,11 +765,27 @@ KEYS(RSA);
 IMPLEMENT_TEST_SUITE(RSA, "RSA")
 KEYS(RSA_PSS);
 IMPLEMENT_TEST_SUITE(RSA_PSS, "RSA-PSS")
+#ifndef OPENSSL_NO_DSA
+IMPLEMENT_TEST_SUITE_MSBLOB(RSA, "RSA")
+# ifndef OPENSSL_NO_RC4
+IMPLEMENT_TEST_SUITE_PVK(RSA, "RSA")
+# endif
+#endif
 
 int setup_tests(void)
 {
     int ok = 1;
 
+#ifndef OPENSSL_NO_DSA
+    static size_t qbits = 160;  /* PVK only tolerates 160 Q bits */
+    static size_t pbits = 1024; /* With 160 Q bits, we MUST use 1024 P bits */
+    OSSL_PARAM DSA_params[] = {
+        OSSL_PARAM_size_t("pbits", &pbits),
+        OSSL_PARAM_size_t("qbits", &qbits),
+        OSSL_PARAM_END
+    };
+#endif
+
 #ifndef OPENSSL_NO_EC
     static char groupname[] = "prime256v1";
     OSSL_PARAM EC_params[] = {
@@ -579,7 +806,7 @@ int setup_tests(void)
     MAKE_DOMAIN_KEYS(DH, "DH", NULL);
 #endif
 #ifndef OPENSSL_NO_DSA
-    MAKE_DOMAIN_KEYS(DSA, "DSA", NULL);
+    MAKE_DOMAIN_KEYS(DSA, "DSA", DSA_params);
 #endif
 #ifndef OPENSSL_NO_EC
     MAKE_DOMAIN_KEYS(EC, "EC", EC_params);
@@ -598,6 +825,10 @@ int setup_tests(void)
 #endif
 #ifndef OPENSSL_NO_DSA
         ADD_TEST_SUITE(DSA);
+        ADD_TEST_SUITE_MSBLOB(DSA);
+# ifndef OPENSSL_NO_RC4
+        ADD_TEST_SUITE_PVK(DSA);
+# endif
 #endif
 #ifndef OPENSSL_NO_EC
         ADD_TEST_SUITE(EC);
@@ -608,6 +839,12 @@ int setup_tests(void)
 #endif
         ADD_TEST_SUITE(RSA);
         ADD_TEST_SUITE(RSA_PSS);
+#ifndef OPENSSL_NO_DSA
+        ADD_TEST_SUITE_MSBLOB(RSA);
+# ifndef OPENSSL_NO_RC4
+        ADD_TEST_SUITE_PVK(RSA);
+# endif
+#endif
     }
 
     return 1;


More information about the openssl-commits mailing list