xref: /openbsd-src/lib/libcrypto/dsa/dsa_pmeth.c (revision a5aac4c5c2beb790313ed29c491b886895baaece)
1*a5aac4c5Stb /* $OpenBSD: dsa_pmeth.c,v 1.21 2024/10/19 14:39:44 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 
59b1d57841Sderaadt #include <limits.h>
60a8913c44Sjsing #include <stdio.h>
611e10d066Sop #include <stdlib.h>
62a8913c44Sjsing #include <string.h>
63a8913c44Sjsing 
64f1535dc8Sdjm #include <openssl/asn1t.h>
65f1535dc8Sdjm #include <openssl/bn.h>
66b6ab114eSjsing #include <openssl/err.h>
67b6ab114eSjsing #include <openssl/evp.h>
68b6ab114eSjsing #include <openssl/x509.h>
69b6ab114eSjsing 
70c9675a23Stb #include "bn_local.h"
71c9675a23Stb #include "dsa_local.h"
72c9675a23Stb #include "evp_local.h"
73f1535dc8Sdjm 
74f1535dc8Sdjm /* DSA pkey context structure */
75f1535dc8Sdjm 
76e85b1b81Smiod typedef struct {
77f1535dc8Sdjm 	/* Parameter gen parameters */
78f1535dc8Sdjm 	int nbits;		/* size of p in bits (default: 1024) */
79f1535dc8Sdjm 	int qbits;		/* size of q in bits (default: 160)  */
80f1535dc8Sdjm 	const EVP_MD *pmd;	/* MD for parameter generation */
81f1535dc8Sdjm 	/* Keygen callback info */
82f1535dc8Sdjm 	int gentmp[2];
83f1535dc8Sdjm 	/* message digest */
84f1535dc8Sdjm 	const EVP_MD *md;	/* MD for the signature */
85f1535dc8Sdjm } DSA_PKEY_CTX;
86f1535dc8Sdjm 
87e85b1b81Smiod static int
88e85b1b81Smiod pkey_dsa_init(EVP_PKEY_CTX *ctx)
89f1535dc8Sdjm {
90f1535dc8Sdjm 	DSA_PKEY_CTX *dctx;
91e85b1b81Smiod 
926f3a6cb1Sbeck 	dctx = malloc(sizeof(DSA_PKEY_CTX));
93f1535dc8Sdjm 	if (!dctx)
94f1535dc8Sdjm 		return 0;
95f1535dc8Sdjm 	dctx->nbits = 1024;
96f1535dc8Sdjm 	dctx->qbits = 160;
97f1535dc8Sdjm 	dctx->pmd = NULL;
98f1535dc8Sdjm 	dctx->md = NULL;
99f1535dc8Sdjm 
100f1535dc8Sdjm 	ctx->data = dctx;
101f1535dc8Sdjm 	ctx->keygen_info = dctx->gentmp;
102f1535dc8Sdjm 	ctx->keygen_info_count = 2;
103f1535dc8Sdjm 
104f1535dc8Sdjm 	return 1;
105f1535dc8Sdjm }
106f1535dc8Sdjm 
107e85b1b81Smiod static int
108e85b1b81Smiod pkey_dsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
109f1535dc8Sdjm {
110f1535dc8Sdjm 	DSA_PKEY_CTX *dctx, *sctx;
111e85b1b81Smiod 
112f1535dc8Sdjm 	if (!pkey_dsa_init(dst))
113f1535dc8Sdjm 		return 0;
114f1535dc8Sdjm 	sctx = src->data;
115f1535dc8Sdjm 	dctx = dst->data;
116f1535dc8Sdjm 	dctx->nbits = sctx->nbits;
117f1535dc8Sdjm 	dctx->qbits = sctx->qbits;
118f1535dc8Sdjm 	dctx->pmd = sctx->pmd;
119f1535dc8Sdjm 	dctx->md  = sctx->md;
120f1535dc8Sdjm 	return 1;
121f1535dc8Sdjm }
122f1535dc8Sdjm 
123e85b1b81Smiod static void
124e85b1b81Smiod pkey_dsa_cleanup(EVP_PKEY_CTX *ctx)
125f1535dc8Sdjm {
126f1535dc8Sdjm 	DSA_PKEY_CTX *dctx = ctx->data;
127e85b1b81Smiod 
1286f3a6cb1Sbeck 	free(dctx);
129f1535dc8Sdjm }
130f1535dc8Sdjm 
131e85b1b81Smiod static int
1324a91dbbdStb pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *out_siglen,
133f1535dc8Sdjm     const unsigned char *tbs, size_t tbslen)
134f1535dc8Sdjm {
135f1535dc8Sdjm 	DSA *dsa = ctx->pkey->pkey.dsa;
1364a91dbbdStb 	DSA_PKEY_CTX *dctx = ctx->data;
1374a91dbbdStb 	unsigned int siglen;
138f1535dc8Sdjm 
1394a91dbbdStb 	*out_siglen = 0;
140f1535dc8Sdjm 
1414a91dbbdStb 	if (tbslen > INT_MAX)
1424a91dbbdStb 		 return 0;
143f1535dc8Sdjm 
1444a91dbbdStb 	if (dctx->md != NULL) {
1454a91dbbdStb 		if (tbslen != EVP_MD_size(dctx->md))
1464a91dbbdStb 			return 0;
1474a91dbbdStb 	}
1484a91dbbdStb 
1494a91dbbdStb 	if (!DSA_sign(0, tbs, tbslen, sig, &siglen, dsa))
1504a91dbbdStb 		return 0;
1514a91dbbdStb 
1524a91dbbdStb 	*out_siglen = siglen;
1534a91dbbdStb 
154f1535dc8Sdjm 	return 1;
155f1535dc8Sdjm }
156f1535dc8Sdjm 
157e85b1b81Smiod static int
158e85b1b81Smiod pkey_dsa_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
159f1535dc8Sdjm     const unsigned char *tbs, size_t tbslen)
160f1535dc8Sdjm {
161f1535dc8Sdjm 	DSA *dsa = ctx->pkey->pkey.dsa;
1624a91dbbdStb 	DSA_PKEY_CTX *dctx = ctx->data;
163f1535dc8Sdjm 
1644a91dbbdStb 	if (tbslen > INT_MAX || siglen > INT_MAX)
1654a91dbbdStb 		 return 0;
166f1535dc8Sdjm 
1674a91dbbdStb 	if (dctx->md != NULL) {
1684a91dbbdStb 		if (tbslen != EVP_MD_size(dctx->md))
1694a91dbbdStb 			return 0;
1704a91dbbdStb 	}
171f1535dc8Sdjm 
1724a91dbbdStb 	return DSA_verify(0, tbs, tbslen, sig, siglen, dsa);
173f1535dc8Sdjm }
174f1535dc8Sdjm 
175e85b1b81Smiod static int
176e85b1b81Smiod pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
177f1535dc8Sdjm {
178f1535dc8Sdjm 	DSA_PKEY_CTX *dctx = ctx->data;
179e85b1b81Smiod 
180e85b1b81Smiod 	switch (type) {
181f1535dc8Sdjm 	case EVP_PKEY_CTRL_DSA_PARAMGEN_BITS:
182f1535dc8Sdjm 		if (p1 < 256)
183f1535dc8Sdjm 			return -2;
184f1535dc8Sdjm 		dctx->nbits = p1;
185f1535dc8Sdjm 		return 1;
186f1535dc8Sdjm 
187f1535dc8Sdjm 	case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS:
188f1535dc8Sdjm 		if (p1 != 160 && p1 != 224 && p1 && p1 != 256)
189f1535dc8Sdjm 			return -2;
190f1535dc8Sdjm 		dctx->qbits = p1;
191f1535dc8Sdjm 		return 1;
192f1535dc8Sdjm 
193f1535dc8Sdjm 	case EVP_PKEY_CTRL_DSA_PARAMGEN_MD:
1941da6504fSmiod 		switch (EVP_MD_type((const EVP_MD *)p2)) {
1951da6504fSmiod 		case NID_sha1:
1961da6504fSmiod 		case NID_sha224:
1971da6504fSmiod 		case NID_sha256:
1981da6504fSmiod 			break;
1991da6504fSmiod 		default:
2005067ae9fSbeck 			DSAerror(DSA_R_INVALID_DIGEST_TYPE);
201f1535dc8Sdjm 			return 0;
202f1535dc8Sdjm 		}
203f1535dc8Sdjm 		dctx->md = p2;
204f1535dc8Sdjm 		return 1;
205f1535dc8Sdjm 
206f1535dc8Sdjm 	case EVP_PKEY_CTRL_MD:
2079a5a6ad9Stb 		/* ANSI X9.57 and NIST CSOR. */
208*a5aac4c5Stb 		switch (EVP_MD_type(p2)) {
2091da6504fSmiod 		case NID_sha1:
2101da6504fSmiod 		case NID_dsa:
2111da6504fSmiod 		case NID_dsaWithSHA:
2121da6504fSmiod 		case NID_sha224:
2131da6504fSmiod 		case NID_sha256:
2141da6504fSmiod 		case NID_sha384:
2151da6504fSmiod 		case NID_sha512:
2169a5a6ad9Stb 		case NID_sha3_224:
2179a5a6ad9Stb 		case NID_sha3_256:
2189a5a6ad9Stb 		case NID_sha3_384:
2199a5a6ad9Stb 		case NID_sha3_512:
2201da6504fSmiod 			break;
2211da6504fSmiod 		default:
2225067ae9fSbeck 			DSAerror(DSA_R_INVALID_DIGEST_TYPE);
223f1535dc8Sdjm 			return 0;
224f1535dc8Sdjm 		}
225f1535dc8Sdjm 		dctx->md = p2;
226f1535dc8Sdjm 		return 1;
227f1535dc8Sdjm 
2286627381bSjsing 	case EVP_PKEY_CTRL_GET_MD:
2296627381bSjsing 		*(const EVP_MD **)p2 = dctx->md;
2306627381bSjsing 		return 1;
2316627381bSjsing 
232f1535dc8Sdjm 	case EVP_PKEY_CTRL_DIGESTINIT:
233f1535dc8Sdjm 	case EVP_PKEY_CTRL_PKCS7_SIGN:
234f1535dc8Sdjm 	case EVP_PKEY_CTRL_CMS_SIGN:
235f1535dc8Sdjm 		return 1;
236f1535dc8Sdjm 
237f1535dc8Sdjm 	case EVP_PKEY_CTRL_PEER_KEY:
2385067ae9fSbeck 		DSAerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
239f1535dc8Sdjm 		return -2;
240f1535dc8Sdjm 	default:
241f1535dc8Sdjm 		return -2;
242f1535dc8Sdjm 	}
243f1535dc8Sdjm }
244f1535dc8Sdjm 
245e85b1b81Smiod static int
246e85b1b81Smiod pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
247f1535dc8Sdjm {
2481e10d066Sop 	const char *errstr;
249b1d57841Sderaadt 
250b1d57841Sderaadt 	if (!strcmp(type, "dsa_paramgen_bits")) {
251f1535dc8Sdjm 		int nbits;
252b1d57841Sderaadt 
2531e10d066Sop 		nbits = strtonum(value, INT_MIN, INT_MAX, &errstr);
2541e10d066Sop 		if (errstr != NULL)
2551e10d066Sop 			return -2;
256f1535dc8Sdjm 		return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits);
257e85b1b81Smiod 	} else if (!strcmp(type, "dsa_paramgen_q_bits")) {
258b1d57841Sderaadt 		int qbits;
259b1d57841Sderaadt 
2601e10d066Sop 		qbits = strtonum(value, INT_MIN, INT_MAX, &errstr);
2611e10d066Sop 		if (errstr != NULL)
2621e10d066Sop 			return -2;
263e85b1b81Smiod 		return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA,
264e85b1b81Smiod 		    EVP_PKEY_OP_PARAMGEN, EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS,
265e85b1b81Smiod 		    qbits, NULL);
266e85b1b81Smiod 	} else if (!strcmp(type, "dsa_paramgen_md")) {
267e85b1b81Smiod 		return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA,
268e85b1b81Smiod 		    EVP_PKEY_OP_PARAMGEN, EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0,
269f1535dc8Sdjm 		    (void *)EVP_get_digestbyname(value));
270f1535dc8Sdjm 	}
2711e10d066Sop 
272f1535dc8Sdjm 	return -2;
273f1535dc8Sdjm }
274f1535dc8Sdjm 
275e85b1b81Smiod static int
276e85b1b81Smiod pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
277f1535dc8Sdjm {
27891192740Stb 	DSA *dsa;
279f1535dc8Sdjm 	DSA_PKEY_CTX *dctx = ctx->data;
28091192740Stb 	BN_GENCB *pcb = NULL;
28191192740Stb 	BN_GENCB cb = {0};
28291192740Stb 	int ret = 0;
283e85b1b81Smiod 
28491192740Stb 	if ((dsa = DSA_new()) == NULL)
28591192740Stb 		goto err;
28691192740Stb 	if (ctx->pkey_gencb != NULL) {
287f1535dc8Sdjm 		pcb = &cb;
288f1535dc8Sdjm 		evp_pkey_set_cb_translate(pcb, ctx);
28991192740Stb 	}
29091192740Stb 	if (!dsa_builtin_paramgen(dsa, dctx->nbits, dctx->qbits, dctx->pmd,
29191192740Stb 	    NULL, 0, NULL, NULL, NULL, pcb))
29291192740Stb 		goto err;
29391192740Stb 	if (!EVP_PKEY_assign_DSA(pkey, dsa))
29491192740Stb 		goto err;
29591192740Stb 	dsa = NULL;
29691192740Stb 
29791192740Stb 	ret = 1;
29891192740Stb 
29991192740Stb  err:
300f1535dc8Sdjm 	DSA_free(dsa);
30191192740Stb 
302f1535dc8Sdjm 	return ret;
303f1535dc8Sdjm }
304f1535dc8Sdjm 
305e85b1b81Smiod static int
306e85b1b81Smiod pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
307f1535dc8Sdjm {
308f1535dc8Sdjm 	DSA *dsa = NULL;
309a21e6844Stb 	int ret = 0;
310e85b1b81Smiod 
311e85b1b81Smiod 	if (ctx->pkey == NULL) {
3125067ae9fSbeck 		DSAerror(DSA_R_NO_PARAMETERS_SET);
313a21e6844Stb 		goto err;
314f1535dc8Sdjm 	}
315a21e6844Stb 	if ((dsa = DSA_new()) == NULL)
316a21e6844Stb 		goto err;
317a21e6844Stb 	if (!EVP_PKEY_set1_DSA(pkey, dsa))
318a21e6844Stb 		goto err;
319a21e6844Stb 
320f1535dc8Sdjm 	if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
321a21e6844Stb 		goto err;
322a21e6844Stb 	if (!DSA_generate_key(dsa))
323a21e6844Stb 		goto err;
324a21e6844Stb 
325a21e6844Stb 	ret = 1;
326a21e6844Stb 
327a21e6844Stb  err:
328a21e6844Stb 	DSA_free(dsa);
329a21e6844Stb 
330a21e6844Stb 	return ret;
331f1535dc8Sdjm }
332f1535dc8Sdjm 
333e402ce74Smiod const EVP_PKEY_METHOD dsa_pkey_meth = {
334e402ce74Smiod 	.pkey_id = EVP_PKEY_DSA,
335e402ce74Smiod 	.flags = EVP_PKEY_FLAG_AUTOARGLEN,
336f1535dc8Sdjm 
337e402ce74Smiod 	.init = pkey_dsa_init,
338e402ce74Smiod 	.copy = pkey_dsa_copy,
339e402ce74Smiod 	.cleanup = pkey_dsa_cleanup,
340f1535dc8Sdjm 
341e402ce74Smiod 	.paramgen = pkey_dsa_paramgen,
342f1535dc8Sdjm 
343e402ce74Smiod 	.keygen = pkey_dsa_keygen,
344f1535dc8Sdjm 
345e402ce74Smiod 	.sign = pkey_dsa_sign,
346f1535dc8Sdjm 
347e402ce74Smiod 	.verify = pkey_dsa_verify,
348f1535dc8Sdjm 
349e402ce74Smiod 	.ctrl = pkey_dsa_ctrl,
350e402ce74Smiod 	.ctrl_str = pkey_dsa_ctrl_str
351f1535dc8Sdjm };
352