[openssl] master update

shane.lontis at oracle.com shane.lontis at oracle.com
Tue Mar 17 22:41:51 UTC 2020


The branch master has been updated
       via  244bc29746c83e76e2fba542ca87552b8aef5c5f (commit)
      from  b3e6d666e351d45e93d29fe3813245b92a0f5815 (commit)


- Log -----------------------------------------------------------------
commit 244bc29746c83e76e2fba542ca87552b8aef5c5f
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Mar 18 08:40:33 2020 +1000

    Implement serializers for ED25519 and ED448
    
    This is largely based on the existing X25519 and X448 serializers - but
    a few adjustments were necessary so that we can identify what type of key
    we are using. Previously we used the keylen for this but X25519 and
    ED25519 have the same keylen.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/11272)

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

Summary of changes:
 crypto/ec/ecx_key.c                                |  18 +++-
 crypto/ec/ecx_meth.c                               |  15 ++--
 include/crypto/ecx.h                               |  20 ++++-
 providers/defltprov.c                              |  26 ++++++
 .../implementations/include/prov/implementations.h |  14 +++
 providers/implementations/keymgmt/ecx_kmgmt.c      |   8 +-
 .../serializers/serializer_common.c                |   1 +
 .../implementations/serializers/serializer_ecx.c   |  32 +++++--
 .../serializers/serializer_ecx_priv.c              |  25 ++++--
 .../serializers/serializer_ecx_pub.c               |  21 ++++-
 .../implementations/serializers/serializer_local.h |   7 +-
 test/evp_pkey_provided_test.c                      |  96 +++++++++++++++++++--
 .../30-test_evp_pkey_provided/ED25519.priv.der     | Bin 0 -> 48 bytes
 .../30-test_evp_pkey_provided/ED25519.priv.pem     |   3 +
 .../30-test_evp_pkey_provided/ED25519.priv.txt     |   9 ++
 .../30-test_evp_pkey_provided/ED25519.pub.der      | Bin 0 -> 44 bytes
 .../30-test_evp_pkey_provided/ED25519.pub.pem      |   3 +
 .../30-test_evp_pkey_provided/ED25519.pub.txt      |   5 ++
 .../30-test_evp_pkey_provided/ED448.priv.der       | Bin 0 -> 73 bytes
 .../30-test_evp_pkey_provided/ED448.priv.pem}      |   0
 .../30-test_evp_pkey_provided/ED448.priv.txt       |  11 +++
 .../30-test_evp_pkey_provided/ED448.pub.der        | Bin 0 -> 69 bytes
 .../30-test_evp_pkey_provided/ED448.pub.pem}       |   0
 .../30-test_evp_pkey_provided/ED448.pub.txt        |   6 ++
 24 files changed, 279 insertions(+), 41 deletions(-)
 create mode 100644 test/recipes/30-test_evp_pkey_provided/ED25519.priv.der
 create mode 100644 test/recipes/30-test_evp_pkey_provided/ED25519.priv.pem
 create mode 100644 test/recipes/30-test_evp_pkey_provided/ED25519.priv.txt
 create mode 100644 test/recipes/30-test_evp_pkey_provided/ED25519.pub.der
 create mode 100644 test/recipes/30-test_evp_pkey_provided/ED25519.pub.pem
 create mode 100644 test/recipes/30-test_evp_pkey_provided/ED25519.pub.txt
 create mode 100644 test/recipes/30-test_evp_pkey_provided/ED448.priv.der
 copy test/{tested448.pem => recipes/30-test_evp_pkey_provided/ED448.priv.pem} (100%)
 create mode 100644 test/recipes/30-test_evp_pkey_provided/ED448.priv.txt
 create mode 100644 test/recipes/30-test_evp_pkey_provided/ED448.pub.der
 copy test/{tested448pub.pem => recipes/30-test_evp_pkey_provided/ED448.pub.pem} (100%)
 create mode 100644 test/recipes/30-test_evp_pkey_provided/ED448.pub.txt

diff --git a/crypto/ec/ecx_key.c b/crypto/ec/ecx_key.c
index 59643cc6ad..0b43d26ae4 100644
--- a/crypto/ec/ecx_key.c
+++ b/crypto/ec/ecx_key.c
@@ -10,7 +10,7 @@
 #include <openssl/err.h>
 #include "crypto/ecx.h"
 
-ECX_KEY *ecx_key_new(size_t keylen, int haspubkey)
+ECX_KEY *ecx_key_new(ECX_KEY_TYPE type, int haspubkey)
 {
     ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret));
 
