[openssl] master update

shane.lontis at oracle.com shane.lontis at oracle.com
Thu Feb 27 22:18:18 UTC 2020


The branch master has been updated
       via  8efc4a9c656b8b3eabeac64c54efdeb07dd42f8e (commit)
      from  30a4cda5e0c67b4e77da4f21b7c5f27991d3367a (commit)


- Log -----------------------------------------------------------------
commit 8efc4a9c656b8b3eabeac64c54efdeb07dd42f8e
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Feb 28 08:08:59 2020 +1000

    Implement the ECX Serializers
    
    Provide serializers for X25519 and X448 for text, pem and der. There are
    no parameter serializers because there are no parameters for these
    algorithms.
    
    Add some documentation about the various import/export types available
    Add additional testing for the serializers
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11095)

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

Summary of changes:
 doc/man3/EVP_PKEY_fromdata.pod                     |   4 +-
 doc/man7/provider-keymgmt.pod                      |  81 +++++
 providers/defltprov.c                              |  28 ++
 .../implementations/include/prov/implementations.h |  16 +
 providers/implementations/keymgmt/ecx_kmgmt.c      |   4 +-
 providers/implementations/serializers/build.info   |   4 +
 .../serializers/serializer_common.c                |  38 ++-
 .../serializers/serializer_dh_pub.c                |   2 +-
 .../implementations/serializers/serializer_ecx.c   | 125 +++++++
 .../serializers/serializer_ecx_priv.c              | 270 +++++++++++++++
 .../serializers/serializer_ecx_pub.c               | 184 +++++++++++
 .../implementations/serializers/serializer_local.h |  26 +-
 test/evp_pkey_provided_test.c                      | 361 +++++++++++++++++++--
 test/recipes/30-test_evp_pkey_provided.t           |   9 +-
 test/recipes/30-test_evp_pkey_provided/DH.priv.der | Bin 0 -> 38 bytes
 test/recipes/30-test_evp_pkey_provided/DH.priv.pem |   3 +
 test/recipes/30-test_evp_pkey_provided/DH.priv.txt |   5 +
 test/recipes/30-test_evp_pkey_provided/DH.pub.der  | Bin 0 -> 36 bytes
 test/recipes/30-test_evp_pkey_provided/DH.pub.pem  |   3 +
 test/recipes/30-test_evp_pkey_provided/DH.pub.txt  |   4 +
 .../recipes/30-test_evp_pkey_provided/RSA.priv.der | Bin 0 -> 70 bytes
 .../recipes/30-test_evp_pkey_provided/RSA.priv.pem |   4 +
 .../recipes/30-test_evp_pkey_provided/RSA.priv.txt |   9 +
 test/recipes/30-test_evp_pkey_provided/RSA.pub.der | Bin 0 -> 34 bytes
 test/recipes/30-test_evp_pkey_provided/RSA.pub.pem |   3 +
 test/recipes/30-test_evp_pkey_provided/RSA.pub.txt |   3 +
 .../30-test_evp_pkey_provided/X25519.priv.der      | Bin 0 -> 48 bytes
 .../30-test_evp_pkey_provided/X25519.priv.pem      |   3 +
 .../30-test_evp_pkey_provided/X25519.priv.txt      |   9 +
 .../30-test_evp_pkey_provided/X25519.pub.der       | Bin 0 -> 44 bytes
 .../30-test_evp_pkey_provided/X25519.pub.pem       |   3 +
 .../30-test_evp_pkey_provided/X25519.pub.txt       |   5 +
 .../30-test_evp_pkey_provided/X448.priv.der        | Bin 0 -> 72 bytes
 .../30-test_evp_pkey_provided/X448.priv.pem        |   4 +
 .../30-test_evp_pkey_provided/X448.priv.txt        |  11 +
 .../recipes/30-test_evp_pkey_provided/X448.pub.der | Bin 0 -> 68 bytes
 .../recipes/30-test_evp_pkey_provided/X448.pub.pem |   4 +
 .../recipes/30-test_evp_pkey_provided/X448.pub.txt |   6 +
 38 files changed, 1187 insertions(+), 44 deletions(-)
 create mode 100644 providers/implementations/serializers/serializer_ecx.c
 create mode 100644 providers/implementations/serializers/serializer_ecx_priv.c
 create mode 100644 providers/implementations/serializers/serializer_ecx_pub.c
 create mode 100644 test/recipes/30-test_evp_pkey_provided/DH.priv.der
 create mode 100644 test/recipes/30-test_evp_pkey_provided/DH.priv.pem
 create mode 100644 test/recipes/30-test_evp_pkey_provided/DH.priv.txt
 create mode 100644 test/recipes/30-test_evp_pkey_provided/DH.pub.der
 create mode 100644 test/recipes/30-test_evp_pkey_provided/DH.pub.pem
 create mode 100644 test/recipes/30-test_evp_pkey_provided/DH.pub.txt
 create mode 100644 test/recipes/30-test_evp_pkey_provided/RSA.priv.der
 create mode 100644 test/recipes/30-test_evp_pkey_provided/RSA.priv.pem
 create mode 100644 test/recipes/30-test_evp_pkey_provided/RSA.priv.txt
 create mode 100644 test/recipes/30-test_evp_pkey_provided/RSA.pub.der
 create mode 100644 test/recipes/30-test_evp_pkey_provided/RSA.pub.pem
 create mode 100644 test/recipes/30-test_evp_pkey_provided/RSA.pub.txt
 create mode 100644 test/recipes/30-test_evp_pkey_provided/X25519.priv.der
 create mode 100644 test/recipes/30-test_evp_pkey_provided/X25519.priv.pem
 create mode 100644 test/recipes/30-test_evp_pkey_provided/X25519.priv.txt
 create mode 100644 test/recipes/30-test_evp_pkey_provided/X25519.pub.der
 create mode 100644 test/recipes/30-test_evp_pkey_provided/X25519.pub.pem
 create mode 100644 test/recipes/30-test_evp_pkey_provided/X25519.pub.txt
 create mode 100644 test/recipes/30-test_evp_pkey_provided/X448.priv.der
 create mode 100644 test/recipes/30-test_evp_pkey_provided/X448.priv.pem
 create mode 100644 test/recipes/30-test_evp_pkey_provided/X448.priv.txt
 create mode 100644 test/recipes/30-test_evp_pkey_provided/X448.pub.der
 create mode 100644 test/recipes/30-test_evp_pkey_provided/X448.pub.pem
 create mode 100644 test/recipes/30-test_evp_pkey_provided/X448.pub.txt

diff --git a/doc/man3/EVP_PKEY_fromdata.pod b/doc/man3/EVP_PKEY_fromdata.pod
index ed8c668e90..2d0059d32f 100644
--- a/doc/man3/EVP_PKEY_fromdata.pod
+++ b/doc/man3/EVP_PKEY_fromdata.pod
@@ -27,7 +27,9 @@ creating a key from user data.
 EVP_PKEY_fromdata() creates key parameters or a key, given data from
 I<params> and a context that's been initialized with
 EVP_PKEY_param_fromdata_init() or EVP_PKEY_key_fromdata_init().  The result is
-written to I<*ppkey>.
+written to I<*ppkey>. The parameters that can be used for various types of key
+are as described in the "Built-in RSA Import/Export Types" section on the
+L<provider-keymgmt(7)> page.
 
 EVP_PKEY_param_fromdata_settable() and EVP_PKEY_key_fromdata_settable()
 get a constant B<OSSL_PARAM> array that describes the settable parameters
diff --git a/doc/man7/provider-keymgmt.pod b/doc/man7/provider-keymgmt.pod
index 279256d567..5141ffdebc 100644
--- a/doc/man7/provider-keymgmt.pod
+++ b/doc/man7/provider-keymgmt.pod
@@ -256,6 +256,87 @@ OP_keymgmt_export_types() should return a constant array of descriptor
 B<OSSL_PARAM> for data indicated by I<selection>, that the
 OP_keymgmt_export() callback can expect to receive.
 
