diff options
author | Richard Levitte <levitte@openssl.org> | 2020-09-07 12:25:17 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2020-09-09 16:35:22 +0200 |
commit | 8ae40cf57d2138af92a3479e23f35037ae8c5c30 (patch) | |
tree | 18b15b731f9b593f93716e05884cb0b9ba0a54a5 /providers/implementations/encode_decode | |
parent | ce43db7a3fcd18866385a4552f5e4a83adfc0979 (diff) |
ENCODER: Refactor provider implementations, and some cleanup
The encoder implementations were implemented by unnecessarily copying
code into numerous topical source files, making them hard to maintain.
This changes merges all those into two source files, one that encodes
into DER and PEM, the other to text.
Diverse small cleanups are included.
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/12803)
Diffstat (limited to 'providers/implementations/encode_decode')
30 files changed, 2044 insertions, 4896 deletions
diff --git a/providers/implementations/encode_decode/build.info b/providers/implementations/encode_decode/build.info index 3e78849dfc..97e2264418 100644 --- a/providers/implementations/encode_decode/build.info +++ b/providers/implementations/encode_decode/build.info @@ -10,26 +10,12 @@ $DSA_GOAL=../../libimplementations.a $ECX_GOAL=../../libimplementations.a $EC_GOAL=../../libimplementations.a -SOURCE[$ENCODER_GOAL]=encoder_common.c decode_common.c +SOURCE[$ENCODER_GOAL]=endecoder_common.c SOURCE[$DECODER_GOAL]=decode_der2key.c decode_pem2der.c IF[{- !$disabled{dsa} -}] SOURCE[$DECODER_GOAL]=decode_ms2key.c ENDIF -SOURCE[$RSA_GOAL]=encoder_rsa.c encoder_rsa_priv.c encoder_rsa_pub.c -DEPEND[encoder_rsa.o]=../../common/include/prov/der_rsa.h - -IF[{- !$disabled{"dh"} || !$disabled{"dsa"} -}] - SOURCE[$FFC_GOAL]=encoder_ffc_params.c -ENDIF -IF[{- !$disabled{dh} -}] - SOURCE[$DH_GOAL]=encoder_dh.c encoder_dh_priv.c encoder_dh_pub.c encoder_dh_param.c -ENDIF -IF[{- !$disabled{dsa} -}] - SOURCE[$DSA_GOAL]=encoder_dsa.c encoder_dsa_priv.c encoder_dsa_pub.c encoder_dsa_param.c -ENDIF -IF[{- !$disabled{ec} -}] - SOURCE[$ECX_GOAL]=encoder_ecx.c encoder_ecx_priv.c encoder_ecx_pub.c - SOURCE[$EC_GOAL]=encoder_ec.c encoder_ec_priv.c encoder_ec_pub.c encoder_ec_param.c -ENDIF +SOURCE[$DECODER_GOAL]=encode_key2any.c encode_key2text.c +DEPEND[encode_key2any.o]=../../common/include/prov/der_rsa.h diff --git a/providers/implementations/encode_decode/decode_common.c b/providers/implementations/encode_decode/decode_common.c deleted file mode 100644 index 798d8f10b2..0000000000 --- a/providers/implementations/encode_decode/decode_common.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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_names.h> -#include <openssl/bio.h> -#include <openssl/err.h> -#include <openssl/buffer.h> -#include <openssl/pem.h> /* For public PEM and PVK functions */ -#include <openssl/pkcs12.h> -#include "internal/pem.h" /* For internal PVK and "blob" functions */ -#include "internal/cryptlib.h" -#include "internal/asn1.h" -#include "internal/passphrase.h" -#include "prov/bio.h" /* ossl_prov_bio_printf() */ -#include "prov/providercommonerr.h" /* PROV_R_READ_KEY */ -#include "encoder_local.h" - -int ossl_prov_read_der(PROV_CTX *provctx, OSSL_CORE_BIO *cin, - unsigned char **data, long *len) -{ - BUF_MEM *mem = NULL; - BIO *in = bio_new_from_core_bio(provctx, cin); - int ok = (asn1_d2i_read_bio(in, &mem) >= 0); - - if (ok) { - *data = (unsigned char *)mem->data; - *len = (long)mem->length; - OPENSSL_free(mem); - } - BIO_free(in); - return ok; -} - -int ossl_prov_read_pem(PROV_CTX *provctx, OSSL_CORE_BIO *cin, - char **pem_name, char **pem_header, - unsigned char **data, long *len) -{ - BIO *in = bio_new_from_core_bio(provctx, cin); - int ok = (PEM_read_bio(in, pem_name, pem_header, data, len) > 0); - - BIO_free(in); - return ok; -} - -#ifndef OPENSSL_NO_DSA -EVP_PKEY *ossl_prov_read_msblob(PROV_CTX *provctx, OSSL_CORE_BIO *cin, - int *ispub) -{ - BIO *in = bio_new_from_core_bio(provctx, cin); - EVP_PKEY *pkey = ossl_b2i_bio(in, ispub); - - BIO_free(in); - return pkey; -} - -# ifndef OPENSSL_NO_RC4 -EVP_PKEY *ossl_prov_read_pvk(PROV_CTX *provctx, OSSL_CORE_BIO *cin, - OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) -{ - BIO *in = NULL; - EVP_PKEY *pkey = NULL; - struct ossl_passphrase_data_st pwdata; - - memset(&pwdata, 0, sizeof(pwdata)); - if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg)) - return NULL; - - in = bio_new_from_core_bio(provctx, cin); - pkey = b2i_PVK_bio(in, ossl_pw_pem_password, &pwdata); - BIO_free(in); - - return pkey; -} -# endif -#endif - -int ossl_prov_der_from_p8(unsigned char **new_der, long *new_der_len, - unsigned char *input_der, long input_der_len, - OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) -{ - const unsigned char *derp; - X509_SIG *p8 = NULL; - int ok = 0; - - if (!ossl_assert(new_der != NULL && *new_der == NULL) - || !ossl_assert(new_der_len != NULL)) - return 0; - - derp = input_der; - if ((p8 = d2i_X509_SIG(NULL, &derp, input_der_len)) != NULL) { - char pbuf[PEM_BUFSIZE]; - size_t plen = 0; - - if (!pw_cb(pbuf, sizeof(pbuf), &plen, NULL, pw_cbarg)) { - ERR_raise(ERR_LIB_PROV, PROV_R_READ_KEY); - } else { - const X509_ALGOR *alg = NULL; - const ASN1_OCTET_STRING *oct = NULL; - int len = 0; - - X509_SIG_get0(p8, &alg, &oct); - if (PKCS12_pbe_crypt(alg, pbuf, plen, oct->data, oct->length, - new_der, &len, 0) != NULL) - ok = 1; - *new_der_len = len; - } - } - X509_SIG_free(p8); - return ok; -} diff --git a/providers/implementations/encode_decode/decode_der2key.c b/providers/implementations/encode_decode/decode_der2key.c index b8b268217d..011f05803d 100644 --- a/providers/implementations/encode_decode/decode_der2key.c +++ b/providers/implementations/encode_decode/decode_der2key.c @@ -17,13 +17,71 @@ #include <openssl/core_names.h> #include <openssl/core_object.h> #include <openssl/crypto.h> +#include <openssl/err.h> #include <openssl/params.h> +#include <openssl/pem.h> /* PEM_BUFSIZE and public PEM functions */ +#include <openssl/pkcs12.h> #include <openssl/x509.h> +#include "internal/cryptlib.h" /* ossl_assert() */ +#include "internal/asn1.h" +#include "crypto/ecx.h" #include "prov/bio.h" #include "prov/implementations.h" -#include "encoder_local.h" +#include "prov/providercommonerr.h" +#include "endecoder_local.h" -static OSSL_FUNC_decoder_newctx_fn der2rsa_newctx; +static int read_der(PROV_CTX *provctx, OSSL_CORE_BIO *cin, + unsigned char **data, long *len) +{ + BUF_MEM *mem = NULL; + BIO *in = bio_new_from_core_bio(provctx, cin); + int ok = (asn1_d2i_read_bio(in, &mem) >= 0); + + if (ok) { + *data = (unsigned char *)mem->data; + *len = (long)mem->length; + OPENSSL_free(mem); + } + BIO_free(in); + return ok; +} + +static int der_from_p8(unsigned char **new_der, long *new_der_len, + unsigned char *input_der, long input_der_len, + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) +{ + const unsigned char *derp; + X509_SIG *p8 = NULL; + int ok = 0; + + if (!ossl_assert(new_der != NULL && *new_der == NULL) + || !ossl_assert(new_der_len != NULL)) + return 0; + + derp = input_der; + if ((p8 = d2i_X509_SIG(NULL, &derp, input_der_len)) != NULL) { + char pbuf[PEM_BUFSIZE]; + size_t plen = 0; + + if (!pw_cb(pbuf, sizeof(pbuf), &plen, NULL, pw_cbarg)) { + ERR_raise(ERR_LIB_PROV, PROV_R_READ_KEY); + } else { + const X509_ALGOR *alg = NULL; + const ASN1_OCTET_STRING *oct = NULL; + int len = 0; + + X509_SIG_get0(p8, &alg, &oct); + if (PKCS12_pbe_crypt(alg, pbuf, plen, oct->data, oct->length, + new_der, &len, 0) != NULL) + ok = 1; + *new_der_len = len; + } + } + X509_SIG_free(p8); + return ok; +} + +/* ---------------------------------------------------------------------- */ static OSSL_FUNC_decoder_freectx_fn der2key_freectx; static OSSL_FUNC_decoder_gettable_params_fn der2key_gettable_params; @@ -109,15 +167,14 @@ static int der2key_decode(void *vctx, OSSL_CORE_BIO *cin, void *key = NULL; int ok = 0; - if (!ossl_prov_read_der(ctx->provctx, cin, &der, &der_len)) + if (!read_der(ctx->provctx, cin, &der, &der_len)) return 0; /* * Opportunistic attempt to decrypt. If it doesn't work, we try to * decode our input unencrypted. */ - if (ossl_prov_der_from_p8(&new_der, &new_der_len, der, der_len, - pw_cb, pw_cbarg)) { + if (der_from_p8(&new_der, &new_der_len, der, der_len, pw_cb, pw_cbarg)) { OPENSSL_free(der); der = new_der; der_len = new_der_len; @@ -203,6 +260,7 @@ static int der2key_export_object(void *vctx, { EVP_PKEY_##KEYTYPE, KEYTYPEstr, keytype##_keymgmt_functions, \ (extract_key_fn *)extract, \ (free_key_fn *)free }; \ + static OSSL_FUNC_decoder_newctx_fn der2##keytype##_newctx; \ static void *der2##keytype##_newctx(void *provctx) \ { \ return der2key_newctx(provctx, &keytype##_desc); \ diff --git a/providers/implementations/encode_decode/decode_ms2key.c b/providers/implementations/encode_decode/decode_ms2key.c index d8aa813ced..707e6bc08f 100644 --- a/providers/implementations/encode_decode/decode_ms2key.c +++ b/providers/implementations/encode_decode/decode_ms2key.c @@ -13,16 +13,51 @@ */ #include "internal/deprecated.h" +#include <string.h> + #include <openssl/core_dispatch.h> #include <openssl/core_names.h> #include <openssl/core_object.h> #include <openssl/crypto.h> #include <openssl/params.h> +#include <openssl/pem.h> /* For public PVK functions */ #include <openssl/x509.h> -#include "internal/pem.h" /* For PVK and "blob" PEM headers */ +#include "internal/pem.h" /* For internal PVK and "blob" headers */ +#include "internal/passphrase.h" #include "prov/bio.h" #include "prov/implementations.h" -#include "encoder_local.h" +#include "endecoder_local.h" + +#ifndef OPENSSL_NO_DSA +static EVP_PKEY *read_msblob(PROV_CTX *provctx, OSSL_CORE_BIO *cin, int *ispub) +{ + BIO *in = bio_new_from_core_bio(provctx, cin); + EVP_PKEY *pkey = ossl_b2i_bio(in, ispub); + + BIO_free(in); + return pkey; +} + +# ifndef OPENSSL_NO_RC4 +static EVP_PKEY *read_pvk(PROV_CTX *provctx, OSSL_CORE_BIO *cin, + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) +{ + BIO *in = NULL; + EVP_PKEY *pkey = NULL; + struct ossl_passphrase_data_st pwdata; + + memset(&pwdata, 0, sizeof(pwdata)); + if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg)) + return NULL; + + in = bio_new_from_core_bio(provctx, cin); + pkey = b2i_PVK_bio(in, ossl_pw_pem_password, &pwdata); + BIO_free(in); + + return pkey; +} +# endif +#endif static OSSL_FUNC_decoder_freectx_fn ms2key_freectx; static OSSL_FUNC_decoder_gettable_params_fn ms2key_gettable_params; @@ -159,7 +194,7 @@ static int msblob2key_decode(void *vctx, OSSL_CORE_BIO *cin, { struct ms2key_ctx_st *ctx = vctx; int ispub = -1; - EVP_PKEY *pkey = ossl_prov_read_msblob(ctx->provctx, cin, &ispub); + EVP_PKEY *pkey = read_msblob(ctx->provctx, cin, &ispub); int ok = ms2key_post(ctx, pkey, data_cb, data_cbarg); EVP_PKEY_free(pkey); @@ -172,7 +207,7 @@ static int pvk2key_decode(void *vctx, OSSL_CORE_BIO *cin, OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) { struct ms2key_ctx_st *ctx = vctx; - EVP_PKEY *pkey = ossl_prov_read_pvk(ctx->provctx, cin, pw_cb, pw_cbarg); + EVP_PKEY *pkey = read_pvk(ctx->provctx, cin, pw_cb, pw_cbarg); int ok = ms2key_post(ctx, pkey, data_cb, data_cbarg); EVP_PKEY_free(pkey); diff --git a/providers/implementations/encode_decode/decode_pem2der.c b/providers/implementations/encode_decode/decode_pem2der.c index cbee397982..6e669884de 100644 --- a/providers/implementations/encode_decode/decode_pem2der.c +++ b/providers/implementations/encode_decode/decode_pem2der.c @@ -24,7 +24,18 @@ #include "prov/bio.h" #include "prov/implementations.h" #include "prov/providercommonerr.h" -#include "encoder_local.h" +#include "endecoder_local.h" + +static int read_pem(PROV_CTX *provctx, OSSL_CORE_BIO *cin, + char **pem_name, char **pem_header, + unsigned char **data, long *len) +{ + BIO *in = bio_new_from_core_bio(provctx, cin); + int ok = (PEM_read_bio(in, pem_name, pem_header, data, len) > 0); + + BIO_free(in); + return ok; +} static OSSL_FUNC_decoder_newctx_fn pem2der_newctx; static OSSL_FUNC_decoder_freectx_fn pem2der_freectx; @@ -104,8 +115,8 @@ static int pem2der_decode(void *vctx, OSSL_CORE_BIO *cin, long der_len = 0; int ok = 0; - if (ossl_prov_read_pem(ctx->provctx, cin, &pem_name, &pem_header, - &der, &der_len) <= 0) + if (read_pem(ctx->provctx, cin, &pem_name, &pem_header, + &der, &der_len) <= 0) return 0; /* diff --git a/providers/implementations/encode_decode/encode_key2any.c b/providers/implementations/encode_decode/encode_key2any.c new file mode 100644 index 0000000000..ba240aa094 --- /dev/null +++ b/providers/implementations/encode_decode/encode_key2any.c @@ -0,0 +1,924 @@ +/* + * 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 + */ + +/* + * Low level APIs are deprecated for public use, but still ok for internal use. + */ +#include "internal/deprecated.h" + +#include <openssl/core.h> +#include <openssl/core_dispatch.h> +#include <openssl/core_names.h> +#include <openssl/crypto.h> +#include <openssl/params.h> +#include <openssl/asn1.h> +#include <openssl/err.h> +#include <openssl/pem.h> +#include <openssl/x509.h> +#include <openssl/pkcs12.h> /* PKCS8_encrypt() */ +#include <openssl/dh.h> +#include <openssl/dsa.h> +#include <openssl/ec.h> +#include "internal/passphrase.h" +#include "internal/cryptlib.h" +#include "crypto/ecx.h" +#include "crypto/rsa.h" +#include "prov/implementations.h" +#include "prov/providercommonerr.h" +#include "prov/bio.h" +#include "prov/provider_ctx.h" +#include "prov/der_rsa.h" +#include "endecoder_local.h" + +struct key2any_ctx_st { + PROV_CTX *provctx; + + /* Set to 1 if intending to encrypt/decrypt, otherwise 0 */ + int cipher_intent; + + EVP_CIPHER *cipher; + + struct ossl_passphrase_data_st pwdata; +}; + +typedef int key_to_paramstring_fn(const void *key, int nid, + void **str, int *strtype); +typedef int key_to_der_fn(BIO *out, const void *key, int key_nid, + key_to_paramstring_fn *p2s, i2d_of_void *k2d, + struct key2any_ctx_st *ctx); +typedef int write_bio_of_void_fn(BIO *bp, const void *x); + +static PKCS8_PRIV_KEY_INFO *key_to_p8info(const void *key, int key_nid, + void *params, int params_type, + i2d_of_void *k2d) +{ + /* der, derlen store the key DER output and its length */ + unsigned char *der = NULL; + int derlen; + /* The final PKCS#8 info */ + PKCS8_PRIV_KEY_INFO *p8info = NULL; + + + if ((p8info = PKCS8_PRIV_KEY_INFO_new()) == NULL + || (derlen = k2d(key, &der)) <= 0 + || !PKCS8_pkey_set0(p8info, OBJ_nid2obj(key_nid), 0, + params_type, params, der, derlen)) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + PKCS8_PRIV_KEY_INFO_free(p8info); + OPENSSL_free(der); + p8info = NULL; + } + + return p8info; +} + +static X509_SIG *p8info_to_encp8(PKCS8_PRIV_KEY_INFO *p8info, + struct key2any_ctx_st *ctx) +{ + X509_SIG *p8 = NULL; + char kstr[PEM_BUFSIZE]; + size_t klen = 0; + + if (ctx->cipher == NULL) + return NULL; + + if (!ossl_pw_get_passphrase(kstr, sizeof(kstr), &klen, NULL, 1, + &ctx->pwdata)) { + ERR_raise(ERR_LIB_PROV, PROV_R_READ_KEY); + return NULL; + } + /* First argument == -1 means "standard" */ + p8 = PKCS8_encrypt(-1, ctx->cipher, kstr, klen, NULL, 0, 0, p8info); + OPENSSL_cleanse(kstr, klen); + return p8; +} + +static X509_SIG *key_to_encp8(const void *key, int key_nid, + void *params, int params_type, + i2d_of_void *k2d, struct key2any_ctx_st *ctx) +{ + PKCS8_PRIV_KEY_INFO *p8info = + key_to_p8info(key, key_nid, params, params_type, k2d); + X509_SIG *p8 = p8info_to_encp8(p8info, ctx); + + PKCS8_PRIV_KEY_INFO_free(p8info); + return p8; +} + +static X509_PUBKEY *key_to_pubkey(const void *key, int key_nid, + void *params, int params_type, + i2d_of_void k2d) +{ + /* der, derlen store the key DER output and its length */ + unsigned char *der = NULL; + int derlen; + /* The final X509_PUBKEY */ + X509_PUBKEY *xpk = NULL; + + + if ((xpk = X509_PUBKEY_new()) == NULL + || (derlen = k2d(key, &der)) <= 0 + || !X509_PUBKEY_set0_param(xpk, OBJ_nid2obj(key_nid), + params_type, params, der, derlen)) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + X509_PUBKEY_free(xpk); + OPENSSL_free(der); + xpk = NULL; + } + + return xpk; +} + +static int key_to_der_pkcs8_bio(BIO *out, const void *key, int key_nid, + key_to_paramstring_fn *p2s, i2d_of_void *k2d, + struct key2any_ctx_st *ctx) +{ + int ret = 0; + void *str = NULL; + int strtype = V_ASN1_UNDEF; + + if (p2s != NULL && !p2s(key, key_nid, &str, &strtype)) + return 0; + + if (ctx->cipher_intent) { + X509_SIG *p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx); + + if (p8 != NULL) + ret = i2d_PKCS8_bio(out, p8); + + X509_SIG_free(p8); + } else { + PKCS8_PRIV_KEY_INFO *p8info = + key_to_p8info(key, key_nid, str, strtype, k2d); + + if (p8info != NULL) + ret = i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8info); + + PKCS8_PRIV_KEY_INFO_free(p8info); + } + + return ret; +} + +static int key_to_pem_pkcs8_bio(BIO *out, const void *key, int key_nid, + key_to_paramstring_fn *p2s, i2d_of_void *k2d, + struct key2any_ctx_st *ctx) +{ + int ret = 0; + void *str = NULL; + int strtype = V_ASN1_UNDEF; + + if (p2s != NULL && !p2s(key, key_nid, &str, &strtype)) + return 0; + + if (ctx->cipher_intent) { + X509_SIG *p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx); + + if (p8 != NULL) + ret = PEM_write_bio_PKCS8(out, p8); + + X509_SIG_free(p8); + } else { + PKCS8_PRIV_KEY_INFO *p8info = + key_to_p8info(key, key_nid, str, strtype, k2d); + + if (p8info != NULL) + ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8info); + + PKCS8_PRIV_KEY_INFO_free(p8info); + } + + return ret; +} + +static int key_to_der_pubkey_bio(BIO *out, const void *key, int key_nid, + key_to_paramstring_fn *p2s, i2d_of_void *k2d, + struct key2any_ctx_st *ctx) +{ + int ret = 0; + void *str = NULL; + int strtype = V_ASN1_UNDEF; + X509_PUBKEY *xpk = NULL; + + if (p2s != NULL && !p2s(key, key_nid, &str, &strtype)) + return 0; + + xpk = key_to_pubkey(key, key_nid, str, strtype, k2d); + + if (xpk != NULL) + ret = i2d_X509_PUBKEY_bio(out, xpk); + + /* Also frees |str| */ + X509_PUBKEY_free(xpk); + return ret; +} + +static int key_to_pem_pubkey_bio(BIO *out, const void *key, int key_nid, + key_to_paramstring_fn *p2s, i2d_of_void *k2d, + struct key2any_ctx_st *ctx) +{ + int ret = 0; + void *str = NULL; + int strtype = V_ASN1_UNDEF; + X509_PUBKEY *xpk = NULL; + + if (p2s != NULL && !p2s(key, key_nid, &str, &strtype)) + return 0; + + xpk = key_to_pubkey(key, key_nid, str, strtype, k2d); + + if (xpk != NULL) + ret = PEM_write_bio_X509_PUBKEY(out, xpk); + + /* Also frees |str| */ + X509_PUBKEY_free(xpk); + return ret; +} + +/* ---------------------------------------------------------------------- */ + +#ifndef OPENSSL_NO_DH +# define dh_param_selection OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS +# define dh_pub_selection (OSSL_KEYMGMT_SELECT_PUBLIC_KEY \ + | dh_param_selection) +# define dh_priv_selection (OSSL_KEYMGMT_SELECT_KEYPAIR \ + | dh_param_selection) + +static int dh_type_to_evp(const DH *dh) +{ + return DH_test_flags(dh, DH_FLAG_TYPE_DHX) ? EVP_PKEY_DHX : EVP_PKEY_DH; +} + +static int prepare_dh_params(const void *dh, int nid, + void **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; +} + +static int dh_pub_to_der(const void *dh, unsigned char **pder) +{ + const BIGNUM *bn = NULL; + ASN1_INTEGER *pub_key = NULL; + int ret; + + if ((bn = DH_get0_pub_key(dh)) == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY); + return 0; + } + if ((pub_key = BN_to_ASN1_INTEGER(bn, NULL)) == 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; +} + +static int dh_priv_to_der(const void *dh, unsigned char **pder) +{ + const BIGNUM *bn = NULL; + ASN1_INTEGER *priv_key = NULL; + int ret; + + if ((bn = DH_get0_priv_key(dh)) == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY); + return 0; + } + if ((priv_key = BN_to_ASN1_INTEGER(bn, NULL)) == 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; +} + +static int dh_params_to_der_bio(BIO *out, const void *key) +{ + return i2d_DHparams_bio(out, key); +} + +static int dh_params_to_pem_bio(BIO *out, const void *key) +{ + return PEM_write_bio_DHparams(out, key); +} +#endif + +/* ---------------------------------------------------------------------- */ + +#ifndef OPENSSL_NO_DSA +# define dsa_param_selection OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS +# define dsa_pub_selection (OSSL_KEYMGMT_SELECT_PUBLIC_KEY \ + | dsa_param_selection) +# define dsa_priv_selection (OSSL_KEYMGMT_SELECT_KEYPAIR \ + | dsa_param_selection) + +# define dsa_type_to_evp(key) EVP_PKEY_DSA + +static int prepare_some_dsa_params(const void *dsa, int nid, + void **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; +} + +static int prepare_all_dsa_params(const void *dsa, int nid, + void **pstr, int *pstrtype) +{ + const BIGNUM *p = DSA_get0_p(dsa); + const BIGNUM *q = DSA_get0_q(dsa); + |