diff options
author | Matt Caswell <matt@openssl.org> | 2020-02-28 08:08:59 +1000 |
---|---|---|
committer | Shane Lontis <shane.lontis@oracle.com> | 2020-02-28 08:08:59 +1000 |
commit | 8efc4a9c656b8b3eabeac64c54efdeb07dd42f8e (patch) | |
tree | b0bc5aac800d9bb912afb2dae10dd3f3bf503a08 /providers | |
parent | 30a4cda5e0c67b4e77da4f21b7c5f27991d3367a (diff) |
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.c | 28 | ||||
-rw-r--r-- | providers/implementations/include/prov/implementations.h | 16 | ||||
-rw-r--r-- | providers/implementations/keymgmt/ecx_kmgmt.c | 4 | ||||
-rw-r--r-- | providers/implementations/serializers/build.info | 4 | ||||
-rw-r--r-- | providers/implementations/serializers/serializer_common.c | 38 | ||||
-rw-r--r-- | providers/implementations/serializers/serializer_dh_pub.c | 2 | ||||
-rw-r--r-- | providers/implementations/serializers/serializer_ecx.c | 125 | ||||
-rw-r--r-- | providers/implementations/serializers/serializer_ecx_priv.c | 270 | ||||
-rw-r--r-- | providers/implementations/serializers/serializer_ecx_pub.c | 184 | ||||
-rw-r--r-- | providers/implementations/serializers/serializer_local.h | 26 |
10 files changed, 689 insertions, 8 deletions
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, |