+=head2 Built-in RSA Import/Export Types
+
+The following Import/Export types are available for the built-in RSA algorithm:
+
+=over 4
+
+=item "n" (B<OSSL_PKEY_PARAM_RSA_N>) <integer>
+
+The RSA "n" value.
+
+=item "e" (B<OSSL_PKEY_PARAM_RSA_E>) <integer>
+
+The RSA "e" value.
+
+=item "d" (B<OSSL_PKEY_PARAM_RSA_D>) <integer>
+
+The RSA "d" value.
+
+=item "rsa-factor" (B<OSSL_PKEY_PARAM_RSA_FACTOR>) <integer>
+
+An RSA factor. In 2 prime RSA these are often known as "p" or "q". This value
+may be repeated up to 10 times in a single key.
+
+=item "rsa-exponent" (B<OSSL_PKEY_PARAM_RSA_EXPONENT>) <integer>
+
+An RSA CRT (Chinese Remainder Theorem) exponent. This value may be repeated up
+to 10 times in a single key.
+
+=item "rsa-coefficient" (B<OSSL_PKEY_PARAM_RSA_COEFFICIENT>) <integer>
+
+An RSA CRT (Chinese Remainder Theorem) coefficient. This value may be repeated
+up to 9 times in a single key.
+
+=back
+
+=head2 Built-in DSA and Diffie-Hellman Import/Export Types
+
+The following Import/Export types are available for the built-in DSA and
+Diffie-Hellman algorithms:
+
+=over 4
+
+=item "pub" (B<OSSL_PKEY_PARAM_PUB_KEY>) <integer> or <octet string>
+
+The public key value.
+
+=item "priv" (B<OSSL_PKEY_PARAM_PRIV_KEY>) <integer> or <octet string>
+
+The private key value.
+
+=item "p" (B<OSSL_PKEY_PARAM_FFC_P>) <integer>
+
+A DSA or Diffie-Hellman "p" value.
+
+=item "q" (B<OSSL_PKEY_PARAM_FFC_Q>) <integer>
+
+A DSA or Diffie-Hellman "q" value.
+
+=item "g" (B<OSSL_PKEY_PARAM_FFC_G>) <integer>
+
+A DSA or Diffie-Hellman "g" value.
+
+=back
+
+=head2 Built-in X25519, X448, ED25519 and ED448 Import/Export Types
+
+The following Import/Export types are available for the built-in X25519, X448,
+ED25519 and X448 algorithms:
+
+=over 4
+
+=item "pub" (B<OSSL_PKEY_PARAM_PUB_KEY>) <octet string>
+
+The public key value.
+
+=item "priv" (B<OSSL_PKEY_PARAM_PRIV_KEY>) <octet string>
+
+The private key value.
+
+=back
+
 =head2 Information Parameters
 
 See L<OSSL_PARAM(3)> for further details on the parameters structure.
diff --git a/providers/defltprov.c b/providers/defltprov.c
index d513dbe3a0..9400eee0c9 100644
--- a/providers/defltprov.c
+++ b/providers/defltprov.c
@@ -470,6 +470,34 @@ static const OSSL_ALGORITHM deflt_serializer[] = {
       dsa_param_pem_serializer_functions },
 #endif
 
+#ifndef OPENSSL_NO_EC
+    { "X25519", "provider=default,format=text,type=private",
+      x25519_priv_print_serializer_functions },
+    { "X25519", "provider=default,format=text,type=public",
+      x25519_pub_print_serializer_functions },
+    { "X25519", "provider=default,format=der,type=private",
+      x25519_priv_der_serializer_functions },
+    { "X25519", "provider=default,format=der,type=public",
+      x25519_pub_der_serializer_functions },
+    { "X25519", "provider=default,format=pem,type=private",
+      x25519_priv_pem_serializer_functions },
+    { "X25519", "provider=default,format=pem,type=public",
+      x25519_pub_pem_serializer_functions },
+
+    { "X448", "provider=default,format=text,type=private",
+      x448_priv_print_serializer_functions },
+    { "X448", "provider=default,format=text,type=public",
+      x448_pub_print_serializer_functions },
+    { "X448", "provider=default,format=der,type=private",
+      x448_priv_der_serializer_functions },
+    { "X448", "provider=default,format=der,type=public",
+      x448_pub_der_serializer_functions },
+    { "X448", "provider=default,format=pem,type=private",
+      x448_priv_pem_serializer_functions },
+    { "X448", "provider=default,format=pem,type=public",
+      x448_pub_pem_serializer_functions },
+#endif
+
     { NULL, NULL, NULL }
 };
 
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h
index 6d6a26d1e0..a98d1139d3 100644
--- a/providers/implementations/include/prov/implementations.h
+++ b/providers/implementations/include/prov/implementations.h
@@ -281,6 +281,7 @@ extern const OSSL_DISPATCH rsa_priv_der_serializer_functions[];
 extern const OSSL_DISPATCH rsa_pub_der_serializer_functions[];
 extern const OSSL_DISPATCH rsa_priv_pem_serializer_functions[];
 extern const OSSL_DISPATCH rsa_pub_pem_serializer_functions[];
+
 extern const OSSL_DISPATCH dh_priv_text_serializer_functions[];
 extern const OSSL_DISPATCH dh_pub_text_serializer_functions[];
 extern const OSSL_DISPATCH dh_param_text_serializer_functions[];
@@ -290,6 +291,7 @@ extern const OSSL_DISPATCH dh_param_der_serializer_functions[];
 extern const OSSL_DISPATCH dh_priv_pem_serializer_functions[];
 extern const OSSL_DISPATCH dh_pub_pem_serializer_functions[];
 extern const OSSL_DISPATCH dh_param_pem_serializer_functions[];
+
 extern const OSSL_DISPATCH dsa_priv_text_serializer_functions[];
 extern const OSSL_DISPATCH dsa_pub_text_serializer_functions[];
 extern const OSSL_DISPATCH dsa_param_text_serializer_functions[];
@@ -299,3 +301,17 @@ extern const OSSL_DISPATCH dsa_param_der_serializer_functions[];
 extern const OSSL_DISPATCH dsa_priv_pem_serializer_functions[];
 extern const OSSL_DISPATCH dsa_pub_pem_serializer_functions[];
 extern const OSSL_DISPATCH dsa_param_pem_serializer_functions[];
+
+extern const OSSL_DISPATCH x25519_priv_print_serializer_functions[];
+extern const OSSL_DISPATCH x25519_pub_print_serializer_functions[];
+extern const OSSL_DISPATCH x25519_priv_der_serializer_functions[];
+extern const OSSL_DISPATCH x25519_pub_der_serializer_functions[];
+extern const OSSL_DISPATCH x25519_priv_pem_serializer_functions[];
+extern const OSSL_DISPATCH x25519_pub_pem_serializer_functions[];
+
+extern const OSSL_DISPATCH x448_priv_print_serializer_functions[];
+extern const OSSL_DISPATCH x448_pub_print_serializer_functions[];
+extern const OSSL_DISPATCH x448_priv_der_serializer_functions[];
+extern const OSSL_DISPATCH x448_pub_der_serializer_functions[];
+extern const OSSL_DISPATCH x448_priv_pem_serializer_functions[];
+extern const OSSL_DISPATCH x448_pub_pem_serializer_functions[];
diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c
index cbb302efc4..fe0193d944 100644
--- a/providers/implementations/keymgmt/ecx_kmgmt.c
+++ b/providers/implementations/keymgmt/ecx_kmgmt.c
@@ -154,8 +154,8 @@ static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
 }
 
 static const OSSL_PARAM ecx_key_types[] = {
-    OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),
-    OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
+    OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),
+    OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
     OSSL_PARAM_END
 };
 static const OSSL_PARAM *ecx_imexport_types(int selection)
diff --git a/providers/implementations/serializers/build.info b/providers/implementations/serializers/build.info
index 0ec2c547fb..d5873d1052 100644
--- a/providers/implementations/serializers/build.info
+++ b/providers/implementations/serializers/build.info
@@ -5,6 +5,7 @@ $SERIALIZER_GOAL=../../libimplementations.a
 $RSA_GOAL=../../libimplementations.a
 $DH_GOAL=../../libimplementations.a
 $DSA_GOAL=../../libimplementations.a
+$ECX_GOAL=../../libimplementations.a
 
 SOURCE[$SERIALIZER_GOAL]=serializer_common.c
 SOURCE[$RSA_GOAL]=serializer_rsa.c serializer_rsa_priv.c serializer_rsa_pub.c
@@ -14,3 +15,6 @@ ENDIF
 IF[{- !$disabled{dsa} -}]
   SOURCE[$DSA_GOAL]=serializer_dsa.c serializer_dsa_priv.c serializer_dsa_pub.c serializer_dsa_param.c
 ENDIF
+IF[{- !$disabled{ec} -}]
+  SOURCE[$ECX_GOAL]=serializer_ecx.c serializer_ecx_priv.c serializer_ecx_pub.c
+ENDIF
diff --git a/providers/implementations/serializers/serializer_common.c b/providers/implementations/serializers/serializer_common.c
index daceb11b8c..b1ad523b71 100644
--- a/providers/implementations/serializers/serializer_common.c
+++ b/providers/implementations/serializers/serializer_common.c
@@ -243,6 +243,36 @@ int ossl_prov_print_labeled_bignum(BIO *out, const char *label,
     return 1;
 }
 
