Exclude the option for passing parameters pre-computed in unverified way.
[oweals/openssl.git] / fips / dsa / fips_dsa_ossl.c
1 /* crypto/dsa/dsa_ossl.c */
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 #include <openssl/bn.h>
63 #include <openssl/dsa.h>
64 #include <openssl/rand.h>
65 #include <openssl/asn1.h>
66 #ifndef OPENSSL_NO_ENGINE
67 #include <openssl/engine.h>
68 #endif
69 #include <openssl/fips.h>
70
71 #ifdef OPENSSL_FIPS
72
73 static DSA_SIG *dsa_do_sign(const unsigned char *dgst, FIPS_DSA_SIZE_T dlen, DSA *dsa);
74 static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp);
75 static int dsa_do_verify(const unsigned char *dgst, FIPS_DSA_SIZE_T dgst_len, DSA_SIG *sig,
76                   DSA *dsa);
77 static int dsa_init(DSA *dsa);
78 static int dsa_finish(DSA *dsa);
79 static int dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1,
80                 BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx,
81                 BN_MONT_CTX *in_mont);
82 static int dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
83                                 const BIGNUM *m, BN_CTX *ctx,
84                                 BN_MONT_CTX *m_ctx);
85
86 static const DSA_METHOD openssl_dsa_meth = {
87 "OpenSSL FIPS DSA method",
88 dsa_do_sign,
89 dsa_sign_setup,
90 dsa_do_verify,
91 dsa_mod_exp,
92 dsa_bn_mod_exp,
93 dsa_init,
94 dsa_finish,
95 0,
96 NULL
97 };
98
99 int FIPS_dsa_check(struct dsa_st *dsa)
100     {
101     if(dsa->meth != &openssl_dsa_meth || dsa->meth->dsa_do_sign != dsa_do_sign
102        || dsa->meth->dsa_sign_setup != dsa_sign_setup
103        || dsa->meth->dsa_mod_exp != dsa_mod_exp
104        || dsa->meth->bn_mod_exp != dsa_bn_mod_exp
105        || dsa->meth->init != dsa_init
106        || dsa->meth->finish != dsa_finish)
107         {
108         FIPSerr(FIPS_F_FIPS_DSA_CHECK,FIPS_R_NON_FIPS_METHOD);
109         return 0;
110         }
111     return 1;
112     }
113
114 const DSA_METHOD *DSA_OpenSSL(void)
115 {
116         return &openssl_dsa_meth;
117 }
118
119 static DSA_SIG *dsa_do_sign(const unsigned char *dgst, FIPS_DSA_SIZE_T dlen, DSA *dsa)
120         {
121         BIGNUM *kinv=NULL,*r=NULL,*s=NULL;
122         BIGNUM m;
123         BIGNUM xr;
124         BN_CTX *ctx=NULL;
125         int i,reason=ERR_R_BN_LIB;
126         DSA_SIG *ret=NULL;
127
128         if(FIPS_selftest_failed())
129             {
130             FIPSerr(FIPS_F_DSA_DO_SIGN,FIPS_R_FIPS_SELFTEST_FAILED);
131             return NULL;
132             }
133
134         BN_init(&m);
135         BN_init(&xr);
136
137         if (!dsa->p || !dsa->q || !dsa->g)
138                 {
139                 reason=DSA_R_MISSING_PARAMETERS;
140                 goto err;
141                 }
142
143         s=BN_new();
144         if (s == NULL) goto err;
145
146         i=BN_num_bytes(dsa->q); /* should be 20 */
147         if ((dlen > i) || (dlen > 50))
148                 {
149                 reason=DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE;
150                 goto err;
151                 }
152
153         ctx=BN_CTX_new();
154         if (ctx == NULL) goto err;
155
156         if (!DSA_sign_setup(dsa,ctx,&kinv,&r)) goto err;
157
158         if (BN_bin2bn(dgst,dlen,&m) == NULL) goto err;
159
160         /* Compute  s = inv(k) (m + xr) mod q */
161         if (!BN_mod_mul(&xr,dsa->priv_key,r,dsa->q,ctx)) goto err;/* s = xr */
162         if (!BN_add(s, &xr, &m)) goto err;              /* s = m + xr */
163         if (BN_cmp(s,dsa->q) > 0)
164                 BN_sub(s,s,dsa->q);
165         if (!BN_mod_mul(s,s,kinv,dsa->q,ctx)) goto err;
166
167         ret=DSA_SIG_new();
168         if (ret == NULL) goto err;
169         ret->r = r;
170         ret->s = s;
171         
172 err:
173         if (!ret)
174                 {
175                 DSAerr(DSA_F_DSA_DO_SIGN,reason);
176                 BN_free(r);
177                 BN_free(s);
178                 }
179         if (ctx != NULL) BN_CTX_free(ctx);
180         BN_clear_free(&m);
181         BN_clear_free(&xr);
182         if (kinv != NULL) /* dsa->kinv is NULL now if we used it */
183             BN_clear_free(kinv);
184         return(ret);
185         }
186
187 static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
188         {
189         BN_CTX *ctx;
190         BIGNUM k,*kinv=NULL,*r=NULL;
191         int ret=0;
192
193         if (!dsa->p || !dsa->q || !dsa->g)
194                 {
195                 DSAerr(DSA_F_DSA_SIGN_SETUP,DSA_R_MISSING_PARAMETERS);
196                 return 0;
197                 }
198
199         BN_init(&k);
200
201         if (ctx_in == NULL)
202                 {
203                 if ((ctx=BN_CTX_new()) == NULL) goto err;
204                 }
205         else
206                 ctx=ctx_in;
207
208         if ((r=BN_new()) == NULL) goto err;
209         kinv=NULL;
210
211         /* Get random k */
212         do
213                 if (!BN_rand_range(&k, dsa->q)) goto err;
214         while (BN_is_zero(&k));
215
216         if (dsa->flags & DSA_FLAG_CACHE_MONT_P)
217                 {
218                 if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
219                                                 CRYPTO_LOCK_DSA,
220                                                 dsa->p, ctx))
221                         goto err;
222                 }
223
224         /* Compute r = (g^k mod p) mod q */
225         if (!dsa->meth->bn_mod_exp(dsa, r,dsa->g,&k,dsa->p,ctx,
226                 (BN_MONT_CTX *)dsa->method_mont_p)) goto err;
227         if (!BN_mod(r,r,dsa->q,ctx)) goto err;
228
229         /* Compute  part of 's = inv(k) (m + xr) mod q' */
230         if ((kinv=BN_mod_inverse(NULL,&k,dsa->q,ctx)) == NULL) goto err;
231
232         if (*kinvp != NULL) BN_clear_free(*kinvp);
233         *kinvp=kinv;
234         kinv=NULL;
235         if (*rp != NULL) BN_clear_free(*rp);
236         *rp=r;
237         ret=1;
238 err:
239         if (!ret)
240                 {
241                 DSAerr(DSA_F_DSA_SIGN_SETUP,ERR_R_BN_LIB);
242                 if (kinv != NULL) BN_clear_free(kinv);
243                 if (r != NULL) BN_clear_free(r);
244                 }
245         if (ctx_in == NULL) BN_CTX_free(ctx);
246         if (kinv != NULL) BN_clear_free(kinv);
247         BN_clear_free(&k);
248         return(ret);
249         }
250
251 static int dsa_do_verify(const unsigned char *dgst, FIPS_DSA_SIZE_T dgst_len, DSA_SIG *sig,
252                   DSA *dsa)
253         {
254         BN_CTX *ctx;
255         BIGNUM u1,u2,t1;
256         BN_MONT_CTX *mont=NULL;
257         int ret = -1;
258
259         if (!dsa->p || !dsa->q || !dsa->g)
260                 {
261                 DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MISSING_PARAMETERS);
262                 return -1;
263                 }
264
265         if(FIPS_selftest_failed())
266             {
267             FIPSerr(FIPS_F_DSA_DO_VERIFY,FIPS_R_FIPS_SELFTEST_FAILED);
268             return -1;
269             }
270
271         BN_init(&u1);
272         BN_init(&u2);
273         BN_init(&t1);
274
275         if ((ctx=BN_CTX_new()) == NULL) goto err;
276
277         if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0)
278                 {
279                 ret = 0;
280                 goto err;
281                 }
282         if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0)
283                 {
284                 ret = 0;
285                 goto err;
286                 }
287
288         /* Calculate W = inv(S) mod Q
289          * save W in u2 */
290         if ((BN_mod_inverse(&u2,sig->s,dsa->q,ctx)) == NULL) goto err;
291
292         /* save M in u1 */
293         if (BN_bin2bn(dgst,dgst_len,&u1) == NULL) goto err;
294
295         /* u1 = M * w mod q */
296         if (!BN_mod_mul(&u1,&u1,&u2,dsa->q,ctx)) goto err;
297
298         /* u2 = r * w mod q */
299         if (!BN_mod_mul(&u2,sig->r,&u2,dsa->q,ctx)) goto err;
300
301
302         if (dsa->flags & DSA_FLAG_CACHE_MONT_P)
303                 {
304                 mont = BN_MONT_CTX_set_locked(
305                                         (BN_MONT_CTX **)&dsa->method_mont_p,
306                                         CRYPTO_LOCK_DSA, dsa->p, ctx);
307                 if (!mont)
308                         goto err;
309                 }
310
311 #if 0
312         {
313         BIGNUM t2;
314
315         BN_init(&t2);
316         /* v = ( g^u1 * y^u2 mod p ) mod q */
317         /* let t1 = g ^ u1 mod p */
318         if (!BN_mod_exp_mont(&t1,dsa->g,&u1,dsa->p,ctx,mont)) goto err;
319         /* let t2 = y ^ u2 mod p */
320         if (!BN_mod_exp_mont(&t2,dsa->pub_key,&u2,dsa->p,ctx,mont)) goto err;
321         /* let u1 = t1 * t2 mod p */
322         if (!BN_mod_mul(&u1,&t1,&t2,dsa->p,ctx)) goto err_bn;
323         BN_free(&t2);
324         }
325         /* let u1 = u1 mod q */
326         if (!BN_mod(&u1,&u1,dsa->q,ctx)) goto err;
327 #else
328         {
329         if (!dsa->meth->dsa_mod_exp(dsa, &t1,dsa->g,&u1,dsa->pub_key,&u2,
330                                                 dsa->p,ctx,mont)) goto err;
331         /* BN_copy(&u1,&t1); */
332         /* let u1 = u1 mod q */
333         if (!BN_mod(&u1,&t1,dsa->q,ctx)) goto err;
334         }
335 #endif
336         /* V is now in u1.  If the signature is correct, it will be
337          * equal to R. */
338         ret=(BN_ucmp(&u1, sig->r) == 0);
339
340         err:
341         if (ret != 1) DSAerr(DSA_F_DSA_DO_VERIFY,ERR_R_BN_LIB);
342         if (ctx != NULL) BN_CTX_free(ctx);
343         BN_free(&u1);
344         BN_free(&u2);
345         BN_free(&t1);
346         return(ret);
347         }
348
349 static int dsa_init(DSA *dsa)
350 {
351         dsa->flags|=DSA_FLAG_CACHE_MONT_P;
352         return(1);
353 }
354
355 static int dsa_finish(DSA *dsa)
356 {
357         if(dsa->method_mont_p)
358                 BN_MONT_CTX_free((BN_MONT_CTX *)dsa->method_mont_p);
359         return(1);
360 }
361
362 static int dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1,
363                 BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx,
364                 BN_MONT_CTX *in_mont)
365 {
366         return BN_mod_exp2_mont(rr, a1, p1, a2, p2, m, ctx, in_mont);
367 }
368         
369 static int dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
370                                 const BIGNUM *m, BN_CTX *ctx,
371                                 BN_MONT_CTX *m_ctx)
372 {
373         return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
374 }
375
376 #else /* ndef OPENSSL_FIPS */
377
378 static void *dummy=&dummy;
379
380 #endif /* ndef OPENSSL_FIPS */