xref: /openbsd-src/lib/libcrypto/dsa/dsa_lib.c (revision 810390e339a5425391477d5d41c78d7cab2424ac)
1 /* $OpenBSD: dsa_lib.c,v 1.46 2023/11/29 21:35:57 tb Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 /* Original version from Steven Schoch <schoch@sheba.arc.nasa.gov> */
60 
61 #include <stdio.h>
62 
63 #include <openssl/opensslconf.h>
64 
65 #include <openssl/asn1.h>
66 #include <openssl/bn.h>
67 #include <openssl/dsa.h>
68 #include <openssl/err.h>
69 
70 #ifndef OPENSSL_NO_DH
71 #include <openssl/dh.h>
72 #endif
73 
74 #include "dh_local.h"
75 #include "dsa_local.h"
76 
77 static const DSA_METHOD *default_DSA_method = NULL;
78 
79 void
80 DSA_set_default_method(const DSA_METHOD *meth)
81 {
82 	default_DSA_method = meth;
83 }
84 LCRYPTO_ALIAS(DSA_set_default_method);
85 
86 const DSA_METHOD *
87 DSA_get_default_method(void)
88 {
89 	if (!default_DSA_method)
90 		default_DSA_method = DSA_OpenSSL();
91 	return default_DSA_method;
92 }
93 LCRYPTO_ALIAS(DSA_get_default_method);
94 
95 DSA *
96 DSA_new(void)
97 {
98 	return DSA_new_method(NULL);
99 }
100 LCRYPTO_ALIAS(DSA_new);
101 
102 int
103 DSA_set_method(DSA *dsa, const DSA_METHOD *meth)
104 {
105 	/*
106 	 * NB: The caller is specifically setting a method, so it's not up to us
107 	 * to deal with which ENGINE it comes from.
108 	 */
109 	const DSA_METHOD *mtmp;
110 	mtmp = dsa->meth;
111 	if (mtmp->finish)
112 		mtmp->finish(dsa);
113 	dsa->meth = meth;
114 	if (meth->init)
115 		meth->init(dsa);
116 	return 1;
117 }
118 LCRYPTO_ALIAS(DSA_set_method);
119 
120 DSA *
121 DSA_new_method(ENGINE *engine)
122 {
123 	DSA *dsa;
124 
125 	if ((dsa = calloc(1, sizeof(DSA))) == NULL) {
126 		DSAerror(ERR_R_MALLOC_FAILURE);
127 		goto err;
128 	}
129 
130 	dsa->meth = DSA_get_default_method();
131 	dsa->flags = dsa->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW;
132 	dsa->references = 1;
133 
134 	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data))
135 		goto err;
136 	if (dsa->meth->init != NULL && !dsa->meth->init(dsa))
137 		goto err;
138 
139 	return dsa;
140 
141  err:
142 	DSA_free(dsa);
143 
144 	return NULL;
145 }
146 LCRYPTO_ALIAS(DSA_new_method);
147 
148 void
149 DSA_free(DSA *r)
150 {
151 	int i;
152 
153 	if (r == NULL)
154 		return;
155 
156 	i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_DSA);
157 	if (i > 0)
158 		return;
159 
160 	if (r->meth != NULL && r->meth->finish != NULL)
161 		r->meth->finish(r);
162 
163 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, r, &r->ex_data);
164 
165 	BN_free(r->p);
166 	BN_free(r->q);
167 	BN_free(r->g);
168 	BN_free(r->pub_key);
169 	BN_free(r->priv_key);
170 	BN_free(r->kinv);
171 	BN_free(r->r);
172 	free(r);
173 }
174 LCRYPTO_ALIAS(DSA_free);
175 
176 int
177 DSA_up_ref(DSA *r)
178 {
179 	int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_DSA);
180 	return i > 1 ? 1 : 0;
181 }
182 LCRYPTO_ALIAS(DSA_up_ref);
183 
184 int
185 DSA_size(const DSA *r)
186 {
187 	DSA_SIG signature;
188 	int ret = 0;
189 
190 	signature.r = r->q;
191 	signature.s = r->q;
192 
193 	if ((ret = i2d_DSA_SIG(&signature, NULL)) < 0)
194 		ret = 0;
195 
196 	return ret;
197 }
198 LCRYPTO_ALIAS(DSA_size);
199 
200 int
201 DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
202     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
203 {
204 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, argl, argp,
205 	    new_func, dup_func, free_func);
206 }
207 LCRYPTO_ALIAS(DSA_get_ex_new_index);
208 
209 int
210 DSA_set_ex_data(DSA *d, int idx, void *arg)
211 {
212 	return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
213 }
214 LCRYPTO_ALIAS(DSA_set_ex_data);
215 
216 void *
217 DSA_get_ex_data(DSA *d, int idx)
218 {
219 	return CRYPTO_get_ex_data(&d->ex_data, idx);
220 }
221 LCRYPTO_ALIAS(DSA_get_ex_data);
222 
223 int
224 DSA_security_bits(const DSA *d)
225 {
226 	if (d->p == NULL || d->q == NULL)
227 		return -1;
228 
229 	return BN_security_bits(BN_num_bits(d->p), BN_num_bits(d->q));
230 }
231 LCRYPTO_ALIAS(DSA_security_bits);
232 
233 #ifndef OPENSSL_NO_DH
234 DH *
235 DSA_dup_DH(const DSA *r)
236 {
237 	/*
238 	 * DSA has p, q, g, optional pub_key, optional priv_key.
239 	 * DH has p, optional length, g, optional pub_key, optional priv_key,
240 	 * optional q.
241 	 */
242 	DH *ret = NULL;
243 
244 	if (r == NULL)
245 		goto err;
246 	ret = DH_new();
247 	if (ret == NULL)
248 		goto err;
249 	if (r->p != NULL)
250 		if ((ret->p = BN_dup(r->p)) == NULL)
251 			goto err;
252 	if (r->q != NULL) {
253 		ret->length = BN_num_bits(r->q);
254 		if ((ret->q = BN_dup(r->q)) == NULL)
255 			goto err;
256 	}
257 	if (r->g != NULL)
258 		if ((ret->g = BN_dup(r->g)) == NULL)
259 			goto err;
260 	if (r->pub_key != NULL)
261 		if ((ret->pub_key = BN_dup(r->pub_key)) == NULL)
262 			goto err;
263 	if (r->priv_key != NULL)
264 		if ((ret->priv_key = BN_dup(r->priv_key)) == NULL)
265 			goto err;
266 
267 	return ret;
268 
269 err:
270 	DH_free(ret);
271 	return NULL;
272 }
273 LCRYPTO_ALIAS(DSA_dup_DH);
274 #endif
275 
276 void
277 DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
278 {
279 	if (p != NULL)
280 		*p = d->p;
281 	if (q != NULL)
282 		*q = d->q;
283 	if (g != NULL)
284 		*g = d->g;
285 }
286 LCRYPTO_ALIAS(DSA_get0_pqg);
287 
288 int
289 DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
290 {
291 	if ((d->p == NULL && p == NULL) || (d->q == NULL && q == NULL) ||
292 	    (d->g == NULL && g == NULL))
293 		return 0;
294 
295 	if (p != NULL) {
296 		BN_free(d->p);
297 		d->p = p;
298 	}
299 	if (q != NULL) {
300 		BN_free(d->q);
301 		d->q = q;
302 	}
303 	if (g != NULL) {
304 		BN_free(d->g);
305 		d->g = g;
306 	}
307 
308 	return 1;
309 }
310 LCRYPTO_ALIAS(DSA_set0_pqg);
311 
312 void
313 DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key)
314 {
315 	if (pub_key != NULL)
316 		*pub_key = d->pub_key;
317 	if (priv_key != NULL)
318 		*priv_key = d->priv_key;
319 }
320 LCRYPTO_ALIAS(DSA_get0_key);
321 
322 int
323 DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
324 {
325 	if (d->pub_key == NULL && pub_key == NULL)
326 		return 0;
327 
328 	if (pub_key != NULL) {
329 		BN_free(d->pub_key);
330 		d->pub_key = pub_key;
331 	}
332 	if (priv_key != NULL) {
333 		BN_free(d->priv_key);
334 		d->priv_key = priv_key;
335 	}
336 
337 	return 1;
338 }
339 LCRYPTO_ALIAS(DSA_set0_key);
340 
341 const BIGNUM *
342 DSA_get0_p(const DSA *d)
343 {
344 	return d->p;
345 }
346 LCRYPTO_ALIAS(DSA_get0_p);
347 
348 const BIGNUM *
349 DSA_get0_q(const DSA *d)
350 {
351 	return d->q;
352 }
353 LCRYPTO_ALIAS(DSA_get0_q);
354 
355 const BIGNUM *
356 DSA_get0_g(const DSA *d)
357 {
358 	return d->g;
359 }
360 LCRYPTO_ALIAS(DSA_get0_g);
361 
362 const BIGNUM *
363 DSA_get0_pub_key(const DSA *d)
364 {
365 	return d->pub_key;
366 }
367 LCRYPTO_ALIAS(DSA_get0_pub_key);
368 
369 const BIGNUM *
370 DSA_get0_priv_key(const DSA *d)
371 {
372 	return d->priv_key;
373 }
374 LCRYPTO_ALIAS(DSA_get0_priv_key);
375 
376 void
377 DSA_clear_flags(DSA *d, int flags)
378 {
379 	d->flags &= ~flags;
380 }
381 LCRYPTO_ALIAS(DSA_clear_flags);
382 
383 int
384 DSA_test_flags(const DSA *d, int flags)
385 {
386 	return d->flags & flags;
387 }
388 LCRYPTO_ALIAS(DSA_test_flags);
389 
390 void
391 DSA_set_flags(DSA *d, int flags)
392 {
393 	d->flags |= flags;
394 }
395 LCRYPTO_ALIAS(DSA_set_flags);
396 
397 ENGINE *
398 DSA_get0_engine(DSA *d)
399 {
400 	return NULL;
401 }
402 LCRYPTO_ALIAS(DSA_get0_engine);
403 
404 int
405 DSA_bits(const DSA *dsa)
406 {
407 	return BN_num_bits(dsa->p);
408 }
409 LCRYPTO_ALIAS(DSA_bits);
410 
411 int
412 dsa_check_key(const DSA *dsa)
413 {
414 	int p_bits, q_bits;
415 
416 	if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
417 		DSAerror(DSA_R_MISSING_PARAMETERS);
418 		return 0;
419 	}
420 
421 	/* Checking that p and q are primes is expensive. Check they are odd. */
422 	if (!BN_is_odd(dsa->p) || !BN_is_odd(dsa->q)) {
423 		DSAerror(DSA_R_INVALID_PARAMETERS);
424 		return 0;
425 	}
426 
427 	/* FIPS 186-4: 1 < g < p. */
428 	if (BN_cmp(dsa->g, BN_value_one()) <= 0 ||
429 	    BN_cmp(dsa->g, dsa->p) >= 0) {
430 		DSAerror(DSA_R_INVALID_PARAMETERS);
431 		return 0;
432 	}
433 
434 	/* We know p and g are positive. The next two checks imply q > 0. */
435 	if (BN_is_negative(dsa->q)) {
436 		DSAerror(DSA_R_BAD_Q_VALUE);
437 		return 0;
438 	}
439 
440 	/* FIPS 186-4 only allows three sizes for q. */
441 	q_bits = BN_num_bits(dsa->q);
442 	if (q_bits != 160 && q_bits != 224 && q_bits != 256) {
443 		DSAerror(DSA_R_BAD_Q_VALUE);
444 		return 0;
445 	}
446 
447 	/*
448 	 * XXX - FIPS 186-4 only allows 1024, 2048, and 3072 bits for p.
449 	 * Cap the size to reduce DoS risks. Poor defaults make keys with
450 	 * incorrect p sizes >= 512 bits common, so only enforce a weak
451 	 * lower bound.
452 	 */
453 	p_bits = BN_num_bits(dsa->p);
454 	if (p_bits > OPENSSL_DSA_MAX_MODULUS_BITS) {
455 		DSAerror(DSA_R_MODULUS_TOO_LARGE);
456 		return 0;
457 	}
458 	if (p_bits < 512) {
459 		DSAerror(DSA_R_INVALID_PARAMETERS);
460 		return 0;
461 	}
462 
463 	/* The public key must be in the multiplicative group (mod p). */
464 	if (dsa->pub_key != NULL) {
465 		if (BN_cmp(dsa->pub_key, BN_value_one()) <= 0 ||
466 		    BN_cmp(dsa->pub_key, dsa->p) >= 0) {
467 			DSAerror(DSA_R_INVALID_PARAMETERS);
468 			return 0;
469 		}
470 	}
471 
472 	/* The private key must be nonzero and in GF(q). */
473 	if (dsa->priv_key != NULL) {
474 		if (BN_cmp(dsa->priv_key, BN_value_one()) < 0 ||
475 		    BN_cmp(dsa->priv_key, dsa->q) >= 0) {
476 			DSAerror(DSA_R_INVALID_PARAMETERS);
477 			return 0;
478 		}
479 	}
480 
481 	return 1;
482 }
483