xref: /openbsd-src/lib/libcrypto/dsa/dsa_ossl.c (revision 7a31e386bf17f78a5df04735a19059c648d96e95)
1*7a31e386Stb /* $OpenBSD: dsa_ossl.c,v 1.56 2024/05/11 06:43:50 tb Exp $ */
2ba5406e9Sbeck /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3ba5406e9Sbeck  * All rights reserved.
4ba5406e9Sbeck  *
5ba5406e9Sbeck  * This package is an SSL implementation written
6ba5406e9Sbeck  * by Eric Young (eay@cryptsoft.com).
7ba5406e9Sbeck  * The implementation was written so as to conform with Netscapes SSL.
8ba5406e9Sbeck  *
9ba5406e9Sbeck  * This library is free for commercial and non-commercial use as long as
10ba5406e9Sbeck  * the following conditions are aheared to.  The following conditions
11ba5406e9Sbeck  * apply to all code found in this distribution, be it the RC4, RSA,
12ba5406e9Sbeck  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13ba5406e9Sbeck  * included with this distribution is covered by the same copyright terms
14ba5406e9Sbeck  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15ba5406e9Sbeck  *
16ba5406e9Sbeck  * Copyright remains Eric Young's, and as such any Copyright notices in
17ba5406e9Sbeck  * the code are not to be removed.
18ba5406e9Sbeck  * If this package is used in a product, Eric Young should be given attribution
19ba5406e9Sbeck  * as the author of the parts of the library used.
20ba5406e9Sbeck  * This can be in the form of a textual message at program startup or
21ba5406e9Sbeck  * in documentation (online or textual) provided with the package.
22ba5406e9Sbeck  *
23ba5406e9Sbeck  * Redistribution and use in source and binary forms, with or without
24ba5406e9Sbeck  * modification, are permitted provided that the following conditions
25ba5406e9Sbeck  * are met:
26ba5406e9Sbeck  * 1. Redistributions of source code must retain the copyright
27ba5406e9Sbeck  *    notice, this list of conditions and the following disclaimer.
28ba5406e9Sbeck  * 2. Redistributions in binary form must reproduce the above copyright
29ba5406e9Sbeck  *    notice, this list of conditions and the following disclaimer in the
30ba5406e9Sbeck  *    documentation and/or other materials provided with the distribution.
31ba5406e9Sbeck  * 3. All advertising materials mentioning features or use of this software
32ba5406e9Sbeck  *    must display the following acknowledgement:
33ba5406e9Sbeck  *    "This product includes cryptographic software written by
34ba5406e9Sbeck  *     Eric Young (eay@cryptsoft.com)"
35ba5406e9Sbeck  *    The word 'cryptographic' can be left out if the rouines from the library
36ba5406e9Sbeck  *    being used are not cryptographic related :-).
37ba5406e9Sbeck  * 4. If you include any Windows specific code (or a derivative thereof) from
38ba5406e9Sbeck  *    the apps directory (application code) you must include an acknowledgement:
39ba5406e9Sbeck  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40ba5406e9Sbeck  *
41ba5406e9Sbeck  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42ba5406e9Sbeck  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43ba5406e9Sbeck  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44ba5406e9Sbeck  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45ba5406e9Sbeck  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46ba5406e9Sbeck  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47ba5406e9Sbeck  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48ba5406e9Sbeck  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49ba5406e9Sbeck  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50ba5406e9Sbeck  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51ba5406e9Sbeck  * SUCH DAMAGE.
52ba5406e9Sbeck  *
53ba5406e9Sbeck  * The licence and distribution terms for any publically available version or
54ba5406e9Sbeck  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55ba5406e9Sbeck  * copied and put under another distribution licence
56ba5406e9Sbeck  * [including the GNU Public Licence.]
57ba5406e9Sbeck  */
58ba5406e9Sbeck 
59ba5406e9Sbeck /* Original version from Steven Schoch <schoch@sheba.arc.nasa.gov> */
60ba5406e9Sbeck 
61ba5406e9Sbeck #include <stdio.h>
62b6ab114eSjsing 
63ba5406e9Sbeck #include <openssl/asn1.h>
64b6ab114eSjsing #include <openssl/bn.h>
65b6ab114eSjsing #include <openssl/dsa.h>
66b6ab114eSjsing #include <openssl/err.h>
67b6ab114eSjsing #include <openssl/sha.h>
68ba5406e9Sbeck 
69c9675a23Stb #include "bn_local.h"
70c9675a23Stb #include "dsa_local.h"
713a88f7afSbeck 
720d37be08Stb /*
730d37be08Stb  * Since DSA parameters are entirely arbitrary and checking them to be
740d37be08Stb  * consistent is very expensive, we cannot do so on every sign operation.
750d37be08Stb  * Instead, cap the number of retries so we do not loop indefinitely if
760d37be08Stb  * the generator of the multiplicative group happens to be nilpotent.
770d37be08Stb  * The probability of needing a retry with valid parameters is negligible,
780d37be08Stb  * so trying 32 times is amply enough.
790d37be08Stb  */
800d37be08Stb #define DSA_MAX_SIGN_ITERATIONS		32
810d37be08Stb 
82e85b1b81Smiod static DSA_SIG *
dsa_do_sign(const unsigned char * dgst,int dlen,DSA * dsa)83e85b1b81Smiod dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
84ba5406e9Sbeck {
8570901374Sjsing 	BIGNUM *b = NULL, *bm = NULL, *bxr = NULL, *binv = NULL, *m = NULL;
8670901374Sjsing 	BIGNUM *kinv = NULL, *r = NULL, *s = NULL;
87ba5406e9Sbeck 	BN_CTX *ctx = NULL;
880a5d6edeSdjm 	int reason = ERR_R_BN_LIB;
89ba5406e9Sbeck 	DSA_SIG *ret = NULL;
900d37be08Stb 	int attempts = 0;
915cdd308eSdjm 	int noredo = 0;
92ba5406e9Sbeck 
9383f09c76Stb 	if (!dsa_check_key(dsa)) {
9483f09c76Stb 		reason = DSA_R_INVALID_PARAMETERS;
95200c0290Sbeck 		goto err;
96200c0290Sbeck 	}
97767fe2ffSmarkus 
9870901374Sjsing 	if ((s = BN_new()) == NULL)
99e85b1b81Smiod 		goto err;
10070901374Sjsing 
10170901374Sjsing 	if ((ctx = BN_CTX_new()) == NULL)
10270901374Sjsing 		goto err;
10370901374Sjsing 
10470901374Sjsing 	BN_CTX_start(ctx);
10570901374Sjsing 
10670901374Sjsing 	if ((b = BN_CTX_get(ctx)) == NULL)
10770901374Sjsing 		goto err;
10870901374Sjsing 	if ((binv = BN_CTX_get(ctx)) == NULL)
10970901374Sjsing 		goto err;
11070901374Sjsing 	if ((bm = BN_CTX_get(ctx)) == NULL)
11170901374Sjsing 		goto err;
11270901374Sjsing 	if ((bxr = BN_CTX_get(ctx)) == NULL)
11370901374Sjsing 		goto err;
11470901374Sjsing 	if ((m = BN_CTX_get(ctx)) == NULL)
115e85b1b81Smiod 		goto err;
116c6a150b7Sjsing 
1172a4f1d4fSjsing 	/*
118cca0da51Sjsing 	 * If the digest length is greater than N (the bit length of q), the
119cca0da51Sjsing 	 * leftmost N bits of the digest shall be used, see FIPS 186-3, 4.2.
120cca0da51Sjsing 	 * In this case the digest length is given in bytes.
1212a4f1d4fSjsing 	 */
1222a4f1d4fSjsing 	if (dlen > BN_num_bytes(dsa->q))
1232a4f1d4fSjsing 		dlen = BN_num_bytes(dsa->q);
12470901374Sjsing 	if (BN_bin2bn(dgst, dlen, m) == NULL)
1252a4f1d4fSjsing 		goto err;
1262a4f1d4fSjsing 
1275cdd308eSdjm  redo:
128e85b1b81Smiod 	if (dsa->kinv == NULL || dsa->r == NULL) {
129e85b1b81Smiod 		if (!DSA_sign_setup(dsa, ctx, &kinv, &r))
130e85b1b81Smiod 			goto err;
131e85b1b81Smiod 	} else {
132ba5406e9Sbeck 		kinv = dsa->kinv;
133ba5406e9Sbeck 		dsa->kinv = NULL;
134ba5406e9Sbeck 		r = dsa->r;
135ba5406e9Sbeck 		dsa->r = NULL;
1365cdd308eSdjm 		noredo = 1;
137ba5406e9Sbeck 	}
138ba5406e9Sbeck 
139e1190f3dSjsing 	/*
140e1190f3dSjsing 	 * Compute:
141e1190f3dSjsing 	 *
142e1190f3dSjsing 	 *  s = inv(k)(m + xr) mod q
143e1190f3dSjsing 	 *
144e1190f3dSjsing 	 * In order to reduce the possibility of a side-channel attack, the
145e1190f3dSjsing 	 * following is calculated using a blinding value:
146e1190f3dSjsing 	 *
147c462c7b3Stb 	 *  s = inv(b)(bm + bxr)inv(k) mod q
148e1190f3dSjsing 	 *
1498a144a0fStb 	 * Where b is a random value in the range [1, q).
150e1190f3dSjsing 	 */
15112347e81Stb 	if (!bn_rand_interval(b, 1, dsa->q))
152e1190f3dSjsing 		goto err;
15370901374Sjsing 	if (BN_mod_inverse_ct(binv, b, dsa->q, ctx) == NULL)
154e1190f3dSjsing 		goto err;
155e1190f3dSjsing 
15670901374Sjsing 	if (!BN_mod_mul(bxr, b, dsa->priv_key, dsa->q, ctx))	/* bx */
157e1190f3dSjsing 		goto err;
15870901374Sjsing 	if (!BN_mod_mul(bxr, bxr, r, dsa->q, ctx))	/* bxr */
159e1190f3dSjsing 		goto err;
16070901374Sjsing 	if (!BN_mod_mul(bm, b, m, dsa->q, ctx))		/* bm */
161e1190f3dSjsing 		goto err;
16270901374Sjsing 	if (!BN_mod_add(s, bxr, bm, dsa->q, ctx))	/* s = bm + bxr */
163e1190f3dSjsing 		goto err;
16439378f3cStb 	if (!BN_mod_mul(s, s, kinv, dsa->q, ctx))	/* s = b(m + xr)k^-1 */
165e85b1b81Smiod 		goto err;
16670901374Sjsing 	if (!BN_mod_mul(s, s, binv, dsa->q, ctx))	/* s = (m + xr)k^-1 */
167e85b1b81Smiod 		goto err;
168ba5406e9Sbeck 
169e85b1b81Smiod 	/*
170c6a150b7Sjsing 	 * Redo if r or s is zero as required by FIPS 186-3: this is very
171c6a150b7Sjsing 	 * unlikely.
1725cdd308eSdjm 	 */
173e85b1b81Smiod 	if (BN_is_zero(r) || BN_is_zero(s)) {
174e85b1b81Smiod 		if (noredo) {
1755cdd308eSdjm 			reason = DSA_R_NEED_NEW_SETUP_VALUES;
1765cdd308eSdjm 			goto err;
1775cdd308eSdjm 		}
1780d37be08Stb 		if (++attempts > DSA_MAX_SIGN_ITERATIONS) {
1790d37be08Stb 			reason = DSA_R_INVALID_PARAMETERS;
1800d37be08Stb 			goto err;
1810d37be08Stb 		}
1825cdd308eSdjm 		goto redo;
1835cdd308eSdjm 	}
184011d7b9eSjsing 
185011d7b9eSjsing 	if ((ret = DSA_SIG_new()) == NULL) {
186011d7b9eSjsing 		reason = ERR_R_MALLOC_FAILURE;
187011d7b9eSjsing 		goto err;
188011d7b9eSjsing 	}
189ba5406e9Sbeck 	ret->r = r;
190ba5406e9Sbeck 	ret->s = s;
191ba5406e9Sbeck 
192ba5406e9Sbeck  err:
193e85b1b81Smiod 	if (!ret) {
1945067ae9fSbeck 		DSAerror(reason);
195ba5406e9Sbeck 		BN_free(r);
196ba5406e9Sbeck 		BN_free(s);
197ba5406e9Sbeck 	}
19870901374Sjsing 	BN_CTX_end(ctx);
199e85b1b81Smiod 	BN_CTX_free(ctx);
20070901374Sjsing 	BN_free(kinv);
201c6a150b7Sjsing 
202e85b1b81Smiod 	return ret;
203ba5406e9Sbeck }
204ba5406e9Sbeck 
205e85b1b81Smiod static int
dsa_sign_setup(DSA * dsa,BN_CTX * ctx_in,BIGNUM ** kinvp,BIGNUM ** rp)206e85b1b81Smiod dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
207ba5406e9Sbeck {
20870901374Sjsing 	BIGNUM *k = NULL, *l = NULL, *m = NULL, *kinv = NULL, *r = NULL;
20970901374Sjsing 	BN_CTX *ctx = NULL;
21070901374Sjsing 	int q_bits;
21170901374Sjsing 	int ret = 0;
212ba5406e9Sbeck 
21383f09c76Stb 	if (!dsa_check_key(dsa))
21483f09c76Stb 		goto err;
215767fe2ffSmarkus 
216e85b1b81Smiod 	if ((r = BN_new()) == NULL)
217e85b1b81Smiod 		goto err;
218ba5406e9Sbeck 
21970901374Sjsing 	if ((ctx = ctx_in) == NULL)
22070901374Sjsing 		ctx = BN_CTX_new();
22170901374Sjsing 	if (ctx == NULL)
22270901374Sjsing 		goto err;
22370901374Sjsing 
22470901374Sjsing 	BN_CTX_start(ctx);
22570901374Sjsing 
22670901374Sjsing 	if ((k = BN_CTX_get(ctx)) == NULL)
22770901374Sjsing 		goto err;
22870901374Sjsing 	if ((l = BN_CTX_get(ctx)) == NULL)
22970901374Sjsing 		goto err;
23070901374Sjsing 	if ((m = BN_CTX_get(ctx)) == NULL)
23170901374Sjsing 		goto err;
23270901374Sjsing 
233edf1f588Stb 	/* Preallocate space */
234edf1f588Stb 	q_bits = BN_num_bits(dsa->q);
23570901374Sjsing 	if (!BN_set_bit(k, q_bits) ||
23670901374Sjsing 	    !BN_set_bit(l, q_bits) ||
23770901374Sjsing 	    !BN_set_bit(m, q_bits))
238edf1f588Stb 		goto err;
239edf1f588Stb 
24012347e81Stb 	if (!bn_rand_interval(k, 1, dsa->q))
241e85b1b81Smiod 		goto err;
2426d388760Sdjm 
24370901374Sjsing 	BN_set_flags(k, BN_FLG_CONSTTIME);
24455cda256Sbcook 
245e85b1b81Smiod 	if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
2464fcf65c5Sdjm 		if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p,
247e85b1b81Smiod 		    CRYPTO_LOCK_DSA, dsa->p, ctx))
2486d388760Sdjm 			goto err;
249ba5406e9Sbeck 	}
250ba5406e9Sbeck 
251ba5406e9Sbeck 	/* Compute r = (g^k mod p) mod q */
2526d388760Sdjm 
253e85b1b81Smiod 	/*
254e85b1b81Smiod 	 * We do not want timing information to leak the length of k,
255edf1f588Stb 	 * so we compute G^k using an equivalent exponent of fixed
256edf1f588Stb 	 * bit-length.
2576d388760Sdjm 	 *
258edf1f588Stb 	 * We unconditionally perform both of these additions to prevent a
259edf1f588Stb 	 * small timing information leakage.  We then choose the sum that is
260edf1f588Stb 	 * one bit longer than the modulus.
261edf1f588Stb 	 *
262cef8f41dStb 	 * TODO: revisit the bn_copy aiming for a memory access agnostic
263edf1f588Stb 	 * conditional copy.
264e85b1b81Smiod 	 */
2656d388760Sdjm 
26670901374Sjsing 	if (!BN_add(l, k, dsa->q) ||
26770901374Sjsing 	    !BN_add(m, l, dsa->q) ||
268cef8f41dStb 	    !bn_copy(k, BN_num_bits(l) > q_bits ? l : m))
269e85b1b81Smiod 		goto err;
2706d388760Sdjm 
271*7a31e386Stb 	if (!BN_mod_exp_mont_ct(r, dsa->g, k, dsa->p, ctx, dsa->method_mont_p))
27255cda256Sbcook 		goto err;
273b274ec66Sbeck 
27444adc1eaSbeck 	if (!BN_mod_ct(r, r, dsa->q, ctx))
275e85b1b81Smiod 		goto err;
276ba5406e9Sbeck 
277ba5406e9Sbeck 	/* Compute  part of 's = inv(k) (m + xr) mod q' */
27870901374Sjsing 	if ((kinv = BN_mod_inverse_ct(NULL, k, dsa->q, ctx)) == NULL)
279e85b1b81Smiod 		goto err;
280ba5406e9Sbeck 
28170901374Sjsing 	BN_free(*kinvp);
282ba5406e9Sbeck 	*kinvp = kinv;
283ba5406e9Sbeck 	kinv = NULL;
28470901374Sjsing 
28570901374Sjsing 	BN_free(*rp);
286ba5406e9Sbeck 	*rp = r;
287c6a150b7Sjsing 
288ba5406e9Sbeck 	ret = 1;
289c6a150b7Sjsing 
290ba5406e9Sbeck  err:
291e85b1b81Smiod 	if (!ret) {
2925067ae9fSbeck 		DSAerror(ERR_R_BN_LIB);
29370901374Sjsing 		BN_free(r);
294ba5406e9Sbeck 	}
29570901374Sjsing 	BN_CTX_end(ctx);
29670901374Sjsing 	if (ctx != ctx_in)
297e85b1b81Smiod 		BN_CTX_free(ctx);
298c6a150b7Sjsing 
299e85b1b81Smiod 	return ret;
300ba5406e9Sbeck }
301ba5406e9Sbeck 
302e85b1b81Smiod static int
dsa_do_verify(const unsigned char * dgst,int dgst_len,DSA_SIG * sig,DSA * dsa)303e85b1b81Smiod dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa)
304ba5406e9Sbeck {
30570901374Sjsing 	BIGNUM *u1 = NULL, *u2 = NULL, *t1 = NULL;
30670901374Sjsing 	BN_CTX *ctx = NULL;
307ba5406e9Sbeck 	BN_MONT_CTX *mont = NULL;
30841651db1Stb 	int qbits;
30941651db1Stb 	int ret = -1;
310e85b1b81Smiod 
31183f09c76Stb 	if (!dsa_check_key(dsa))
31283f09c76Stb 		goto err;
31341651db1Stb 
314e85b1b81Smiod 	if ((ctx = BN_CTX_new()) == NULL)
315e85b1b81Smiod 		goto err;
316767fe2ffSmarkus 
31770901374Sjsing 	BN_CTX_start(ctx);
31870901374Sjsing 
31970901374Sjsing 	if ((u1 = BN_CTX_get(ctx)) == NULL)
32070901374Sjsing 		goto err;
32170901374Sjsing 	if ((u2 = BN_CTX_get(ctx)) == NULL)
32270901374Sjsing 		goto err;
32370901374Sjsing 	if ((t1 = BN_CTX_get(ctx)) == NULL)
32470901374Sjsing 		goto err;
32570901374Sjsing 
3264fcf65c5Sdjm 	if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
327e85b1b81Smiod 	    BN_ucmp(sig->r, dsa->q) >= 0) {
328200c0290Sbeck 		ret = 0;
329200c0290Sbeck 		goto err;
330200c0290Sbeck 	}
3314fcf65c5Sdjm 	if (BN_is_zero(sig->s) || BN_is_negative(sig->s) ||
332e85b1b81Smiod 	    BN_ucmp(sig->s, dsa->q) >= 0) {
333200c0290Sbeck 		ret = 0;
334200c0290Sbeck 		goto err;
335200c0290Sbeck 	}
336200c0290Sbeck 
337c6a150b7Sjsing 	/* Calculate w = inv(s) mod q, saving w in u2. */
33870901374Sjsing 	if ((BN_mod_inverse_ct(u2, sig->s, dsa->q, ctx)) == NULL)
339e85b1b81Smiod 		goto err;
340ba5406e9Sbeck 
341e85b1b81Smiod 	/*
342e85b1b81Smiod 	 * If the digest length is greater than the size of q use the
34383f09c76Stb 	 * BN_num_bits(dsa->q) leftmost bits of the digest, see FIPS 186-4, 4.2.
344e85b1b81Smiod 	 */
34583f09c76Stb 	qbits = BN_num_bits(dsa->q);
34641651db1Stb 	if (dgst_len > (qbits >> 3))
34741651db1Stb 		dgst_len = (qbits >> 3);
348c6a150b7Sjsing 
349c6a150b7Sjsing 	/* Save m in u1. */
35070901374Sjsing 	if (BN_bin2bn(dgst, dgst_len, u1) == NULL)
351e85b1b81Smiod 		goto err;
352ba5406e9Sbeck 
353c6a150b7Sjsing 	/* u1 = m * w mod q */
35470901374Sjsing 	if (!BN_mod_mul(u1, u1, u2, dsa->q, ctx))
355e85b1b81Smiod 		goto err;
356ba5406e9Sbeck 
357ba5406e9Sbeck 	/* u2 = r * w mod q */
35870901374Sjsing 	if (!BN_mod_mul(u2, sig->r, u2, dsa->q, ctx))
359e85b1b81Smiod 		goto err;
360ba5406e9Sbeck 
361e85b1b81Smiod 	if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
3624fcf65c5Sdjm 		mont = BN_MONT_CTX_set_locked(&dsa->method_mont_p,
3636d388760Sdjm 		    CRYPTO_LOCK_DSA, dsa->p, ctx);
3646d388760Sdjm 		if (!mont)
3656d388760Sdjm 			goto err;
366ba5406e9Sbeck 	}
367ba5406e9Sbeck 
368*7a31e386Stb 	if (!BN_mod_exp2_mont(t1, dsa->g, u1, dsa->pub_key, u2, dsa->p,
369*7a31e386Stb 	    ctx, mont))
37055cda256Sbcook 		goto err;
37155cda256Sbcook 
372ba5406e9Sbeck 	/* let u1 = u1 mod q */
37370901374Sjsing 	if (!BN_mod_ct(u1, t1, dsa->q, ctx))
374e85b1b81Smiod 		goto err;
3754fcf65c5Sdjm 
376c6a150b7Sjsing 	/* v is in u1 - if the signature is correct, it will be equal to r. */
37770901374Sjsing 	ret = BN_ucmp(u1, sig->r) == 0;
378ba5406e9Sbeck 
379ba5406e9Sbeck  err:
380ba04b2cdSbcook 	if (ret < 0)
3815067ae9fSbeck 		DSAerror(ERR_R_BN_LIB);
38270901374Sjsing 	BN_CTX_end(ctx);
383e85b1b81Smiod 	BN_CTX_free(ctx);
384c6a150b7Sjsing 
385e85b1b81Smiod 	return ret;
386ba5406e9Sbeck }
387ba5406e9Sbeck 
388e85b1b81Smiod static int
dsa_init(DSA * dsa)389e85b1b81Smiod dsa_init(DSA *dsa)
390ba5406e9Sbeck {
391ba5406e9Sbeck 	dsa->flags |= DSA_FLAG_CACHE_MONT_P;
392e85b1b81Smiod 	return 1;
393ba5406e9Sbeck }
394ba5406e9Sbeck 
395e85b1b81Smiod static int
dsa_finish(DSA * dsa)396e85b1b81Smiod dsa_finish(DSA *dsa)
397ba5406e9Sbeck {
3984fcf65c5Sdjm 	BN_MONT_CTX_free(dsa->method_mont_p);
399e85b1b81Smiod 	return 1;
400ba5406e9Sbeck }
401c2cf2d55Stb 
4023d9fb52eStb static const DSA_METHOD openssl_dsa_meth = {
40389625feaStb 	.name = "OpenSSL DSA method",
40489625feaStb 	.dsa_do_sign = dsa_do_sign,
40589625feaStb 	.dsa_sign_setup = dsa_sign_setup,
40689625feaStb 	.dsa_do_verify = dsa_do_verify,
40789625feaStb 	.init = dsa_init,
40889625feaStb 	.finish = dsa_finish,
40989625feaStb };
41089625feaStb 
41189625feaStb const DSA_METHOD *
DSA_OpenSSL(void)41289625feaStb DSA_OpenSSL(void)
41389625feaStb {
41489625feaStb 	return &openssl_dsa_meth;
41589625feaStb }
41689625feaStb LCRYPTO_ALIAS(DSA_OpenSSL);
41789625feaStb 
418c2cf2d55Stb DSA_SIG *
DSA_SIG_new(void)419c2cf2d55Stb DSA_SIG_new(void)
420c2cf2d55Stb {
421c2cf2d55Stb 	return calloc(1, sizeof(DSA_SIG));
422c2cf2d55Stb }
42381dbdadeSbeck LCRYPTO_ALIAS(DSA_SIG_new);
424c2cf2d55Stb 
425c2cf2d55Stb void
DSA_SIG_free(DSA_SIG * sig)426c2cf2d55Stb DSA_SIG_free(DSA_SIG *sig)
427c2cf2d55Stb {
428c2cf2d55Stb 	if (sig == NULL)
429c2cf2d55Stb 		return;
430c2cf2d55Stb 
431c2cf2d55Stb 	BN_free(sig->r);
432c2cf2d55Stb 	BN_free(sig->s);
433c2cf2d55Stb 	free(sig);
434c2cf2d55Stb }
43581dbdadeSbeck LCRYPTO_ALIAS(DSA_SIG_free);
436c2cf2d55Stb 
437c2cf2d55Stb int
DSA_sign_setup(DSA * dsa,BN_CTX * ctx_in,BIGNUM ** kinvp,BIGNUM ** rp)438c2cf2d55Stb DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
439c2cf2d55Stb {
440c2cf2d55Stb 	return dsa->meth->dsa_sign_setup(dsa, ctx_in, kinvp, rp);
441c2cf2d55Stb }
44281dbdadeSbeck LCRYPTO_ALIAS(DSA_sign_setup);
443c2cf2d55Stb 
444c2cf2d55Stb DSA_SIG *
DSA_do_sign(const unsigned char * dgst,int dlen,DSA * dsa)445c2cf2d55Stb DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
446c2cf2d55Stb {
447c2cf2d55Stb 	return dsa->meth->dsa_do_sign(dgst, dlen, dsa);
448c2cf2d55Stb }
44981dbdadeSbeck LCRYPTO_ALIAS(DSA_do_sign);
450c2cf2d55Stb 
451c2cf2d55Stb int
DSA_do_verify(const unsigned char * dgst,int dgst_len,DSA_SIG * sig,DSA * dsa)452c2cf2d55Stb DSA_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa)
453c2cf2d55Stb {
454c2cf2d55Stb 	return dsa->meth->dsa_do_verify(dgst, dgst_len, sig, dsa);
455c2cf2d55Stb }
45681dbdadeSbeck LCRYPTO_ALIAS(DSA_do_verify);
457