aboutsummaryrefslogtreecommitdiff
path: root/providers
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2020-02-28 08:08:59 +1000
committerShane Lontis <shane.lontis@oracle.com>2020-02-28 08:08:59 +1000
commit8efc4a9c656b8b3eabeac64c54efdeb07dd42f8e (patch)
treeb0bc5aac800d9bb912afb2dae10dd3f3bf503a08 /providers
parent30a4cda5e0c67b4e77da4f21b7c5f27991d3367a (diff)
downloadopenssl-8efc4a9c656b8b3eabeac64c54efdeb07dd42f8e.zip
openssl-8efc4a9c656b8b3eabeac64c54efdeb07dd42f8e.tar.gz
openssl-8efc4a9c656b8b3eabeac64c54efdeb07dd42f8e.tar.bz2
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@oracle.com> (Merged from https://github.com/openssl/openssl/pull/11095)
Diffstat (limited to 'providers')
-rw-r--r--providers/defltprov.c28
-rw-r--r--providers/implementations/include/prov/implementations.h16
-rw-r--r--providers/implementations/keymgmt/ecx_kmgmt.c4
-rw-r--r--providers/implementations/serializers/build.info4
-rw-r--r--providers/implementations/serializers/serializer_common.c38
-rw-r--r--providers/implementations/serializers/serializer_dh_pub.c2
-rw-r--r--providers/implementations/serializers/serializer_ecx.c125
-rw-r--r--providers/implementations/serializers/serializer_ecx_priv.c270
-rw-r--r--providers/implementations/serializers/serializer_ecx_pub.c184
-rw-r--r--providers/implementations/serializers/serializer_local.h26
10 files changed, 689 insertions, 8 deletions
diff --git a/providers/defltprov.c b/providers/defltprov.c
index d513dbe..9400eee 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 6d6a26d..a98d113 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 cbb302e..fe0193d 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 0ec2c54..d5873d1 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 daceb11..b1ad523 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 57da48c..567a0f0 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 0000000..589c6c2
--- /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 0000000..64dc594
--- /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 0000000..384d75e
--- /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 801d221..ec27f14 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,