From: Richard Levitte Date: Mon, 18 Nov 2019 00:57:56 +0000 (+0100) Subject: PROV SERIALIZER: add support for writing DH keys and parameters X-Git-Tag: openssl-3.0.0-alpha1~876 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=045e51cbf49a0773f7d045180d9d8b8b73d70e90;p=oweals%2Fopenssl.git PROV SERIALIZER: add support for writing DH keys and parameters Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/10394) --- diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index f7a8b8f7d5..e81c32fe4f 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2684,6 +2684,7 @@ PROV_R_AES_KEY_SETUP_FAILED:101:aes key setup failed PROV_R_BAD_DECRYPT:100:bad decrypt PROV_R_BAD_ENCODING:141:bad encoding PROV_R_BAD_LENGTH:142:bad length +PROV_R_BN_ERROR:160:bn error PROV_R_BOTH_MODE_AND_MODE_INT:127:both mode and mode int PROV_R_CIPHER_OPERATION_FAILED:102:cipher operation failed PROV_R_FAILED_TO_GENERATE_KEY:121:failed to generate key diff --git a/providers/common/include/prov/providercommonerr.h b/providers/common/include/prov/providercommonerr.h index 5493ed5879..85e5856d30 100644 --- a/providers/common/include/prov/providercommonerr.h +++ b/providers/common/include/prov/providercommonerr.h @@ -53,6 +53,7 @@ int ERR_load_PROV_strings(void); # define PROV_R_BAD_DECRYPT 100 # define PROV_R_BAD_ENCODING 141 # define PROV_R_BAD_LENGTH 142 +# define PROV_R_BN_ERROR 160 # define PROV_R_BOTH_MODE_AND_MODE_INT 127 # define PROV_R_CIPHER_OPERATION_FAILED 102 # define PROV_R_FAILED_TO_GENERATE_KEY 121 diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index 440efe5bbf..7cae969c79 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -19,6 +19,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_DECRYPT), "bad decrypt"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_ENCODING), "bad encoding"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_LENGTH), "bad length"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BN_ERROR), "bn error"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BOTH_MODE_AND_MODE_INT), "both mode and mode int"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_CIPHER_OPERATION_FAILED), diff --git a/providers/defltprov.c b/providers/defltprov.c index 84e580366d..b8e96f9c21 100644 --- a/providers/defltprov.c +++ b/providers/defltprov.c @@ -399,6 +399,25 @@ static const OSSL_ALGORITHM deflt_serializer[] = { { "RSA", "default=yes,format=pem,type=public", rsa_pub_pem_serializer_functions }, + { "DH", "default=yes,format=text,type=private", + dh_priv_text_serializer_functions }, + { "DH", "default=yes,format=text,type=public", + dh_pub_text_serializer_functions }, + { "DH", "default=yes,format=text,type=domainparams", + dh_param_text_serializer_functions }, + { "DH", "default=yes,format=der,type=private", + dh_priv_der_serializer_functions }, + { "DH", "default=yes,format=der,type=public", + dh_pub_der_serializer_functions }, + { "DH", "default=yes,format=der,type=domainparams", + dh_param_der_serializer_functions }, + { "DH", "default=yes,format=pem,type=private", + dh_priv_pem_serializer_functions }, + { "DH", "default=yes,format=pem,type=public", + dh_pub_pem_serializer_functions }, + { "DH", "default=yes,format=pem,type=domainparams", + dh_param_pem_serializer_functions }, + { NULL, NULL, NULL } }; diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index 438f9a25fa..3142a66233 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -269,3 +269,12 @@ 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[]; +extern const OSSL_DISPATCH dh_priv_der_serializer_functions[]; +extern const OSSL_DISPATCH dh_pub_der_serializer_functions[]; +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[]; diff --git a/providers/implementations/serializers/build.info b/providers/implementations/serializers/build.info index 8dc5376183..eee59366c8 100644 --- a/providers/implementations/serializers/build.info +++ b/providers/implementations/serializers/build.info @@ -3,6 +3,8 @@ $SERIALIZER_GOAL=../../libimplementations.a $RSA_GOAL=../../libimplementations.a +$DH_GOAL=../../libimplementations.a SOURCE[$SERIALIZER_GOAL]=serializer_common.c SOURCE[$RSA_GOAL]=serializer_rsa.c serializer_rsa_priv.c serializer_rsa_pub.c +SOURCE[$DH_GOAL]=serializer_dh.c serializer_dh_priv.c serializer_dh_pub.c serializer_dh_param.c diff --git a/providers/implementations/serializers/serializer_dh.c b/providers/implementations/serializers/serializer_dh.c new file mode 100644 index 0000000000..313fae0e30 --- /dev/null +++ b/providers/implementations/serializers/serializer_dh.c @@ -0,0 +1,151 @@ +/* + * Copyright 2019 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 +#include +#include "prov/bio.h" /* ossl_prov_bio_printf() */ +#include "prov/implementations.h" /* rsa_keymgmt_functions */ +#include "prov/providercommonerr.h" /* PROV_R_BN_ERROR */ +#include "serializer_local.h" + +OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_dh_importkey(void) +{ + return ossl_prov_get_importkey(dh_keymgmt_functions); +} + +int ossl_prov_print_dh(BIO *out, DH *dh, enum dh_print_type type) +{ + const char *type_label = NULL; + const BIGNUM *priv_key = NULL, *pub_key = NULL; + const BIGNUM *p = NULL, *g = NULL; + + + switch (type) { + case dh_print_priv: + type_label = "DH Private-Key"; + break; + case dh_print_pub: + type_label = "DH Public-Key"; + break; + case dh_print_params: + type_label = "DH Parameters"; + break; + } + + if (type == dh_print_priv) { + priv_key = DH_get0_priv_key(dh); + if (priv_key == NULL) + goto null_err; + } + + if (type == dh_print_priv || type == dh_print_pub) { + pub_key = DH_get0_pub_key(dh); + if (pub_key == NULL) + goto null_err; + } + + p = DH_get0_p(dh); + g = DH_get0_p(dh); + if (p == NULL || g == NULL) + goto null_err; + + /* + * TODO(3.0): add printing of: + * + * - q (label "subgroup order:") + * - j (label "subgroup factor:") + * - seed (label "seed:") + * - counter (label "counter:") + * + * This can happen as soon as there are DH_get0_ functions for them. + */ + + if (ossl_prov_bio_printf(out, "%s: (%d bit)\n", type_label, BN_num_bits(p)) + <= 0) + goto err; + if (priv_key != NULL + && !ossl_prov_print_labeled_bignum(out, " private-key:", priv_key)) + goto err; + if (pub_key != NULL + && !ossl_prov_print_labeled_bignum(out, " public-key:", pub_key)) + goto err; + if (p != NULL + && !ossl_prov_print_labeled_bignum(out, " prime:", p)) + goto err; + if (g != NULL + && !ossl_prov_print_labeled_bignum(out, " generator:", g)) + goto err; + + return 1; + err: + return 0; + null_err: + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + goto err; +} + +int ossl_prov_prepare_dh_params(const void *dh, int nid, + ASN1_STRING **pstr, int *pstrtype) +{ + ASN1_STRING *params = ASN1_STRING_new(); + + if (params == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (nid == EVP_PKEY_DHX) + params->length = i2d_DHxparams(dh, ¶ms->data); + else + params->length = i2d_DHparams(dh, ¶ms->data); + + if (params->length <= 0) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + ASN1_STRING_free(params); + return 0; + } + params->type = V_ASN1_SEQUENCE; + + *pstr = params; + *pstrtype = V_ASN1_SEQUENCE; + return 1; +} + +int ossl_prov_dh_pub_to_der(const void *dh, unsigned char **pder) +{ + ASN1_INTEGER *pub_key = BN_to_ASN1_INTEGER(DH_get0_pub_key(dh), NULL); + int ret; + + if (pub_key == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR); + return 0; + } + + ret = i2d_ASN1_INTEGER(pub_key, pder); + + ASN1_STRING_clear_free(pub_key); + return ret; +} + +int ossl_prov_dh_priv_to_der(const void *dh, unsigned char **pder) +{ + ASN1_INTEGER *priv_key = BN_to_ASN1_INTEGER(DH_get0_priv_key(dh), NULL); + int ret; + + if (priv_key == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR); + return 0; + } + + ret = i2d_ASN1_INTEGER(priv_key, pder); + + ASN1_STRING_clear_free(priv_key); + return ret; +} + diff --git a/providers/implementations/serializers/serializer_dh_param.c b/providers/implementations/serializers/serializer_dh_param.c new file mode 100644 index 0000000000..ca3371e19f --- /dev/null +++ b/providers/implementations/serializers/serializer_dh_param.c @@ -0,0 +1,135 @@ +/* + * Copyright 2019 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 +#include +#include +#include +#include +#include "prov/bio.h" +#include "prov/implementations.h" +#include "prov/providercommonerr.h" +#include "serializer_local.h" + +static OSSL_OP_serializer_newctx_fn dh_param_newctx; +static OSSL_OP_serializer_freectx_fn dh_param_freectx; +static OSSL_OP_serializer_serialize_data_fn dh_param_der_data; +static OSSL_OP_serializer_serialize_object_fn dh_param_der; +static OSSL_OP_serializer_serialize_data_fn dh_param_pem_data; +static OSSL_OP_serializer_serialize_object_fn dh_param_pem; + +static OSSL_OP_serializer_serialize_data_fn dh_param_print_data; +static OSSL_OP_serializer_serialize_object_fn dh_param_print; + +/* Parameters : context */ + +/* + * There's no specific implementation context, so we use the provider context + */ +static void *dh_param_newctx(void *provctx) +{ + return provctx; +} + +static void dh_param_freectx(void *ctx) +{ +} + +/* Public key : DER */ +static int dh_param_der_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dh_importkey = + ossl_prov_get_dh_importkey(); + int ok = 0; + + if (dh_importkey != NULL) { + DH *dh = dh_importkey(ctx, params); /* ctx == provctx */ + + ok = dh_param_der(ctx, dh, out, cb, cbarg); + DH_free(dh); + } + return ok; +} + +static int dh_param_der(void *ctx, void *dh, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return i2d_DHparams_bio(out, dh); +} + +/* Public key : PEM */ +static int dh_param_pem_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dh_importkey = + ossl_prov_get_dh_importkey(); + int ok = 0; + + if (dh_importkey != NULL) { + DH *dh = dh_importkey(ctx, params); /* ctx == provctx */ + + ok = dh_param_pem(ctx, dh, out, cb, cbarg); + DH_free(dh); + } + return ok; +} + +static int dh_param_pem(void *ctx, void *dh, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return PEM_write_bio_DHparams(out, dh); +} + +static int dh_param_print_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dh_importkey = + ossl_prov_get_dh_importkey(); + int ok = 0; + + if (dh_importkey != NULL) { + DH *dh = dh_importkey(ctx, params); /* ctx == provctx */ + + ok = dh_param_print(ctx, dh, out, cb, cbarg); + DH_free(dh); + } + return ok; +} + +static int dh_param_print(void *ctx, void *dh, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return ossl_prov_print_dh(out, dh, dh_print_params); +} + +const OSSL_DISPATCH dh_param_der_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dh_param_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dh_param_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dh_param_der_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dh_param_der }, + { 0, NULL } +}; + +const OSSL_DISPATCH dh_param_pem_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dh_param_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dh_param_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dh_param_pem_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dh_param_pem }, + { 0, NULL } +}; + +const OSSL_DISPATCH dh_param_text_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dh_param_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dh_param_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dh_param_print }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, + (void (*)(void))dh_param_print_data }, + { 0, NULL } +}; diff --git a/providers/implementations/serializers/serializer_dh_priv.c b/providers/implementations/serializers/serializer_dh_priv.c new file mode 100644 index 0000000000..80d87ac738 --- /dev/null +++ b/providers/implementations/serializers/serializer_dh_priv.c @@ -0,0 +1,250 @@ +/* + * Copyright 2019 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 +#include +#include +#include +#include +#include +#include +#include "prov/bio.h" +#include "prov/implementations.h" +#include "serializer_local.h" + +static OSSL_OP_serializer_newctx_fn dh_priv_newctx; +static OSSL_OP_serializer_freectx_fn dh_priv_freectx; +static OSSL_OP_serializer_set_ctx_params_fn dh_priv_set_ctx_params; +static OSSL_OP_serializer_settable_ctx_params_fn dh_priv_settable_ctx_params; +static OSSL_OP_serializer_serialize_data_fn dh_priv_der_data; +static OSSL_OP_serializer_serialize_object_fn dh_priv_der; +static OSSL_OP_serializer_serialize_data_fn dh_pem_priv_data; +static OSSL_OP_serializer_serialize_object_fn dh_pem_priv; + +static OSSL_OP_serializer_newctx_fn dh_print_newctx; +static OSSL_OP_serializer_freectx_fn dh_print_freectx; +static OSSL_OP_serializer_serialize_data_fn dh_priv_print_data; +static OSSL_OP_serializer_serialize_object_fn dh_priv_print; + + /* + * Context used for private key serialization. + */ +struct dh_priv_ctx_st { + void *provctx; + + struct pkcs8_encrypt_ctx_st sc; +}; + +/* Private key : context */ +static void *dh_priv_newctx(void *provctx) +{ + struct dh_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; + + return ctx; +} + +static void dh_priv_freectx(void *vctx) +{ + struct dh_priv_ctx_st *ctx = vctx; + + EVP_CIPHER_free(ctx->sc.cipher); + OPENSSL_free(ctx->sc.cipher_pass); + OPENSSL_free(ctx); +} + +static const OSSL_PARAM *dh_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 dh_priv_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + struct dh_priv_ctx_st *ctx = vctx; + const OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_CIPHER)) + != NULL) { + const OSSL_PARAM *propsp = + OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PROPERTIES); + const char *props = NULL; + + 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; + } + if ((p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PASS)) + != 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 dh_priv_der_data(void *vctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + struct dh_priv_ctx_st *ctx = vctx; + OSSL_OP_keymgmt_importkey_fn *dh_importkey = + ossl_prov_get_dh_importkey(); + int ok = 0; + + if (dh_importkey != NULL) { + DH *dh = dh_importkey(ctx->provctx, params); + + ok = dh_priv_der(ctx, dh, out, cb, cbarg); + DH_free(dh); + } + return ok; +} + +static int dh_priv_der(void *vctx, void *dh, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + struct dh_priv_ctx_st *ctx = vctx; + int ret; + + ctx->sc.cb = cb; + ctx->sc.cbarg = cbarg; + + ret = ossl_prov_write_priv_der_from_obj(out, dh, EVP_PKEY_DH, + ossl_prov_prepare_dh_params, + ossl_prov_dh_priv_to_der, + &ctx->sc); + + return ret; +} + +/* Private key : PEM */ +static int dh_pem_priv_data(void *vctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + struct dh_priv_ctx_st *ctx = vctx; + OSSL_OP_keymgmt_importkey_fn *dh_importkey = + ossl_prov_get_dh_importkey(); + int ok = 0; + + if (dh_importkey != NULL) { + DH *dh = dh_importkey(ctx, params); + + ok = dh_pem_priv(ctx->provctx, dh, out, cb, cbarg); + DH_free(dh); + } + return ok; +} + +static int dh_pem_priv(void *vctx, void *dh, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + struct dh_priv_ctx_st *ctx = vctx; + int ret; + + ctx->sc.cb = cb; + ctx->sc.cbarg = cbarg; + + ret = ossl_prov_write_priv_pem_from_obj(out, dh, EVP_PKEY_DH, + ossl_prov_prepare_dh_params, + ossl_prov_dh_priv_to_der, + &ctx->sc); + + return ret; +} + +/* + * There's no specific print context, so we use the provider context + */ +static void *dh_print_newctx(void *provctx) +{ + return provctx; +} + +static void dh_print_freectx(void *ctx) +{ +} + +static int dh_priv_print_data(void *provctx, const OSSL_PARAM params[], + BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dh_importkey = + ossl_prov_get_dh_importkey(); + int ok = 0; + + if (dh_importkey != NULL) { + DH *dh = dh_importkey(provctx, params); /* ctx == provctx */ + + ok = dh_priv_print(provctx, dh, out, cb, cbarg); + DH_free(dh); + } + return ok; +} + +static int dh_priv_print(void *ctx, void *dh, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return ossl_prov_print_dh(out, dh, dh_print_priv); +} + +const OSSL_DISPATCH dh_priv_der_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dh_priv_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dh_priv_freectx }, + { OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS, + (void (*)(void))dh_priv_set_ctx_params }, + { OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS, + (void (*)(void))dh_priv_settable_ctx_params }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dh_priv_der_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dh_priv_der }, + { 0, NULL } +}; + +const OSSL_DISPATCH dh_priv_pem_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dh_priv_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dh_priv_freectx }, + { OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS, + (void (*)(void))dh_priv_set_ctx_params }, + { OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS, + (void (*)(void))dh_priv_settable_ctx_params }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dh_pem_priv_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dh_pem_priv }, + { 0, NULL } +}; + +const OSSL_DISPATCH dh_priv_text_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dh_print_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dh_print_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dh_priv_print }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, + (void (*)(void))dh_priv_print_data }, + { 0, NULL } +}; diff --git a/providers/implementations/serializers/serializer_dh_pub.c b/providers/implementations/serializers/serializer_dh_pub.c new file mode 100644 index 0000000000..73095c8fd1 --- /dev/null +++ b/providers/implementations/serializers/serializer_dh_pub.c @@ -0,0 +1,140 @@ +/* + * Copyright 2019 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 +#include +#include +#include +#include +#include +#include "prov/bio.h" +#include "prov/implementations.h" +#include "serializer_local.h" + +static OSSL_OP_serializer_newctx_fn dh_pub_newctx; +static OSSL_OP_serializer_freectx_fn dh_pub_freectx; +static OSSL_OP_serializer_serialize_data_fn dh_pub_der_data; +static OSSL_OP_serializer_serialize_object_fn dh_pub_der; +static OSSL_OP_serializer_serialize_data_fn dh_pub_pem_data; +static OSSL_OP_serializer_serialize_object_fn dh_pub_pem; + +static OSSL_OP_serializer_serialize_data_fn dh_pub_print_data; +static OSSL_OP_serializer_serialize_object_fn dh_pub_print; + +/* Public key : context */ + +/* + * There's no specific implementation context, so we use the provider context + */ +static void *dh_pub_newctx(void *provctx) +{ + return provctx; +} + +static void dh_pub_freectx(void *ctx) +{ +} + +/* Public key : DER */ +static int dh_pub_der_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dh_importkey = + ossl_prov_get_dh_importkey(); + int ok = 0; + + if (dh_importkey != NULL) { + DH *dh = dh_importkey(ctx, params); /* ctx == provctx */ + + ok = dh_pub_der(ctx, dh, out, cb, cbarg); + DH_free(dh); + } + return ok; +} + +static int dh_pub_der(void *ctx, void *dh, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return ossl_prov_write_pub_der_from_obj(out, dh, EVP_PKEY_DH, + ossl_prov_prepare_dh_params, + ossl_prov_dh_pub_to_der); +} + +/* Public key : PEM */ +static int dh_pub_pem_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dh_importkey = + ossl_prov_get_dh_importkey(); + int ok = 0; + + if (dh_importkey != NULL) { + DH *dh = dh_importkey(ctx, params); /* ctx == provctx */ + + ok = dh_pub_pem(ctx, dh, out, cb, cbarg); + DH_free(dh); + } + return ok; +} + +static int dh_pub_pem(void *ctx, void *dh, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return ossl_prov_write_pub_pem_from_obj(out, dh, EVP_PKEY_DH, + ossl_prov_prepare_dh_params, + ossl_prov_dh_pub_to_der); + +} + +static int dh_pub_print_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dh_importkey = + ossl_prov_get_dh_importkey(); + int ok = 0; + + if (dh_importkey != NULL) { + DH *dh = dh_importkey(ctx, params); /* ctx == provctx */ + + ok = dh_pub_print(ctx, dh, out, cb, cbarg); + DH_free(dh); + } + return ok; +} + +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); +} + +const OSSL_DISPATCH dh_pub_der_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dh_pub_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dh_pub_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dh_pub_der_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dh_pub_der }, + { 0, NULL } +}; + +const OSSL_DISPATCH dh_pub_pem_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dh_pub_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dh_pub_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dh_pub_pem_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dh_pub_pem }, + { 0, NULL } +}; + +const OSSL_DISPATCH dh_pub_text_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dh_pub_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dh_pub_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dh_pub_print }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, + (void (*)(void))dh_pub_print_data }, + { 0, NULL } +}; diff --git a/providers/implementations/serializers/serializer_local.h b/providers/implementations/serializers/serializer_local.h index 47d025c0c3..c9135eb197 100644 --- a/providers/implementations/serializers/serializer_local.h +++ b/providers/implementations/serializers/serializer_local.h @@ -33,11 +33,25 @@ struct pkcs8_encrypt_ctx_st { OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_importkey(const OSSL_DISPATCH *fns); OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_rsa_importkey(void); +OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_dh_importkey(void); + +int ossl_prov_prepare_dh_params(const void *dh, int nid, + ASN1_STRING **pstr, int *pstrtype); +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); int ossl_prov_print_labeled_bignum(BIO *out, const char *label, const BIGNUM *n); int ossl_prov_print_rsa(BIO *out, RSA *rsa, int priv); +enum dh_print_type { + dh_print_priv, + dh_print_pub, + dh_print_params +}; + +int ossl_prov_print_dh(BIO *out, DH *dh, enum dh_print_type type); + 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,