+/* Number of octets per line */
+#define LABELED_BUF_PRINT_WIDTH    15
+
+int ossl_prov_print_labeled_buf(BIO *out, const char *label,
+                                const unsigned char *buf, size_t buflen)
+{
+    size_t i;
+
+    if (ossl_prov_bio_printf(out, "%s\n", label) <= 0)
+        return 0;
+
+    for (i = 0; i < buflen; i++) {
+        if ((i % LABELED_BUF_PRINT_WIDTH) == 0) {
+            if (i > 0 && ossl_prov_bio_printf(out, "\n") <= 0)
+                return 0;
+            if (ossl_prov_bio_printf(out, "    ") <= 0)
+                return 0;
+        }
+
+        if (ossl_prov_bio_printf(out, "%02x%s", buf[i],
+                                 (i == buflen - 1) ? "" : ":") <= 0)
+            return 0;
+    }
+    if (ossl_prov_bio_printf(out, "\n") <= 0)
+        return 0;
+
+    return 1;
+}
+
+
 /* p2s = param to asn1_string, k2d = key to der */
 int ossl_prov_write_priv_der_from_obj(BIO *out, const void *obj, int obj_nid,
                                       int (*p2s)(const void *obj, int nid,
@@ -254,7 +284,7 @@ int ossl_prov_write_priv_der_from_obj(BIO *out, const void *obj, int obj_nid,
 {
     int ret = 0;
     ASN1_STRING *str = NULL;
-    int strtype = 0;
+    int strtype = V_ASN1_UNDEF;
 
     if (p2s != NULL && !p2s(obj, obj_nid, &str, &strtype))
         return 0;
@@ -290,7 +320,7 @@ int ossl_prov_write_priv_pem_from_obj(BIO *out, const void *obj, int obj_nid,
 {
     int ret = 0;
     ASN1_STRING *str = NULL;
-    int strtype = 0;
+    int strtype = V_ASN1_UNDEF;
 
     if (p2s != NULL && !p2s(obj, obj_nid, &str, &strtype))
         return 0;
@@ -325,7 +355,7 @@ int ossl_prov_write_pub_der_from_obj(BIO *out, const void *obj, int obj_nid,
 {
     int ret = 0;
     ASN1_STRING *str = NULL;
-    int strtype = 0;
+    int strtype = V_ASN1_UNDEF;
     X509_PUBKEY *xpk = NULL;
 
     if (p2s != NULL && !p2s(obj, obj_nid, &str, &strtype))
@@ -350,7 +380,7 @@ int ossl_prov_write_pub_pem_from_obj(BIO *out, const void *obj, int obj_nid,
 {
     int ret = 0;
     ASN1_STRING *str = NULL;
-    int strtype = 0;
+    int strtype = V_ASN1_UNDEF;
     X509_PUBKEY *xpk = NULL;
 
     if (p2s != NULL && !p2s(obj, obj_nid, &str, &strtype))
diff --git a/providers/implementations/serializers/serializer_dh_pub.c b/providers/implementations/serializers/serializer_dh_pub.c
index 57da48c705..567a0f03ea 100644
--- a/providers/implementations/serializers/serializer_dh_pub.c
+++ b/providers/implementations/serializers/serializer_dh_pub.c
@@ -132,7 +132,7 @@ static int dh_pub_print_data(void *ctx, const OSSL_PARAM params[], BIO *out,
 static int dh_pub_print(void *ctx, void *dh, BIO *out,
                          OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
 {
-    return ossl_prov_print_dh(out, dh, 0);
+    return ossl_prov_print_dh(out, dh, dh_print_pub);
 }
 
 const OSSL_DISPATCH dh_pub_der_serializer_functions[] = {
diff --git a/providers/implementations/serializers/serializer_ecx.c b/providers/implementations/serializers/serializer_ecx.c
new file mode 100644
index 0000000000..589c6c25f5
--- /dev/null
+++ b/providers/implementations/serializers/serializer_ecx.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include "crypto/ecx.h"
+#include "prov/bio.h"             /* ossl_prov_bio_printf() */
+#include "prov/implementations.h" /* ecx_keymgmt_functions */
+#include "serializer_local.h"
+
+void ecx_get_new_free_import(ECX_KEY_TYPE type,
+                             OSSL_OP_keymgmt_new_fn **ecx_new,
+                             OSSL_OP_keymgmt_free_fn **ecx_free,
+                             OSSL_OP_keymgmt_import_fn **ecx_import)
+{
+    if (type == ECX_KEY_TYPE_X25519) {
+        *ecx_new = ossl_prov_get_keymgmt_new(x25519_keymgmt_functions);
+        *ecx_free = ossl_prov_get_keymgmt_free(x25519_keymgmt_functions);
+        *ecx_import = ossl_prov_get_keymgmt_import(x25519_keymgmt_functions);
+    } else if (type == ECX_KEY_TYPE_X448) {
+        *ecx_new = ossl_prov_get_keymgmt_new(x448_keymgmt_functions);
+        *ecx_free = ossl_prov_get_keymgmt_free(x448_keymgmt_functions);
+        *ecx_import = ossl_prov_get_keymgmt_import(x448_keymgmt_functions);
+    } else {
+        *ecx_new = NULL;
+        *ecx_free = NULL;
+        *ecx_import = NULL;
+    }
+}
+
+
+int ossl_prov_print_ecx(BIO *out, ECX_KEY *ecxkey, enum ecx_print_type type)
+{
+    const char *type_label = NULL;
+
+    switch (type) {
+    case ecx_print_priv:
+        switch (ecxkey->keylen) {
+        case X25519_KEYLEN:
+            type_label = "X25519 Private-Key";
+            break;
+        case X448_KEYLEN:
+            type_label = "X448 Private-Key";
+            break;
+        }
+        break;
+    case ecx_print_pub:
+        switch (ecxkey->keylen) {
+        case X25519_KEYLEN:
+            type_label = "X25519 Public-Key";
+            break;
+        case X448_KEYLEN:
+            type_label = "X448 Public-Key";
+            break;
+        }
+        break;
+    }
+
+    if (type == ecx_print_priv && ecxkey->privkey == NULL) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+
+    if (ossl_prov_bio_printf(out, "%s:\n", type_label) <= 0)
+        return 0;
+    if (type == ecx_print_priv
+            && !ossl_prov_print_labeled_buf(out, "priv:", ecxkey->privkey,
+                                            ecxkey->keylen))
+        return 0;
+    if (!ossl_prov_print_labeled_buf(out, "pub:", ecxkey->pubkey,
+                                     ecxkey->keylen))
+        return 0;
+
+    return 1;
+}
+
+
+int ossl_prov_ecx_pub_to_der(const void *vecxkey, unsigned char **pder)
+{
+    const ECX_KEY *ecxkey = vecxkey;
+    unsigned char *keyblob;
+
+    if (ecxkey == NULL) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+
+    keyblob = OPENSSL_memdup(ecxkey->pubkey, ecxkey->keylen);
+    if (keyblob == NULL) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    *pder = keyblob;
+    return ecxkey->keylen;
+}
+
+int ossl_prov_ecx_priv_to_der(const void *vecxkey, unsigned char **pder)
+{
+    const ECX_KEY *ecxkey = vecxkey;
+    ASN1_OCTET_STRING oct;
+    int keybloblen;
+
+    if (ecxkey == NULL || ecxkey->privkey == NULL) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+
+    oct.data = ecxkey->privkey;
+    oct.length = ecxkey->keylen;
+    oct.flags = 0;
+
+    keybloblen = i2d_ASN1_OCTET_STRING(&oct, pder);
+    if (keybloblen < 0) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    return keybloblen;
+}
diff --git a/providers/implementations/serializers/serializer_ecx_priv.c b/providers/implementations/serializers/serializer_ecx_priv.c
new file mode 100644
index 0000000000..64dc594624
--- /dev/null
+++ b/providers/implementations/serializers/serializer_ecx_priv.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/types.h>
+#include <openssl/params.h>
+#include "prov/bio.h"
+#include "prov/implementations.h"
+#include "serializer_local.h"
+
+static OSSL_OP_serializer_newctx_fn x25519_priv_newctx;
+static OSSL_OP_serializer_newctx_fn x448_priv_newctx;
+static OSSL_OP_serializer_freectx_fn ecx_priv_freectx;
+static OSSL_OP_serializer_set_ctx_params_fn ecx_priv_set_ctx_params;
+static OSSL_OP_serializer_settable_ctx_params_fn ecx_priv_settable_ctx_params;
+static OSSL_OP_serializer_serialize_data_fn ecx_priv_der_data;
+static OSSL_OP_serializer_serialize_object_fn ecx_priv_der;
+static OSSL_OP_serializer_serialize_data_fn ecx_priv_pem_data;
+static OSSL_OP_serializer_serialize_object_fn ecx_priv_pem;
+
+static OSSL_OP_serializer_serialize_data_fn ecx_priv_print_data;
+static OSSL_OP_serializer_serialize_object_fn ecx_priv_print;
+
+ /*
+ * Context used for private key serialization.
+ */
+struct ecx_priv_ctx_st {
+    void *provctx;
+
+    struct pkcs8_encrypt_ctx_st sc;
+    ECX_KEY_TYPE type;
+};
+
+/* Private key : context */
+static void *ecx_priv_newctx(void *provctx, ECX_KEY_TYPE type)
+{
+    struct ecx_priv_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+    if (ctx != NULL) {
+        ctx->provctx = provctx;
+
+        /* -1 is the "whatever" indicator, i.e. the PKCS8 library default PBE */
+        ctx->sc.pbe_nid = -1;
+        ctx->type = type;
+    }
+    return ctx;
+}
+
+static void *x25519_priv_newctx(void *provctx)
+{
+    return ecx_priv_newctx(provctx, ECX_KEY_TYPE_X25519);
+}
+
+static void *x448_priv_newctx(void *provctx)
+{
+    return ecx_priv_newctx(provctx, ECX_KEY_TYPE_X448);
+}
+
+static void ecx_priv_freectx(void *vctx)
+{
+    struct ecx_priv_ctx_st *ctx = vctx;
+
+    EVP_CIPHER_free(ctx->sc.cipher);
+    OPENSSL_free(ctx->sc.cipher_pass);
+    OPENSSL_free(ctx);
+}
+
+static const OSSL_PARAM *ecx_priv_settable_ctx_params(void)
+{
+    static const OSSL_PARAM settables[] = {
+        OSSL_PARAM_utf8_string(OSSL_SERIALIZER_PARAM_CIPHER, NULL, 0),
+        OSSL_PARAM_octet_string(OSSL_SERIALIZER_PARAM_PASS, NULL, 0),
+        OSSL_PARAM_END,
+    };
+
+    return settables;
+}
+
+static int ecx_priv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+    struct ecx_priv_ctx_st *ctx = vctx;
+    const OSSL_PARAM *p;
+
+    p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_CIPHER);
+    if (p != NULL) {
+        const OSSL_PARAM *propsp =
+            OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PROPERTIES);
+        const char *props;
+
+        if (p->data_type != OSSL_PARAM_UTF8_STRING)
+            return 0;
+        if (propsp != NULL && propsp->data_type != OSSL_PARAM_UTF8_STRING)
+            return 0;
+        props = (propsp != NULL ? propsp->data : NULL);
+
+        EVP_CIPHER_free(ctx->sc.cipher);
+        ctx->sc.cipher_intent = p->data != NULL;
+        if (p->data != NULL
+            && ((ctx->sc.cipher = EVP_CIPHER_fetch(NULL, p->data, props))
+                == NULL))
+            return 0;
+    }
+    p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PASS);
+    if (p != NULL) {
+        OPENSSL_free(ctx->sc.cipher_pass);
+        ctx->sc.cipher_pass = NULL;
+        if (!OSSL_PARAM_get_octet_string(p, &ctx->sc.cipher_pass, 0,
+                                         &ctx->sc.cipher_pass_length))
+            return 0;
+    }
+    return 1;
+}
+
+/* Private key : DER */
+static int ecx_priv_der_data(void *vctx, const OSSL_PARAM params[], BIO *out,
+                             OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+    struct ecx_priv_ctx_st *ctx = vctx;
+    OSSL_OP_keymgmt_new_fn *ecx_new;
+    OSSL_OP_keymgmt_free_fn *ecx_free;
+    OSSL_OP_keymgmt_import_fn *ecx_import;
+    int ok = 0;
+
+    ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
+
+    if (ecx_import != NULL) {
+        ECX_KEY *ecxkey;
+
+        if ((ecxkey = ecx_new(ctx->provctx)) != NULL
+            && ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && ecx_priv_der(ctx, ecxkey, out, cb, cbarg))
+            ok = 1;
+        ecx_free(ecxkey);
+    }
+    return ok;
+}
+
+static int ecx_priv_der(void *vctx, void *vecxkey, BIO *out,
+                        OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+    struct ecx_priv_ctx_st *ctx = vctx;
+    ECX_KEY *ecxkey = vecxkey;
+    int ret;
+    int type = (ctx->type == ECX_KEY_TYPE_X25519) ? EVP_PKEY_X25519
+                                                  : EVP_PKEY_X448;
+
+    ctx->sc.cb = cb;
+    ctx->sc.cbarg = cbarg;
+
+    ret = ossl_prov_write_priv_der_from_obj(out, ecxkey,
+                                            type,
+                                            NULL,
+                                            ossl_prov_ecx_priv_to_der,
+                                            &ctx->sc);
+
+    return ret;
+}
+
+/* Private key : PEM */
+static int ecx_priv_pem_data(void *vctx, const OSSL_PARAM params[], BIO *out,
+                             OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+    struct ecx_priv_ctx_st *ctx = vctx;
+    OSSL_OP_keymgmt_new_fn *ecx_new;
+    OSSL_OP_keymgmt_free_fn *ecx_free;
+    OSSL_OP_keymgmt_import_fn *ecx_import;
+    int ok = 0;
+
+    ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
+
+    if (ecx_import != NULL) {
+        ECX_KEY *ecxkey;
+
+        if ((ecxkey = ecx_new(ctx->provctx)) != NULL
+            && ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && ecx_priv_pem(ctx->provctx, ecxkey, out, cb, cbarg))
+            ok = 1;
+        ecx_free(ecxkey);
+    }
+    return ok;
+}
+
+static int ecx_priv_pem(void *vctx, void *ecxkey, BIO *out,
+                       OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+    struct ecx_priv_ctx_st *ctx = vctx;
+    int ret;
+    int type = (ctx->type == ECX_KEY_TYPE_X25519) ? EVP_PKEY_X25519
+                                                  : EVP_PKEY_X448;
+
+    ctx->sc.cb = cb;
+    ctx->sc.cbarg = cbarg;
+
+    ret = ossl_prov_write_priv_pem_from_obj(out, ecxkey,
+                                            type,
+                                            NULL,
+                                            ossl_prov_ecx_priv_to_der,
+                                            &ctx->sc);
+
+    return ret;
+}
+
+static int ecx_priv_print_data(void *vctx, const OSSL_PARAM params[], BIO *out,
+                               OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+    struct ecx_priv_ctx_st *ctx = vctx;
+    OSSL_OP_keymgmt_new_fn *ecx_new;
+    OSSL_OP_keymgmt_free_fn *ecx_free;
+    OSSL_OP_keymgmt_import_fn *ecx_import;
+    int ok = 0;
+
+    ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
+
+    if (ecx_import != NULL) {
+        ECX_KEY *ecxkey;
+
+        if ((ecxkey = ecx_new(ctx->provctx)) != NULL
+            && ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && ecx_priv_print(ctx, ecxkey, out, cb, cbarg))
+            ok = 1;
+        ecx_free(ecxkey);
+    }
+    return ok;
+}
+
+static int ecx_priv_print(void *ctx, void *ecxkey, BIO *out,
+                         OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+    return ossl_prov_print_ecx(out, ecxkey, ecx_print_priv);
+}
+
+#define MAKE_SERIALIZER_FUNCTIONS(alg, type) \
+    const OSSL_DISPATCH alg##_priv_##type##_serializer_functions[] = { \
+        { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))alg##_priv_newctx }, \
+        { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))ecx_priv_freectx }, \
+        { OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS, \
+          (void (*)(void))ecx_priv_set_ctx_params }, \
+        { OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS, \
+          (void (*)(void))ecx_priv_settable_ctx_params }, \
+        { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, \
+          (void (*)(void))ecx_priv_##type##_data }, \
+        { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, \
+          (void (*)(void))ecx_priv_##type }, \
+        { 0, NULL } \
+    };
+
+#define MAKE_SERIALIZER_FUNCTIONS_GROUP(alg) \
+    MAKE_SERIALIZER_FUNCTIONS(alg, der) \
+    MAKE_SERIALIZER_FUNCTIONS(alg, pem) \
+    const OSSL_DISPATCH alg##_priv_print_serializer_functions[] = { \
+        { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))alg##_priv_newctx }, \
+        { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))ecx_priv_freectx }, \
+        { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, \
+          (void (*)(void))ecx_priv_print }, \
+        { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, \
+          (void (*)(void))ecx_priv_print_data }, \
+        { 0, NULL } \
+    };
+
+MAKE_SERIALIZER_FUNCTIONS_GROUP(x25519)
+MAKE_SERIALIZER_FUNCTIONS_GROUP(x448)
diff --git a/providers/implementations/serializers/serializer_ecx_pub.c b/providers/implementations/serializers/serializer_ecx_pub.c
new file mode 100644
index 0000000000..384d75e6b3
--- /dev/null
+++ b/providers/implementations/serializers/serializer_ecx_pub.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_numbers.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/types.h>
+#include <openssl/params.h>
+#include "prov/bio.h"
+#include "prov/implementations.h"
+#include "serializer_local.h"
+
+static OSSL_OP_serializer_newctx_fn x25519_pub_newctx;
+static OSSL_OP_serializer_newctx_fn x448_pub_newctx;
+static OSSL_OP_serializer_freectx_fn ecx_pub_freectx;
+static OSSL_OP_serializer_serialize_data_fn ecx_pub_der_data;
+static OSSL_OP_serializer_serialize_object_fn ecx_pub_der;
+static OSSL_OP_serializer_serialize_data_fn ecx_pub_pem_data;
+static OSSL_OP_serializer_serialize_object_fn ecx_pub_pem;
+
+static OSSL_OP_serializer_serialize_data_fn ecx_pub_print_data;
+static OSSL_OP_serializer_serialize_object_fn ecx_pub_print;
+
+/*
+ * Context used for public key serialization.
+ */
+struct ecx_pub_ctx_st {
+    void *provctx;
+    ECX_KEY_TYPE type;
+};
+
+/* Public key : context */
+static void *ecx_pub_newctx(void *provctx, ECX_KEY_TYPE type)
+{
+    struct ecx_pub_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+    if (ctx != NULL) {
+        ctx->provctx = provctx;
+        ctx->type = type;
+    }
+    return ctx;
+}
+
+static void *x25519_pub_newctx(void *provctx)
+{
+    return ecx_pub_newctx(provctx, ECX_KEY_TYPE_X25519);
+}
+
+static void *x448_pub_newctx(void *provctx)
+{
+    return ecx_pub_newctx(provctx, ECX_KEY_TYPE_X448);
+}
+
+static void ecx_pub_freectx(void *ctx)
+{
+    OPENSSL_free(ctx);
+}
+
+/* Public key : DER */
+static int ecx_pub_der_data(void *vctx, const OSSL_PARAM params[], BIO *out,
+                            OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+    struct ecx_pub_ctx_st *ctx = vctx;
+    OSSL_OP_keymgmt_new_fn *ecx_new;
+    OSSL_OP_keymgmt_free_fn *ecx_free;
+    OSSL_OP_keymgmt_import_fn *ecx_import;
+    int ok = 0;
+
+    ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
+
+    if (ecx_import != NULL) {
+        ECX_KEY *ecxkey;
+
+        if ((ecxkey = ecx_new(ctx->provctx)) != NULL
+            && ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && ecx_pub_der(ctx, ecxkey, out, cb, cbarg))
+            ok = 1;
+        ecx_free(ecxkey);
+    }
+    return ok;
+}
+
+static int ecx_pub_der(void *vctx, void *ecxkey, BIO *out,
+                       OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+    struct ecx_pub_ctx_st *ctx = vctx;
+
+    return ossl_prov_write_pub_der_from_obj(out, ecxkey,
+                                            ctx->type == ECX_KEY_TYPE_X25519
+                                            ? EVP_PKEY_X25519 : EVP_PKEY_X448,
+                                            NULL,
+                                            ossl_prov_ecx_pub_to_der);
+}
+
+/* Public key : PEM */
+static int ecx_pub_pem_data(void *vctx, const OSSL_PARAM params[], BIO *out,
+                            OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+    struct ecx_pub_ctx_st *ctx = vctx;
+    OSSL_OP_keymgmt_new_fn *ecx_new;
+    OSSL_OP_keymgmt_free_fn *ecx_free;
+    OSSL_OP_keymgmt_import_fn *ecx_import;
+    int ok = 0;
+
+    ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
+
+    if (ecx_import != NULL) {
+        ECX_KEY *ecxkey;
+
+        if ((ecxkey = ecx_new(ctx->provctx)) != NULL
+            && ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && ecx_pub_pem(ctx, ecxkey, out, cb, cbarg))
+            ok = 1;
+        ecx_free(ecxkey);
+    }
+    return ok;
+}
+
+static int ecx_pub_pem(void *vctx, void *ecxkey, BIO *out,
+                       OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+    struct ecx_pub_ctx_st *ctx = vctx;
+
+    return ossl_prov_write_pub_pem_from_obj(out, ecxkey,
+                                            ctx->type == ECX_KEY_TYPE_X25519
+                                            ? EVP_PKEY_X25519 : EVP_PKEY_X448,
+                                            NULL,
+                                            ossl_prov_ecx_pub_to_der);
+
+}
+
+static int ecx_pub_print_data(void *vctx, const OSSL_PARAM params[], BIO *out,
+                              OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+    struct ecx_pub_ctx_st *ctx = vctx;
+    OSSL_OP_keymgmt_new_fn *ecx_new;
+    OSSL_OP_keymgmt_free_fn *ecx_free;
+    OSSL_OP_keymgmt_import_fn *ecx_import;
+    int ok = 0;
+
+    ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
+
+    if (ecx_import != NULL) {
+        ECX_KEY *ecxkey;
+
+        if ((ecxkey = ecx_new(ctx)) != NULL
+            && ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
+            && ecx_pub_print(ctx, ecxkey, out, cb, cbarg))
+            ok = 1;
+        ecx_free(ecxkey);
+    }
+    return ok;
+}
+
+static int ecx_pub_print(void *ctx, void *ecxkey, BIO *out,
+                         OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
+{
+    return ossl_prov_print_ecx(out, ecxkey, ecx_print_pub);
+}
+
+#define MAKE_SERIALIZER_FUNCTIONS(alg, type) \
+    const OSSL_DISPATCH alg##_pub_##type##_serializer_functions[] = { \
+        { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))alg##_pub_newctx }, \
+        { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))ecx_pub_freectx }, \
+        { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, \
+          (void (*)(void))ecx_pub_##type##_data }, \
+        { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, \
+          (void (*)(void))ecx_pub_##type }, \
+        { 0, NULL } \
+    };
+
+#define MAKE_SERIALIZER_FUNCTIONS_GROUP(alg) \
+    MAKE_SERIALIZER_FUNCTIONS(alg, der) \
+    MAKE_SERIALIZER_FUNCTIONS(alg, pem) \
+    MAKE_SERIALIZER_FUNCTIONS(alg, print)
+
+MAKE_SERIALIZER_FUNCTIONS_GROUP(x25519)
+MAKE_SERIALIZER_FUNCTIONS_GROUP(x448)
diff --git a/providers/implementations/serializers/serializer_local.h b/providers/implementations/serializers/serializer_local.h
index 801d221da6..ec27f1443b 100644
--- a/providers/implementations/serializers/serializer_local.h
+++ b/providers/implementations/serializers/serializer_local.h
@@ -13,6 +13,7 @@
 #include <openssl/asn1.h>        /* i2d_of_void */
 #include <openssl/x509.h>        /* X509_SIG */
 #include <openssl/types.h>
+#include <crypto/ecx.h>
 
 struct pkcs8_encrypt_ctx_st {
     /* Set to 1 if intending to encrypt/decrypt, otherwise 0 */
@@ -30,6 +31,11 @@ struct pkcs8_encrypt_ctx_st {
     void *cbarg;
 };
 
+typedef enum {
+    ECX_KEY_TYPE_X25519,
+    ECX_KEY_TYPE_X448
+} ECX_KEY_TYPE;
+
 OSSL_OP_keymgmt_new_fn *ossl_prov_get_keymgmt_new(const OSSL_DISPATCH *fns);
 OSSL_OP_keymgmt_free_fn *ossl_prov_get_keymgmt_free(const OSSL_DISPATCH *fns);
 OSSL_OP_keymgmt_import_fn *ossl_prov_get_keymgmt_import(const OSSL_DISPATCH *fns);
@@ -49,8 +55,15 @@ int ossl_prov_prepare_dh_params(const void *dh, int nid,
 int ossl_prov_dh_pub_to_der(const void *dh, unsigned char **pder);
 int ossl_prov_dh_priv_to_der(const void *dh, unsigned char **pder);
 
+void ecx_get_new_free_import(ECX_KEY_TYPE type,
+                             OSSL_OP_keymgmt_new_fn **ecx_new,
+                             OSSL_OP_keymgmt_free_fn **ecx_free,
+                             OSSL_OP_keymgmt_import_fn **ecx_import);
+int ossl_prov_ecx_pub_to_der(const void *ecxkey, unsigned char **pder);
+int ossl_prov_ecx_priv_to_der(const void *ecxkey, unsigned char **pder);
+
 int ossl_prov_prepare_dsa_params(const void *dsa, int nid,
-                                ASN1_STRING **pstr, int *pstrtype);
+                                 ASN1_STRING **pstr, int *pstrtype);
 /*
  * Special variant of ossl_prov_prepare_dsa_params() that requires all
  * three parameters (P, Q and G) to be set.  This is used when serializing
@@ -63,6 +76,8 @@ int ossl_prov_dsa_priv_to_der(const void *dsa, unsigned char **pder);
 
 int ossl_prov_print_labeled_bignum(BIO *out, const char *label,
                                    const BIGNUM *bn);
+int ossl_prov_print_labeled_buf(BIO *out, const char *label,
+                                const unsigned char *buf, size_t buflen);
 int ossl_prov_print_rsa(BIO *out, RSA *rsa, int priv);
 
 enum dh_print_type {
@@ -81,6 +96,15 @@ enum dsa_print_type {
 
 int ossl_prov_print_dsa(BIO *out, DSA *dsa, enum dsa_print_type type);
 
+enum ecx_print_type {
+    ecx_print_priv,
+    ecx_print_pub
+};
+
+#ifndef OPENSSL_NO_EC
+int ossl_prov_print_ecx(BIO *out, ECX_KEY *ecxkey, enum ecx_print_type type);
+#endif
+
 int ossl_prov_write_priv_der_from_obj(BIO *out, const void *obj, int obj_nid,
                                       int (*p2s)(const void *obj, int nid,
                                                  ASN1_STRING **str,
diff --git a/test/evp_pkey_provided_test.c b/test/evp_pkey_provided_test.c
index 3c1c090bde..c161698505 100644
--- a/test/evp_pkey_provided_test.c
+++ b/test/evp_pkey_provided_test.c
@@ -13,72 +13,242 @@
 #include <openssl/provider.h>
 #include <openssl/params.h>
 #include <openssl/core_names.h>
+#include "crypto/ecx.h"
 #include "internal/nelem.h"
 #include "crypto/evp.h"          /* For the internal API */
 #include "testutil.h"
 
-static int test_print_key_using_pem(const EVP_PKEY *pk)
+static char *datadir = NULL;
+
+#define PRIV_TEXT    0
+#define PRIV_PEM     1
+#define PRIV_DER     2
+#define PUB_TEXT     3
+#define PUB_PEM      4
+#define PUB_DER      5
+
+static void stripcr(char *buf, size_t *len)
+{
+    size_t i;
+    char *curr, *writ;
+
+    for (i = *len, curr = buf, writ = buf; i > 0; i--, curr++) {
+        if (*curr == '\r') {
+            (*len)--;
+            continue;
+        }
+        if (curr != writ)
+            *writ = *curr;
+        writ++;
+    }
+}
+
+static int compare_with_file(const char *alg, int type, BIO *membio)
+{
+    char filename[80];
+    BIO *file = NULL;
+    char buf[1024];
+    char *memdata, *fullfile = NULL;
+    const char *suffix;
+    size_t readbytes;
+    int ret = 0;
+    int len;
+    size_t slen;
+
+    switch (type) {
+    case PRIV_TEXT:
+        suffix = "priv.txt";
+        break;
+
+    case PRIV_PEM:
+        suffix = "priv.pem";
+        break;
+
+    case PRIV_DER:
+        suffix = "priv.der";
+        break;
+
+    case PUB_TEXT:
+        suffix = "pub.txt";
+        break;
+
+    case PUB_PEM:
+        suffix = "pub.pem";
+        break;
+
+    case PUB_DER:
+        suffix = "pub.der";
+        break;
+
+    default:
+        TEST_error("Invalid file type");
+        goto err;
+    }
+
+    BIO_snprintf(filename, sizeof(filename), "%s.%s", alg, suffix);
+    fullfile = test_mk_file_path(datadir, filename);
+    if (!TEST_ptr(fullfile))
+        goto err;
+
+    file = BIO_new_file(fullfile, "rb");
+    if (!TEST_ptr(file))
+        goto err;
+
+    if (!TEST_true(BIO_read_ex(file, buf, sizeof(buf), &readbytes))
+            || !TEST_true(BIO_eof(file))
+            || !TEST_size_t_lt(readbytes, sizeof(buf)))
+        goto err;
+
+    len = BIO_get_mem_data(membio, &memdata);
+    if (!TEST_int_gt(len, 0))
+        goto err;
+
+    slen = len;
+    if (type != PRIV_DER && type != PUB_DER) {
+        stripcr(memdata, &slen);
+        stripcr(buf, &readbytes);
+    }
+
+    if (!TEST_mem_eq(memdata, slen, buf, readbytes))
+        goto err;
+
+    ret = 1;
+ err:
+    OPENSSL_free(fullfile);
+    (void)BIO_reset(membio);
+    BIO_free(file);
+    return ret;
+}
+
+static int test_print_key_using_pem(const char *alg, const EVP_PKEY *pk)
 {
-    if (!TEST_true(EVP_PKEY_print_private(bio_out, pk, 0, NULL))
+    BIO *membio = BIO_new(BIO_s_mem());
+    int ret = 0;
+
+    if (!TEST_ptr(membio))
+        goto err;
+
+    if (!TEST_true(EVP_PKEY_print_private(membio, pk, 0, NULL))
+        || !TEST_true(compare_with_file(alg, PRIV_TEXT, membio))
         /* Public key in PEM form */
-        || !TEST_true(PEM_write_bio_PUBKEY(bio_out, pk))
+        || !TEST_true(PEM_write_bio_PUBKEY(membio, pk))
+        || !TEST_true(compare_with_file(alg, PUB_PEM, membio))
         /* Unencrypted private key in PEM form */
-        || !TEST_true(PEM_write_bio_PrivateKey(bio_out, pk,
+        || !TEST_true(PEM_write_bio_PrivateKey(membio, pk,
                                                NULL, NULL, 0, NULL, NULL))
+        || !TEST_true(compare_with_file(alg, PRIV_PEM, membio))
         /* Encrypted private key in PEM form */
         || !TEST_true(PEM_write_bio_PrivateKey(bio_out, pk, EVP_aes_256_cbc(),
                                                (unsigned char *)"pass", 4,
                                                NULL, NULL)))
-        return 0;
+        goto err;
 
-    return 1;
+    ret = 1;
+ err:
+    BIO_free(membio);
+    return ret;
 }
 
-static int test_print_key_using_serializer(const EVP_PKEY *pk)
+static int test_print_key_type_using_serializer(const char *alg, int type,
+                                                const EVP_PKEY *pk)
 {
-    const char *pq = OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ;
+    const char *pq;
     OSSL_SERIALIZER_CTX *ctx = NULL;
+    BIO *membio = BIO_new(BIO_s_mem());
     int ret = 1;
 
+    switch (type) {
+    case PRIV_TEXT:
+        pq = OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ;
+        break;
+
+    case PRIV_PEM:
+        pq = OSSL_SERIALIZER_PrivateKey_TO_PEM_PQ;
+        break;
+
+    case PRIV_DER:
+        pq = OSSL_SERIALIZER_PrivateKey_TO_DER_PQ;
+        break;
+
+    case PUB_TEXT:
+        pq = OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ;
+        break;
+
+    case PUB_PEM:
+        pq = OSSL_SERIALIZER_PUBKEY_TO_PEM_PQ;
+        break;
+
+    case PUB_DER:
+        pq = OSSL_SERIALIZER_PUBKEY_TO_DER_PQ;
+        break;
+
+    default:
+        TEST_error("Invalid serialization type");
+        goto err;
+    }
+
+    if (!TEST_ptr(membio)) {
+        ret = 0;
+        goto err;
+    }
+
     /* Make a context, it's valid for several prints */
     TEST_note("Setting up a OSSL_SERIALIZER context with passphrase");
     if (!TEST_ptr(ctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pk, pq))
         /* Check that this operation is supported */
-        || !TEST_ptr(OSSL_SERIALIZER_CTX_get_serializer(ctx))
-        /* Set a passphrase to be used later */
-        || !TEST_true(OSSL_SERIALIZER_CTX_set_passphrase(ctx,
-                                                         (unsigned char *)"pass",
-                                                         4)))
+        || !TEST_ptr(OSSL_SERIALIZER_CTX_get_serializer(ctx)))
         goto err;
 
     /* Use no cipher.  This should give us an unencrypted PEM */
-    TEST_note("Displaying PEM with no encryption");
-    if (!TEST_true(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
+    TEST_note("Testing with no encryption");
+    if (!TEST_true(OSSL_SERIALIZER_to_bio(ctx, membio))
+        || !TEST_true(compare_with_file(alg, type, membio)))
         ret = 0;
 
-    /* Use a valid cipher name */
-    TEST_note("Displaying PEM encrypted with AES-256-CBC");
-    if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, "AES-256-CBC", NULL))
-        || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
-        ret = 0;
+    if (type == PRIV_PEM) {
+        /* Set a passphrase to be used later */
+        if (!TEST_true(OSSL_SERIALIZER_CTX_set_passphrase(ctx,
+                                                          (unsigned char *)"pass",
+                                                          4)))
+            goto err;
 
-    /* Use an invalid cipher name, which should generate no output */
-    TEST_note("NOT Displaying PEM encrypted with (invalid) FOO");
-    if (!TEST_false(OSSL_SERIALIZER_CTX_set_cipher(ctx, "FOO", NULL))
-        || !TEST_false(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
-        ret = 0;
+        /* Use a valid cipher name */
+        TEST_note("Displaying PEM encrypted with AES-256-CBC");
+        if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, "AES-256-CBC", NULL))
+            || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
+            ret = 0;
 
-    /* Clear the cipher.  This should give us an unencrypted PEM again */
-    TEST_note("Displaying PEM with encryption cleared (no encryption)");
-    if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, NULL, NULL))
-        || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
-        ret = 0;
+        /* Use an invalid cipher name, which should generate no output */
+        TEST_note("NOT Displaying PEM encrypted with (invalid) FOO");
+        if (!TEST_false(OSSL_SERIALIZER_CTX_set_cipher(ctx, "FOO", NULL))
+            || !TEST_false(OSSL_SERIALIZER_to_bio(ctx, bio_out)))
+            ret = 0;
+
+        /* Clear the cipher.  This should give us an unencrypted PEM again */
+        TEST_note("Testing with encryption cleared (no encryption)");
+        if (!TEST_true(OSSL_SERIALIZER_CTX_set_cipher(ctx, NULL, NULL))
+            || !TEST_true(OSSL_SERIALIZER_to_bio(ctx, membio))
+            || !TEST_true(compare_with_file(alg, type, membio)))
+            ret = 0;
+    }
 
 err:
+    BIO_free(membio);
     OSSL_SERIALIZER_CTX_free(ctx);
     return ret;
 }
 
+static int test_print_key_using_serializer(const char *alg, const EVP_PKEY *pk)
+{
+    int i;
+    int ret = 1;
+
+    for (i = 0; i < 6; i++)
+        ret = ret && test_print_key_type_using_serializer(alg, i, pk);
+
+    return ret;
+}
+
 /* Array indexes used in test_fromdata_rsa */
 #define N       0
 #define E       1
@@ -141,8 +311,8 @@ static int test_fromdata_rsa(void)
         || !TEST_true(EVP_PKEY_pairwise_check(key_ctx)))
         goto err;
 
-    ret = test_print_key_using_pem(pk)
-        | test_print_key_using_serializer(pk);
+    ret = test_print_key_using_pem("RSA", pk)
+          && test_print_key_using_serializer("RSA", pk);
 
  err:
     EVP_PKEY_free(pk);
@@ -195,8 +365,119 @@ static int test_fromdata_dh(void)
         || !TEST_int_eq(EVP_PKEY_size(pk), 4))
         goto err;
 