@@ -18,7 +18,21 @@ ECX_KEY *ecx_key_new(size_t keylen, int haspubkey)
         return NULL;
 
     ret->haspubkey = haspubkey;
-    ret->keylen = keylen;
+    switch (type) {
+    case ECX_KEY_TYPE_X25519:
+        ret->keylen = X25519_KEYLEN;
+        break;
+    case ECX_KEY_TYPE_X448:
+        ret->keylen = X448_KEYLEN;
+        break;
+    case ECX_KEY_TYPE_ED25519:
+        ret->keylen = ED25519_KEYLEN;
+        break;
+    case ECX_KEY_TYPE_ED448:
+        ret->keylen = ED448_KEYLEN;
+        break;
+    }
+    ret->type = type;
     ret->references = 1;
 
     ret->lock = CRYPTO_THREAD_lock_new();
diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c
index f107df3aa4..5f85927bd0 100644
--- a/crypto/ec/ecx_meth.c
+++ b/crypto/ec/ecx_meth.c
@@ -31,6 +31,11 @@
 #define KEYLENID(id)    (IS25519(id) ? X25519_KEYLEN \
                                      : ((id) == EVP_PKEY_X448 ? X448_KEYLEN \
                                                               : ED448_KEYLEN))
+#define KEYNID2TYPE(id) \
+    (IS25519(id) ?  ECX_KEY_TYPE_X25519 \
+                 : ((id) == EVP_PKEY_X448 ? ECX_KEY_TYPE_X448 \
+                                          : ((id) == EVP_PKEY_ED25519 ? ECX_KEY_TYPE_ED25519 \
+                                                                      : ECX_KEY_TYPE_ED448)))
 #define KEYLEN(p)       KEYLENID((p)->ameth->pkey_id)
 
 
@@ -65,7 +70,7 @@ static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg,
         }
     }
 
-    key = ecx_key_new(KEYLENID(id), 1);
+    key = ecx_key_new(KEYNID2TYPE(id), 1);
     if (key == NULL) {
         ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
         return 0;
@@ -1104,7 +1109,7 @@ static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     };
-    ECX_KEY *key = ecx_key_new(X25519_KEYLEN, 1);
+    ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X25519, 1);
     unsigned char *privkey = NULL, *pubkey;
 
     if (key == NULL) {
@@ -1146,7 +1151,7 @@ static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     };
-    ECX_KEY *key = ecx_key_new(X448_KEYLEN, 1);
+    ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X448, 1);
     unsigned char *privkey = NULL, *pubkey;
 
     if (key == NULL) {
@@ -1191,7 +1196,7 @@ static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
     };
     unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
-    ECX_KEY *key = ecx_key_new(ED25519_KEYLEN, 1);
+    ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED25519, 1);
     unsigned char *privkey = NULL, *pubkey;
     unsigned int sz;
 
@@ -1248,7 +1253,7 @@ static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
         0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
     };
     unsigned char x_dst[57], buff[114];
-    ECX_KEY *key = ecx_key_new(ED448_KEYLEN, 1);
+    ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED448, 1);
     unsigned char *privkey = NULL, *pubkey;
     EVP_MD_CTX *hashctx = NULL;
 
diff --git a/include/crypto/ecx.h b/include/crypto/ecx.h
index 3e494bf092..8afb104438 100644
--- a/include/crypto/ecx.h
+++ b/include/crypto/ecx.h
@@ -42,18 +42,36 @@
 #  define ED448_SECURITY_BITS   224
 #  define ED448_SIGSIZE         114
 
+
+typedef enum {
+    ECX_KEY_TYPE_X25519,
+    ECX_KEY_TYPE_X448,
+    ECX_KEY_TYPE_ED25519,
+    ECX_KEY_TYPE_ED448
+} ECX_KEY_TYPE;
+
+#define KEYTYPE2NID(type) \
+    ((type) == ECX_KEY_TYPE_X25519 \
+     ?  EVP_PKEY_X25519 \
+     : ((type) == ECX_KEY_TYPE_X448 \
+        ? EVP_PKEY_X448 \
+        : ((type) == ECX_KEY_TYPE_ED25519 \
+           ? EVP_PKEY_ED25519 \
+           : EVP_PKEY_ED448)))
+
 struct ecx_key_st {
     unsigned int haspubkey:1;
     unsigned char pubkey[MAX_KEYLEN];
     unsigned char *privkey;
     size_t keylen;
+    ECX_KEY_TYPE type;
     CRYPTO_REF_COUNT references;
     CRYPTO_RWLOCK *lock;
 };
 
 typedef struct ecx_key_st ECX_KEY;
 
