xref: /openbsd-src/lib/libcrypto/dsa/dsa_ameth.c (revision d5a216b5d189ec352945f87cf4d85200ce83c317)
1*d5a216b5Stb /* $OpenBSD: dsa_ameth.c,v 1.59 2024/04/13 14:02:51 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>
608cf4d6a6Sjsing 
618cf4d6a6Sjsing #include <openssl/opensslconf.h>
628cf4d6a6Sjsing 
63f1535dc8Sdjm #include <openssl/asn1.h>
64f1535dc8Sdjm #include <openssl/bn.h>
650214b3aaSjsing #include <openssl/cms.h>
66b6ab114eSjsing #include <openssl/dsa.h>
67b6ab114eSjsing #include <openssl/err.h>
68b6ab114eSjsing #include <openssl/x509.h>
69b6ab114eSjsing 
70c9675a23Stb #include "asn1_local.h"
71c9675a23Stb #include "bn_local.h"
72c9675a23Stb #include "dsa_local.h"
73c9675a23Stb #include "evp_local.h"
74*d5a216b5Stb #include "x509_local.h"
75f1535dc8Sdjm 
76e85b1b81Smiod static int
dsa_pub_decode(EVP_PKEY * pkey,X509_PUBKEY * pubkey)77e85b1b81Smiod dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
78f1535dc8Sdjm {
79b42bcaecStb 	X509_ALGOR *algor;
80f1535dc8Sdjm 	int ptype;
810267c206Stb 	const void *pval;
825c3bbfbbStb 	const ASN1_STRING *astr;
835c3bbfbbStb 	const unsigned char *key, *params, *p;
84b42bcaecStb 	int key_len, params_len;
855c3bbfbbStb 	ASN1_INTEGER *aint = NULL;
86f1535dc8Sdjm 	DSA *dsa = NULL;
87b42bcaecStb 	int ret = 0;
88f1535dc8Sdjm 
895c3bbfbbStb 	if (!X509_PUBKEY_get0_param(NULL, &key, &key_len, &algor, pubkey))
90b42bcaecStb 		goto err;
91b42bcaecStb 	X509_ALGOR_get0(NULL, &ptype, &pval, algor);
92f1535dc8Sdjm 
93e85b1b81Smiod 	if (ptype == V_ASN1_SEQUENCE) {
945c3bbfbbStb 		astr = pval;
955c3bbfbbStb 		params = astr->data;
965c3bbfbbStb 		params_len = astr->length;
97f1535dc8Sdjm 
985c3bbfbbStb 		p = params;
99b42bcaecStb 		if ((dsa = d2i_DSAparams(NULL, &p, params_len)) == NULL) {
1005067ae9fSbeck 			DSAerror(DSA_R_DECODE_ERROR);
101f1535dc8Sdjm 			goto err;
102f1535dc8Sdjm 		}
103e85b1b81Smiod 	} else if (ptype == V_ASN1_NULL || ptype == V_ASN1_UNDEF) {
104b42bcaecStb 		if ((dsa = DSA_new()) == NULL) {
1055067ae9fSbeck 			DSAerror(ERR_R_MALLOC_FAILURE);
106f1535dc8Sdjm 			goto err;
107f1535dc8Sdjm 		}
108e85b1b81Smiod 	} else {
1095067ae9fSbeck 		DSAerror(DSA_R_PARAMETER_ENCODING_ERROR);
110f1535dc8Sdjm 		goto err;
111f1535dc8Sdjm 	}
112f1535dc8Sdjm 
1135c3bbfbbStb 	p = key;
1145c3bbfbbStb 	if ((aint = d2i_ASN1_INTEGER(NULL, &p, key_len)) == NULL) {
1155067ae9fSbeck 		DSAerror(DSA_R_DECODE_ERROR);
116f1535dc8Sdjm 		goto err;
117f1535dc8Sdjm 	}
11852d22fd7Stb 	BN_free(dsa->pub_key);
1195c3bbfbbStb 	if ((dsa->pub_key = ASN1_INTEGER_to_BN(aint, NULL)) == NULL) {
1205067ae9fSbeck 		DSAerror(DSA_R_BN_DECODE_ERROR);
121f1535dc8Sdjm 		goto err;
122f1535dc8Sdjm 	}
12329b50e09Stb 
124f1d158b4Stb 	/* We can only check for key consistency if we have parameters. */
125f1d158b4Stb 	if (ptype == V_ASN1_SEQUENCE) {
126f1d158b4Stb 		if (!dsa_check_key(dsa))
127f1d158b4Stb 			goto err;
128f1d158b4Stb 	}
129f1d158b4Stb 
130b42bcaecStb 	if (!EVP_PKEY_assign_DSA(pkey, dsa))
131b42bcaecStb 		goto err;
132b42bcaecStb 	dsa = NULL;
133b42bcaecStb 
134b42bcaecStb 	ret = 1;
135f1535dc8Sdjm 
136f1535dc8Sdjm  err:
1375c3bbfbbStb 	ASN1_INTEGER_free(aint);
138f1535dc8Sdjm 	DSA_free(dsa);
139b42bcaecStb 
140b42bcaecStb 	return ret;
141f1535dc8Sdjm }
142f1535dc8Sdjm 
143e85b1b81Smiod static int
dsa_pub_encode(X509_PUBKEY * pk,const EVP_PKEY * pkey)144e85b1b81Smiod dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
145f1535dc8Sdjm {
1460e358455Stb 	const DSA *dsa = pkey->pkey.dsa;
1475c3bbfbbStb 	ASN1_STRING *astr = NULL;
148c3954054Stb 	int ptype = V_ASN1_UNDEF;
1495c3bbfbbStb 	ASN1_INTEGER *aint = NULL;
1500e358455Stb 	ASN1_OBJECT *aobj;
1515c3bbfbbStb 	unsigned char *params = NULL, *key = NULL;
152fed21370Stb 	int params_len = 0, key_len = 0;
153fed21370Stb 	int ret = 0;
154f1535dc8Sdjm 
155741c2858Stb 	if (pkey->save_parameters > 0 && !EVP_PKEY_missing_parameters(pkey)) {
1565c3bbfbbStb 		if ((params_len = i2d_DSAparams(dsa, &params)) <= 0) {
1570e358455Stb 			DSAerror(ERR_R_MALLOC_FAILURE);
158fed21370Stb 			params_len = 0;
1590e358455Stb 			goto err;
1600e358455Stb 		}
1615c3bbfbbStb 		if ((astr = ASN1_STRING_new()) == NULL) {
1625067ae9fSbeck 			DSAerror(ERR_R_MALLOC_FAILURE);
1633fca064fSmiod 			goto err;
1643fca064fSmiod 		}
1655c3bbfbbStb 		ASN1_STRING_set0(astr, params, params_len);
1665c3bbfbbStb 		params = NULL;
167fed21370Stb 		params_len = 0;
168f1535dc8Sdjm 		ptype = V_ASN1_SEQUENCE;
169c3954054Stb 	}
170f1535dc8Sdjm 
1715c3bbfbbStb 	if ((aint = BN_to_ASN1_INTEGER(dsa->pub_key, NULL)) == NULL) {
172354ae18bStb 		DSAerror(ERR_R_MALLOC_FAILURE);
173354ae18bStb 		goto err;
174354ae18bStb 	}
1755c3bbfbbStb 	if ((key_len = i2d_ASN1_INTEGER(aint, &key)) <= 0) {
1765067ae9fSbeck 		DSAerror(ERR_R_MALLOC_FAILURE);
177fed21370Stb 		key_len = 0;
178f1535dc8Sdjm 		goto err;
179f1535dc8Sdjm 	}
180f1535dc8Sdjm 
1810e358455Stb 	if ((aobj = OBJ_nid2obj(EVP_PKEY_DSA)) == NULL)
1820e358455Stb 		goto err;
1835c3bbfbbStb 	if (!X509_PUBKEY_set0_param(pk, aobj, ptype, astr, key, key_len))
1840e358455Stb 		goto err;
1855c3bbfbbStb 	astr = NULL;
1865c3bbfbbStb 	key = NULL;
187fed21370Stb 	key_len = 0;
1880e358455Stb 
189fed21370Stb 	ret = 1;
190f1535dc8Sdjm 
191f1535dc8Sdjm  err:
1925c3bbfbbStb 	ASN1_STRING_free(astr);
1935c3bbfbbStb 	ASN1_INTEGER_free(aint);
1945c3bbfbbStb 	freezero(params, params_len);
1955c3bbfbbStb 	freezero(key, key_len);
196f1535dc8Sdjm 
197fed21370Stb 	return ret;
198f1535dc8Sdjm }
199f1535dc8Sdjm 
200b42bcaecStb /*
201b42bcaecStb  * In PKCS#8 DSA: you just get a private key integer and parameters in the
202f1535dc8Sdjm  * AlgorithmIdentifier the pubkey must be recalculated.
203f1535dc8Sdjm  */
204e85b1b81Smiod static int
dsa_priv_decode(EVP_PKEY * pkey,const PKCS8_PRIV_KEY_INFO * p8)2058d6bc8b3Stb dsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
206f1535dc8Sdjm {
207b42bcaecStb 	const X509_ALGOR *algor;
208f1535dc8Sdjm 	int ptype;
2090267c206Stb 	const void *pval;
2105c3bbfbbStb 	const ASN1_STRING *astr;
2115c3bbfbbStb 	const unsigned char *key, *params, *p;
212b42bcaecStb 	int key_len, params_len;
2135c3bbfbbStb 	ASN1_INTEGER *aint = NULL;
214f1535dc8Sdjm 	BN_CTX *ctx = NULL;
215f1535dc8Sdjm 	DSA *dsa = NULL;
216ebef6bdeSdoug 	int ret = 0;
217ebef6bdeSdoug 
2185c3bbfbbStb 	if (!PKCS8_pkey_get0(NULL, &key, &key_len, &algor, p8))
219b42bcaecStb 		goto err;
220b42bcaecStb 	X509_ALGOR_get0(NULL, &ptype, &pval, algor);
221ebef6bdeSdoug 
222b42bcaecStb 	if (ptype != V_ASN1_SEQUENCE) {
223b42bcaecStb 		DSAerror(DSA_R_PARAMETER_ENCODING_ERROR);
224b42bcaecStb 		goto err;
225b42bcaecStb 	}
226f1535dc8Sdjm 
2275c3bbfbbStb 	astr = pval;
2285c3bbfbbStb 	params = astr->data;
2295c3bbfbbStb 	params_len = astr->length;
230b42bcaecStb 
2315c3bbfbbStb 	p = params;
232b42bcaecStb 	if ((dsa = d2i_DSAparams(NULL, &p, params_len)) == NULL) {
233b42bcaecStb 		DSAerror(DSA_R_DECODE_ERROR);
234b42bcaecStb 		goto err;
235b42bcaecStb 	}
2365c3bbfbbStb 	p = key;
2375c3bbfbbStb 	if ((aint = d2i_ASN1_INTEGER(NULL, &p, key_len)) == NULL) {
238b42bcaecStb 		DSAerror(DSA_R_DECODE_ERROR);
239b42bcaecStb 		goto err;
240b42bcaecStb 	}
24152d22fd7Stb 	BN_free(dsa->priv_key);
2425c3bbfbbStb 	if ((dsa->priv_key = ASN1_INTEGER_to_BN(aint, NULL)) == NULL) {
243b42bcaecStb 		DSAerror(DSA_R_BN_DECODE_ERROR);
244b42bcaecStb 		goto err;
245f1535dc8Sdjm 	}
246f1d158b4Stb 
247f1d158b4Stb 	/* Check the key for basic consistency before doing expensive things. */
248f1d158b4Stb 	if (!dsa_check_key(dsa))
249b42bcaecStb 		goto err;
250f1d158b4Stb 
251f1535dc8Sdjm 	/* Calculate public key */
25252d22fd7Stb 	BN_free(dsa->pub_key);
253b42bcaecStb 	if ((dsa->pub_key = BN_new()) == NULL) {
2545067ae9fSbeck 		DSAerror(ERR_R_MALLOC_FAILURE);
255b42bcaecStb 		goto err;
256f1535dc8Sdjm 	}
25770901374Sjsing 
25870901374Sjsing 	if ((ctx = BN_CTX_new()) == NULL) {
2595067ae9fSbeck 		DSAerror(ERR_R_MALLOC_FAILURE);
260b42bcaecStb 		goto err;
261f1535dc8Sdjm 	}
262f1535dc8Sdjm 
26370901374Sjsing 	BN_CTX_start(ctx);
26470901374Sjsing 
2653a88f7afSbeck 	if (!BN_mod_exp_ct(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
2665067ae9fSbeck 		DSAerror(DSA_R_BN_ERROR);
267b42bcaecStb 		goto err;
268f1535dc8Sdjm 	}
269f1535dc8Sdjm 
270ebef6bdeSdoug 	if (!EVP_PKEY_assign_DSA(pkey, dsa))
271b42bcaecStb 		goto err;
272b42bcaecStb 	dsa = NULL;
273f1535dc8Sdjm 
274ebef6bdeSdoug 	ret = 1;
275f1535dc8Sdjm 
276b42bcaecStb  err:
277f1535dc8Sdjm 	DSA_free(dsa);
27870901374Sjsing 	BN_CTX_end(ctx);
279ebef6bdeSdoug 	BN_CTX_free(ctx);
2805c3bbfbbStb 	ASN1_INTEGER_free(aint);
28170901374Sjsing 
282ebef6bdeSdoug 	return ret;
283f1535dc8Sdjm }
284f1535dc8Sdjm 
285e85b1b81Smiod static int
dsa_priv_encode(PKCS8_PRIV_KEY_INFO * p8,const EVP_PKEY * pkey)286e85b1b81Smiod dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
287f1535dc8Sdjm {
288d4662417Stb 	const DSA *dsa = pkey->pkey.dsa;
2895c3bbfbbStb 	ASN1_STRING *astr = NULL;
290fed21370Stb 	int ptype = V_ASN1_SEQUENCE;
2915c3bbfbbStb 	ASN1_INTEGER *aint = NULL;
292d4662417Stb 	ASN1_OBJECT *aobj;
2935c3bbfbbStb 	unsigned char *params = NULL, *key = NULL;
294fed21370Stb 	int params_len = 0, key_len = 0;
295fed21370Stb 	int ret = 0;
296f1535dc8Sdjm 
2975c3bbfbbStb 	if ((params_len = i2d_DSAparams(dsa, &params)) <= 0) {
298d4662417Stb 		DSAerror(ERR_R_MALLOC_FAILURE);
299fed21370Stb 		params_len = 0;
300d4662417Stb 		goto err;
301d4662417Stb 	}
3025c3bbfbbStb 	if ((astr = ASN1_STRING_type_new(V_ASN1_SEQUENCE)) == NULL) {
3035067ae9fSbeck 		DSAerror(ERR_R_MALLOC_FAILURE);
304f1535dc8Sdjm 		goto err;
305f1535dc8Sdjm 	}
3065c3bbfbbStb 	ASN1_STRING_set0(astr, params, params_len);
3075c3bbfbbStb 	params = NULL;
308fed21370Stb 	params_len = 0;
309f1535dc8Sdjm 
3105c3bbfbbStb 	if ((aint = BN_to_ASN1_INTEGER(dsa->priv_key, NULL)) == NULL) {
3115067ae9fSbeck 		DSAerror(DSA_R_BN_ERROR);
312f1535dc8Sdjm 		goto err;
313f1535dc8Sdjm 	}
3145c3bbfbbStb 	if ((key_len = i2d_ASN1_INTEGER(aint, &key)) <= 0) {
315d4662417Stb 		DSAerror(ERR_R_MALLOC_FAILURE);
316fed21370Stb 		key_len = 0;
317d4662417Stb 		goto err;
318d4662417Stb 	}
319f1535dc8Sdjm 
320d4662417Stb 	if ((aobj = OBJ_nid2obj(NID_dsa)) == NULL)
321d4662417Stb 		goto err;
3225c3bbfbbStb 	if (!PKCS8_pkey_set0(p8, aobj, 0, ptype, astr, key, key_len))
323f1535dc8Sdjm 		goto err;
3245c3bbfbbStb 	astr = NULL;
3255c3bbfbbStb 	key = NULL;
326fed21370Stb 	key_len = 0;
327f1535dc8Sdjm 
328fed21370Stb 	ret = 1;
329f1535dc8Sdjm 
330f1535dc8Sdjm  err:
3315c3bbfbbStb 	ASN1_STRING_free(astr);
3325c3bbfbbStb 	ASN1_INTEGER_free(aint);
3335c3bbfbbStb 	freezero(params, params_len);
3345c3bbfbbStb 	freezero(key, key_len);
335d4662417Stb 
336fed21370Stb 	return ret;
337f1535dc8Sdjm }
338f1535dc8Sdjm 
339e85b1b81Smiod static int
dsa_size(const EVP_PKEY * pkey)3407244e844Stb dsa_size(const EVP_PKEY *pkey)
341f1535dc8Sdjm {
342e85b1b81Smiod 	return DSA_size(pkey->pkey.dsa);
343f1535dc8Sdjm }
344f1535dc8Sdjm 
345e85b1b81Smiod static int
dsa_bits(const EVP_PKEY * pkey)346e85b1b81Smiod dsa_bits(const EVP_PKEY *pkey)
347f1535dc8Sdjm {
348f1535dc8Sdjm 	return BN_num_bits(pkey->pkey.dsa->p);
349f1535dc8Sdjm }
350f1535dc8Sdjm 
351e85b1b81Smiod static int
dsa_security_bits(const EVP_PKEY * pkey)3525cdf0398Stb dsa_security_bits(const EVP_PKEY *pkey)
3535cdf0398Stb {
3545cdf0398Stb 	return DSA_security_bits(pkey->pkey.dsa);
3555cdf0398Stb }
3565cdf0398Stb 
3575cdf0398Stb static int
dsa_missing_parameters(const EVP_PKEY * pkey)358e85b1b81Smiod dsa_missing_parameters(const EVP_PKEY *pkey)
359f1535dc8Sdjm {
360a13d6b7aStb 	const DSA *dsa = pkey->pkey.dsa;
361e85b1b81Smiod 
362a13d6b7aStb 	return dsa->p == NULL || dsa->q == NULL || dsa->g == NULL;
363f1535dc8Sdjm }
364f1535dc8Sdjm 
365e85b1b81Smiod static int
dsa_copy_parameters(EVP_PKEY * to,const EVP_PKEY * from)366e85b1b81Smiod dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
367f1535dc8Sdjm {
368f1535dc8Sdjm 	BIGNUM *a;
369f1535dc8Sdjm 
370f1535dc8Sdjm 	if ((a = BN_dup(from->pkey.dsa->p)) == NULL)
371f1535dc8Sdjm 		return 0;
372f1535dc8Sdjm 	BN_free(to->pkey.dsa->p);
373f1535dc8Sdjm 	to->pkey.dsa->p = a;
374f1535dc8Sdjm 
375f1535dc8Sdjm 	if ((a = BN_dup(from->pkey.dsa->q)) == NULL)
376f1535dc8Sdjm 		return 0;
377f1535dc8Sdjm 	BN_free(to->pkey.dsa->q);
378f1535dc8Sdjm 	to->pkey.dsa->q = a;
379f1535dc8Sdjm 
380f1535dc8Sdjm 	if ((a = BN_dup(from->pkey.dsa->g)) == NULL)
381f1535dc8Sdjm 		return 0;
382f1535dc8Sdjm 	BN_free(to->pkey.dsa->g);
383f1535dc8Sdjm 	to->pkey.dsa->g = a;
384f1535dc8Sdjm 	return 1;
385f1535dc8Sdjm }
386f1535dc8Sdjm 
387e85b1b81Smiod static int
dsa_cmp_parameters(const EVP_PKEY * a,const EVP_PKEY * b)388e85b1b81Smiod dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
389f1535dc8Sdjm {
390f1535dc8Sdjm 	if (BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) ||
391f1535dc8Sdjm 	    BN_cmp(a->pkey.dsa->q, b->pkey.dsa->q) ||
392f1535dc8Sdjm 	    BN_cmp(a->pkey.dsa->g, b->pkey.dsa->g))
393f1535dc8Sdjm 		return 0;
394f1535dc8Sdjm 	else
395f1535dc8Sdjm 		return 1;
396f1535dc8Sdjm }
397f1535dc8Sdjm 
398e85b1b81Smiod static int
dsa_pub_cmp(const EVP_PKEY * a,const EVP_PKEY * b)399e85b1b81Smiod dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
400f1535dc8Sdjm {
401f1535dc8Sdjm 	if (BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) != 0)
402f1535dc8Sdjm 		return 0;
403f1535dc8Sdjm 	else
404f1535dc8Sdjm 		return 1;
405f1535dc8Sdjm }
406f1535dc8Sdjm 
407e85b1b81Smiod static void
dsa_free(EVP_PKEY * pkey)4087244e844Stb dsa_free(EVP_PKEY *pkey)
409f1535dc8Sdjm {
410f1535dc8Sdjm 	DSA_free(pkey->pkey.dsa);
411f1535dc8Sdjm }
412f1535dc8Sdjm 
413e85b1b81Smiod static int
do_dsa_print(BIO * bp,const DSA * x,int off,int ptype)414e85b1b81Smiod do_dsa_print(BIO *bp, const DSA *x, int off, int ptype)
415f1535dc8Sdjm {
416f1535dc8Sdjm 	const char *ktype = NULL;
417f1535dc8Sdjm 	const BIGNUM *priv_key, *pub_key;
418549c133bStb 	int ret = 0;
419f1535dc8Sdjm 
420f1535dc8Sdjm 	if (ptype == 2)
421f1535dc8Sdjm 		priv_key = x->priv_key;
422f1535dc8Sdjm 	else
423f1535dc8Sdjm 		priv_key = NULL;
424f1535dc8Sdjm 
425f1535dc8Sdjm 	if (ptype > 0)
426f1535dc8Sdjm 		pub_key = x->pub_key;
427f1535dc8Sdjm 	else
428f1535dc8Sdjm 		pub_key = NULL;
429f1535dc8Sdjm 
430f1535dc8Sdjm 	if (ptype == 2)
431f1535dc8Sdjm 		ktype = "Private-Key";
432f1535dc8Sdjm 	else if (ptype == 1)
433f1535dc8Sdjm 		ktype = "Public-Key";
434f1535dc8Sdjm 	else
435f1535dc8Sdjm 		ktype = "DSA-Parameters";
436f1535dc8Sdjm 
437e85b1b81Smiod 	if (priv_key) {
438f1535dc8Sdjm 		if (!BIO_indent(bp, off, 128))
439f1535dc8Sdjm 			goto err;
440e85b1b81Smiod 		if (BIO_printf(bp, "%s: (%d bit)\n", ktype,
441e85b1b81Smiod 		    BN_num_bits(x->p)) <= 0)
442e85b1b81Smiod 			goto err;
443f1535dc8Sdjm 	}
444f1535dc8Sdjm 
445549c133bStb 	if (!bn_printf(bp, priv_key, off, "priv:"))
446f1535dc8Sdjm 		goto err;
447549c133bStb 	if (!bn_printf(bp, pub_key, off, "pub: "))
448f1535dc8Sdjm 		goto err;
449549c133bStb 	if (!bn_printf(bp, x->p, off, "P:   "))
450e85b1b81Smiod 		goto err;
451549c133bStb 	if (!bn_printf(bp, x->q, off, "Q:   "))
452e85b1b81Smiod 		goto err;
453549c133bStb 	if (!bn_printf(bp, x->g, off, "G:   "))
454e85b1b81Smiod 		goto err;
455549c133bStb 
456f1535dc8Sdjm 	ret = 1;
457549c133bStb 
458f1535dc8Sdjm  err:
459d21f5001Stb 	return ret;
460f1535dc8Sdjm }
461f1535dc8Sdjm 
462e85b1b81Smiod static int
dsa_param_decode(EVP_PKEY * pkey,const unsigned char ** params,int params_len)463e6a172b0Stb dsa_param_decode(EVP_PKEY *pkey, const unsigned char **params, int params_len)
464f1535dc8Sdjm {
465b42bcaecStb 	DSA *dsa = NULL;
466b42bcaecStb 	int ret = 0;
467e85b1b81Smiod 
468e6a172b0Stb 	if ((dsa = d2i_DSAparams(NULL, params, params_len)) == NULL) {
4695067ae9fSbeck 		DSAerror(ERR_R_DSA_LIB);
470b42bcaecStb 		goto err;
471f1535dc8Sdjm 	}
472b42bcaecStb 	if (!dsa_check_key(dsa))
473b42bcaecStb 		goto err;
474b42bcaecStb 	if (!EVP_PKEY_assign_DSA(pkey, dsa))
475b42bcaecStb 		goto err;
476b42bcaecStb 	dsa = NULL;
477b42bcaecStb 
478b42bcaecStb 	ret = 1;
479b42bcaecStb 
480b42bcaecStb  err:
481f1d158b4Stb 	DSA_free(dsa);
482b42bcaecStb 
483b42bcaecStb 	return ret;
484f1535dc8Sdjm }
485f1535dc8Sdjm 
486e85b1b81Smiod static int
dsa_param_encode(const EVP_PKEY * pkey,unsigned char ** params)487e6a172b0Stb dsa_param_encode(const EVP_PKEY *pkey, unsigned char **params)
488f1535dc8Sdjm {
489e6a172b0Stb 	return i2d_DSAparams(pkey->pkey.dsa, params);
490f1535dc8Sdjm }
491f1535dc8Sdjm 
492e85b1b81Smiod static int
dsa_param_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)493e85b1b81Smiod dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
494f1535dc8Sdjm {
495f1535dc8Sdjm 	return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
496f1535dc8Sdjm }
497f1535dc8Sdjm 
498e85b1b81Smiod static int
dsa_pub_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)499e85b1b81Smiod dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
500f1535dc8Sdjm {
501f1535dc8Sdjm 	return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
502f1535dc8Sdjm }
503f1535dc8Sdjm 
504e85b1b81Smiod static int
dsa_priv_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)505e85b1b81Smiod dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
506f1535dc8Sdjm {
507f1535dc8Sdjm 	return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
508f1535dc8Sdjm }
509f1535dc8Sdjm 
510e85b1b81Smiod static int
old_dsa_priv_decode(EVP_PKEY * pkey,const unsigned char ** key,int key_len)51176239e4fStb old_dsa_priv_decode(EVP_PKEY *pkey, const unsigned char **key, int key_len)
512f1535dc8Sdjm {
513b42bcaecStb 	DSA *dsa = NULL;
51490bc814bSmiod 	BN_CTX *ctx = NULL;
51594bb0884Stb 	BIGNUM *result;
516b42bcaecStb 	int ret = 0;
517e85b1b81Smiod 
51876239e4fStb 	if ((dsa = d2i_DSAPrivateKey(NULL, key, key_len)) == NULL) {
5195067ae9fSbeck 		DSAerror(ERR_R_DSA_LIB);
520ad41f5e1Stb 		goto err;
521f1535dc8Sdjm 	}
52290bc814bSmiod 
523f1d158b4Stb 	if (!dsa_check_key(dsa))
52483bd653dStb 		goto err;
5255c3491c8Stb 
52670901374Sjsing 	if ((ctx = BN_CTX_new()) == NULL)
52790bc814bSmiod 		goto err;
52890bc814bSmiod 
52970901374Sjsing 	BN_CTX_start(ctx);
53070901374Sjsing 
53194bb0884Stb 	if ((result = BN_CTX_get(ctx)) == NULL)
53294bb0884Stb 		goto err;
53394bb0884Stb 
53490bc814bSmiod 	/*
53594bb0884Stb 	 * Check that p and q are consistent with each other. dsa_check_key()
53694bb0884Stb 	 * ensures that 1 < q < p. Now check that q divides p - 1.
53790bc814bSmiod 	 */
53870901374Sjsing 
53994bb0884Stb 	if (!BN_sub(result, dsa->p, BN_value_one()))
54090bc814bSmiod 		goto err;
54194bb0884Stb 	if (!BN_mod_ct(result, result, dsa->q, ctx))
54290bc814bSmiod 		goto err;
54394bb0884Stb 	if (!BN_is_zero(result)) {
5445067ae9fSbeck 		DSAerror(DSA_R_BAD_Q_VALUE);
54590bc814bSmiod 		goto err;
54690bc814bSmiod 	}
54790bc814bSmiod 
54890bc814bSmiod 	/*
5495c3491c8Stb 	 * Check that g generates a multiplicative subgroup of order q.
5505c3491c8Stb 	 * We only check that g^q == 1, so the order is a divisor of q.
5515c3491c8Stb 	 * Once we know that q is prime, this is enough.
5525c3491c8Stb 	 */
5535c3491c8Stb 
55494bb0884Stb 	if (!BN_mod_exp_ct(result, dsa->g, dsa->q, dsa->p, ctx))
5555c3491c8Stb 		goto err;
55694bb0884Stb 	if (BN_cmp(result, BN_value_one()) != 0) {
55794bb0884Stb 		DSAerror(DSA_R_INVALID_PARAMETERS);
5585c3491c8Stb 		goto err;
5595c3491c8Stb 	}
5605c3491c8Stb 
5615c3491c8Stb 	/*
56290bc814bSmiod 	 * Check that q is not a composite number.
56390bc814bSmiod 	 */
56490bc814bSmiod 
5659af159c9Stb 	if (BN_is_prime_ex(dsa->q, BN_prime_checks, ctx, NULL) <= 0) {
5665067ae9fSbeck 		DSAerror(DSA_R_BAD_Q_VALUE);
56790bc814bSmiod 		goto err;
56890bc814bSmiod 	}
56990bc814bSmiod 
570b42bcaecStb 	if (!EVP_PKEY_assign_DSA(pkey, dsa))
571b42bcaecStb 		goto err;
572b42bcaecStb 	dsa = NULL;
57390bc814bSmiod 
574b42bcaecStb 	ret = 1;
57590bc814bSmiod 
57690bc814bSmiod  err:
57770901374Sjsing 	BN_CTX_end(ctx);
57890bc814bSmiod 	BN_CTX_free(ctx);
57990bc814bSmiod 	DSA_free(dsa);
580b42bcaecStb 
581b42bcaecStb 	return ret;
582f1535dc8Sdjm }
583f1535dc8Sdjm 
584e85b1b81Smiod static int
old_dsa_priv_encode(const EVP_PKEY * pkey,unsigned char ** key)58576239e4fStb old_dsa_priv_encode(const EVP_PKEY *pkey, unsigned char **key)
586f1535dc8Sdjm {
58776239e4fStb 	return i2d_DSAPrivateKey(pkey->pkey.dsa, key);
588f1535dc8Sdjm }
589f1535dc8Sdjm 
590e85b1b81Smiod static int
dsa_sig_print(BIO * bp,const X509_ALGOR * sigalg,const ASN1_STRING * sig,int indent,ASN1_PCTX * pctx)591e85b1b81Smiod dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg, const ASN1_STRING *sig,
592ec07fdf1Sdjm     int indent, ASN1_PCTX *pctx)
593ec07fdf1Sdjm {
594ec07fdf1Sdjm 	DSA_SIG *dsa_sig;
595ec07fdf1Sdjm 	const unsigned char *p;
596e85b1b81Smiod 
597e85b1b81Smiod 	if (!sig) {
598ec07fdf1Sdjm 		if (BIO_puts(bp, "\n") <= 0)
599ec07fdf1Sdjm 			return 0;
600ec07fdf1Sdjm 		else
601ec07fdf1Sdjm 			return 1;
602ec07fdf1Sdjm 	}
603ec07fdf1Sdjm 	p = sig->data;
604ec07fdf1Sdjm 	dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length);
605e85b1b81Smiod 	if (dsa_sig) {
606ec07fdf1Sdjm 		int rv = 0;
607ec07fdf1Sdjm 
608ec07fdf1Sdjm 		if (BIO_write(bp, "\n", 1) != 1)
609ec07fdf1Sdjm 			goto err;
610ec07fdf1Sdjm 
611549c133bStb 		if (!bn_printf(bp, dsa_sig->r, indent, "r:   "))
612ec07fdf1Sdjm 			goto err;
613549c133bStb 		if (!bn_printf(bp, dsa_sig->s, indent, "s:   "))
614ec07fdf1Sdjm 			goto err;
615ec07fdf1Sdjm 		rv = 1;
616ec07fdf1Sdjm  err:
617ec07fdf1Sdjm 		DSA_SIG_free(dsa_sig);
618ec07fdf1Sdjm 		return rv;
619ec07fdf1Sdjm 	}
620ec07fdf1Sdjm 	return X509_signature_dump(bp, sig, indent);
621ec07fdf1Sdjm }
622ec07fdf1Sdjm 
623e85b1b81Smiod static int
dsa_pkey_ctrl(EVP_PKEY * pkey,int op,long arg1,void * arg2)624e85b1b81Smiod dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
625f1535dc8Sdjm {
626e85b1b81Smiod 	switch (op) {
627f1535dc8Sdjm 	case ASN1_PKEY_CTRL_PKCS7_SIGN:
628e85b1b81Smiod 		if (arg1 == 0) {
629f1535dc8Sdjm 			int snid, hnid;
630f1535dc8Sdjm 			X509_ALGOR *alg1, *alg2;
631e85b1b81Smiod 
632f1535dc8Sdjm 			PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
633f1535dc8Sdjm 			if (alg1 == NULL || alg1->algorithm == NULL)
634f1535dc8Sdjm 				return -1;
635f1535dc8Sdjm 			hnid = OBJ_obj2nid(alg1->algorithm);
636f1535dc8Sdjm 			if (hnid == NID_undef)
637f1535dc8Sdjm 				return -1;
63823b107b8Stb 			if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
639f1535dc8Sdjm 				return -1;
640*d5a216b5Stb 			if (!X509_ALGOR_set0_by_nid(alg2, snid, V_ASN1_UNDEF,
641*d5a216b5Stb 			    NULL))
642*d5a216b5Stb 				return -1;
643f1535dc8Sdjm 		}
644f1535dc8Sdjm 		return 1;
645f1535dc8Sdjm 
6460214b3aaSjsing #ifndef OPENSSL_NO_CMS
6470214b3aaSjsing 	case ASN1_PKEY_CTRL_CMS_SIGN:
6480214b3aaSjsing 		if (arg1 == 0) {
6490214b3aaSjsing 			int snid, hnid;
6500214b3aaSjsing 			X509_ALGOR *alg1, *alg2;
6510214b3aaSjsing 
6520214b3aaSjsing 			CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
6530214b3aaSjsing 			if (alg1 == NULL || alg1->algorithm == NULL)
6540214b3aaSjsing 				return -1;
6550214b3aaSjsing 			hnid = OBJ_obj2nid(alg1->algorithm);
6560214b3aaSjsing 			if (hnid == NID_undef)
6570214b3aaSjsing 				return -1;
6580214b3aaSjsing 			if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
6590214b3aaSjsing 				return -1;
660*d5a216b5Stb 			if (!X509_ALGOR_set0_by_nid(alg2, snid, V_ASN1_UNDEF,
661*d5a216b5Stb 			    NULL))
662*d5a216b5Stb 				return -1;
6630214b3aaSjsing 		}
6640214b3aaSjsing 		return 1;
6650214b3aaSjsing 
6660214b3aaSjsing 	case ASN1_PKEY_CTRL_CMS_RI_TYPE:
6670214b3aaSjsing 		*(int *)arg2 = CMS_RECIPINFO_NONE;
6680214b3aaSjsing 		return 1;
6690214b3aaSjsing #endif
6700214b3aaSjsing 
671f1535dc8Sdjm 	case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
672f1535dc8Sdjm 		*(int *)arg2 = NID_sha1;
673f1535dc8Sdjm 		return 2;
674f1535dc8Sdjm 
675f1535dc8Sdjm 	default:
676f1535dc8Sdjm 		return -2;
677f1535dc8Sdjm 	}
678f1535dc8Sdjm }
679f1535dc8Sdjm 
680fa20815cStb const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
6819ed721ecStb 	.base_method = &dsa_asn1_meth,
682e402ce74Smiod 	.pkey_id = EVP_PKEY_DSA,
683f1535dc8Sdjm 
684e402ce74Smiod 	.pem_str = "DSA",
685e402ce74Smiod 	.info = "OpenSSL DSA method",
686f1535dc8Sdjm 
687e402ce74Smiod 	.pub_decode = dsa_pub_decode,
688e402ce74Smiod 	.pub_encode = dsa_pub_encode,
689e402ce74Smiod 	.pub_cmp = dsa_pub_cmp,
690e402ce74Smiod 	.pub_print = dsa_pub_print,
691f1535dc8Sdjm 
692e402ce74Smiod 	.priv_decode = dsa_priv_decode,
693e402ce74Smiod 	.priv_encode = dsa_priv_encode,
694e402ce74Smiod 	.priv_print = dsa_priv_print,
695f1535dc8Sdjm 
6967244e844Stb 	.pkey_size = dsa_size,
697e402ce74Smiod 	.pkey_bits = dsa_bits,
6985cdf0398Stb 	.pkey_security_bits = dsa_security_bits,
699f1535dc8Sdjm 
700e402ce74Smiod 	.param_decode = dsa_param_decode,
701e402ce74Smiod 	.param_encode = dsa_param_encode,
702e402ce74Smiod 	.param_missing = dsa_missing_parameters,
703e402ce74Smiod 	.param_copy = dsa_copy_parameters,
704e402ce74Smiod 	.param_cmp = dsa_cmp_parameters,
705e402ce74Smiod 	.param_print = dsa_param_print,
706e402ce74Smiod 	.sig_print = dsa_sig_print,
707f1535dc8Sdjm 
7087244e844Stb 	.pkey_free = dsa_free,
709e402ce74Smiod 	.pkey_ctrl = dsa_pkey_ctrl,
710e402ce74Smiod 	.old_priv_decode = old_dsa_priv_decode,
711e402ce74Smiod 	.old_priv_encode = old_dsa_priv_encode
712fa20815cStb };
713fa20815cStb 
714fa20815cStb const EVP_PKEY_ASN1_METHOD dsa1_asn1_meth = {
7159ed721ecStb 	.base_method = &dsa_asn1_meth,
716fa20815cStb 	.pkey_id = EVP_PKEY_DSA1,
717fa20815cStb 	.pkey_flags = ASN1_PKEY_ALIAS,
718fa20815cStb };
719fa20815cStb 
720fa20815cStb const EVP_PKEY_ASN1_METHOD dsa2_asn1_meth = {
7219ed721ecStb 	.base_method = &dsa_asn1_meth,
722fa20815cStb 	.pkey_id = EVP_PKEY_DSA2,
723fa20815cStb 	.pkey_flags = ASN1_PKEY_ALIAS,
724fa20815cStb };
725fa20815cStb 
726fa20815cStb const EVP_PKEY_ASN1_METHOD dsa3_asn1_meth = {
7279ed721ecStb 	.base_method = &dsa_asn1_meth,
728fa20815cStb 	.pkey_id = EVP_PKEY_DSA3,
729fa20815cStb 	.pkey_flags = ASN1_PKEY_ALIAS,
730fa20815cStb };
731fa20815cStb 
732fa20815cStb const EVP_PKEY_ASN1_METHOD dsa4_asn1_meth = {
7339ed721ecStb 	.base_method = &dsa_asn1_meth,
734fa20815cStb 	.pkey_id = EVP_PKEY_DSA4,
735fa20815cStb 	.pkey_flags = ASN1_PKEY_ALIAS,
736f1535dc8Sdjm };
737