-    ret = test_print_key_using_pem(pk)
-        | test_print_key_using_serializer(pk);
+    ret = test_print_key_using_pem("DH", pk)
+          && test_print_key_using_serializer("DH", pk);
+
+ err:
+    EVP_PKEY_free(pk);
+    EVP_PKEY_CTX_free(ctx);
+
+    return ret;
+}
+#endif
+
+#ifndef OPENSSL_NO_EC
+/* Array indexes used in test_fromdata_ecx */
+# define PRIV_KEY        0
+# define PUB_KEY         1
+
+# define X25519_IDX      0
+# define X448_IDX        1
+
+static int test_fromdata_ecx(int tst)
+{
+    int ret = 0;
+    EVP_PKEY_CTX *ctx = NULL;
+    EVP_PKEY *pk = NULL;
+    const char *alg = (tst == X25519_IDX) ? "X25519" : "X448";
+
+    /* X448_KEYLEN > X25519_KEYLEN */
+    static unsigned char key_numbers[2][2][X448_KEYLEN] = {
+        /* X25519: Keys from RFC 7748 6.1 */
+        {
+            /* Private Key */
+            {
+                0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16,
+                0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87,
+                0xeb, 0xc0, 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9,
+                0x2c, 0x2a
+            },
+            /* Public Key */
+            {
+                0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b,
+                0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d,
+                0x26, 0x38, 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b,
+                0x4e, 0x6a
+            }
+        },
+        /* X448: Keys from RFC 7748 6.2 */
+        {
+            /* Private Key */
+            {
+                0x9a, 0x8f, 0x49, 0x25, 0xd1, 0x51, 0x9f, 0x57, 0x75, 0xcf,
+                0x46, 0xb0, 0x4b, 0x58, 0x00, 0xd4, 0xee, 0x9e, 0xe8, 0xba,
+                0xe8, 0xbc, 0x55, 0x65, 0xd4, 0x98, 0xc2, 0x8d, 0xd9, 0xc9,
+                0xba, 0xf5, 0x74, 0xa9, 0x41, 0x97, 0x44, 0x89, 0x73, 0x91,
+                0x00, 0x63, 0x82, 0xa6, 0xf1, 0x27, 0xab, 0x1d, 0x9a, 0xc2,
+                0xd8, 0xc0, 0xa5, 0x98, 0x72, 0x6b
+            },
+            /* Public Key */
+            {
+                0x9b, 0x08, 0xf7, 0xcc, 0x31, 0xb7, 0xe3, 0xe6, 0x7d, 0x22,
+                0xd5, 0xae, 0xa1, 0x21, 0x07, 0x4a, 0x27, 0x3b, 0xd2, 0xb8,
+                0x3d, 0xe0, 0x9c, 0x63, 0xfa, 0xa7, 0x3d, 0x2c, 0x22, 0xc5,
+                0xd9, 0xbb, 0xc8, 0x36, 0x64, 0x72, 0x41, 0xd9, 0x53, 0xd4,
+                0x0c, 0x5b, 0x12, 0xda, 0x88, 0x12, 0x0d, 0x53, 0x17, 0x7f,
+                0x80, 0xe5, 0x32, 0xc4, 0x1f, 0xa0
+            }
+        }
+    };
+    OSSL_PARAM x25519_fromdata_params[] = {
+        OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
+                                key_numbers[X25519_IDX][PRIV_KEY],
+                                X25519_KEYLEN),
+        OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
+                                key_numbers[X25519_IDX][PUB_KEY],
+                                X25519_KEYLEN),
+        OSSL_PARAM_END
+    };
+    OSSL_PARAM x448_fromdata_params[] = {
+        OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
+                                key_numbers[X448_IDX][PRIV_KEY],
+                                X448_KEYLEN),
+        OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
+                                key_numbers[X448_IDX][PUB_KEY],
+                                X448_KEYLEN),
+        OSSL_PARAM_END
+    };
+    OSSL_PARAM *fromdata_params;
+    int bits, security_bits, size;
+
+    if (tst == X25519_IDX) {
+        fromdata_params = x25519_fromdata_params;
+        bits = X25519_BITS;
+        security_bits = X25519_SECURITY_BITS;
+        size = X25519_KEYLEN;
+    } else {
+        fromdata_params = x448_fromdata_params;
+        bits = X448_BITS;
+        security_bits = X448_SECURITY_BITS;
+        size = X448_KEYLEN;
+    }
+
+    ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
+    if (!TEST_ptr(ctx))
+        goto err;
+
+    if (!TEST_true(EVP_PKEY_key_fromdata_init(ctx))
+        || !TEST_true(EVP_PKEY_fromdata(ctx, &pk, fromdata_params))
+        || !TEST_int_eq(EVP_PKEY_bits(pk), bits)
+        || !TEST_int_eq(EVP_PKEY_security_bits(pk), security_bits)
+        || !TEST_int_eq(EVP_PKEY_size(pk), size))
+        goto err;
+
+    ret = test_print_key_using_pem(alg, pk)
+          && test_print_key_using_serializer(alg, pk);
 
  err:
     EVP_PKEY_free(pk);