-ECX_KEY *ecx_key_new(size_t keylen, int haspubkey);
+ECX_KEY *ecx_key_new(ECX_KEY_TYPE type, int haspubkey);
 unsigned char *ecx_key_allocate_privkey(ECX_KEY *key);
 void ecx_key_free(ECX_KEY *key);
 int ecx_key_up_ref(ECX_KEY *key);
diff --git a/providers/defltprov.c b/providers/defltprov.c
index f89363341a..2ec229e16b 100644
--- a/providers/defltprov.c
+++ b/providers/defltprov.c
@@ -504,6 +504,32 @@ static const OSSL_ALGORITHM deflt_serializer[] = {
     { "X448", "provider=default,format=pem,type=public",
       x448_pub_pem_serializer_functions },
 
+    { "ED25519", "provider=default,fips=yes,format=text,type=private",
+      ed25519_priv_print_serializer_functions },
+    { "ED25519", "provider=default,fips=yes,format=text,type=public",
+      ed25519_pub_print_serializer_functions },
+    { "ED25519", "provider=default,fips=yes,format=der,type=private",
+      ed25519_priv_der_serializer_functions },
+    { "ED25519", "provider=default,fips=yes,format=der,type=public",
+      ed25519_pub_der_serializer_functions },
+    { "ED25519", "provider=default,fips=yes,format=pem,type=private",
+      ed25519_priv_pem_serializer_functions },
+    { "ED25519", "provider=default,fips=yes,format=pem,type=public",
+      ed25519_pub_pem_serializer_functions },
+
+    { "ED448", "provider=default,format=text,type=private",
+      ed448_priv_print_serializer_functions },
+    { "ED448", "provider=default,format=text,type=public",
+      ed448_pub_print_serializer_functions },
+    { "ED448", "provider=default,format=der,type=private",
+      ed448_priv_der_serializer_functions },
+    { "ED448", "provider=default,format=der,type=public",
+      ed448_pub_der_serializer_functions },
+    { "ED448", "provider=default,format=pem,type=private",
+      ed448_priv_pem_serializer_functions },
+    { "ED448", "provider=default,format=pem,type=public",
+      ed448_pub_pem_serializer_functions },
+
     { "EC", "provider=default,fips=yes,format=text,type=private",
       ec_priv_text_serializer_functions },
     { "EC", "provider=default,fips=yes,format=text,type=public",
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h
index 57a3122b13..9b5017a144 100644
--- a/providers/implementations/include/prov/implementations.h
+++ b/providers/implementations/include/prov/implementations.h
@@ -322,6 +322,20 @@ 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[];
 
+extern const OSSL_DISPATCH ed25519_priv_print_serializer_functions[];
+extern const OSSL_DISPATCH ed25519_pub_print_serializer_functions[];
+extern const OSSL_DISPATCH ed25519_priv_der_serializer_functions[];
+extern const OSSL_DISPATCH ed25519_pub_der_serializer_functions[];
+extern const OSSL_DISPATCH ed25519_priv_pem_serializer_functions[];
+extern const OSSL_DISPATCH ed25519_pub_pem_serializer_functions[];
+
+extern const OSSL_DISPATCH ed448_priv_print_serializer_functions[];
+extern const OSSL_DISPATCH ed448_pub_print_serializer_functions[];
+extern const OSSL_DISPATCH ed448_priv_der_serializer_functions[];
+extern const OSSL_DISPATCH ed448_pub_der_serializer_functions[];
+extern const OSSL_DISPATCH ed448_priv_pem_serializer_functions[];
+extern const OSSL_DISPATCH ed448_pub_pem_serializer_functions[];
+
 extern const OSSL_DISPATCH ec_priv_text_serializer_functions[];
 extern const OSSL_DISPATCH ec_pub_text_serializer_functions[];
 extern const OSSL_DISPATCH ec_param_text_serializer_functions[];
diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c
index b078c6de58..6450fbb22e 100644
--- a/providers/implementations/keymgmt/ecx_kmgmt.c
+++ b/providers/implementations/keymgmt/ecx_kmgmt.c
@@ -35,22 +35,22 @@ static OSSL_OP_keymgmt_export_types_fn ecx_imexport_types;
 
 static void *x25519_new_key(void *provctx)
 {
-    return ecx_key_new(X25519_KEYLEN, 0);
+    return ecx_key_new(ECX_KEY_TYPE_X25519, 0);
 }
 
 static void *x448_new_key(void *provctx)
 {
-    return ecx_key_new(X448_KEYLEN, 0);
+    return ecx_key_new(ECX_KEY_TYPE_X448, 0);
 }
 
 static void *ed25519_new_key(void *provctx)
 {
-    return ecx_key_new(ED25519_KEYLEN, 0);
+    return ecx_key_new(ECX_KEY_TYPE_ED25519, 0);
 }
 
 static void *ed448_new_key(void *provctx)
 {
-    return ecx_key_new(ED448_KEYLEN, 0);
+    return ecx_key_new(ECX_KEY_TYPE_ED448, 0);
 }
 
 static int ecx_has(void *keydata, int selection)
diff --git a/providers/implementations/serializers/serializer_common.c b/providers/implementations/serializers/serializer_common.c
index 0b99f4939b..7c6b5afe18 100644
--- a/providers/implementations/serializers/serializer_common.c
+++ b/providers/implementations/serializers/serializer_common.c
@@ -14,6 +14,7 @@
 #include <openssl/types.h>
 #include <openssl/x509.h>        /* i2d_X509_PUBKEY_bio() */
 #include "crypto/bn.h"           /* bn_get_words() */
+#include "crypto/ecx.h"
 #include "prov/bio.h"            /* ossl_prov_bio_printf() */
 #include "prov/implementations.h"
 #include "prov/providercommonerr.h" /* PROV_R_READ_KEY */
diff --git a/providers/implementations/serializers/serializer_ecx.c b/providers/implementations/serializers/serializer_ecx.c
index 589c6c25f5..78b6ec9691 100644
--- a/providers/implementations/serializers/serializer_ecx.c
+++ b/providers/implementations/serializers/serializer_ecx.c
@@ -26,6 +26,14 @@ void ecx_get_new_free_import(ECX_KEY_TYPE type,
         *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 if (type == ECX_KEY_TYPE_ED25519) {
+        *ecx_new = ossl_prov_get_keymgmt_new(ed25519_keymgmt_functions);
+        *ecx_free = ossl_prov_get_keymgmt_free(ed25519_keymgmt_functions);
+        *ecx_import = ossl_prov_get_keymgmt_import(ed25519_keymgmt_functions);
+    } else if (type == ECX_KEY_TYPE_ED448) {
+        *ecx_new = ossl_prov_get_keymgmt_new(ed448_keymgmt_functions);
+        *ecx_free = ossl_prov_get_keymgmt_free(ed448_keymgmt_functions);
+        *ecx_import = ossl_prov_get_keymgmt_import(ed448_keymgmt_functions);
     } else {
         *ecx_new = NULL;
         *ecx_free = NULL;
@@ -40,23 +48,35 @@ int ossl_prov_print_ecx(BIO *out, ECX_KEY *ecxkey, enum ecx_print_type type)
 
     switch (type) {
     case ecx_print_priv:
-        switch (ecxkey->keylen) {
-        case X25519_KEYLEN:
+        switch (ecxkey->type) {
+        case ECX_KEY_TYPE_X25519:
             type_label = "X25519 Private-Key";
             break;
-        case X448_KEYLEN:
+        case ECX_KEY_TYPE_X448:
             type_label = "X448 Private-Key";
             break;
+        case ECX_KEY_TYPE_ED25519:
+            type_label = "ED25519 Private-Key";
+            break;
+        case ECX_KEY_TYPE_ED448:
+            type_label = "ED448 Private-Key";
+            break;
         }
         break;
     case ecx_print_pub:
-        switch (ecxkey->keylen) {
-        case X25519_KEYLEN:
+        switch (ecxkey->type) {
+        case ECX_KEY_TYPE_X25519:
             type_label = "X25519 Public-Key";
             break;
-        case X448_KEYLEN:
+        case ECX_KEY_TYPE_X448:
             type_label = "X448 Public-Key";
             break;
+        case ECX_KEY_TYPE_ED25519:
+            type_label = "ED25519 Public-Key";
+            break;
+        case ECX_KEY_TYPE_ED448:
+            type_label = "ED448 Public-Key";
+            break;
         }
         break;
     }
diff --git a/providers/implementations/serializers/serializer_ecx_priv.c b/providers/implementations/serializers/serializer_ecx_priv.c
index 64dc594624..c746109424 100644
--- a/providers/implementations/serializers/serializer_ecx_priv.c
+++ b/providers/implementations/serializers/serializer_ecx_priv.c
@@ -13,12 +13,15 @@
 #include <openssl/pem.h>
 #include <openssl/types.h>
 #include <openssl/params.h>
+#include "crypto/ecx.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_newctx_fn ed25519_priv_newctx;
+static OSSL_OP_serializer_newctx_fn ed448_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;
@@ -65,6 +68,16 @@ static void *x448_priv_newctx(void *provctx)
     return ecx_priv_newctx(provctx, ECX_KEY_TYPE_X448);
 }
 
+static void *ed25519_priv_newctx(void *provctx)
+{
+    return ecx_priv_newctx(provctx, ECX_KEY_TYPE_ED25519);
+}
+
+static void *ed448_priv_newctx(void *provctx)
+{
+    return ecx_priv_newctx(provctx, ECX_KEY_TYPE_ED448);
+}
+
 static void ecx_priv_freectx(void *vctx)
 {
     struct ecx_priv_ctx_st *ctx = vctx;
@@ -150,14 +163,13 @@ static int ecx_priv_der(void *vctx, void *vecxkey, BIO *out,
     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;
+    int nid = KEYTYPE2NID(ctx->type);
 
     ctx->sc.cb = cb;
     ctx->sc.cbarg = cbarg;
 
     ret = ossl_prov_write_priv_der_from_obj(out, ecxkey,
-                                            type,
+                                            nid,
                                             NULL,
                                             ossl_prov_ecx_priv_to_der,
                                             &ctx->sc);
@@ -194,14 +206,13 @@ static int ecx_priv_pem(void *vctx, void *ecxkey, BIO *out,
 {
     struct ecx_priv_ctx_st *ctx = vctx;
     int ret;
-    int type = (ctx->type == ECX_KEY_TYPE_X25519) ? EVP_PKEY_X25519
-                                                  : EVP_PKEY_X448;
+    int nid = KEYTYPE2NID(ctx->type);
 
     ctx->sc.cb = cb;
     ctx->sc.cbarg = cbarg;
 
     ret = ossl_prov_write_priv_pem_from_obj(out, ecxkey,
-                                            type,
+                                            nid,
                                             NULL,
                                             ossl_prov_ecx_priv_to_der,
                                             &ctx->sc);
@@ -268,3 +279,5 @@ static int ecx_priv_print(void *ctx, void *ecxkey, BIO *out,
 
 MAKE_SERIALIZER_FUNCTIONS_GROUP(x25519)
 MAKE_SERIALIZER_FUNCTIONS_GROUP(x448)
+MAKE_SERIALIZER_FUNCTIONS_GROUP(ed25519)
+MAKE_SERIALIZER_FUNCTIONS_GROUP(ed448)
diff --git a/providers/implementations/serializers/serializer_ecx_pub.c b/providers/implementations/serializers/serializer_ecx_pub.c
index 384d75e6b3..cd09cd6abb 100644
--- a/providers/implementations/serializers/serializer_ecx_pub.c
+++ b/providers/implementations/serializers/serializer_ecx_pub.c
@@ -12,12 +12,15 @@
 #include <openssl/pem.h>
 #include <openssl/types.h>
 #include <openssl/params.h>
+#include "crypto/ecx.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_newctx_fn ed25519_pub_newctx;
+static OSSL_OP_serializer_newctx_fn ed448_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;
@@ -57,6 +60,16 @@ static void *x448_pub_newctx(void *provctx)
     return ecx_pub_newctx(provctx, ECX_KEY_TYPE_X448);
 }
 
+static void *ed25519_pub_newctx(void *provctx)
+{
+    return ecx_pub_newctx(provctx, ECX_KEY_TYPE_ED25519);
+}
+
+static void *ed448_pub_newctx(void *provctx)
+{
+    return ecx_pub_newctx(provctx, ECX_KEY_TYPE_ED448);
+}
+
 static void ecx_pub_freectx(void *ctx)
 {
     OPENSSL_free(ctx);
@@ -92,8 +105,7 @@ static int ecx_pub_der(void *vctx, void *ecxkey, BIO *out,
     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,
+                                            KEYTYPE2NID(ctx->type),
                                             NULL,
                                             ossl_prov_ecx_pub_to_der);
 }
@@ -128,8 +140,7 @@ static int ecx_pub_pem(void *vctx, void *ecxkey, BIO *out,
     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,
+                                            KEYTYPE2NID(ctx->type),
                                             NULL,
                                             ossl_prov_ecx_pub_to_der);
 
@@ -182,3 +193,5 @@ static int ecx_pub_print(void *ctx, void *ecxkey, BIO *out,
 
 MAKE_SERIALIZER_FUNCTIONS_GROUP(x25519)
 MAKE_SERIALIZER_FUNCTIONS_GROUP(x448)
+MAKE_SERIALIZER_FUNCTIONS_GROUP(ed25519)
+MAKE_SERIALIZER_FUNCTIONS_GROUP(ed448)
diff --git a/providers/implementations/serializers/serializer_local.h b/providers/implementations/serializers/serializer_local.h
index 3125dc8f74..b1c36a2221 100644
--- a/providers/implementations/serializers/serializer_local.h
+++ b/providers/implementations/serializers/serializer_local.h
@@ -31,11 +31,6 @@ 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);
@@ -64,12 +59,14 @@ 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);
 
+#ifndef OPENSSL_NO_EC
 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);
+#endif
 
 int ossl_prov_prepare_dsa_params(const void *dsa, int nid,
                                 void **pstr, int *pstrtype);
diff --git a/test/evp_pkey_provided_test.c b/test/evp_pkey_provided_test.c
index c395f185dd..d0a87b08d3 100644
--- a/test/evp_pkey_provided_test.c
+++ b/test/evp_pkey_provided_test.c
@@ -392,16 +392,18 @@ static int test_fromdata_dh(void)
 
 # define X25519_IDX      0
 # define X448_IDX        1
+# define ED25519_IDX     2
+# define ED448_IDX       3
 
 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";
+    const char *alg = NULL;
 
-    /* X448_KEYLEN > X25519_KEYLEN */
-    static unsigned char key_numbers[2][2][X448_KEYLEN] = {
+    /* ED448_KEYLEN > X448_KEYLEN > X25519_KEYLEN == ED25519_KEYLEN */
+    static unsigned char key_numbers[4][2][ED448_KEYLEN] = {
         /* X25519: Keys from RFC 7748 6.1 */
         {
             /* Private Key */
@@ -439,6 +441,44 @@ static int test_fromdata_ecx(int tst)
                 0x0c, 0x5b, 0x12, 0xda, 0x88, 0x12, 0x0d, 0x53, 0x17, 0x7f,
                 0x80, 0xe5, 0x32, 0xc4, 0x1f, 0xa0
             }
+        },
+        /* ED25519: Keys from RFC 8032 */
+        {
+            /* Private Key */
+            {
+                0x9d, 0x61, 0xb1, 0x9d, 0xef, 0xfd, 0x5a, 0x60, 0xba, 0x84,
+                0x4a, 0xf4, 0x92, 0xec, 0x2c, 0xc4, 0x44, 0x49, 0xc5, 0x69,
+                0x7b, 0x32, 0x69, 0x19, 0x70, 0x3b, 0xac, 0x03, 0x1c, 0xae,
+                0x7f, 0x60
+            },
+            /* Public Key */
+            {
+                0xd7, 0x5a, 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, 0xd5, 0x4b,
+                0xfe, 0xd3, 0xc9, 0x64, 0x07, 0x3a, 0x0e, 0xe1, 0x72, 0xf3,
+                0xda, 0xa6, 0x23, 0x25, 0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07,
+                0x51, 0x1a
+            }
+        },
+        /* ED448: Keys from RFC 8032 */
+        {
+            /* Private Key */
+            {
+                0x6c, 0x82, 0xa5, 0x62, 0xcb, 0x80, 0x8d, 0x10, 0xd6, 0x32,
+                0xbe, 0x89, 0xc8, 0x51, 0x3e, 0xbf, 0x6c, 0x92, 0x9f, 0x34,
+                0xdd, 0xfa, 0x8c, 0x9f, 0x63, 0xc9, 0x96, 0x0e, 0xf6, 0xe3,
+                0x48, 0xa3, 0x52, 0x8c, 0x8a, 0x3f, 0xcc, 0x2f, 0x04, 0x4e,
+                0x39, 0xa3, 0xfc, 0x5b, 0x94, 0x49, 0x2f, 0x8f, 0x03, 0x2e,
+                0x75, 0x49, 0xa2, 0x00, 0x98, 0xf9, 0x5b
+            },
+            /* Public Key */
+            {
+                0x5f, 0xd7, 0x44, 0x9b, 0x59, 0xb4, 0x61, 0xfd, 0x2c, 0xe7,
+                0x87, 0xec, 0x61, 0x6a, 0xd4, 0x6a, 0x1d, 0xa1, 0x34, 0x24,
+                0x85, 0xa7, 0x0e, 0x1f, 0x8a, 0x0e, 0xa7, 0x5d, 0x80, 0xe9,
+                0x67, 0x78, 0xed, 0xf1, 0x24, 0x76, 0x9b, 0x46, 0xc7, 0x06,
+                0x1b, 0xd6, 0x78, 0x3d, 0xf1, 0xe5, 0x0f, 0x6c, 0xd1, 0xfa,
+                0x1a, 0xbe, 0xaf, 0xe8, 0x25, 0x61, 0x80
+            }
         }
     };
     OSSL_PARAM x25519_fromdata_params[] = {
@@ -459,19 +499,59 @@ static int test_fromdata_ecx(int tst)
                                 X448_KEYLEN),
         OSSL_PARAM_END
     };
-    OSSL_PARAM *fromdata_params;
-    int bits, security_bits, size;
+    OSSL_PARAM ed25519_fromdata_params[] = {
+        OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
+                                key_numbers[ED25519_IDX][PRIV_KEY],
+                                ED25519_KEYLEN),
+        OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
+                                key_numbers[ED25519_IDX][PUB_KEY],
+                                ED25519_KEYLEN),
+        OSSL_PARAM_END
+    };
+    OSSL_PARAM ed448_fromdata_params[] = {
+        OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
+                                key_numbers[ED448_IDX][PRIV_KEY],
+                                ED448_KEYLEN),
+        OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
+                                key_numbers[ED448_IDX][PUB_KEY],
+                                ED448_KEYLEN),
+        OSSL_PARAM_END
+    };
+    OSSL_PARAM *fromdata_params = NULL;
+    int bits = 0, security_bits = 0, size = 0;
 
-    if (tst == X25519_IDX) {
+    switch (tst) {
+    case X25519_IDX:
         fromdata_params = x25519_fromdata_params;
         bits = X25519_BITS;
         security_bits = X25519_SECURITY_BITS;
         size = X25519_KEYLEN;
-    } else {
+        alg = "X25519";
+        break;
+
+    case X448_IDX:
         fromdata_params = x448_fromdata_params;
         bits = X448_BITS;
         security_bits = X448_SECURITY_BITS;
         size = X448_KEYLEN;
+        alg = "X448";
+        break;
+
+    case ED25519_IDX:
+        fromdata_params = ed25519_fromdata_params;
+        bits = ED25519_BITS;
+        security_bits = ED25519_SECURITY_BITS;
+        size = ED25519_KEYLEN;
+        alg = "ED25519";
+        break;
+
+    case ED448_IDX:
+        fromdata_params = ed448_fromdata_params;
+        bits = ED448_BITS;
+        security_bits = ED448_SECURITY_BITS;
+        size = ED448_KEYLEN;
+        alg = "ED448";
+        break;
     }
 
     ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL);
@@ -577,7 +657,7 @@ int setup_tests(void)
     ADD_TEST(test_fromdata_dh);
 #endif
 #ifndef OPENSSL_NO_EC
-    ADD_ALL_TESTS(test_fromdata_ecx, 2);
+    ADD_ALL_TESTS(test_fromdata_ecx, 4);
     ADD_TEST(test_fromdata_ec);
 #endif
     return 1;
diff --git a/test/recipes/30-test_evp_pkey_provided/ED25519.priv.der b/test/recipes/30-test_evp_pkey_provided/ED25519.priv.der
new file mode 100644
index 0000000000..71783b74d3
Binary files /dev/null and b/test/recipes/30-test_evp_pkey_provided/ED25519.priv.der differ
diff --git a/test/recipes/30-test_evp_pkey_provided/ED25519.priv.pem b/test/recipes/30-test_evp_pkey_provided/ED25519.priv.pem
new file mode 100644
index 0000000000..7cf2b728c9
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/ED25519.priv.pem
@@ -0,0 +1,3 @@
+-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VwBCIEIJ1hsZ3v/VpguoRK9JLsLMREScVpezJpGXA7rAMcrn9g
+-----END PRIVATE KEY-----
diff --git a/test/recipes/30-test_evp_pkey_provided/ED25519.priv.txt b/test/recipes/30-test_evp_pkey_provided/ED25519.priv.txt
new file mode 100644
index 0000000000..43ed486f40
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/ED25519.priv.txt
@@ -0,0 +1,9 @@
+ED25519 Private-Key:
+priv:
+    9d:61:b1:9d:ef:fd:5a:60:ba:84:4a:f4:92:ec:2c:
+    c4:44:49:c5:69:7b:32:69:19:70:3b:ac:03:1c:ae:
+    7f:60
+pub:
+    d7:5a:98:01:82:b1:0a:b7:d5:4b:fe:d3:c9:64:07:
+    3a:0e:e1:72:f3:da:a6:23:25:af:02:1a:68:f7:07:
+    51:1a
diff --git a/test/recipes/30-test_evp_pkey_provided/ED25519.pub.der b/test/recipes/30-test_evp_pkey_provided/ED25519.pub.der
new file mode 100644
index 0000000000..5b33e7546d
Binary files /dev/null and b/test/recipes/30-test_evp_pkey_provided/ED25519.pub.der differ
diff --git a/test/recipes/30-test_evp_pkey_provided/ED25519.pub.pem b/test/recipes/30-test_evp_pkey_provided/ED25519.pub.pem
new file mode 100644
index 0000000000..9749b691de
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/ED25519.pub.pem
@@ -0,0 +1,3 @@
+-----BEGIN PUBLIC KEY-----
+MCowBQYDK2VwAyEA11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo=
+-----END PUBLIC KEY-----
diff --git a/test/recipes/30-test_evp_pkey_provided/ED25519.pub.txt b/test/recipes/30-test_evp_pkey_provided/ED25519.pub.txt
new file mode 100644
index 0000000000..7456dfc252
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/ED25519.pub.txt
@@ -0,0 +1,5 @@
+ED25519 Public-Key:
+pub:
+    d7:5a:98:01:82:b1:0a:b7:d5:4b:fe:d3:c9:64:07:
+    3a:0e:e1:72:f3:da:a6:23:25:af:02:1a:68:f7:07:
+    51:1a
diff --git a/test/recipes/30-test_evp_pkey_provided/ED448.priv.der b/test/recipes/30-test_evp_pkey_provided/ED448.priv.der
new file mode 100644
index 0000000000..5718a54734
Binary files /dev/null and b/test/recipes/30-test_evp_pkey_provided/ED448.priv.der differ
diff --git a/test/tested448.pem b/test/recipes/30-test_evp_pkey_provided/ED448.priv.pem
similarity index 100%
copy from test/tested448.pem
copy to test/recipes/30-test_evp_pkey_provided/ED448.priv.pem
diff --git a/test/recipes/30-test_evp_pkey_provided/ED448.priv.txt b/test/recipes/30-test_evp_pkey_provided/ED448.priv.txt
new file mode 100644
index 0000000000..071ee6c5f7
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/ED448.priv.txt
@@ -0,0 +1,11 @@
+ED448 Private-Key:
+priv:
+    6c:82:a5:62:cb:80:8d:10:d6:32:be:89:c8:51:3e:
+    bf:6c:92:9f:34:dd:fa:8c:9f:63:c9:96:0e:f6:e3:
+    48:a3:52:8c:8a:3f:cc:2f:04:4e:39:a3:fc:5b:94:
+    49:2f:8f:03:2e:75:49:a2:00:98:f9:5b
+pub:
+    5f:d7:44:9b:59:b4:61:fd:2c:e7:87:ec:61:6a:d4:
+    6a:1d:a1:34:24:85:a7:0e:1f:8a:0e:a7:5d:80:e9:
+    67:78:ed:f1:24:76:9b:46:c7:06:1b:d6:78:3d:f1:
+    e5:0f:6c:d1:fa:1a:be:af:e8:25:61:80
diff --git a/test/recipes/30-test_evp_pkey_provided/ED448.pub.der b/test/recipes/30-test_evp_pkey_provided/ED448.pub.der
new file mode 100644
index 0000000000..bd2a95530b
Binary files /dev/null and b/test/recipes/30-test_evp_pkey_provided/ED448.pub.der differ
diff --git a/test/tested448pub.pem b/test/recipes/30-test_evp_pkey_provided/ED448.pub.pem
similarity index 100%
copy from test/tested448pub.pem
copy to test/recipes/30-test_evp_pkey_provided/ED448.pub.pem
diff --git a/test/recipes/30-test_evp_pkey_provided/ED448.pub.txt b/test/recipes/30-test_evp_pkey_provided/ED448.pub.txt
new file mode 100644
index 0000000000..06a2967b44
--- /dev/null
+++ b/test/recipes/30-test_evp_pkey_provided/ED448.pub.txt
@@ -0,0 +1,6 @@
+ED448 Public-Key:
+pub:
+    5f:d7:44:9b:59:b4:61:fd:2c:e7:87:ec:61:6a:d4:
+    6a:1d:a1:34:24:85:a7:0e:1f:8a:0e:a7:5d:80:e9:
+    67:78:ed:f1:24:76:9b:46:c7:06:1b:d6:78:3d:f1:
+    e5:0f:6c:d1:fa:1a:be:af:e8:25:61:80


More information about the openssl-commits mailing list