xref: /openbsd/lib/libcrypto/dh/dh_ameth.c (revision 9ed721ec)
1*9ed721ecStb /* $OpenBSD: dh_ameth.c,v 1.40 2024/01/04 17:01:26 tb Exp $ */
2f1535dc8Sdjm /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3f1535dc8Sdjm  * project 2006.
4f1535dc8Sdjm  */
5f1535dc8Sdjm /* ====================================================================
6f1535dc8Sdjm  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7f1535dc8Sdjm  *
8f1535dc8Sdjm  * Redistribution and use in source and binary forms, with or without
9f1535dc8Sdjm  * modification, are permitted provided that the following conditions
10f1535dc8Sdjm  * are met:
11f1535dc8Sdjm  *
12f1535dc8Sdjm  * 1. Redistributions of source code must retain the above copyright
13f1535dc8Sdjm  *    notice, this list of conditions and the following disclaimer.
14f1535dc8Sdjm  *
15f1535dc8Sdjm  * 2. Redistributions in binary form must reproduce the above copyright
16f1535dc8Sdjm  *    notice, this list of conditions and the following disclaimer in
17f1535dc8Sdjm  *    the documentation and/or other materials provided with the
18f1535dc8Sdjm  *    distribution.
19f1535dc8Sdjm  *
20f1535dc8Sdjm  * 3. All advertising materials mentioning features or use of this
21f1535dc8Sdjm  *    software must display the following acknowledgment:
22f1535dc8Sdjm  *    "This product includes software developed by the OpenSSL Project
23f1535dc8Sdjm  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24f1535dc8Sdjm  *
25f1535dc8Sdjm  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26f1535dc8Sdjm  *    endorse or promote products derived from this software without
27f1535dc8Sdjm  *    prior written permission. For written permission, please contact
28f1535dc8Sdjm  *    licensing@OpenSSL.org.
29f1535dc8Sdjm  *
30f1535dc8Sdjm  * 5. Products derived from this software may not be called "OpenSSL"
31f1535dc8Sdjm  *    nor may "OpenSSL" appear in their names without prior written
32f1535dc8Sdjm  *    permission of the OpenSSL Project.
33f1535dc8Sdjm  *
34f1535dc8Sdjm  * 6. Redistributions of any form whatsoever must retain the following
35f1535dc8Sdjm  *    acknowledgment:
36f1535dc8Sdjm  *    "This product includes software developed by the OpenSSL Project
37f1535dc8Sdjm  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38f1535dc8Sdjm  *
39f1535dc8Sdjm  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40f1535dc8Sdjm  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41f1535dc8Sdjm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42f1535dc8Sdjm  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43f1535dc8Sdjm  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44f1535dc8Sdjm  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45f1535dc8Sdjm  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46f1535dc8Sdjm  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47f1535dc8Sdjm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48f1535dc8Sdjm  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49f1535dc8Sdjm  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50f1535dc8Sdjm  * OF THE POSSIBILITY OF SUCH DAMAGE.
51f1535dc8Sdjm  * ====================================================================
52f1535dc8Sdjm  *
53f1535dc8Sdjm  * This product includes cryptographic software written by Eric Young
54f1535dc8Sdjm  * (eay@cryptsoft.com).  This product includes software written by Tim
55f1535dc8Sdjm  * Hudson (tjh@cryptsoft.com).
56f1535dc8Sdjm  *
57f1535dc8Sdjm  */
58f1535dc8Sdjm 
59f1535dc8Sdjm #include <stdio.h>
60b6ab114eSjsing 
61f1535dc8Sdjm #include <openssl/asn1.h>
62f1535dc8Sdjm #include <openssl/bn.h>
63b6ab114eSjsing #include <openssl/dh.h>
64b6ab114eSjsing #include <openssl/err.h>
65b6ab114eSjsing #include <openssl/x509.h>
66b6ab114eSjsing 
67c9675a23Stb #include "asn1_local.h"
68549c133bStb #include "bn_local.h"
69a69386beStb #include "dh_local.h"
70c9675a23Stb #include "evp_local.h"
71f1535dc8Sdjm 
725b87c283Smiod static void
dh_free(EVP_PKEY * pkey)737244e844Stb dh_free(EVP_PKEY *pkey)
74f1535dc8Sdjm {
75f1535dc8Sdjm 	DH_free(pkey->pkey.dh);
76f1535dc8Sdjm }
77f1535dc8Sdjm 
785b87c283Smiod static int
dh_pub_decode(EVP_PKEY * pkey,X509_PUBKEY * pubkey)795b87c283Smiod dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
80f1535dc8Sdjm {
81b42bcaecStb 	X509_ALGOR *algor;
82f1535dc8Sdjm 	int ptype;
830267c206Stb 	const void *pval;
845c3bbfbbStb 	const ASN1_STRING *astr;
855c3bbfbbStb 	const unsigned char *key, *params, *p;
86b42bcaecStb 	int key_len, params_len;
875c3bbfbbStb 	ASN1_INTEGER *aint = NULL;
88f1535dc8Sdjm 	DH *dh = NULL;
89b42bcaecStb 	int ret = 0;
90f1535dc8Sdjm 
915c3bbfbbStb 	if (!X509_PUBKEY_get0_param(NULL, &key, &key_len, &algor, pubkey))
92b42bcaecStb 		goto err;
93b42bcaecStb 	X509_ALGOR_get0(NULL, &ptype, &pval, algor);
94f1535dc8Sdjm 
955b87c283Smiod 	if (ptype != V_ASN1_SEQUENCE) {
965067ae9fSbeck 		DHerror(DH_R_PARAMETER_ENCODING_ERROR);
97f1535dc8Sdjm 		goto err;
98f1535dc8Sdjm 	}
99f1535dc8Sdjm 
1005c3bbfbbStb 	astr = pval;
1015c3bbfbbStb 	params = astr->data;
1025c3bbfbbStb 	params_len = astr->length;
103f1535dc8Sdjm 
1045c3bbfbbStb 	p = params;
105b42bcaecStb 	if ((dh = d2i_DHparams(NULL, &p, params_len)) == NULL) {
1065067ae9fSbeck 		DHerror(DH_R_DECODE_ERROR);
107f1535dc8Sdjm 		goto err;
108f1535dc8Sdjm 	}
1095c3bbfbbStb 	p = key;
1105c3bbfbbStb 	if ((aint = d2i_ASN1_INTEGER(NULL, &p, key_len)) == NULL) {
1115067ae9fSbeck 		DHerror(DH_R_DECODE_ERROR);
112f1535dc8Sdjm 		goto err;
113f1535dc8Sdjm 	}
11452d22fd7Stb 	BN_free(dh->pub_key);
1155c3bbfbbStb 	if ((dh->pub_key = ASN1_INTEGER_to_BN(aint, NULL)) == NULL) {
1165067ae9fSbeck 		DHerror(DH_R_BN_DECODE_ERROR);
117f1535dc8Sdjm 		goto err;
118f1535dc8Sdjm 	}
119f1535dc8Sdjm 
120b42bcaecStb 	if (!EVP_PKEY_assign_DH(pkey, dh))
121b42bcaecStb 		goto err;
122b42bcaecStb 	dh = NULL;
123b42bcaecStb 
124b42bcaecStb 	ret = 1;
125f1535dc8Sdjm 
126f1535dc8Sdjm  err:
1275c3bbfbbStb 	ASN1_INTEGER_free(aint);
128f1535dc8Sdjm 	DH_free(dh);
129b42bcaecStb 
130b42bcaecStb 	return ret;
131f1535dc8Sdjm }
132f1535dc8Sdjm 
1335b87c283Smiod static int
dh_pub_encode(X509_PUBKEY * pk,const EVP_PKEY * pkey)1345b87c283Smiod dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
135f1535dc8Sdjm {
1360e358455Stb 	const DH *dh = pkey->pkey.dh;
1375c3bbfbbStb 	ASN1_STRING *astr = NULL;
1380e358455Stb 	int ptype = V_ASN1_SEQUENCE;
1395c3bbfbbStb 	ASN1_INTEGER *aint = NULL;
1400e358455Stb 	ASN1_OBJECT *aobj;
1415c3bbfbbStb 	unsigned char *params = NULL, *key = NULL;
142fed21370Stb 	int params_len = 0, key_len = 0;
143fed21370Stb 	int ret = 0;
144f1535dc8Sdjm 
1455c3bbfbbStb 	if ((params_len = i2d_DHparams(dh, &params)) <= 0) {
1460e358455Stb 		DHerror(ERR_R_MALLOC_FAILURE);
147fed21370Stb 		params_len = 0;
1480e358455Stb 		goto err;
1490e358455Stb 	}
1505c3bbfbbStb 	if ((astr = ASN1_STRING_new()) == NULL) {
1515067ae9fSbeck 		DHerror(ERR_R_MALLOC_FAILURE);
152602d5a56Stedu 		goto err;
153602d5a56Stedu 	}
1545c3bbfbbStb 	ASN1_STRING_set0(astr, params, params_len);
1555c3bbfbbStb 	params = NULL;
156fed21370Stb 	params_len = 0;
157602d5a56Stedu 
1585c3bbfbbStb 	if ((aint = BN_to_ASN1_INTEGER(dh->pub_key, NULL)) == NULL)
1590e358455Stb 		goto err;
1605c3bbfbbStb 	if ((key_len = i2d_ASN1_INTEGER(aint, &key)) <= 0) {
1615067ae9fSbeck 		DHerror(ERR_R_MALLOC_FAILURE);
162fed21370Stb 		key_len = 0;
163f1535dc8Sdjm 		goto err;
164f1535dc8Sdjm 	}
165f1535dc8Sdjm 
1660e358455Stb 	if ((aobj = OBJ_nid2obj(EVP_PKEY_DH)) == NULL)
167f1535dc8Sdjm 		goto err;
1685c3bbfbbStb 	if (!X509_PUBKEY_set0_param(pk, aobj, ptype, astr, key, key_len))
1690e358455Stb 		goto err;
1705c3bbfbbStb 	astr = NULL;
1715c3bbfbbStb 	key = NULL;
172fed21370Stb 	key_len = 0;
173f1535dc8Sdjm 
174fed21370Stb 	ret = 1;
175f1535dc8Sdjm 
176f1535dc8Sdjm  err:
1775c3bbfbbStb 	ASN1_STRING_free(astr);
1785c3bbfbbStb 	ASN1_INTEGER_free(aint);
1795c3bbfbbStb 	freezero(params, params_len);
1805c3bbfbbStb 	freezero(key, key_len);
181f1535dc8Sdjm 
182fed21370Stb 	return ret;
183f1535dc8Sdjm }
184f1535dc8Sdjm 
1855b87c283Smiod /*
1865b87c283Smiod  * PKCS#8 DH is defined in PKCS#11 of all places. It is similar to DH in
18771743258Sjmc  * that the AlgorithmIdentifier contains the parameters, the private key
188f1535dc8Sdjm  * is explcitly included and the pubkey must be recalculated.
189f1535dc8Sdjm  */
190f1535dc8Sdjm 
1915b87c283Smiod static int
dh_priv_decode(EVP_PKEY * pkey,const PKCS8_PRIV_KEY_INFO * p8)1928d6bc8b3Stb dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
193f1535dc8Sdjm {
194b42bcaecStb 	const X509_ALGOR *algor;
195f1535dc8Sdjm 	int ptype;
1960267c206Stb 	const void *pval;
1975c3bbfbbStb 	const ASN1_STRING *astr;
1985c3bbfbbStb 	const unsigned char *key, *params, *p;
199b42bcaecStb 	int key_len, params_len;
2005c3bbfbbStb 	ASN1_INTEGER *aint = NULL;
201f1535dc8Sdjm 	DH *dh = NULL;
202b42bcaecStb 	int ret = 0;
203f1535dc8Sdjm 
2045c3bbfbbStb 	if (!PKCS8_pkey_get0(NULL, &key, &key_len, &algor, p8))
205b42bcaecStb 		goto err;
206b42bcaecStb 	X509_ALGOR_get0(NULL, &ptype, &pval, algor);
207f1535dc8Sdjm 
208b42bcaecStb 	if (ptype != V_ASN1_SEQUENCE) {
209b42bcaecStb 		DHerror(DH_R_PARAMETER_ENCODING_ERROR);
210b42bcaecStb 		goto err;
211f1535dc8Sdjm 	}
212b42bcaecStb 
2135c3bbfbbStb 	astr = pval;
2145c3bbfbbStb 	params = astr->data;
2155c3bbfbbStb 	params_len = astr->length;
216b42bcaecStb 
2175c3bbfbbStb 	p = params;
218b42bcaecStb 	if ((dh = d2i_DHparams(NULL, &p, params_len)) == NULL) {
219b42bcaecStb 		DHerror(DH_R_DECODE_ERROR);
220b42bcaecStb 		goto err;
221b42bcaecStb 	}
2225c3bbfbbStb 	p = key;
2235c3bbfbbStb 	if ((aint = d2i_ASN1_INTEGER(NULL, &p, key_len)) == NULL) {
224b42bcaecStb 		DHerror(DH_R_DECODE_ERROR);
225b42bcaecStb 		goto err;
226b42bcaecStb 	}
22752d22fd7Stb 	BN_free(dh->priv_key);
2285c3bbfbbStb 	if ((dh->priv_key = ASN1_INTEGER_to_BN(aint, NULL)) == NULL) {
229b42bcaecStb 		DHerror(DH_R_BN_DECODE_ERROR);
230b42bcaecStb 		goto err;
231b42bcaecStb 	}
232f1535dc8Sdjm 	if (!DH_generate_key(dh))
233b42bcaecStb 		goto err;
234f1535dc8Sdjm 
235b42bcaecStb 	if (!EVP_PKEY_assign_DH(pkey, dh))
236b42bcaecStb 		goto err;
237b42bcaecStb 	dh = NULL;
238f1535dc8Sdjm 
239b42bcaecStb 	ret = 1;
240f1535dc8Sdjm 
241b42bcaecStb  err:
2425c3bbfbbStb 	ASN1_INTEGER_free(aint);
243f1535dc8Sdjm 	DH_free(dh);
244b42bcaecStb 
245b42bcaecStb 	return ret;
246f1535dc8Sdjm }
247f1535dc8Sdjm 
2485b87c283Smiod static int
dh_priv_encode(PKCS8_PRIV_KEY_INFO * p8,const EVP_PKEY * pkey)2495b87c283Smiod dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
250f1535dc8Sdjm {
251d4662417Stb 	const DH *dh = pkey->pkey.dh;
2525c3bbfbbStb 	ASN1_STRING *astr = NULL;
253fed21370Stb 	int ptype = V_ASN1_SEQUENCE;
2545c3bbfbbStb 	ASN1_INTEGER *aint = NULL;
255d4662417Stb 	ASN1_OBJECT *aobj;
2565c3bbfbbStb 	unsigned char *params = NULL, *key = NULL;
257fed21370Stb 	int params_len = 0, key_len = 0;
258fed21370Stb 	int ret = 0;
259f1535dc8Sdjm 
2605c3bbfbbStb 	if ((params_len = i2d_DHparams(dh, &params)) <= 0) {
261d4662417Stb 		DHerror(ERR_R_MALLOC_FAILURE);
262fed21370Stb 		params_len = 0;
263d4662417Stb 		goto err;
264d4662417Stb 	}
2655c3bbfbbStb 	if ((astr = ASN1_STRING_type_new(V_ASN1_SEQUENCE)) == NULL) {
2665067ae9fSbeck 		DHerror(ERR_R_MALLOC_FAILURE);
267f1535dc8Sdjm 		goto err;
268f1535dc8Sdjm 	}
2695c3bbfbbStb 	ASN1_STRING_set0(astr, params, params_len);
2705c3bbfbbStb 	params = NULL;
271fed21370Stb 	params_len = 0;
272f1535dc8Sdjm 
2735c3bbfbbStb 	if ((aint = BN_to_ASN1_INTEGER(dh->priv_key, NULL)) == NULL) {
2745067ae9fSbeck 		DHerror(DH_R_BN_ERROR);
275f1535dc8Sdjm 		goto err;
276f1535dc8Sdjm 	}
2775c3bbfbbStb 	if ((key_len = i2d_ASN1_INTEGER(aint, &key)) <= 0) {
278d4662417Stb 		DHerror(ERR_R_MALLOC_FAILURE);
279fed21370Stb 		key_len = 0;
280d4662417Stb 		goto err;
281d4662417Stb 	}
282f1535dc8Sdjm 
283d4662417Stb 	if ((aobj = OBJ_nid2obj(NID_dhKeyAgreement)) == NULL)
284d4662417Stb 		goto err;
2855c3bbfbbStb 	if (!PKCS8_pkey_set0(p8, aobj, 0, ptype, astr, key, key_len))
286f1535dc8Sdjm 		goto err;
2875c3bbfbbStb 	astr = NULL;
2885c3bbfbbStb 	key = NULL;
289fed21370Stb 	key_len = 0;
290f1535dc8Sdjm 
291fed21370Stb 	ret = 1;
292f1535dc8Sdjm 
293f1535dc8Sdjm  err:
2945c3bbfbbStb 	ASN1_STRING_free(astr);
2955c3bbfbbStb 	ASN1_INTEGER_free(aint);
2965c3bbfbbStb 	freezero(params, params_len);
2975c3bbfbbStb 	freezero(key, key_len);
298d4662417Stb 
299fed21370Stb 	return ret;
300f1535dc8Sdjm }
301f1535dc8Sdjm 
3025b87c283Smiod static int
dh_param_decode(EVP_PKEY * pkey,const unsigned char ** params,int params_len)303e6a172b0Stb dh_param_decode(EVP_PKEY *pkey, const unsigned char **params, int params_len)
304f1535dc8Sdjm {
305b42bcaecStb 	DH *dh = NULL;
306b42bcaecStb 	int ret = 0;
3075b87c283Smiod 
308e6a172b0Stb 	if ((dh = d2i_DHparams(NULL, params, params_len)) == NULL) {
3095067ae9fSbeck 		DHerror(ERR_R_DH_LIB);
310b42bcaecStb 		goto err;
311f1535dc8Sdjm 	}
312b42bcaecStb 	if (!EVP_PKEY_assign_DH(pkey, dh))
313b42bcaecStb 		goto err;
314b42bcaecStb 	dh = NULL;
315b42bcaecStb 
316b42bcaecStb 	ret = 1;
317b42bcaecStb 
318b42bcaecStb  err:
319b42bcaecStb 	DH_free(dh);
320b42bcaecStb 
321b42bcaecStb 	return ret;
322f1535dc8Sdjm }
323f1535dc8Sdjm 
3245b87c283Smiod static int
dh_param_encode(const EVP_PKEY * pkey,unsigned char ** params)325e6a172b0Stb dh_param_encode(const EVP_PKEY *pkey, unsigned char **params)
326f1535dc8Sdjm {
327e6a172b0Stb 	return i2d_DHparams(pkey->pkey.dh, params);
328f1535dc8Sdjm }
329f1535dc8Sdjm 
3305b87c283Smiod static int
do_dh_print(BIO * bp,const DH * x,int indent,ASN1_PCTX * ctx,int ptype)3315b87c283Smiod do_dh_print(BIO *bp, const DH *x, int indent, ASN1_PCTX *ctx, int ptype)
332f1535dc8Sdjm {
333f1535dc8Sdjm 	int reason = ERR_R_BUF_LIB, ret = 0;
334f1535dc8Sdjm 	const char *ktype = NULL;
335f1535dc8Sdjm 	BIGNUM *priv_key, *pub_key;
336f1535dc8Sdjm 
337f1535dc8Sdjm 	if (ptype == 2)
338f1535dc8Sdjm 		priv_key = x->priv_key;
339f1535dc8Sdjm 	else
340f1535dc8Sdjm 		priv_key = NULL;
341f1535dc8Sdjm 
342f1535dc8Sdjm 	if (ptype > 0)
343f1535dc8Sdjm 		pub_key = x->pub_key;
344f1535dc8Sdjm 	else
345f1535dc8Sdjm 		pub_key = NULL;
346f1535dc8Sdjm 
347f1535dc8Sdjm 	if (ptype == 2)
348f1535dc8Sdjm 		ktype = "PKCS#3 DH Private-Key";
349f1535dc8Sdjm 	else if (ptype == 1)
350f1535dc8Sdjm 		ktype = "PKCS#3 DH Public-Key";
351f1535dc8Sdjm 	else
352f1535dc8Sdjm 		ktype = "PKCS#3 DH Parameters";
353f1535dc8Sdjm 
354549c133bStb 	if (x->p == NULL) {
355549c133bStb 		reason = ERR_R_PASSED_NULL_PARAMETER;
356f1535dc8Sdjm 		goto err;
357f1535dc8Sdjm 	}
358f1535dc8Sdjm 
3597cd40e1cSinoguchi 	if (!BIO_indent(bp, indent, 128))
3607cd40e1cSinoguchi 		goto err;
361f1535dc8Sdjm 	if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0)
362f1535dc8Sdjm 		goto err;
363f1535dc8Sdjm 	indent += 4;
364f1535dc8Sdjm 
365549c133bStb 	if (!bn_printf(bp, priv_key, indent, "private-key:"))
3665b87c283Smiod 		goto err;
367549c133bStb 	if (!bn_printf(bp, pub_key, indent, "public-key:"))
3685b87c283Smiod 		goto err;
369f1535dc8Sdjm 
370549c133bStb 	if (!bn_printf(bp, x->p, indent, "prime:"))
3715b87c283Smiod 		goto err;
372549c133bStb 	if (!bn_printf(bp, x->g, indent, "generator:"))
3735b87c283Smiod 		goto err;
3745b87c283Smiod 	if (x->length != 0) {
3757cd40e1cSinoguchi 		if (!BIO_indent(bp, indent, 128))
3767cd40e1cSinoguchi 			goto err;
377f1535dc8Sdjm 		if (BIO_printf(bp, "recommended-private-length: %d bits\n",
3785b87c283Smiod 		    (int)x->length) <= 0)
3795b87c283Smiod 			goto err;
380f1535dc8Sdjm 	}
381f1535dc8Sdjm 
382f1535dc8Sdjm 	ret = 1;
3835b87c283Smiod 	if (0) {
384f1535dc8Sdjm  err:
3855067ae9fSbeck 		DHerror(reason);
386f1535dc8Sdjm 	}
387f1535dc8Sdjm 	return(ret);
388f1535dc8Sdjm }
389f1535dc8Sdjm 
3905b87c283Smiod static int
dh_size(const EVP_PKEY * pkey)3917244e844Stb dh_size(const EVP_PKEY *pkey)
392f1535dc8Sdjm {
3935b87c283Smiod 	return DH_size(pkey->pkey.dh);
394f1535dc8Sdjm }
395f1535dc8Sdjm 
3965b87c283Smiod static int
dh_bits(const EVP_PKEY * pkey)3975b87c283Smiod dh_bits(const EVP_PKEY *pkey)
398f1535dc8Sdjm {
399f1535dc8Sdjm 	return BN_num_bits(pkey->pkey.dh->p);
400f1535dc8Sdjm }
401f1535dc8Sdjm 
4025b87c283Smiod static int
dh_security_bits(const EVP_PKEY * pkey)4035cdf0398Stb dh_security_bits(const EVP_PKEY *pkey)
4045cdf0398Stb {
4055cdf0398Stb 	return DH_security_bits(pkey->pkey.dh);
4065cdf0398Stb }
4075cdf0398Stb 
4085cdf0398Stb static int
dh_cmp_parameters(const EVP_PKEY * a,const EVP_PKEY * b)4095b87c283Smiod dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
410f1535dc8Sdjm {
411f1535dc8Sdjm 	if (BN_cmp(a->pkey.dh->p, b->pkey.dh->p) ||
412f1535dc8Sdjm 	    BN_cmp(a->pkey.dh->g, b->pkey.dh->g))
413f1535dc8Sdjm 		return 0;
414f1535dc8Sdjm 	else
415f1535dc8Sdjm 		return 1;
416f1535dc8Sdjm }
417f1535dc8Sdjm 
4185b87c283Smiod static int
dh_copy_parameters(EVP_PKEY * to,const EVP_PKEY * from)4195b87c283Smiod dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
420f1535dc8Sdjm {
421f1535dc8Sdjm 	BIGNUM *a;
422f1535dc8Sdjm 
423f1535dc8Sdjm 	if ((a = BN_dup(from->pkey.dh->p)) == NULL)
424f1535dc8Sdjm 		return 0;
425f1535dc8Sdjm 	BN_free(to->pkey.dh->p);
426f1535dc8Sdjm 	to->pkey.dh->p = a;
427f1535dc8Sdjm 
428f1535dc8Sdjm 	if ((a = BN_dup(from->pkey.dh->g)) == NULL)
429f1535dc8Sdjm 		return 0;
430f1535dc8Sdjm 	BN_free(to->pkey.dh->g);
431f1535dc8Sdjm 	to->pkey.dh->g = a;
432f1535dc8Sdjm 
433f1535dc8Sdjm 	return 1;
434f1535dc8Sdjm }
435f1535dc8Sdjm 
4365b87c283Smiod static int
dh_missing_parameters(const EVP_PKEY * pkey)437a13d6b7aStb dh_missing_parameters(const EVP_PKEY *pkey)
438f1535dc8Sdjm {
439a13d6b7aStb 	const DH *dh = pkey->pkey.dh;
440a13d6b7aStb 
441a13d6b7aStb 	return dh->p == NULL || dh->g == NULL;
442f1535dc8Sdjm }
443f1535dc8Sdjm 
4445b87c283Smiod static int
dh_pub_cmp(const EVP_PKEY * a,const EVP_PKEY * b)4455b87c283Smiod dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
446f1535dc8Sdjm {
447f1535dc8Sdjm 	if (dh_cmp_parameters(a, b) == 0)
448f1535dc8Sdjm 		return 0;
449f1535dc8Sdjm 	if (BN_cmp(b->pkey.dh->pub_key, a->pkey.dh->pub_key) != 0)
450f1535dc8Sdjm 		return 0;
451f1535dc8Sdjm 	else
452f1535dc8Sdjm 		return 1;
453f1535dc8Sdjm }
454f1535dc8Sdjm 
4555b87c283Smiod static int
dh_param_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)4565b87c283Smiod dh_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
457f1535dc8Sdjm {
458f1535dc8Sdjm 	return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 0);
459f1535dc8Sdjm }
460f1535dc8Sdjm 
4615b87c283Smiod static int
dh_public_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)4625b87c283Smiod dh_public_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
463f1535dc8Sdjm {
464f1535dc8Sdjm 	return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 1);
465f1535dc8Sdjm }
466f1535dc8Sdjm 
4675b87c283Smiod static int
dh_private_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)4685b87c283Smiod dh_private_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
469f1535dc8Sdjm {
470f1535dc8Sdjm 	return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 2);
471f1535dc8Sdjm }
472f1535dc8Sdjm 
4735b87c283Smiod int
DHparams_print(BIO * bp,const DH * x)4745b87c283Smiod DHparams_print(BIO *bp, const DH *x)
475f1535dc8Sdjm {
476f1535dc8Sdjm 	return do_dh_print(bp, x, 4, NULL, 0);
477f1535dc8Sdjm }
478d6d0b2f3Sbeck LCRYPTO_ALIAS(DHparams_print);
479f1535dc8Sdjm 
480cf220632Stb int
DHparams_print_fp(FILE * fp,const DH * x)481cf220632Stb DHparams_print_fp(FILE *fp, const DH *x)
482cf220632Stb {
483cf220632Stb 	BIO *b;
484cf220632Stb 	int ret;
485cf220632Stb 
486cf220632Stb 	if ((b = BIO_new(BIO_s_file())) == NULL) {
487cf220632Stb 		DHerror(ERR_R_BUF_LIB);
488cf220632Stb 		return 0;
489cf220632Stb 	}
49028db4cbbStb 
491cf220632Stb 	BIO_set_fp(b, fp, BIO_NOCLOSE);
492cf220632Stb 	ret = DHparams_print(b, x);
493cf220632Stb 	BIO_free(b);
49428db4cbbStb 
495cf220632Stb 	return ret;
496cf220632Stb }
497d6d0b2f3Sbeck LCRYPTO_ALIAS(DHparams_print_fp);
498cf220632Stb 
499262d8eccStb static int
dh_pkey_public_check(const EVP_PKEY * pkey)500262d8eccStb dh_pkey_public_check(const EVP_PKEY *pkey)
501262d8eccStb {
502262d8eccStb 	DH *dh = pkey->pkey.dh;
503262d8eccStb 
504262d8eccStb 	if (dh->pub_key == NULL) {
505262d8eccStb 		DHerror(DH_R_MISSING_PUBKEY);
506262d8eccStb 		return 0;
507262d8eccStb 	}
508262d8eccStb 
509262d8eccStb 	return DH_check_pub_key_ex(dh, dh->pub_key);
510262d8eccStb }
511262d8eccStb 
512262d8eccStb static int
dh_pkey_param_check(const EVP_PKEY * pkey)513262d8eccStb dh_pkey_param_check(const EVP_PKEY *pkey)
514262d8eccStb {
515262d8eccStb 	DH *dh = pkey->pkey.dh;
516262d8eccStb 
517262d8eccStb 	/*
518262d8eccStb 	 * It would have made more sense to support EVP_PKEY_check() for DH
519262d8eccStb 	 * keys and call DH_check_ex() there and keeping this as a wrapper
520262d8eccStb 	 * for DH_param_check_ex(). We follow OpenSSL's choice.
521262d8eccStb 	 */
522262d8eccStb 	return DH_check_ex(dh);
523262d8eccStb }
524262d8eccStb 
525e402ce74Smiod const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
526*9ed721ecStb 	.base_method = &dh_asn1_meth,
527e402ce74Smiod 	.pkey_id = EVP_PKEY_DH,
528f1535dc8Sdjm 
529e402ce74Smiod 	.pem_str = "DH",
530e402ce74Smiod 	.info = "OpenSSL PKCS#3 DH method",
531f1535dc8Sdjm 
532e402ce74Smiod 	.pub_decode = dh_pub_decode,
533e402ce74Smiod 	.pub_encode = dh_pub_encode,
534e402ce74Smiod 	.pub_cmp = dh_pub_cmp,
535e402ce74Smiod 	.pub_print = dh_public_print,
536f1535dc8Sdjm 
537e402ce74Smiod 	.priv_decode = dh_priv_decode,
538e402ce74Smiod 	.priv_encode = dh_priv_encode,
539e402ce74Smiod 	.priv_print = dh_private_print,
540f1535dc8Sdjm 
5417244e844Stb 	.pkey_size = dh_size,
542e402ce74Smiod 	.pkey_bits = dh_bits,
5435cdf0398Stb 	.pkey_security_bits = dh_security_bits,
544f1535dc8Sdjm 
545e402ce74Smiod 	.param_decode = dh_param_decode,
546e402ce74Smiod 	.param_encode = dh_param_encode,
547e402ce74Smiod 	.param_missing = dh_missing_parameters,
548e402ce74Smiod 	.param_copy = dh_copy_parameters,
549e402ce74Smiod 	.param_cmp = dh_cmp_parameters,
550e402ce74Smiod 	.param_print = dh_param_print,
551f1535dc8Sdjm 
5527244e844Stb 	.pkey_free = dh_free,
553262d8eccStb 
554262d8eccStb 	.pkey_check = NULL,
555262d8eccStb 	.pkey_public_check = dh_pkey_public_check,
556262d8eccStb 	.pkey_param_check = dh_pkey_param_check,
557f1535dc8Sdjm };
558