From 264b789bc240e6d0f642b274b6ab3cf8470e4aef Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Mon, 18 Nov 2019 02:01:13 +0100 Subject: [PATCH] PROV SERIALIZER: add support for writing DSA keys and parameters Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/10394) --- .../include/prov/implementations.h | 9 + .../implementations/serializers/build.info | 2 + .../serializers/serializer_dsa.c | 152 +++++++++++ .../serializers/serializer_dsa_param.c | 135 ++++++++++ .../serializers/serializer_dsa_priv.c | 244 ++++++++++++++++++ .../serializers/serializer_dsa_pub.c | 151 +++++++++++ .../serializers/serializer_local.h | 21 ++ 7 files changed, 714 insertions(+) create mode 100644 providers/implementations/serializers/serializer_dsa.c create mode 100644 providers/implementations/serializers/serializer_dsa_param.c create mode 100644 providers/implementations/serializers/serializer_dsa_priv.c create mode 100644 providers/implementations/serializers/serializer_dsa_pub.c diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index 3142a66233..75c20a096e 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -278,3 +278,12 @@ 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[]; +extern const OSSL_DISPATCH dsa_priv_der_serializer_functions[]; +extern const OSSL_DISPATCH dsa_pub_der_serializer_functions[]; +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[]; diff --git a/providers/implementations/serializers/build.info b/providers/implementations/serializers/build.info index eee59366c8..43bdee6b77 100644 --- a/providers/implementations/serializers/build.info +++ b/providers/implementations/serializers/build.info @@ -4,7 +4,9 @@ $SERIALIZER_GOAL=../../libimplementations.a $RSA_GOAL=../../libimplementations.a $DH_GOAL=../../libimplementations.a +$DSA_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 +SOURCE[$DSA_GOAL]=serializer_dsa.c serializer_dsa_priv.c serializer_dsa_pub.c serializer_dsa_param.c diff --git a/providers/implementations/serializers/serializer_dsa.c b/providers/implementations/serializers/serializer_dsa.c new file mode 100644 index 0000000000..7578c4ef2e --- /dev/null +++ b/providers/implementations/serializers/serializer_dsa.c @@ -0,0 +1,152 @@ +/* + * 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_dsa_importkey(void) +{ + return ossl_prov_get_importkey(dsa_keymgmt_functions); +} + +int ossl_prov_print_dsa(BIO *out, DSA *dsa, enum dsa_print_type type) +{ + const char *type_label = NULL; + const BIGNUM *priv_key = NULL, *pub_key = NULL; + const BIGNUM *p = NULL, *q = NULL, *g = NULL; + + + switch (type) { + case dsa_print_priv: + type_label = "Private-Key"; + break; + case dsa_print_pub: + type_label = "Public-Key"; + break; + case dsa_print_params: + type_label = "DSA-Parameters"; + break; + } + + if (type == dsa_print_priv) { + priv_key = DSA_get0_priv_key(dsa); + if (priv_key == NULL) + goto null_err; + } + + if (type == dsa_print_priv || type == dsa_print_pub) { + pub_key = DSA_get0_pub_key(dsa); + if (pub_key == NULL) + goto null_err; + } + + p = DSA_get0_p(dsa); + q = DSA_get0_q(dsa); + g = DSA_get0_p(dsa); + + if (p == NULL || q == NULL || g == NULL) + goto null_err; + + 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, "priv:", priv_key)) + goto err; + if (pub_key != NULL + && !ossl_prov_print_labeled_bignum(out, "pub: ", pub_key)) + goto err; + if (!ossl_prov_print_labeled_bignum(out, "P: ", p)) + goto err; + if (!ossl_prov_print_labeled_bignum(out, "Q: ", q)) + goto err; + if (!ossl_prov_print_labeled_bignum(out, "G: ", 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_dsa_params(const void *dsa, 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; + } + + params->length = i2d_DSAparams(dsa, ¶ms->data); + + if (params->length <= 0) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + ASN1_STRING_free(params); + return 0; + } + + *pstrtype = V_ASN1_SEQUENCE; + *pstr = params; + return 1; +} + +int ossl_prov_prepare_all_dsa_params(const void *dsa, int nid, + ASN1_STRING **pstr, int *pstrtype) +{ + const BIGNUM *p = DSA_get0_p(dsa); + const BIGNUM *q = DSA_get0_q(dsa); + const BIGNUM *g = DSA_get0_g(dsa); + + if (p != NULL && q != NULL && g != NULL) + return ossl_prov_prepare_dsa_params(dsa, nid, pstr, pstrtype); + + *pstr = NULL; + *pstrtype = V_ASN1_UNDEF; + return 1; +} + +int ossl_prov_dsa_pub_to_der(const void *dsa, unsigned char **pder) +{ + ASN1_INTEGER *pub_key = BN_to_ASN1_INTEGER(DSA_get0_pub_key(dsa), 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_dsa_priv_to_der(const void *dsa, unsigned char **pder) +{ + ASN1_INTEGER *priv_key = BN_to_ASN1_INTEGER(DSA_get0_priv_key(dsa), 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_dsa_param.c b/providers/implementations/serializers/serializer_dsa_param.c new file mode 100644 index 0000000000..3a108f61ad --- /dev/null +++ b/providers/implementations/serializers/serializer_dsa_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 dsa_param_newctx; +static OSSL_OP_serializer_freectx_fn dsa_param_freectx; +static OSSL_OP_serializer_serialize_data_fn dsa_param_der_data; +static OSSL_OP_serializer_serialize_object_fn dsa_param_der; +static OSSL_OP_serializer_serialize_data_fn dsa_param_pem_data; +static OSSL_OP_serializer_serialize_object_fn dsa_param_pem; + +static OSSL_OP_serializer_serialize_data_fn dsa_param_print_data; +static OSSL_OP_serializer_serialize_object_fn dsa_param_print; + +/* Parameters : context */ + +/* + * There's no specific implementation context, so we use the provider context + */ +static void *dsa_param_newctx(void *provctx) +{ + return provctx; +} + +static void dsa_param_freectx(void *ctx) +{ +} + +/* Public key : DER */ +static int dsa_param_der_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dsa_importkey = + ossl_prov_get_dsa_importkey(); + int ok = 0; + + if (dsa_importkey != NULL) { + DSA *dsa = dsa_importkey(ctx, params); /* ctx == provctx */ + + ok = dsa_param_der(ctx, dsa, out, cb, cbarg); + DSA_free(dsa); + } + return ok; +} + +static int dsa_param_der(void *ctx, void *dsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return i2d_DSAparams_bio(out, dsa); +} + +/* Public key : PEM */ +static int dsa_param_pem_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dsa_importkey = + ossl_prov_get_dsa_importkey(); + int ok = 0; + + if (dsa_importkey != NULL) { + DSA *dsa = dsa_importkey(ctx, params); /* ctx == provctx */ + + ok = dsa_param_pem(ctx, dsa, out, cb, cbarg); + DSA_free(dsa); + } + return ok; +} + +static int dsa_param_pem(void *ctx, void *dsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return PEM_write_bio_DSAparams(out, dsa); +} + +static int dsa_param_print_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dsa_importkey = + ossl_prov_get_dsa_importkey(); + int ok = 0; + + if (dsa_importkey != NULL) { + DSA *dsa = dsa_importkey(ctx, params); /* ctx == provctx */ + + ok = dsa_param_print(ctx, dsa, out, cb, cbarg); + DSA_free(dsa); + } + return ok; +} + +static int dsa_param_print(void *ctx, void *dsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return ossl_prov_print_dsa(out, dsa, dsa_print_params); +} + +const OSSL_DISPATCH dsa_param_der_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dsa_param_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dsa_param_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dsa_param_der_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dsa_param_der }, + { 0, NULL } +}; + +const OSSL_DISPATCH dsa_param_pem_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dsa_param_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dsa_param_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dsa_param_pem_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dsa_param_pem }, + { 0, NULL } +}; + +const OSSL_DISPATCH dsa_param_text_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dsa_param_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dsa_param_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dsa_param_print }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, + (void (*)(void))dsa_param_print_data }, + { 0, NULL } +}; diff --git a/providers/implementations/serializers/serializer_dsa_priv.c b/providers/implementations/serializers/serializer_dsa_priv.c new file mode 100644 index 0000000000..603904369a --- /dev/null +++ b/providers/implementations/serializers/serializer_dsa_priv.c @@ -0,0 +1,244 @@ +/* + * 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 dsa_priv_newctx; +static OSSL_OP_serializer_freectx_fn dsa_priv_freectx; +static OSSL_OP_serializer_set_ctx_params_fn dsa_priv_set_ctx_params; +static OSSL_OP_serializer_settable_ctx_params_fn dsa_priv_settable_ctx_params; +static OSSL_OP_serializer_serialize_data_fn dsa_priv_der_data; +static OSSL_OP_serializer_serialize_object_fn dsa_priv_der; +static OSSL_OP_serializer_serialize_data_fn dsa_pem_priv_data; +static OSSL_OP_serializer_serialize_object_fn dsa_pem_priv; + +static OSSL_OP_serializer_newctx_fn dsa_print_newctx; +static OSSL_OP_serializer_freectx_fn dsa_print_freectx; +static OSSL_OP_serializer_serialize_data_fn dsa_priv_print_data; +static OSSL_OP_serializer_serialize_object_fn dsa_priv_print; + + /* + * Context used for private key serialization. + */ +struct dsa_priv_ctx_st { + void *provctx; + + struct pkcs8_encrypt_ctx_st sc; +}; + +/* Private key : context */ +static void *dsa_priv_newctx(void *provctx) +{ + struct dsa_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 dsa_priv_freectx(void *vctx) +{ + struct dsa_priv_ctx_st *ctx = vctx; + + EVP_CIPHER_free(ctx->sc.cipher); + OPENSSL_free(ctx->sc.cipher_pass); + OPENSSL_free(ctx); +} + +static const OSSL_PARAM *dsa_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 dsa_priv_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + struct dsa_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 dsa_priv_der_data(void *vctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + struct dsa_priv_ctx_st *ctx = vctx; + OSSL_OP_keymgmt_importkey_fn *dsa_importkey = + ossl_prov_get_dsa_importkey(); + int ok = 0; + + if (dsa_importkey != NULL) { + DSA *dsa = dsa_importkey(ctx->provctx, params); + + ok = dsa_priv_der(ctx, dsa, out, cb, cbarg); + DSA_free(dsa); + } + return ok; +} + +static int dsa_priv_der(void *vctx, void *dsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + struct dsa_priv_ctx_st *ctx = vctx; + + ctx->sc.cb = cb; + ctx->sc.cbarg = cbarg; + + return ossl_prov_write_priv_der_from_obj(out, dsa, EVP_PKEY_DSA, + ossl_prov_prepare_dsa_params, + ossl_prov_dsa_priv_to_der, + &ctx->sc); +} + +/* Private key : PEM */ +static int dsa_pem_priv_data(void *vctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + struct dsa_priv_ctx_st *ctx = vctx; + OSSL_OP_keymgmt_importkey_fn *dsa_importkey = + ossl_prov_get_dsa_importkey(); + int ok = 0; + + if (dsa_importkey != NULL) { + DSA *dsa = dsa_importkey(ctx, params); + + ok = dsa_pem_priv(ctx->provctx, dsa, out, cb, cbarg); + DSA_free(dsa); + } + return ok; +} + +static int dsa_pem_priv(void *vctx, void *dsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + struct dsa_priv_ctx_st *ctx = vctx; + + ctx->sc.cb = cb; + ctx->sc.cbarg = cbarg; + + return ossl_prov_write_priv_pem_from_obj(out, dsa, EVP_PKEY_DSA, + ossl_prov_prepare_dsa_params, + ossl_prov_dsa_priv_to_der, + &ctx->sc); +} + +/* + * There's no specific print context, so we use the provider context + */ +static void *dsa_print_newctx(void *provctx) +{ + return provctx; +} + +static void dsa_print_freectx(void *ctx) +{ +} + +static int dsa_priv_print_data(void *provctx, const OSSL_PARAM params[], + BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dsa_importkey = + ossl_prov_get_dsa_importkey(); + int ok = 0; + + if (dsa_importkey != NULL) { + DSA *dsa = dsa_importkey(provctx, params); /* ctx == provctx */ + + ok = dsa_priv_print(provctx, dsa, out, cb, cbarg); + DSA_free(dsa); + } + return ok; +} + +static int dsa_priv_print(void *ctx, void *dsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return ossl_prov_print_dsa(out, dsa, dsa_print_priv); +} + +const OSSL_DISPATCH dsa_priv_der_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dsa_priv_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dsa_priv_freectx }, + { OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS, + (void (*)(void))dsa_priv_set_ctx_params }, + { OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS, + (void (*)(void))dsa_priv_settable_ctx_params }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dsa_priv_der_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dsa_priv_der }, + { 0, NULL } +}; + +const OSSL_DISPATCH dsa_priv_pem_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dsa_priv_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dsa_priv_freectx }, + { OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS, + (void (*)(void))dsa_priv_set_ctx_params }, + { OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS, + (void (*)(void))dsa_priv_settable_ctx_params }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dsa_pem_priv_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dsa_pem_priv }, + { 0, NULL } +}; + +const OSSL_DISPATCH dsa_priv_text_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dsa_print_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dsa_print_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dsa_priv_print }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, + (void (*)(void))dsa_priv_print_data }, + { 0, NULL } +}; diff --git a/providers/implementations/serializers/serializer_dsa_pub.c b/providers/implementations/serializers/serializer_dsa_pub.c new file mode 100644 index 0000000000..0901718a93 --- /dev/null +++ b/providers/implementations/serializers/serializer_dsa_pub.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 +#include +#include +#include +#include "prov/bio.h" +#include "prov/implementations.h" +#include "serializer_local.h" + +static OSSL_OP_serializer_newctx_fn dsa_pub_newctx; +static OSSL_OP_serializer_freectx_fn dsa_pub_freectx; +static OSSL_OP_serializer_serialize_data_fn dsa_pub_der_data; +static OSSL_OP_serializer_serialize_object_fn dsa_pub_der; +static OSSL_OP_serializer_serialize_data_fn dsa_pub_pem_data; +static OSSL_OP_serializer_serialize_object_fn dsa_pub_pem; + +static OSSL_OP_serializer_serialize_data_fn dsa_pub_print_data; +static OSSL_OP_serializer_serialize_object_fn dsa_pub_print; + +/* Public key : context */ + +/* + * There's no specific implementation context, so we use the provider context + */ +static void *dsa_pub_newctx(void *provctx) +{ + return provctx; +} + +static void dsa_pub_freectx(void *ctx) +{ +} + +/* Public key : DER */ +static int dsa_pub_der_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dsa_importkey = + ossl_prov_get_dsa_importkey(); + int ok = 0; + + if (dsa_importkey != NULL) { + DSA *dsa = dsa_importkey(ctx, params); /* ctx == provctx */ + + ok = dsa_pub_der(ctx, dsa, out, cb, cbarg); + DSA_free(dsa); + } + return ok; +} + +static int dsa_pub_der(void *ctx, void *dsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + /* + * TODO(v3.0) implement setting save_parameters, see dsa_pub_encode() + * in crypto/dsa/dsa_ameth.c + */ + int save_parameters = 1; + + return + save_parameters + ? ossl_prov_write_pub_der_from_obj(out, dsa, EVP_PKEY_DSA, + ossl_prov_prepare_all_dsa_params, + ossl_prov_dsa_pub_to_der) + : ossl_prov_write_pub_der_from_obj(out, dsa, EVP_PKEY_DSA, + ossl_prov_prepare_dsa_params, + ossl_prov_dsa_pub_to_der); + +} + +/* Public key : PEM */ +static int dsa_pub_pem_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dsa_importkey = + ossl_prov_get_dsa_importkey(); + int ok = 0; + + if (dsa_importkey != NULL) { + DSA *dsa = dsa_importkey(ctx, params); /* ctx == provctx */ + + ok = dsa_pub_pem(ctx, dsa, out, cb, cbarg); + DSA_free(dsa); + } + return ok; +} + +static int dsa_pub_pem(void *ctx, void *dsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return ossl_prov_write_pub_pem_from_obj(out, dsa, EVP_PKEY_DSA, + ossl_prov_prepare_dsa_params, + ossl_prov_dsa_pub_to_der); +} + +static int dsa_pub_print_data(void *ctx, const OSSL_PARAM params[], BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + OSSL_OP_keymgmt_importkey_fn *dsa_importkey = + ossl_prov_get_dsa_importkey(); + int ok = 0; + + if (dsa_importkey != NULL) { + DSA *dsa = dsa_importkey(ctx, params); /* ctx == provctx */ + + ok = dsa_pub_print(ctx, dsa, out, cb, cbarg); + DSA_free(dsa); + } + return ok; +} + +static int dsa_pub_print(void *ctx, void *dsa, BIO *out, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return ossl_prov_print_dsa(out, dsa, 0); +} + +const OSSL_DISPATCH dsa_pub_der_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dsa_pub_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dsa_pub_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dsa_pub_der_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dsa_pub_der }, + { 0, NULL } +}; + +const OSSL_DISPATCH dsa_pub_pem_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dsa_pub_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dsa_pub_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, (void (*)(void))dsa_pub_pem_data }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dsa_pub_pem }, + { 0, NULL } +}; + +const OSSL_DISPATCH dsa_pub_text_serializer_functions[] = { + { OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))dsa_pub_newctx }, + { OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))dsa_pub_freectx }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, (void (*)(void))dsa_pub_print }, + { OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, + (void (*)(void))dsa_pub_print_data }, + { 0, NULL } +}; diff --git a/providers/implementations/serializers/serializer_local.h b/providers/implementations/serializers/serializer_local.h index c9135eb197..57365f94a9 100644 --- a/providers/implementations/serializers/serializer_local.h +++ b/providers/implementations/serializers/serializer_local.h @@ -34,12 +34,25 @@ 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); +OSSL_OP_keymgmt_importkey_fn *ossl_prov_get_dsa_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_prepare_dsa_params(const void *dsa, int nid, + 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 + * the public key. + */ +int ossl_prov_prepare_all_dsa_params(const void *dsa, int nid, + ASN1_STRING **pstr, int *pstrtype); +int ossl_prov_dsa_pub_to_der(const void *dsa, unsigned char **pder); +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 *n); int ossl_prov_print_rsa(BIO *out, RSA *rsa, int priv); @@ -52,6 +65,14 @@ enum dh_print_type { int ossl_prov_print_dh(BIO *out, DH *dh, enum dh_print_type type); +enum dsa_print_type { + dsa_print_priv, + dsa_print_pub, + dsa_print_params +}; + +int ossl_prov_print_dsa(BIO *out, DSA *dsa, enum dsa_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, -- 2.25.1