X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fdh%2Fdh_ameth.c;h=d93d51944458c02fef6532759f948fadf5ddc07d;hp=2ead91ff4438a35ff0ce08df507b0f189cef5e0d;hb=7674e92324648b59786d86d8e9014bbaed4e6d07;hpb=0f113f3ee4d629ef9a4a30911b22b224772085e5 diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c index 2ead91ff44..d93d519444 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c @@ -1,73 +1,31 @@ /* - * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project - * 2006. - */ -/* ==================================================================== - * Copyright (c) 2006 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). + * Copyright 2006-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 + */ + +/* + * DH low level APIs are deprecated for public use, but still ok for + * internal use. */ +#include "internal/deprecated.h" #include -#include "cryptlib.h" +#include "internal/cryptlib.h" #include #include -#include +#include "dh_local.h" #include -#include "asn1_locl.h" -#ifndef OPENSSL_NO_CMS -# include -#endif - -extern const EVP_PKEY_ASN1_METHOD dhx_asn1_meth; +#include "crypto/asn1.h" +#include "crypto/dh.h" +#include "crypto/evp.h" +#include +#include +#include +#include "internal/ffc.h" /* * i2d/d2i like DH parameter functions which use the appropriate routine for @@ -94,13 +52,13 @@ static void int_dh_free(EVP_PKEY *pkey) DH_free(pkey->pkey.dh); } -static int dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) +static int dh_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey) { const unsigned char *p, *pm; int pklen, pmlen; int ptype; - void *pval; - ASN1_STRING *pstr; + const void *pval; + const ASN1_STRING *pstr; X509_ALGOR *palg; ASN1_INTEGER *public_key = NULL; @@ -119,18 +77,18 @@ static int dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) pm = pstr->data; pmlen = pstr->length; - if (!(dh = d2i_dhp(pkey, &pm, pmlen))) { + if ((dh = d2i_dhp(pkey, &pm, pmlen)) == NULL) { DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR); goto err; } - if (!(public_key = d2i_ASN1_INTEGER(NULL, &p, pklen))) { + if ((public_key = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) { DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR); goto err; } /* We have parameters now set public key */ - if (!(dh->pub_key = ASN1_INTEGER_to_BN(public_key, NULL))) { + if ((dh->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL) { DHerr(DH_F_DH_PUB_DECODE, DH_R_BN_DECODE_ERROR); goto err; } @@ -140,10 +98,8 @@ static int dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) return 1; err: - if (public_key) - ASN1_INTEGER_free(public_key); - if (dh) - DH_free(dh); + ASN1_INTEGER_free(public_key); + DH_free(dh); return 0; } @@ -151,7 +107,6 @@ static int dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) { DH *dh; - void *pval = NULL; int ptype; unsigned char *penc = NULL; int penclen; @@ -161,16 +116,19 @@ static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) dh = pkey->pkey.dh; str = ASN1_STRING_new(); + if (str == NULL) { + DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE); + goto err; + } str->length = i2d_dhp(pkey, dh, &str->data); if (str->length <= 0) { DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE); goto err; } - pval = str; ptype = V_ASN1_SEQUENCE; pub_key = BN_to_ASN1_INTEGER(dh->pub_key, NULL); - if (!pub_key) + if (pub_key == NULL) goto err; penclen = i2d_ASN1_INTEGER(pub_key, &penc); @@ -183,14 +141,12 @@ static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) } if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id), - ptype, pval, penc, penclen)) + ptype, str, penc, penclen)) return 1; err: - if (penc) - OPENSSL_free(penc); - if (pval) - ASN1_STRING_free(pval); + OPENSSL_free(penc); + ASN1_STRING_free(str); return 0; } @@ -198,19 +154,18 @@ static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) /* * PKCS#8 DH is defined in PKCS#11 of all places. It is similar to DH in that * the AlgorithmIdentifier contains the parameters, the private key is - * explcitly included and the pubkey must be recalculated. + * explicitly included and the pubkey must be recalculated. */ -static int dh_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) +static int dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8) { const unsigned char *p, *pm; int pklen, pmlen; int ptype; - void *pval; - ASN1_STRING *pstr; - X509_ALGOR *palg; + const void *pval; + const ASN1_STRING *pstr; + const X509_ALGOR *palg; ASN1_INTEGER *privkey = NULL; - DH *dh = NULL; if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) @@ -220,27 +175,28 @@ static int dh_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) if (ptype != V_ASN1_SEQUENCE) goto decerr; - - if (!(privkey = d2i_ASN1_INTEGER(NULL, &p, pklen))) + if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) goto decerr; pstr = pval; pm = pstr->data; pmlen = pstr->length; - if (!(dh = d2i_dhp(pkey, &pm, pmlen))) + if ((dh = d2i_dhp(pkey, &pm, pmlen)) == NULL) goto decerr; + /* We have parameters now set private key */ - if (!(dh->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) { + if ((dh->priv_key = BN_secure_new()) == NULL + || !ASN1_INTEGER_to_BN(privkey, dh->priv_key)) { DHerr(DH_F_DH_PRIV_DECODE, DH_R_BN_ERROR); goto dherr; } - /* Calculate public key */ + /* Calculate public key, increments dirty_cnt */ if (!DH_generate_key(dh)) goto dherr; EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh); - ASN1_INTEGER_free(privkey); + ASN1_STRING_clear_free(privkey); return 1; @@ -248,6 +204,7 @@ static int dh_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) DHerr(DH_F_DH_PRIV_DECODE, EVP_R_DECODE_ERROR); dherr: DH_free(dh); + ASN1_STRING_clear_free(privkey); return 0; } @@ -260,7 +217,7 @@ static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) params = ASN1_STRING_new(); - if (!params) { + if (params == NULL) { DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); goto err; } @@ -275,14 +232,15 @@ static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) /* Get private key into integer */ prkey = BN_to_ASN1_INTEGER(pkey->pkey.dh->priv_key, NULL); - if (!prkey) { + if (prkey == NULL) { DHerr(DH_F_DH_PRIV_ENCODE, DH_R_BN_ERROR); goto err; } dplen = i2d_ASN1_INTEGER(prkey, &dp); - ASN1_INTEGER_free(prkey); + ASN1_STRING_clear_free(prkey); + prkey = NULL; if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0, V_ASN1_SEQUENCE, params, dp, dplen)) @@ -291,32 +249,22 @@ static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) return 1; err: - if (dp != NULL) - OPENSSL_free(dp); - if (params != NULL) - ASN1_STRING_free(params); - if (prkey != NULL) - ASN1_INTEGER_free(prkey); + OPENSSL_free(dp); + ASN1_STRING_free(params); + ASN1_STRING_clear_free(prkey); return 0; } -static void update_buflen(const BIGNUM *b, size_t *pbuflen) -{ - size_t i; - if (!b) - return; - if (*pbuflen < (i = (size_t)BN_num_bytes(b))) - *pbuflen = i; -} - static int dh_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) { DH *dh; - if (!(dh = d2i_dhp(pkey, pder, derlen))) { + + if ((dh = d2i_dhp(pkey, pder, derlen)) == NULL) { DHerr(DH_F_DH_PARAM_DECODE, ERR_R_DH_LIB); return 0; } + dh->dirty_cnt++; EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh); return 1; } @@ -326,15 +274,10 @@ static int dh_param_encode(const EVP_PKEY *pkey, unsigned char **pder) return i2d_dhp(pkey, pkey->pkey.dh, pder); } -static int do_dh_print(BIO *bp, const DH *x, int indent, - ASN1_PCTX *ctx, int ptype) +static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype) { - unsigned char *m = NULL; - int reason = ERR_R_BUF_LIB, ret = 0; - size_t buf_len = 0; - + int reason = ERR_R_BUF_LIB; const char *ktype = NULL; - BIGNUM *priv_key, *pub_key; if (ptype == 2) @@ -347,20 +290,12 @@ static int do_dh_print(BIO *bp, const DH *x, int indent, else pub_key = NULL; - update_buflen(x->p, &buf_len); - - if (buf_len == 0) { + if (x->params.p == NULL || (ptype == 2 && priv_key == NULL) + || (ptype > 0 && pub_key == NULL)) { reason = ERR_R_PASSED_NULL_PARAMETER; goto err; } - update_buflen(x->g, &buf_len); - update_buflen(x->q, &buf_len); - update_buflen(x->j, &buf_len); - update_buflen(x->counter, &buf_len); - update_buflen(pub_key, &buf_len); - update_buflen(priv_key, &buf_len); - if (ptype == 2) ktype = "DH Private-Key"; else if (ptype == 1) @@ -368,74 +303,41 @@ static int do_dh_print(BIO *bp, const DH *x, int indent, else ktype = "DH Parameters"; - m = OPENSSL_malloc(buf_len + 10); - if (m == NULL) { - reason = ERR_R_MALLOC_FAILURE; - goto err; - } - - BIO_indent(bp, indent, 128); - if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) + if (!BIO_indent(bp, indent, 128) + || BIO_printf(bp, "%s: (%d bit)\n", ktype, DH_bits(x)) <= 0) goto err; indent += 4; - if (!ASN1_bn_print(bp, "private-key:", priv_key, m, indent)) + if (!ASN1_bn_print(bp, "private-key:", priv_key, NULL, indent)) goto err; - if (!ASN1_bn_print(bp, "public-key:", pub_key, m, indent)) + if (!ASN1_bn_print(bp, "public-key:", pub_key, NULL, indent)) goto err; - if (!ASN1_bn_print(bp, "prime:", x->p, m, indent)) - goto err; - if (!ASN1_bn_print(bp, "generator:", x->g, m, indent)) - goto err; - if (x->q && !ASN1_bn_print(bp, "subgroup order:", x->q, m, indent)) - goto err; - if (x->j && !ASN1_bn_print(bp, "subgroup factor:", x->j, m, indent)) - goto err; - if (x->seed) { - int i; - BIO_indent(bp, indent, 128); - BIO_puts(bp, "seed:"); - for (i = 0; i < x->seedlen; i++) { - if ((i % 15) == 0) { - if (BIO_puts(bp, "\n") <= 0 - || !BIO_indent(bp, indent + 4, 128)) - goto err; - } - if (BIO_printf(bp, "%02x%s", x->seed[i], - ((i + 1) == x->seedlen) ? "" : ":") <= 0) - goto err; - } - if (BIO_write(bp, "\n", 1) <= 0) - return (0); - } - if (x->counter && !ASN1_bn_print(bp, "counter:", x->counter, m, indent)) + if (!ffc_params_print(bp, &x->params, indent)) goto err; + if (x->length != 0) { - BIO_indent(bp, indent, 128); - if (BIO_printf(bp, "recommended-private-length: %d bits\n", - (int)x->length) <= 0) + if (!BIO_indent(bp, indent, 128) + || BIO_printf(bp, "recommended-private-length: %d bits\n", + (int)x->length) <= 0) goto err; } - ret = 1; - if (0) { + return 1; + err: - DHerr(DH_F_DO_DH_PRINT, reason); - } - if (m != NULL) - OPENSSL_free(m); - return (ret); + DHerr(DH_F_DO_DH_PRINT, reason); + return 0; } static int int_dh_size(const EVP_PKEY *pkey) { - return (DH_size(pkey->pkey.dh)); + return DH_size(pkey->pkey.dh); } static int dh_bits(const EVP_PKEY *pkey) { - return BN_num_bits(pkey->pkey.dh->p); + return DH_bits(pkey->pkey.dh); } static int dh_security_bits(const EVP_PKEY *pkey) @@ -445,65 +347,27 @@ static int dh_security_bits(const EVP_PKEY *pkey) static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) { - if (BN_cmp(a->pkey.dh->p, b->pkey.dh->p) || - BN_cmp(a->pkey.dh->g, b->pkey.dh->g)) - return 0; - else if (a->ameth == &dhx_asn1_meth) { - if (BN_cmp(a->pkey.dh->q, b->pkey.dh->q)) - return 0; - } - return 1; -} - -static int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src) -{ - BIGNUM *a; - if (src) { - a = BN_dup(src); - if (!a) - return 0; - } else - a = NULL; - if (*dst) - BN_free(*dst); - *dst = a; - return 1; + return ffc_params_cmp(&a->pkey.dh->params, &a->pkey.dh->params, + a->ameth != &dhx_asn1_meth); } static int int_dh_param_copy(DH *to, const DH *from, int is_x942) { if (is_x942 == -1) - is_x942 = ! !from->q; - if (!int_dh_bn_cpy(&to->p, from->p)) - return 0; - if (!int_dh_bn_cpy(&to->g, from->g)) + is_x942 = (from->params.q != NULL); + if (!ffc_params_copy(&to->params, &from->params)) return 0; - if (is_x942) { - if (!int_dh_bn_cpy(&to->q, from->q)) - return 0; - if (!int_dh_bn_cpy(&to->j, from->j)) - return 0; - if (to->seed) { - OPENSSL_free(to->seed); - to->seed = NULL; - to->seedlen = 0; - } - if (from->seed) { - to->seed = BUF_memdup(from->seed, from->seedlen); - if (!to->seed) - return 0; - to->seedlen = from->seedlen; - } - } else + if (!is_x942) to->length = from->length; + to->dirty_cnt++; return 1; } -DH *DHparams_dup(DH *dh) +DH *DHparams_dup(const DH *dh) { DH *ret; ret = DH_new(); - if (!ret) + if (ret == NULL) return NULL; if (!int_dh_param_copy(ret, dh, -1)) { DH_free(ret); @@ -514,15 +378,20 @@ DH *DHparams_dup(DH *dh) static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { + if (to->pkey.dh == NULL) { + to->pkey.dh = DH_new(); + if (to->pkey.dh == NULL) + return 0; + } return int_dh_param_copy(to->pkey.dh, from->pkey.dh, from->ameth == &dhx_asn1_meth); } static int dh_missing_parameters(const EVP_PKEY *a) { - if (!a->pkey.dh->p || !a->pkey.dh->g) - return 1; - return 0; + return a->pkey.dh == NULL + || a->pkey.dh->params.p == NULL + || a->pkey.dh->params.g == NULL; } static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) @@ -538,24 +407,24 @@ static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) static int dh_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx) { - return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 0); + return do_dh_print(bp, pkey->pkey.dh, indent, 0); } static int dh_public_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx) { - return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 1); + return do_dh_print(bp, pkey->pkey.dh, indent, 1); } static int dh_private_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx) { - return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 2); + return do_dh_print(bp, pkey->pkey.dh, indent, 2); } int DHparams_print(BIO *bp, const DH *x) { - return do_dh_print(bp, x, 4, NULL, 0); + return do_dh_print(bp, x, 4, 0); } #ifndef OPENSSL_NO_CMS @@ -564,6 +433,18 @@ static int dh_cms_encrypt(CMS_RecipientInfo *ri); #endif static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) +{ + switch (op) { + case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: + return dh_buf2key(EVP_PKEY_get0_DH(pkey), arg2, arg1); + case ASN1_PKEY_CTRL_GET1_TLS_ENCPT: + return dh_key2buf(EVP_PKEY_get0_DH(pkey), arg2); + default: + return -2; + } +} + +static int dhx_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) { switch (op) { #ifndef OPENSSL_NO_CMS @@ -585,6 +466,108 @@ static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) } +static int dh_pkey_public_check(const EVP_PKEY *pkey) +{ + DH *dh = pkey->pkey.dh; + + if (dh->pub_key == NULL) { + DHerr(DH_F_DH_PKEY_PUBLIC_CHECK, DH_R_MISSING_PUBKEY); + return 0; + } + + return DH_check_pub_key_ex(dh, dh->pub_key); +} + +static int dh_pkey_param_check(const EVP_PKEY *pkey) +{ + DH *dh = pkey->pkey.dh; + + return DH_check_ex(dh); +} + +static size_t dh_pkey_dirty_cnt(const EVP_PKEY *pkey) +{ + return pkey->pkey.dh->dirty_cnt; +} + +static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata, + EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx, + const char *propq) +{ + DH *dh = from->pkey.dh; + OSSL_PARAM_BLD *tmpl; + const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh); + const BIGNUM *pub_key = DH_get0_pub_key(dh); + const BIGNUM *priv_key = DH_get0_priv_key(dh); + OSSL_PARAM *params = NULL; + int selection = 0; + int rv = 0; + + /* + * If the DH method is foreign, then we can't be sure of anything, and + * can therefore not export or pretend to export. + */ + if (dh_get_method(dh) != DH_OpenSSL()) + return 0; + + if (p == NULL || g == NULL) + return 0; + + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) + return 0; + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p) + || !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, g)) + goto err; + if (q != NULL) { + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, q)) + goto err; + } + selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS; + if (pub_key != NULL) { + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; + } + if (priv_key != NULL) { + if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, + priv_key)) + goto err; + selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY; + } + + if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) + goto err; + + /* We export, the provider imports */ + rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params); + + OSSL_PARAM_BLD_free_params(params); +err: + OSSL_PARAM_BLD_free(tmpl); + return rv; +} + +static int dh_pkey_import_from(const OSSL_PARAM params[], void *vpctx) +{ + EVP_PKEY_CTX *pctx = vpctx; + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx); + DH *dh = dh_new_with_libctx(pctx->libctx); + + if (dh == NULL) { + ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!dh_ffc_params_fromdata(dh, params) + || !dh_key_fromdata(dh, params) + || !EVP_PKEY_assign_DH(pkey, dh)) { + DH_free(dh); + return 0; + } + return 1; +} + const EVP_PKEY_ASN1_METHOD dh_asn1_meth = { EVP_PKEY_DH, EVP_PKEY_DH, @@ -615,7 +598,19 @@ const EVP_PKEY_ASN1_METHOD dh_asn1_meth = { 0, int_dh_free, - 0 + dh_pkey_ctrl, + + 0, 0, 0, 0, 0, + + 0, + dh_pkey_public_check, + dh_pkey_param_check, + + 0, 0, 0, 0, + + dh_pkey_dirty_cnt, + dh_pkey_export_to, + dh_pkey_import_from, }; const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = { @@ -648,7 +643,13 @@ const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = { 0, int_dh_free, - dh_pkey_ctrl + dhx_pkey_ctrl, + + 0, 0, 0, 0, 0, + + 0, + dh_pkey_public_check, + dh_pkey_param_check }; #ifndef OPENSSL_NO_CMS @@ -656,9 +657,9 @@ const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = { static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx, X509_ALGOR *alg, ASN1_BIT_STRING *pubkey) { - ASN1_OBJECT *aoid; + const ASN1_OBJECT *aoid; int atype; - void *aval; + const void *aval; ASN1_INTEGER *public_key = NULL; int rv = 0; EVP_PKEY *pkpeer = NULL, *pk = NULL; @@ -674,7 +675,7 @@ static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx, goto err; pk = EVP_PKEY_CTX_get0_pkey(pctx); - if (!pk) + if (pk == NULL) goto err; if (pk->type != EVP_PKEY_DHX) goto err; @@ -682,35 +683,32 @@ static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx, dhpeer = DHparams_dup(pk->pkey.dh); /* We have parameters now set public key */ plen = ASN1_STRING_length(pubkey); - p = ASN1_STRING_data(pubkey); - if (!p || !plen) + p = ASN1_STRING_get0_data(pubkey); + if (p == NULL || plen == 0) goto err; - if (!(public_key = d2i_ASN1_INTEGER(NULL, &p, plen))) { + if ((public_key = d2i_ASN1_INTEGER(NULL, &p, plen)) == NULL) { DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_DECODE_ERROR); goto err; } /* We have parameters now set public key */ - if (!(dhpeer->pub_key = ASN1_INTEGER_to_BN(public_key, NULL))) { + if ((dhpeer->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL) { DHerr(DH_F_DH_CMS_SET_PEERKEY, DH_R_BN_DECODE_ERROR); goto err; } pkpeer = EVP_PKEY_new(); - if (!pkpeer) + if (pkpeer == NULL) goto err; EVP_PKEY_assign(pkpeer, pk->ameth->pkey_id, dhpeer); dhpeer = NULL; if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0) rv = 1; err: - if (public_key) - ASN1_INTEGER_free(public_key); - if (pkpeer) - EVP_PKEY_free(pkpeer); - if (dhpeer) - DH_free(dhpeer); + ASN1_INTEGER_free(public_key); + EVP_PKEY_free(pkpeer); + DH_free(dhpeer); return rv; } @@ -775,7 +773,7 @@ static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) if (ukm) { dukmlen = ASN1_STRING_length(ukm); - dukm = BUF_memdup(ASN1_STRING_data(ukm), dukmlen); + dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen); if (!dukm) goto err; } @@ -786,18 +784,18 @@ static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) rv = 1; err: - if (kekalg) - X509_ALGOR_free(kekalg); - if (dukm) - OPENSSL_free(dukm); + X509_ALGOR_free(kekalg); + OPENSSL_free(dukm); return rv; } static int dh_cms_decrypt(CMS_RecipientInfo *ri) { EVP_PKEY_CTX *pctx; + pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); - if (!pctx) + + if (pctx == NULL) return 0; /* See if we need to set peer key */ if (!EVP_PKEY_CTX_get0_peerkey(pctx)) { @@ -828,7 +826,7 @@ static int dh_cms_encrypt(CMS_RecipientInfo *ri) EVP_CIPHER_CTX *ctx; int keylen; X509_ALGOR *talg, *wrap_alg = NULL; - ASN1_OBJECT *aoid; + const ASN1_OBJECT *aoid; ASN1_BIT_STRING *pubkey; ASN1_STRING *wrap_str; ASN1_OCTET_STRING *ukm; @@ -838,8 +836,9 @@ static int dh_cms_encrypt(CMS_RecipientInfo *ri) int rv = 0; int kdf_type, wrap_nid; const EVP_MD *kdf_md; + pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); - if (!pctx) + if (pctx == NULL) return 0; /* Get ephemeral key */ pkey = EVP_PKEY_CTX_get0_pkey(pctx); @@ -849,9 +848,9 @@ static int dh_cms_encrypt(CMS_RecipientInfo *ri) X509_ALGOR_get0(&aoid, NULL, NULL, talg); /* Is everything uninitialised? */ if (aoid == OBJ_nid2obj(NID_undef)) { - ASN1_INTEGER *pubk; - pubk = BN_to_ASN1_INTEGER(pkey->pkey.dh->pub_key, NULL); - if (!pubk) + ASN1_INTEGER *pubk = BN_to_ASN1_INTEGER(pkey->pkey.dh->pub_key, NULL); + + if (pubk == NULL) goto err; /* Set the key */ @@ -868,7 +867,7 @@ static int dh_cms_encrypt(CMS_RecipientInfo *ri) V_ASN1_UNDEF, NULL); } - /* See if custom paraneters set */ + /* See if custom parameters set */ kdf_type = EVP_PKEY_CTX_get_dh_kdf_type(pctx); if (kdf_type <= 0) goto err; @@ -904,11 +903,11 @@ static int dh_cms_encrypt(CMS_RecipientInfo *ri) /* Package wrap algorithm in an AlgorithmIdentifier */ wrap_alg = X509_ALGOR_new(); - if (!wrap_alg) + if (wrap_alg == NULL) goto err; wrap_alg->algorithm = OBJ_nid2obj(wrap_nid); wrap_alg->parameter = ASN1_TYPE_new(); - if (!wrap_alg->parameter) + if (wrap_alg->parameter == NULL) goto err; if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0) goto err; @@ -922,7 +921,7 @@ static int dh_cms_encrypt(CMS_RecipientInfo *ri) if (ukm) { dukmlen = ASN1_STRING_length(ukm); - dukm = BUF_memdup(ASN1_STRING_data(ukm), dukmlen); + dukm = OPENSSL_memdup(ASN1_STRING_get0_data(ukm), dukmlen); if (!dukm) goto err; } @@ -937,10 +936,10 @@ static int dh_cms_encrypt(CMS_RecipientInfo *ri) */ penc = NULL; penclen = i2d_X509_ALGOR(wrap_alg, &penc); - if (!penc || !penclen) + if (penc == NULL || penclen == 0) goto err; wrap_str = ASN1_STRING_new(); - if (!wrap_str) + if (wrap_str == NULL) goto err; ASN1_STRING_set0(wrap_str, penc, penclen); penc = NULL; @@ -950,10 +949,9 @@ static int dh_cms_encrypt(CMS_RecipientInfo *ri) rv = 1; err: - if (penc) - OPENSSL_free(penc); - if (wrap_alg) - X509_ALGOR_free(wrap_alg); + OPENSSL_free(penc); + X509_ALGOR_free(wrap_alg); + OPENSSL_free(dukm); return rv; }