@@ -206,11 +487,23 @@ static int test_fromdata_dh(void)
 }
 #endif
 
+
 int setup_tests(void)
 {
+    if (!test_skip_common_options()) {
+        TEST_error("Error parsing test options\n");
+        return 0;
+    }
+
+    if (!TEST_ptr(datadir = test_get_argument(0)))
+        return 0;
+
     ADD_TEST(test_fromdata_rsa);
 #ifndef OPENSSL_NO_DH
     ADD_TEST(test_fromdata_dh);
+#endif
+#ifndef OPENSSL_NO_EC
+    ADD_ALL_TESTS(test_fromdata_ecx, 2);
 #endif
     return 1;
 }
diff --git a/test/recipes/30-test_evp_pkey_provided.t b/test/recipes/30-test_evp_pkey_provided.t
index 669438caed..74b366451d 100644
--- a/test/recipes/30-test_evp_pkey_provided.t
+++ b/test/recipes/30-test_evp_pkey_provided.t
@@ -9,5 +9,12 @@
 
 
 use OpenSSL::Test::Simple;
+use OpenSSL::Test qw/:DEFAULT srctop_dir/;
 
-simple_test("test_evp_pkey_provided", "evp_pkey_provided_test");
+setup("test_evp_pkey_provided");
+
+plan tests => 1;
+
+ok(run(test(["evp_pkey_provided_test",
+            srctop_dir("test", "recipes", "30-test_evp_pkey_provided")])),
+   "running evp_pkey_provided_test");
diff --git a/test/recipes/30-test_evp_pkey_provided/DH.priv.der b/test/recipes/30-test_evp_pkey_provided/DH.priv.der
new file mode 100644
index 0000000000..0063e62ecd
Binary files /dev/null and b/test/recipes/30-test_evp_pkey_provided/DH.priv.der differ
diff --git a/test/recipes/30-test_evp_pkey_provided/DH.priv.pem b/test/recipes/30-test_evp_pkey_provided/DH.priv.pem
new file mode 100644
index 0000000000..73cc465041
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/DH.priv.pem
@@ -0,0 +1,3 @@
+-----BEGIN PRIVATE KEY-----
+MCQCAQAwFwYJKoZIhvcNAQMBMAoCBQCLtF9TAgECBAYCBGZsKwY=
+-----END PRIVATE KEY-----
diff --git a/test/recipes/30-test_evp_pkey_provided/DH.priv.txt b/test/recipes/30-test_evp_pkey_provided/DH.priv.txt
new file mode 100644
index 0000000000..cedef99629
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/DH.priv.txt
@@ -0,0 +1,5 @@
+DH Private-Key: (32 bit)
+    private-key: 1718364934 (0x666c2b06)
+    public-key: 1873206864 (0x6fa6de50)
+    prime: 2343853907 (0x8bb45f53)
+    generator: 2 (0x2)
diff --git a/test/recipes/30-test_evp_pkey_provided/DH.pub.der b/test/recipes/30-test_evp_pkey_provided/DH.pub.der
new file mode 100644
index 0000000000..95a30014fd
Binary files /dev/null and b/test/recipes/30-test_evp_pkey_provided/DH.pub.der differ
diff --git a/test/recipes/30-test_evp_pkey_provided/DH.pub.pem b/test/recipes/30-test_evp_pkey_provided/DH.pub.pem
new file mode 100644
index 0000000000..709ac89864
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/DH.pub.pem
@@ -0,0 +1,3 @@
+-----BEGIN PUBLIC KEY-----
+MCIwFwYJKoZIhvcNAQMBMAoCBQCLtF9TAgECAwcAAgRvpt5Q
+-----END PUBLIC KEY-----
diff --git a/test/recipes/30-test_evp_pkey_provided/DH.pub.txt b/test/recipes/30-test_evp_pkey_provided/DH.pub.txt
new file mode 100644
index 0000000000..b7b465f56a
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/DH.pub.txt
@@ -0,0 +1,4 @@
+DH Public-Key: (32 bit)
+    public-key: 1873206864 (0x6fa6de50)
+    prime: 2343853907 (0x8bb45f53)
+    generator: 2 (0x2)
diff --git a/test/recipes/30-test_evp_pkey_provided/RSA.priv.der b/test/recipes/30-test_evp_pkey_provided/RSA.priv.der
new file mode 100644
index 0000000000..08925e43aa
Binary files /dev/null and b/test/recipes/30-test_evp_pkey_provided/RSA.priv.der differ
diff --git a/test/recipes/30-test_evp_pkey_provided/RSA.priv.pem b/test/recipes/30-test_evp_pkey_provided/RSA.priv.pem
new file mode 100644
index 0000000000..548b3f56d9
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/RSA.priv.pem
@@ -0,0 +1,4 @@
+-----BEGIN PRIVATE KEY-----
+MEQCAQAwDQYJKoZIhvcNAQEBBQAEMDAuAgEAAgUAvHR/xQIDAQABAgR7EzOZAgMA
+6WMCAwDOtwIDAIWZAgMAvYcCAwDMOw==
+-----END PRIVATE KEY-----
diff --git a/test/recipes/30-test_evp_pkey_provided/RSA.priv.txt b/test/recipes/30-test_evp_pkey_provided/RSA.priv.txt
new file mode 100644
index 0000000000..d34e9ef2f7
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/RSA.priv.txt
@@ -0,0 +1,9 @@
+Private-Key: (32 bit, 2 primes)
+modulus: 3161751493 (0xbc747fc5)
+publicExponent: 65537 (0x10001)
+privateExponent: 2064855961 (0x7b133399)
+prime1: 59747 (0xe963)
+prime2: 52919 (0xceb7)
+exponent1: 34201 (0x8599)
+exponent2: 48519 (0xbd87)
+coefficient: 52283 (0xcc3b)
diff --git a/test/recipes/30-test_evp_pkey_provided/RSA.pub.der b/test/recipes/30-test_evp_pkey_provided/RSA.pub.der
new file mode 100644
index 0000000000..bff32528a3
Binary files /dev/null and b/test/recipes/30-test_evp_pkey_provided/RSA.pub.der differ
diff --git a/test/recipes/30-test_evp_pkey_provided/RSA.pub.pem b/test/recipes/30-test_evp_pkey_provided/RSA.pub.pem
new file mode 100644
index 0000000000..a1366b70b1
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/RSA.pub.pem
@@ -0,0 +1,3 @@
+-----BEGIN PUBLIC KEY-----
+MCAwDQYJKoZIhvcNAQEBBQADDwAwDAIFALx0f8UCAwEAAQ==
+-----END PUBLIC KEY-----
diff --git a/test/recipes/30-test_evp_pkey_provided/RSA.pub.txt b/test/recipes/30-test_evp_pkey_provided/RSA.pub.txt
new file mode 100644
index 0000000000..f6dad2a0f7
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/RSA.pub.txt
@@ -0,0 +1,3 @@
+Public-Key: (32 bit)
+Modulus: 3161751493 (0xbc747fc5)
+Exponent: 65537 (0x10001)
diff --git a/test/recipes/30-test_evp_pkey_provided/X25519.priv.der b/test/recipes/30-test_evp_pkey_provided/X25519.priv.der
new file mode 100644
index 0000000000..d8d244be76
Binary files /dev/null and b/test/recipes/30-test_evp_pkey_provided/X25519.priv.der differ
diff --git a/test/recipes/30-test_evp_pkey_provided/X25519.priv.pem b/test/recipes/30-test_evp_pkey_provided/X25519.priv.pem
new file mode 100644
index 0000000000..ff18c24026
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/X25519.priv.pem
@@ -0,0 +1,3 @@
+-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VuBCIEIHcHbQpzGKV9PBbBclGyZkXfTC+H68CZKrF3+6UduSwq
+-----END PRIVATE KEY-----
diff --git a/test/recipes/30-test_evp_pkey_provided/X25519.priv.txt b/test/recipes/30-test_evp_pkey_provided/X25519.priv.txt
new file mode 100644
index 0000000000..a18bc1dacb
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/X25519.priv.txt
@@ -0,0 +1,9 @@
+X25519 Private-Key:
+priv:
+    77:07:6d:0a:73:18:a5:7d:3c:16:c1:72:51:b2:66:
+    45:df:4c:2f:87:eb:c0:99:2a:b1:77:fb:a5:1d:b9:
+    2c:2a
+pub:
+    85:20:f0:09:89:30:a7:54:74:8b:7d:dc:b4:3e:f7:
+    5a:0d:bf:3a:0d:26:38:1a:f4:eb:a4:a9:8e:aa:9b:
+    4e:6a
diff --git a/test/recipes/30-test_evp_pkey_provided/X25519.pub.der b/test/recipes/30-test_evp_pkey_provided/X25519.pub.der
new file mode 100644
index 0000000000..4945db18f1
Binary files /dev/null and b/test/recipes/30-test_evp_pkey_provided/X25519.pub.der differ
diff --git a/test/recipes/30-test_evp_pkey_provided/X25519.pub.pem b/test/recipes/30-test_evp_pkey_provided/X25519.pub.pem
new file mode 100644
index 0000000000..4ccf96098c
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/X25519.pub.pem
@@ -0,0 +1,3 @@
+-----BEGIN PUBLIC KEY-----
+MCowBQYDK2VuAyEAhSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo=
+-----END PUBLIC KEY-----
diff --git a/test/recipes/30-test_evp_pkey_provided/X25519.pub.txt b/test/recipes/30-test_evp_pkey_provided/X25519.pub.txt
new file mode 100644
index 0000000000..a57851b151
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/X25519.pub.txt
@@ -0,0 +1,5 @@
+X25519 Public-Key:
+pub:
+    85:20:f0:09:89:30:a7:54:74:8b:7d:dc:b4:3e:f7:
+    5a:0d:bf:3a:0d:26:38:1a:f4:eb:a4:a9:8e:aa:9b:
+    4e:6a
diff --git a/test/recipes/30-test_evp_pkey_provided/X448.priv.der b/test/recipes/30-test_evp_pkey_provided/X448.priv.der
new file mode 100644
index 0000000000..8875333a5b
Binary files /dev/null and b/test/recipes/30-test_evp_pkey_provided/X448.priv.der differ
diff --git a/test/recipes/30-test_evp_pkey_provided/X448.priv.pem b/test/recipes/30-test_evp_pkey_provided/X448.priv.pem
new file mode 100644
index 0000000000..c93235cc06
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/X448.priv.pem
@@ -0,0 +1,4 @@
+-----BEGIN PRIVATE KEY-----
+MEYCAQAwBQYDK2VvBDoEOJqPSSXRUZ9Xdc9GsEtYANTunui66LxVZdSYwo3Zybr1
+dKlBl0SJc5EAY4Km8SerHZrC2MClmHJr
+-----END PRIVATE KEY-----
diff --git a/test/recipes/30-test_evp_pkey_provided/X448.priv.txt b/test/recipes/30-test_evp_pkey_provided/X448.priv.txt
new file mode 100644
index 0000000000..f91620ccf3
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/X448.priv.txt
@@ -0,0 +1,11 @@
+X448 Private-Key:
+priv:
+    9a:8f:49:25:d1:51:9f:57:75:cf:46:b0:4b:58:00:
+    d4:ee:9e:e8:ba:e8:bc:55:65:d4:98:c2:8d:d9:c9:
+    ba:f5:74:a9:41:97:44:89:73:91:00:63:82:a6:f1:
+    27:ab:1d:9a:c2:d8:c0:a5:98:72:6b
+pub:
+    9b:08:f7:cc:31:b7:e3:e6:7d:22:d5:ae:a1:21:07:
+    4a:27:3b:d2:b8:3d:e0:9c:63:fa:a7:3d:2c:22:c5:
+    d9:bb:c8:36:64:72:41:d9:53:d4:0c:5b:12:da:88:
+    12:0d:53:17:7f:80:e5:32:c4:1f:a0
diff --git a/test/recipes/30-test_evp_pkey_provided/X448.pub.der b/test/recipes/30-test_evp_pkey_provided/X448.pub.der
new file mode 100644
index 0000000000..15da4b7146
Binary files /dev/null and b/test/recipes/30-test_evp_pkey_provided/X448.pub.der differ
diff --git a/test/recipes/30-test_evp_pkey_provided/X448.pub.pem b/test/recipes/30-test_evp_pkey_provided/X448.pub.pem
new file mode 100644
index 0000000000..559bf68839
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/X448.pub.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MEIwBQYDK2VvAzkAmwj3zDG34+Z9ItWuoSEHSic70rg94Jxj+qc9LCLF2bvINmRy
+QdlT1AxbEtqIEg1TF3+A5TLEH6A=
+-----END PUBLIC KEY-----
diff --git a/test/recipes/30-test_evp_pkey_provided/X448.pub.txt b/test/recipes/30-test_evp_pkey_provided/X448.pub.txt
new file mode 100644
index 0000000000..d2b6659f3e
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/X448.pub.txt
@@ -0,0 +1,6 @@
+X448 Public-Key:
+pub:
+    9b:08:f7:cc:31:b7:e3:e6:7d:22:d5:ae:a1:21:07:
+    4a:27:3b:d2:b8:3d:e0:9c:63:fa:a7:3d:2c:22:c5:
+    d9:bb:c8:36:64:72:41:d9:53:d4:0c:5b:12:da:88:
+    12:0d:53:17:7f:80:e5:32:c4:1f:a0


More information about the openssl-commits mailing list