xref: /openbsd/lib/libcrypto/dsa/dsa_ossl.c (revision 4bdff4be)
1 /* $OpenBSD: dsa_ossl.c,v 1.53 2023/08/03 18:53:55 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/asn1.h>
64 #include <openssl/bn.h>
65 #include <openssl/dsa.h>
66 #include <openssl/err.h>
67 #include <openssl/sha.h>
68 
69 #include "bn_local.h"
70 #include "dsa_local.h"
71 
72 static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
73 static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
74     BIGNUM **rp);
75 static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
76     DSA *dsa);
77 static int dsa_init(DSA *dsa);
78 static int dsa_finish(DSA *dsa);
79 
80 static DSA_METHOD openssl_dsa_meth = {
81 	.name = "OpenSSL DSA method",
82 	.dsa_do_sign = dsa_do_sign,
83 	.dsa_sign_setup = dsa_sign_setup,
84 	.dsa_do_verify = dsa_do_verify,
85 	.init = dsa_init,
86 	.finish = dsa_finish,
87 };
88 
89 const DSA_METHOD *
90 DSA_OpenSSL(void)
91 {
92 	return &openssl_dsa_meth;
93 }
94 LCRYPTO_ALIAS(DSA_OpenSSL);
95 
96 /*
97  * Since DSA parameters are entirely arbitrary and checking them to be
98  * consistent is very expensive, we cannot do so on every sign operation.
99  * Instead, cap the number of retries so we do not loop indefinitely if
100  * the generator of the multiplicative group happens to be nilpotent.
101  * The probability of needing a retry with valid parameters is negligible,
102  * so trying 32 times is amply enough.
103  */
104 #define DSA_MAX_SIGN_ITERATIONS		32
105 
106 static DSA_SIG *
107 dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
108 {
109 	BIGNUM *b = NULL, *bm = NULL, *bxr = NULL, *binv = NULL, *m = NULL;
110 	BIGNUM *kinv = NULL, *r = NULL, *s = NULL;
111 	BN_CTX *ctx = NULL;
112 	int reason = ERR_R_BN_LIB;
113 	DSA_SIG *ret = NULL;
114 	int attempts = 0;
115 	int noredo = 0;
116 
117 	if (!dsa_check_key(dsa)) {
118 		reason = DSA_R_INVALID_PARAMETERS;
119 		goto err;
120 	}
121 
122 	if ((s = BN_new()) == NULL)
123 		goto err;
124 
125 	if ((ctx = BN_CTX_new()) == NULL)
126 		goto err;
127 
128 	BN_CTX_start(ctx);
129 
130 	if ((b = BN_CTX_get(ctx)) == NULL)
131 		goto err;
132 	if ((binv = BN_CTX_get(ctx)) == NULL)
133 		goto err;
134 	if ((bm = BN_CTX_get(ctx)) == NULL)
135 		goto err;
136 	if ((bxr = BN_CTX_get(ctx)) == NULL)
137 		goto err;
138 	if ((m = BN_CTX_get(ctx)) == NULL)
139 		goto err;
140 
141 	/*
142 	 * If the digest length is greater than N (the bit length of q), the
143 	 * leftmost N bits of the digest shall be used, see FIPS 186-3, 4.2.
144 	 * In this case the digest length is given in bytes.
145 	 */
146 	if (dlen > BN_num_bytes(dsa->q))
147 		dlen = BN_num_bytes(dsa->q);
148 	if (BN_bin2bn(dgst, dlen, m) == NULL)
149 		goto err;
150 
151  redo:
152 	if (dsa->kinv == NULL || dsa->r == NULL) {
153 		if (!DSA_sign_setup(dsa, ctx, &kinv, &r))
154 			goto err;
155 	} else {
156 		kinv = dsa->kinv;
157 		dsa->kinv = NULL;
158 		r = dsa->r;
159 		dsa->r = NULL;
160 		noredo = 1;
161 	}
162 
163 	/*
164 	 * Compute:
165 	 *
166 	 *  s = inv(k)(m + xr) mod q
167 	 *
168 	 * In order to reduce the possibility of a side-channel attack, the
169 	 * following is calculated using a blinding value:
170 	 *
171 	 *  s = inv(b)(bm + bxr)inv(k) mod q
172 	 *
173 	 * Where b is a random value in the range [1, q).
174 	 */
175 	if (!bn_rand_interval(b, 1, dsa->q))
176 		goto err;
177 	if (BN_mod_inverse_ct(binv, b, dsa->q, ctx) == NULL)
178 		goto err;
179 
180 	if (!BN_mod_mul(bxr, b, dsa->priv_key, dsa->q, ctx))	/* bx */
181 		goto err;
182 	if (!BN_mod_mul(bxr, bxr, r, dsa->q, ctx))	/* bxr */
183 		goto err;
184 	if (!BN_mod_mul(bm, b, m, dsa->q, ctx))		/* bm */
185 		goto err;
186 	if (!BN_mod_add(s, bxr, bm, dsa->q, ctx))	/* s = bm + bxr */
187 		goto err;
188 	if (!BN_mod_mul(s, s, kinv, dsa->q, ctx))	/* s = b(m + xr)k^-1 */
189 		goto err;
190 	if (!BN_mod_mul(s, s, binv, dsa->q, ctx))	/* s = (m + xr)k^-1 */
191 		goto err;
192 
193 	/*
194 	 * Redo if r or s is zero as required by FIPS 186-3: this is very
195 	 * unlikely.
196 	 */
197 	if (BN_is_zero(r) || BN_is_zero(s)) {
198 		if (noredo) {
199 			reason = DSA_R_NEED_NEW_SETUP_VALUES;
200 			goto err;
201 		}
202 		if (++attempts > DSA_MAX_SIGN_ITERATIONS) {
203 			reason = DSA_R_INVALID_PARAMETERS;
204 			goto err;
205 		}
206 		goto redo;
207 	}
208 
209 	if ((ret = DSA_SIG_new()) == NULL) {
210 		reason = ERR_R_MALLOC_FAILURE;
211 		goto err;
212 	}
213 	ret->r = r;
214 	ret->s = s;
215 
216  err:
217 	if (!ret) {
218 		DSAerror(reason);
219 		BN_free(r);
220 		BN_free(s);
221 	}
222 	BN_CTX_end(ctx);
223 	BN_CTX_free(ctx);
224 	BN_free(kinv);
225 
226 	return ret;
227 }
228 
229 static int
230 dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
231 {
232 	BIGNUM *k = NULL, *l = NULL, *m = NULL, *kinv = NULL, *r = NULL;
233 	BN_CTX *ctx = NULL;
234 	int q_bits;
235 	int ret = 0;
236 
237 	if (!dsa_check_key(dsa))
238 		goto err;
239 
240 	if ((r = BN_new()) == NULL)
241 		goto err;
242 
243 	if ((ctx = ctx_in) == NULL)
244 		ctx = BN_CTX_new();
245 	if (ctx == NULL)
246 		goto err;
247 
248 	BN_CTX_start(ctx);
249 
250 	if ((k = BN_CTX_get(ctx)) == NULL)
251 		goto err;
252 	if ((l = BN_CTX_get(ctx)) == NULL)
253 		goto err;
254 	if ((m = BN_CTX_get(ctx)) == NULL)
255 		goto err;
256 
257 	/* Preallocate space */
258 	q_bits = BN_num_bits(dsa->q);
259 	if (!BN_set_bit(k, q_bits) ||
260 	    !BN_set_bit(l, q_bits) ||
261 	    !BN_set_bit(m, q_bits))
262 		goto err;
263 
264 	if (!bn_rand_interval(k, 1, dsa->q))
265 		goto err;
266 
267 	BN_set_flags(k, BN_FLG_CONSTTIME);
268 
269 	if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
270 		if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p,
271 		    CRYPTO_LOCK_DSA, dsa->p, ctx))
272 			goto err;
273 	}
274 
275 	/* Compute r = (g^k mod p) mod q */
276 
277 	/*
278 	 * We do not want timing information to leak the length of k,
279 	 * so we compute G^k using an equivalent exponent of fixed
280 	 * bit-length.
281 	 *
282 	 * We unconditionally perform both of these additions to prevent a
283 	 * small timing information leakage.  We then choose the sum that is
284 	 * one bit longer than the modulus.
285 	 *
286 	 * TODO: revisit the bn_copy aiming for a memory access agnostic
287 	 * conditional copy.
288 	 */
289 
290 	if (!BN_add(l, k, dsa->q) ||
291 	    !BN_add(m, l, dsa->q) ||
292 	    !bn_copy(k, BN_num_bits(l) > q_bits ? l : m))
293 		goto err;
294 
295 	if (dsa->meth->bn_mod_exp != NULL) {
296 		if (!dsa->meth->bn_mod_exp(dsa, r, dsa->g, k, dsa->p, ctx,
297 		    dsa->method_mont_p))
298 			goto err;
299 	} else {
300 		if (!BN_mod_exp_mont_ct(r, dsa->g, k, dsa->p, ctx,
301 		    dsa->method_mont_p))
302 			goto err;
303 	}
304 
305 	if (!BN_mod_ct(r, r, dsa->q, ctx))
306 		goto err;
307 
308 	/* Compute  part of 's = inv(k) (m + xr) mod q' */
309 	if ((kinv = BN_mod_inverse_ct(NULL, k, dsa->q, ctx)) == NULL)
310 		goto err;
311 
312 	BN_free(*kinvp);
313 	*kinvp = kinv;
314 	kinv = NULL;
315 
316 	BN_free(*rp);
317 	*rp = r;
318 
319 	ret = 1;
320 
321  err:
322 	if (!ret) {
323 		DSAerror(ERR_R_BN_LIB);
324 		BN_free(r);
325 	}
326 	BN_CTX_end(ctx);
327 	if (ctx != ctx_in)
328 		BN_CTX_free(ctx);
329 
330 	return ret;
331 }
332 
333 static int
334 dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa)
335 {
336 	BIGNUM *u1 = NULL, *u2 = NULL, *t1 = NULL;
337 	BN_CTX *ctx = NULL;
338 	BN_MONT_CTX *mont = NULL;
339 	int qbits;
340 	int ret = -1;
341 
342 	if (!dsa_check_key(dsa))
343 		goto err;
344 
345 	if ((ctx = BN_CTX_new()) == NULL)
346 		goto err;
347 
348 	BN_CTX_start(ctx);
349 
350 	if ((u1 = BN_CTX_get(ctx)) == NULL)
351 		goto err;
352 	if ((u2 = BN_CTX_get(ctx)) == NULL)
353 		goto err;
354 	if ((t1 = BN_CTX_get(ctx)) == NULL)
355 		goto err;
356 
357 	if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
358 	    BN_ucmp(sig->r, dsa->q) >= 0) {
359 		ret = 0;
360 		goto err;
361 	}
362 	if (BN_is_zero(sig->s) || BN_is_negative(sig->s) ||
363 	    BN_ucmp(sig->s, dsa->q) >= 0) {
364 		ret = 0;
365 		goto err;
366 	}
367 
368 	/* Calculate w = inv(s) mod q, saving w in u2. */
369 	if ((BN_mod_inverse_ct(u2, sig->s, dsa->q, ctx)) == NULL)
370 		goto err;
371 
372 	/*
373 	 * If the digest length is greater than the size of q use the
374 	 * BN_num_bits(dsa->q) leftmost bits of the digest, see FIPS 186-4, 4.2.
375 	 */
376 	qbits = BN_num_bits(dsa->q);
377 	if (dgst_len > (qbits >> 3))
378 		dgst_len = (qbits >> 3);
379 
380 	/* Save m in u1. */
381 	if (BN_bin2bn(dgst, dgst_len, u1) == NULL)
382 		goto err;
383 
384 	/* u1 = m * w mod q */
385 	if (!BN_mod_mul(u1, u1, u2, dsa->q, ctx))
386 		goto err;
387 
388 	/* u2 = r * w mod q */
389 	if (!BN_mod_mul(u2, sig->r, u2, dsa->q, ctx))
390 		goto err;
391 
392 	if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
393 		mont = BN_MONT_CTX_set_locked(&dsa->method_mont_p,
394 		    CRYPTO_LOCK_DSA, dsa->p, ctx);
395 		if (!mont)
396 			goto err;
397 	}
398 
399 	if (dsa->meth->dsa_mod_exp != NULL) {
400 		if (!dsa->meth->dsa_mod_exp(dsa, t1, dsa->g, u1, dsa->pub_key,
401 		    u2, dsa->p, ctx, mont))
402 			goto err;
403 	} else {
404 		if (!BN_mod_exp2_mont(t1, dsa->g, u1, dsa->pub_key, u2,
405 		    dsa->p, ctx, mont))
406 			goto err;
407 	}
408 
409 	/* let u1 = u1 mod q */
410 	if (!BN_mod_ct(u1, t1, dsa->q, ctx))
411 		goto err;
412 
413 	/* v is in u1 - if the signature is correct, it will be equal to r. */
414 	ret = BN_ucmp(u1, sig->r) == 0;
415 
416  err:
417 	if (ret < 0)
418 		DSAerror(ERR_R_BN_LIB);
419 	BN_CTX_end(ctx);
420 	BN_CTX_free(ctx);
421 
422 	return ret;
423 }
424 
425 static int
426 dsa_init(DSA *dsa)
427 {
428 	dsa->flags |= DSA_FLAG_CACHE_MONT_P;
429 	return 1;
430 }
431 
432 static int
433 dsa_finish(DSA *dsa)
434 {
435 	BN_MONT_CTX_free(dsa->method_mont_p);
436 	return 1;
437 }
438 
439 DSA_SIG *
440 DSA_SIG_new(void)
441 {
442 	return calloc(1, sizeof(DSA_SIG));
443 }
444 LCRYPTO_ALIAS(DSA_SIG_new);
445 
446 void
447 DSA_SIG_free(DSA_SIG *sig)
448 {
449 	if (sig == NULL)
450 		return;
451 
452 	BN_free(sig->r);
453 	BN_free(sig->s);
454 	free(sig);
455 }
456 LCRYPTO_ALIAS(DSA_SIG_free);
457 
458 int
459 DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
460 {
461 	return dsa->meth->dsa_sign_setup(dsa, ctx_in, kinvp, rp);
462 }
463 LCRYPTO_ALIAS(DSA_sign_setup);
464 
465 DSA_SIG *
466 DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
467 {
468 	return dsa->meth->dsa_do_sign(dgst, dlen, dsa);
469 }
470 LCRYPTO_ALIAS(DSA_do_sign);
471 
472 int
473 DSA_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa)
474 {
475 	return dsa->meth->dsa_do_verify(dgst, dgst_len, sig, dsa);
476 }
477 LCRYPTO_ALIAS(DSA_do_verify);
478