1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: dsa_ossl.c,v 1.44 2022/02/24 08:35:45 tb Exp $ */
2f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3f5b1c8a1SJohn Marino  * All rights reserved.
4f5b1c8a1SJohn Marino  *
5f5b1c8a1SJohn Marino  * This package is an SSL implementation written
6f5b1c8a1SJohn Marino  * by Eric Young (eay@cryptsoft.com).
7f5b1c8a1SJohn Marino  * The implementation was written so as to conform with Netscapes SSL.
8f5b1c8a1SJohn Marino  *
9f5b1c8a1SJohn Marino  * This library is free for commercial and non-commercial use as long as
10f5b1c8a1SJohn Marino  * the following conditions are aheared to.  The following conditions
11f5b1c8a1SJohn Marino  * apply to all code found in this distribution, be it the RC4, RSA,
12f5b1c8a1SJohn Marino  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13f5b1c8a1SJohn Marino  * included with this distribution is covered by the same copyright terms
14f5b1c8a1SJohn Marino  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15f5b1c8a1SJohn Marino  *
16f5b1c8a1SJohn Marino  * Copyright remains Eric Young's, and as such any Copyright notices in
17f5b1c8a1SJohn Marino  * the code are not to be removed.
18f5b1c8a1SJohn Marino  * If this package is used in a product, Eric Young should be given attribution
19f5b1c8a1SJohn Marino  * as the author of the parts of the library used.
20f5b1c8a1SJohn Marino  * This can be in the form of a textual message at program startup or
21f5b1c8a1SJohn Marino  * in documentation (online or textual) provided with the package.
22f5b1c8a1SJohn Marino  *
23f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
24f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
25f5b1c8a1SJohn Marino  * are met:
26f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the copyright
27f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
28f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
29f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
30f5b1c8a1SJohn Marino  *    documentation and/or other materials provided with the distribution.
31f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this software
32f5b1c8a1SJohn Marino  *    must display the following acknowledgement:
33f5b1c8a1SJohn Marino  *    "This product includes cryptographic software written by
34f5b1c8a1SJohn Marino  *     Eric Young (eay@cryptsoft.com)"
35f5b1c8a1SJohn Marino  *    The word 'cryptographic' can be left out if the rouines from the library
36f5b1c8a1SJohn Marino  *    being used are not cryptographic related :-).
37f5b1c8a1SJohn Marino  * 4. If you include any Windows specific code (or a derivative thereof) from
38f5b1c8a1SJohn Marino  *    the apps directory (application code) you must include an acknowledgement:
39f5b1c8a1SJohn Marino  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40f5b1c8a1SJohn Marino  *
41f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42f5b1c8a1SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44f5b1c8a1SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45f5b1c8a1SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46f5b1c8a1SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47f5b1c8a1SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49f5b1c8a1SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50f5b1c8a1SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51f5b1c8a1SJohn Marino  * SUCH DAMAGE.
52f5b1c8a1SJohn Marino  *
53f5b1c8a1SJohn Marino  * The licence and distribution terms for any publically available version or
54f5b1c8a1SJohn Marino  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55f5b1c8a1SJohn Marino  * copied and put under another distribution licence
56f5b1c8a1SJohn Marino  * [including the GNU Public Licence.]
57f5b1c8a1SJohn Marino  */
58f5b1c8a1SJohn Marino 
59f5b1c8a1SJohn Marino /* Original version from Steven Schoch <schoch@sheba.arc.nasa.gov> */
60f5b1c8a1SJohn Marino 
61f5b1c8a1SJohn Marino #include <stdio.h>
62f5b1c8a1SJohn Marino 
63f5b1c8a1SJohn Marino #include <openssl/asn1.h>
64f5b1c8a1SJohn Marino #include <openssl/bn.h>
65f5b1c8a1SJohn Marino #include <openssl/dsa.h>
66f5b1c8a1SJohn Marino #include <openssl/err.h>
67f5b1c8a1SJohn Marino #include <openssl/sha.h>
68f5b1c8a1SJohn Marino 
6972c33676SMaxim Ag #include "bn_lcl.h"
70*de0e0e4dSAntonio Huete Jimenez #include "dsa_locl.h"
7172c33676SMaxim Ag 
72f5b1c8a1SJohn Marino static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
73f5b1c8a1SJohn Marino static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
74f5b1c8a1SJohn Marino     BIGNUM **rp);
75f5b1c8a1SJohn Marino static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
76f5b1c8a1SJohn Marino     DSA *dsa);
77f5b1c8a1SJohn Marino static int dsa_init(DSA *dsa);
78f5b1c8a1SJohn Marino static int dsa_finish(DSA *dsa);
79f5b1c8a1SJohn Marino 
80f5b1c8a1SJohn Marino static DSA_METHOD openssl_dsa_meth = {
81f5b1c8a1SJohn Marino 	.name = "OpenSSL DSA method",
82f5b1c8a1SJohn Marino 	.dsa_do_sign = dsa_do_sign,
83f5b1c8a1SJohn Marino 	.dsa_sign_setup = dsa_sign_setup,
84f5b1c8a1SJohn Marino 	.dsa_do_verify = dsa_do_verify,
85f5b1c8a1SJohn Marino 	.init = dsa_init,
8672c33676SMaxim Ag 	.finish = dsa_finish,
87f5b1c8a1SJohn Marino };
88f5b1c8a1SJohn Marino 
89f5b1c8a1SJohn Marino const DSA_METHOD *
DSA_OpenSSL(void)90f5b1c8a1SJohn Marino DSA_OpenSSL(void)
91f5b1c8a1SJohn Marino {
92f5b1c8a1SJohn Marino 	return &openssl_dsa_meth;
93f5b1c8a1SJohn Marino }
94f5b1c8a1SJohn Marino 
95f5b1c8a1SJohn Marino static DSA_SIG *
dsa_do_sign(const unsigned char * dgst,int dlen,DSA * dsa)96f5b1c8a1SJohn Marino dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
97f5b1c8a1SJohn Marino {
9872c33676SMaxim Ag 	BIGNUM b, bm, bxr, binv, m, *kinv = NULL, *r = NULL, *s = NULL;
99f5b1c8a1SJohn Marino 	BN_CTX *ctx = NULL;
100f5b1c8a1SJohn Marino 	int reason = ERR_R_BN_LIB;
101f5b1c8a1SJohn Marino 	DSA_SIG *ret = NULL;
102f5b1c8a1SJohn Marino 	int noredo = 0;
103f5b1c8a1SJohn Marino 
10472c33676SMaxim Ag 	BN_init(&b);
10572c33676SMaxim Ag 	BN_init(&binv);
10672c33676SMaxim Ag 	BN_init(&bm);
10772c33676SMaxim Ag 	BN_init(&bxr);
108f5b1c8a1SJohn Marino 	BN_init(&m);
109f5b1c8a1SJohn Marino 
110f5b1c8a1SJohn Marino 	if (!dsa->p || !dsa->q || !dsa->g) {
111f5b1c8a1SJohn Marino 		reason = DSA_R_MISSING_PARAMETERS;
112f5b1c8a1SJohn Marino 		goto err;
113f5b1c8a1SJohn Marino 	}
114f5b1c8a1SJohn Marino 
115f5b1c8a1SJohn Marino 	s = BN_new();
116f5b1c8a1SJohn Marino 	if (s == NULL)
117f5b1c8a1SJohn Marino 		goto err;
118f5b1c8a1SJohn Marino 	ctx = BN_CTX_new();
119f5b1c8a1SJohn Marino 	if (ctx == NULL)
120f5b1c8a1SJohn Marino 		goto err;
12172c33676SMaxim Ag 
12272c33676SMaxim Ag 	/*
12372c33676SMaxim Ag 	 * If the digest length is greater than N (the bit length of q), the
12472c33676SMaxim Ag 	 * leftmost N bits of the digest shall be used, see FIPS 186-3, 4.2.
12572c33676SMaxim Ag 	 * In this case the digest length is given in bytes.
12672c33676SMaxim Ag 	 */
12772c33676SMaxim Ag 	if (dlen > BN_num_bytes(dsa->q))
12872c33676SMaxim Ag 		dlen = BN_num_bytes(dsa->q);
12972c33676SMaxim Ag 	if (BN_bin2bn(dgst, dlen, &m) == NULL)
13072c33676SMaxim Ag 		goto err;
13172c33676SMaxim Ag 
132f5b1c8a1SJohn Marino  redo:
133f5b1c8a1SJohn Marino 	if (dsa->kinv == NULL || dsa->r == NULL) {
134f5b1c8a1SJohn Marino 		if (!DSA_sign_setup(dsa, ctx, &kinv, &r))
135f5b1c8a1SJohn Marino 			goto err;
136f5b1c8a1SJohn Marino 	} else {
137f5b1c8a1SJohn Marino 		kinv = dsa->kinv;
138f5b1c8a1SJohn Marino 		dsa->kinv = NULL;
139f5b1c8a1SJohn Marino 		r = dsa->r;
140f5b1c8a1SJohn Marino 		dsa->r = NULL;
141f5b1c8a1SJohn Marino 		noredo = 1;
142f5b1c8a1SJohn Marino 	}
143f5b1c8a1SJohn Marino 
144f5b1c8a1SJohn Marino 	/*
14572c33676SMaxim Ag 	 * Compute:
14672c33676SMaxim Ag 	 *
14772c33676SMaxim Ag 	 *  s = inv(k)(m + xr) mod q
14872c33676SMaxim Ag 	 *
14972c33676SMaxim Ag 	 * In order to reduce the possibility of a side-channel attack, the
15072c33676SMaxim Ag 	 * following is calculated using a blinding value:
15172c33676SMaxim Ag 	 *
152cca6fc52SDaniel Fojt 	 *  s = inv(b)(bm + bxr)inv(k) mod q
15372c33676SMaxim Ag 	 *
15472c33676SMaxim Ag 	 * Where b is a random value in the range [1, q).
155f5b1c8a1SJohn Marino 	 */
15672c33676SMaxim Ag 	if (!bn_rand_interval(&b, BN_value_one(), dsa->q))
15772c33676SMaxim Ag 		goto err;
15872c33676SMaxim Ag 	if (BN_mod_inverse_ct(&binv, &b, dsa->q, ctx) == NULL)
159f5b1c8a1SJohn Marino 		goto err;
160f5b1c8a1SJohn Marino 
16172c33676SMaxim Ag 	if (!BN_mod_mul(&bxr, &b, dsa->priv_key, dsa->q, ctx))	/* bx */
162f5b1c8a1SJohn Marino 		goto err;
16372c33676SMaxim Ag 	if (!BN_mod_mul(&bxr, &bxr, r, dsa->q, ctx))	/* bxr */
164f5b1c8a1SJohn Marino 		goto err;
16572c33676SMaxim Ag 	if (!BN_mod_mul(&bm, &b, &m, dsa->q, ctx))	/* bm */
16672c33676SMaxim Ag 		goto err;
16772c33676SMaxim Ag 	if (!BN_mod_add(s, &bxr, &bm, dsa->q, ctx))	/* s = bm + bxr */
16872c33676SMaxim Ag 		goto err;
169cca6fc52SDaniel Fojt 	if (!BN_mod_mul(s, s, kinv, dsa->q, ctx))	/* s = b(m + xr)k^-1 */
170f5b1c8a1SJohn Marino 		goto err;
171cca6fc52SDaniel Fojt 	if (!BN_mod_mul(s, s, &binv, dsa->q, ctx))	/* s = (m + xr)k^-1 */
172f5b1c8a1SJohn Marino 		goto err;
173f5b1c8a1SJohn Marino 
174f5b1c8a1SJohn Marino 	/*
17572c33676SMaxim Ag 	 * Redo if r or s is zero as required by FIPS 186-3: this is very
17672c33676SMaxim Ag 	 * unlikely.
177f5b1c8a1SJohn Marino 	 */
178f5b1c8a1SJohn Marino 	if (BN_is_zero(r) || BN_is_zero(s)) {
179f5b1c8a1SJohn Marino 		if (noredo) {
180f5b1c8a1SJohn Marino 			reason = DSA_R_NEED_NEW_SETUP_VALUES;
181f5b1c8a1SJohn Marino 			goto err;
182f5b1c8a1SJohn Marino 		}
183f5b1c8a1SJohn Marino 		goto redo;
184f5b1c8a1SJohn Marino 	}
18572c33676SMaxim Ag 
18672c33676SMaxim Ag 	if ((ret = DSA_SIG_new()) == NULL) {
18772c33676SMaxim Ag 		reason = ERR_R_MALLOC_FAILURE;
18872c33676SMaxim Ag 		goto err;
18972c33676SMaxim Ag 	}
190f5b1c8a1SJohn Marino 	ret->r = r;
191f5b1c8a1SJohn Marino 	ret->s = s;
192f5b1c8a1SJohn Marino 
193f5b1c8a1SJohn Marino  err:
194f5b1c8a1SJohn Marino 	if (!ret) {
19572c33676SMaxim Ag 		DSAerror(reason);
196f5b1c8a1SJohn Marino 		BN_free(r);
197f5b1c8a1SJohn Marino 		BN_free(s);
198f5b1c8a1SJohn Marino 	}
199f5b1c8a1SJohn Marino 	BN_CTX_free(ctx);
20072c33676SMaxim Ag 	BN_clear_free(&b);
20172c33676SMaxim Ag 	BN_clear_free(&bm);
20272c33676SMaxim Ag 	BN_clear_free(&bxr);
20372c33676SMaxim Ag 	BN_clear_free(&binv);
204f5b1c8a1SJohn Marino 	BN_clear_free(&m);
205f5b1c8a1SJohn Marino 	BN_clear_free(kinv);
20672c33676SMaxim Ag 
207f5b1c8a1SJohn Marino 	return ret;
208f5b1c8a1SJohn Marino }
209f5b1c8a1SJohn Marino 
210f5b1c8a1SJohn Marino static int
dsa_sign_setup(DSA * dsa,BN_CTX * ctx_in,BIGNUM ** kinvp,BIGNUM ** rp)211f5b1c8a1SJohn Marino dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
212f5b1c8a1SJohn Marino {
213f5b1c8a1SJohn Marino 	BN_CTX *ctx;
21472c33676SMaxim Ag 	BIGNUM k, l, m, *kinv = NULL, *r = NULL;
21572c33676SMaxim Ag 	int q_bits, ret = 0;
216f5b1c8a1SJohn Marino 
217f5b1c8a1SJohn Marino 	if (!dsa->p || !dsa->q || !dsa->g) {
21872c33676SMaxim Ag 		DSAerror(DSA_R_MISSING_PARAMETERS);
219f5b1c8a1SJohn Marino 		return 0;
220f5b1c8a1SJohn Marino 	}
221f5b1c8a1SJohn Marino 
222f5b1c8a1SJohn Marino 	BN_init(&k);
22372c33676SMaxim Ag 	BN_init(&l);
22472c33676SMaxim Ag 	BN_init(&m);
225f5b1c8a1SJohn Marino 
226f5b1c8a1SJohn Marino 	if (ctx_in == NULL) {
227f5b1c8a1SJohn Marino 		if ((ctx = BN_CTX_new()) == NULL)
228f5b1c8a1SJohn Marino 			goto err;
229f5b1c8a1SJohn Marino 	} else
230f5b1c8a1SJohn Marino 		ctx = ctx_in;
231f5b1c8a1SJohn Marino 
232f5b1c8a1SJohn Marino 	if ((r = BN_new()) == NULL)
233f5b1c8a1SJohn Marino 		goto err;
234f5b1c8a1SJohn Marino 
23572c33676SMaxim Ag 	/* Preallocate space */
23672c33676SMaxim Ag 	q_bits = BN_num_bits(dsa->q);
23772c33676SMaxim Ag 	if (!BN_set_bit(&k, q_bits) ||
23872c33676SMaxim Ag 	    !BN_set_bit(&l, q_bits) ||
23972c33676SMaxim Ag 	    !BN_set_bit(&m, q_bits))
240f5b1c8a1SJohn Marino 		goto err;
24172c33676SMaxim Ag 
24272c33676SMaxim Ag 	if (!bn_rand_interval(&k, BN_value_one(), dsa->q))
24372c33676SMaxim Ag 		goto err;
244f5b1c8a1SJohn Marino 
245f5b1c8a1SJohn Marino 	BN_set_flags(&k, BN_FLG_CONSTTIME);
246f5b1c8a1SJohn Marino 
247f5b1c8a1SJohn Marino 	if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
248f5b1c8a1SJohn Marino 		if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p,
249f5b1c8a1SJohn Marino 		    CRYPTO_LOCK_DSA, dsa->p, ctx))
250f5b1c8a1SJohn Marino 			goto err;
251f5b1c8a1SJohn Marino 	}
252f5b1c8a1SJohn Marino 
253f5b1c8a1SJohn Marino 	/* Compute r = (g^k mod p) mod q */
254f5b1c8a1SJohn Marino 
255f5b1c8a1SJohn Marino 	/*
256f5b1c8a1SJohn Marino 	 * We do not want timing information to leak the length of k,
25772c33676SMaxim Ag 	 * so we compute G^k using an equivalent exponent of fixed
25872c33676SMaxim Ag 	 * bit-length.
259f5b1c8a1SJohn Marino 	 *
26072c33676SMaxim Ag 	 * We unconditionally perform both of these additions to prevent a
26172c33676SMaxim Ag 	 * small timing information leakage.  We then choose the sum that is
26272c33676SMaxim Ag 	 * one bit longer than the modulus.
26372c33676SMaxim Ag 	 *
26472c33676SMaxim Ag 	 * TODO: revisit the BN_copy aiming for a memory access agnostic
26572c33676SMaxim Ag 	 * conditional copy.
266f5b1c8a1SJohn Marino 	 */
267f5b1c8a1SJohn Marino 
26872c33676SMaxim Ag 	if (!BN_add(&l, &k, dsa->q) ||
26972c33676SMaxim Ag 	    !BN_add(&m, &l, dsa->q) ||
27072c33676SMaxim Ag 	    !BN_copy(&k, BN_num_bits(&l) > q_bits ? &l : &m))
271f5b1c8a1SJohn Marino 		goto err;
272f5b1c8a1SJohn Marino 
273f5b1c8a1SJohn Marino 	if (dsa->meth->bn_mod_exp != NULL) {
274f5b1c8a1SJohn Marino 		if (!dsa->meth->bn_mod_exp(dsa, r, dsa->g, &k, dsa->p, ctx,
275f5b1c8a1SJohn Marino 		    dsa->method_mont_p))
276f5b1c8a1SJohn Marino 			goto err;
277f5b1c8a1SJohn Marino 	} else {
27872c33676SMaxim Ag 		if (!BN_mod_exp_mont_ct(r, dsa->g, &k, dsa->p, ctx,
27972c33676SMaxim Ag 		    dsa->method_mont_p))
280f5b1c8a1SJohn Marino 			goto err;
281f5b1c8a1SJohn Marino 	}
282f5b1c8a1SJohn Marino 
28372c33676SMaxim Ag 	if (!BN_mod_ct(r, r, dsa->q, ctx))
284f5b1c8a1SJohn Marino 		goto err;
285f5b1c8a1SJohn Marino 
286f5b1c8a1SJohn Marino 	/* Compute  part of 's = inv(k) (m + xr) mod q' */
28772c33676SMaxim Ag 	if ((kinv = BN_mod_inverse_ct(NULL, &k, dsa->q, ctx)) == NULL)
288f5b1c8a1SJohn Marino 		goto err;
289f5b1c8a1SJohn Marino 
290f5b1c8a1SJohn Marino 	BN_clear_free(*kinvp);
291f5b1c8a1SJohn Marino 	*kinvp = kinv;
292f5b1c8a1SJohn Marino 	kinv = NULL;
293f5b1c8a1SJohn Marino 	BN_clear_free(*rp);
294f5b1c8a1SJohn Marino 	*rp = r;
29572c33676SMaxim Ag 
296f5b1c8a1SJohn Marino 	ret = 1;
29772c33676SMaxim Ag 
298f5b1c8a1SJohn Marino  err:
299f5b1c8a1SJohn Marino 	if (!ret) {
30072c33676SMaxim Ag 		DSAerror(ERR_R_BN_LIB);
301f5b1c8a1SJohn Marino 		BN_clear_free(r);
302f5b1c8a1SJohn Marino 	}
303f5b1c8a1SJohn Marino 	if (ctx_in == NULL)
304f5b1c8a1SJohn Marino 		BN_CTX_free(ctx);
305f5b1c8a1SJohn Marino 	BN_clear_free(&k);
30672c33676SMaxim Ag 	BN_clear_free(&l);
30772c33676SMaxim Ag 	BN_clear_free(&m);
30872c33676SMaxim Ag 
309f5b1c8a1SJohn Marino 	return ret;
310f5b1c8a1SJohn Marino }
311f5b1c8a1SJohn Marino 
312f5b1c8a1SJohn Marino static int
dsa_do_verify(const unsigned char * dgst,int dgst_len,DSA_SIG * sig,DSA * dsa)313f5b1c8a1SJohn Marino dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa)
314f5b1c8a1SJohn Marino {
315f5b1c8a1SJohn Marino 	BN_CTX *ctx;
316f5b1c8a1SJohn Marino 	BIGNUM u1, u2, t1;
317f5b1c8a1SJohn Marino 	BN_MONT_CTX *mont = NULL;
318*de0e0e4dSAntonio Huete Jimenez 	int qbits;
319*de0e0e4dSAntonio Huete Jimenez 	int ret = -1;
320f5b1c8a1SJohn Marino 
321f5b1c8a1SJohn Marino 	if (!dsa->p || !dsa->q || !dsa->g) {
32272c33676SMaxim Ag 		DSAerror(DSA_R_MISSING_PARAMETERS);
323f5b1c8a1SJohn Marino 		return -1;
324f5b1c8a1SJohn Marino 	}
325f5b1c8a1SJohn Marino 
32672c33676SMaxim Ag 	/* FIPS 186-3 allows only three different sizes for q. */
327*de0e0e4dSAntonio Huete Jimenez 	qbits = BN_num_bits(dsa->q);
328*de0e0e4dSAntonio Huete Jimenez 	if (qbits != 160 && qbits != 224 && qbits != 256) {
32972c33676SMaxim Ag 		DSAerror(DSA_R_BAD_Q_VALUE);
330f5b1c8a1SJohn Marino 		return -1;
331f5b1c8a1SJohn Marino 	}
332f5b1c8a1SJohn Marino 	if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) {
33372c33676SMaxim Ag 		DSAerror(DSA_R_MODULUS_TOO_LARGE);
334f5b1c8a1SJohn Marino 		return -1;
335f5b1c8a1SJohn Marino 	}
336*de0e0e4dSAntonio Huete Jimenez 
337f5b1c8a1SJohn Marino 	BN_init(&u1);
338f5b1c8a1SJohn Marino 	BN_init(&u2);
339f5b1c8a1SJohn Marino 	BN_init(&t1);
340f5b1c8a1SJohn Marino 
341f5b1c8a1SJohn Marino 	if ((ctx = BN_CTX_new()) == NULL)
342f5b1c8a1SJohn Marino 		goto err;
343f5b1c8a1SJohn Marino 
344f5b1c8a1SJohn Marino 	if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
345f5b1c8a1SJohn Marino 	    BN_ucmp(sig->r, dsa->q) >= 0) {
346f5b1c8a1SJohn Marino 		ret = 0;
347f5b1c8a1SJohn Marino 		goto err;
348f5b1c8a1SJohn Marino 	}
349f5b1c8a1SJohn Marino 	if (BN_is_zero(sig->s) || BN_is_negative(sig->s) ||
350f5b1c8a1SJohn Marino 	    BN_ucmp(sig->s, dsa->q) >= 0) {
351f5b1c8a1SJohn Marino 		ret = 0;
352f5b1c8a1SJohn Marino 		goto err;
353f5b1c8a1SJohn Marino 	}
354f5b1c8a1SJohn Marino 
35572c33676SMaxim Ag 	/* Calculate w = inv(s) mod q, saving w in u2. */
35672c33676SMaxim Ag 	if ((BN_mod_inverse_ct(&u2, sig->s, dsa->q, ctx)) == NULL)
357f5b1c8a1SJohn Marino 		goto err;
358f5b1c8a1SJohn Marino 
359f5b1c8a1SJohn Marino 	/*
360f5b1c8a1SJohn Marino 	 * If the digest length is greater than the size of q use the
36172c33676SMaxim Ag 	 * BN_num_bits(dsa->q) leftmost bits of the digest, see FIPS 186-3, 4.2.
362f5b1c8a1SJohn Marino 	 */
363*de0e0e4dSAntonio Huete Jimenez 	if (dgst_len > (qbits >> 3))
364*de0e0e4dSAntonio Huete Jimenez 		dgst_len = (qbits >> 3);
36572c33676SMaxim Ag 
36672c33676SMaxim Ag 	/* Save m in u1. */
367f5b1c8a1SJohn Marino 	if (BN_bin2bn(dgst, dgst_len, &u1) == NULL)
368f5b1c8a1SJohn Marino 		goto err;
369f5b1c8a1SJohn Marino 
37072c33676SMaxim Ag 	/* u1 = m * w mod q */
371f5b1c8a1SJohn Marino 	if (!BN_mod_mul(&u1, &u1, &u2, dsa->q, ctx))
372f5b1c8a1SJohn Marino 		goto err;
373f5b1c8a1SJohn Marino 
374f5b1c8a1SJohn Marino 	/* u2 = r * w mod q */
375f5b1c8a1SJohn Marino 	if (!BN_mod_mul(&u2, sig->r, &u2, dsa->q, ctx))
376f5b1c8a1SJohn Marino 		goto err;
377f5b1c8a1SJohn Marino 
378f5b1c8a1SJohn Marino 	if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
379f5b1c8a1SJohn Marino 		mont = BN_MONT_CTX_set_locked(&dsa->method_mont_p,
380f5b1c8a1SJohn Marino 		    CRYPTO_LOCK_DSA, dsa->p, ctx);
381f5b1c8a1SJohn Marino 		if (!mont)
382f5b1c8a1SJohn Marino 			goto err;
383f5b1c8a1SJohn Marino 	}
384f5b1c8a1SJohn Marino 
385f5b1c8a1SJohn Marino 	if (dsa->meth->dsa_mod_exp != NULL) {
38672c33676SMaxim Ag 		if (!dsa->meth->dsa_mod_exp(dsa, &t1, dsa->g, &u1, dsa->pub_key,
38772c33676SMaxim Ag 		    &u2, dsa->p, ctx, mont))
388f5b1c8a1SJohn Marino 			goto err;
389f5b1c8a1SJohn Marino 	} else {
39072c33676SMaxim Ag 		if (!BN_mod_exp2_mont(&t1, dsa->g, &u1, dsa->pub_key, &u2,
39172c33676SMaxim Ag 		    dsa->p, ctx, mont))
392f5b1c8a1SJohn Marino 			goto err;
393f5b1c8a1SJohn Marino 	}
394f5b1c8a1SJohn Marino 
395f5b1c8a1SJohn Marino 	/* BN_copy(&u1,&t1); */
396f5b1c8a1SJohn Marino 	/* let u1 = u1 mod q */
39772c33676SMaxim Ag 	if (!BN_mod_ct(&u1, &t1, dsa->q, ctx))
398f5b1c8a1SJohn Marino 		goto err;
399f5b1c8a1SJohn Marino 
40072c33676SMaxim Ag 	/* v is in u1 - if the signature is correct, it will be equal to r. */
401f5b1c8a1SJohn Marino 	ret = BN_ucmp(&u1, sig->r) == 0;
402f5b1c8a1SJohn Marino 
403f5b1c8a1SJohn Marino  err:
404f5b1c8a1SJohn Marino 	if (ret < 0)
40572c33676SMaxim Ag 		DSAerror(ERR_R_BN_LIB);
406f5b1c8a1SJohn Marino 	BN_CTX_free(ctx);
407f5b1c8a1SJohn Marino 	BN_free(&u1);
408f5b1c8a1SJohn Marino 	BN_free(&u2);
409f5b1c8a1SJohn Marino 	BN_free(&t1);
41072c33676SMaxim Ag 
411f5b1c8a1SJohn Marino 	return ret;
412f5b1c8a1SJohn Marino }
413f5b1c8a1SJohn Marino 
414f5b1c8a1SJohn Marino static int
dsa_init(DSA * dsa)415f5b1c8a1SJohn Marino dsa_init(DSA *dsa)
416f5b1c8a1SJohn Marino {
417f5b1c8a1SJohn Marino 	dsa->flags |= DSA_FLAG_CACHE_MONT_P;
418f5b1c8a1SJohn Marino 	return 1;
419f5b1c8a1SJohn Marino }
420f5b1c8a1SJohn Marino 
421f5b1c8a1SJohn Marino static int
dsa_finish(DSA * dsa)422f5b1c8a1SJohn Marino dsa_finish(DSA *dsa)
423f5b1c8a1SJohn Marino {
424f5b1c8a1SJohn Marino 	BN_MONT_CTX_free(dsa->method_mont_p);
425f5b1c8a1SJohn Marino 	return 1;
426f5b1c8a1SJohn Marino }
427f5b1c8a1SJohn Marino 
428