1 /*
2  *
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifdef FREEBL_NO_DEPEND
8 #include "stubs.h"
9 #endif
10 
11 #include "prerror.h"
12 #include "secerr.h"
13 
14 #include "prtypes.h"
15 #include "prinit.h"
16 #include "blapi.h"
17 #include "nssilock.h"
18 #include "secitem.h"
19 #include "blapit.h"
20 #include "mpi.h"
21 #include "secmpi.h"
22 #include "pqg.h"
23 
24 /*
25  * FIPS 186-2 requires result from random output to be reduced mod q when
26  * generating random numbers for DSA.
27  *
28  * Input: w, 2*qLen bytes
29  *        q, qLen bytes
30  * Output: xj, qLen bytes
31  */
32 static SECStatus
fips186Change_ReduceModQForDSA(const PRUint8 * w,const PRUint8 * q,unsigned int qLen,PRUint8 * xj)33 fips186Change_ReduceModQForDSA(const PRUint8 *w, const PRUint8 *q,
34                                unsigned int qLen, PRUint8 *xj)
35 {
36     mp_int W, Q, Xj;
37     mp_err err;
38     SECStatus rv = SECSuccess;
39 
40     /* Initialize MPI integers. */
41     MP_DIGITS(&W) = 0;
42     MP_DIGITS(&Q) = 0;
43     MP_DIGITS(&Xj) = 0;
44     CHECK_MPI_OK(mp_init(&W));
45     CHECK_MPI_OK(mp_init(&Q));
46     CHECK_MPI_OK(mp_init(&Xj));
47     /*
48      * Convert input arguments into MPI integers.
49      */
50     CHECK_MPI_OK(mp_read_unsigned_octets(&W, w, 2 * qLen));
51     CHECK_MPI_OK(mp_read_unsigned_octets(&Q, q, qLen));
52 
53     /*
54      * Algorithm 1 of FIPS 186-2 Change Notice 1, Step 3.3
55      *
56      * xj = (w0 || w1) mod q
57      */
58     CHECK_MPI_OK(mp_mod(&W, &Q, &Xj));
59     CHECK_MPI_OK(mp_to_fixlen_octets(&Xj, xj, qLen));
60 cleanup:
61     mp_clear(&W);
62     mp_clear(&Q);
63     mp_clear(&Xj);
64     if (err) {
65         MP_TO_SEC_ERROR(err);
66         rv = SECFailure;
67     }
68     return rv;
69 }
70 
71 /*
72  * FIPS 186-2 requires result from random output to be reduced mod q when
73  * generating random numbers for DSA.
74  */
75 SECStatus
FIPS186Change_ReduceModQForDSA(const unsigned char * w,const unsigned char * q,unsigned char * xj)76 FIPS186Change_ReduceModQForDSA(const unsigned char *w,
77                                const unsigned char *q,
78                                unsigned char *xj)
79 {
80     return fips186Change_ReduceModQForDSA(w, q, DSA1_SUBPRIME_LEN, xj);
81 }
82 
83 /*
84  * The core of Algorithm 1 of FIPS 186-2 Change Notice 1.
85  *
86  * We no longer support FIPS 186-2 RNG. This function was exported
87  * for power-up self tests and FIPS tests. Keep this stub, which fails,
88  * to prevent crashes, but also to signal to test code that FIPS 186-2
89  * RNG is no longer supported.
90  */
91 SECStatus
FIPS186Change_GenerateX(PRUint8 * XKEY,const PRUint8 * XSEEDj,PRUint8 * x_j)92 FIPS186Change_GenerateX(PRUint8 *XKEY, const PRUint8 *XSEEDj,
93                         PRUint8 *x_j)
94 {
95     PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
96     return SECFailure;
97 }
98 
99 /*
100  * Specialized RNG for DSA
101  *
102  * As per Algorithm 1 of FIPS 186-2 Change Notice 1, in step 3.3 the value
103  * Xj should be reduced mod q, a 160-bit prime number.  Since this parameter
104  * is only meaningful in the context of DSA, the above RNG functions
105  * were implemented without it.  They are re-implemented below for use
106  * with DSA.
107  */
108 
109 /*
110 ** Generate some random bytes, using the global random number generator
111 ** object.  In DSA mode, so there is a q.
112 */
113 static SECStatus
dsa_GenerateGlobalRandomBytes(const SECItem * qItem,PRUint8 * dest,unsigned int * destLen,unsigned int maxDestLen)114 dsa_GenerateGlobalRandomBytes(const SECItem *qItem, PRUint8 *dest,
115                               unsigned int *destLen, unsigned int maxDestLen)
116 {
117     SECStatus rv;
118     SECItem w;
119     const PRUint8 *q = qItem->data;
120     unsigned int qLen = qItem->len;
121 
122     if (*q == 0) {
123         ++q;
124         --qLen;
125     }
126     if (maxDestLen < qLen) {
127         /* This condition can occur when DSA_SignDigest is passed a group
128            with a subprime that is larger than DSA_MAX_SUBPRIME_LEN. */
129         PORT_SetError(SEC_ERROR_INVALID_ARGS);
130         return SECFailure;
131     }
132     w.data = NULL; /* otherwise SECITEM_AllocItem asserts */
133     if (!SECITEM_AllocItem(NULL, &w, 2 * qLen)) {
134         return SECFailure;
135     }
136     *destLen = qLen;
137 
138     rv = RNG_GenerateGlobalRandomBytes(w.data, w.len);
139     if (rv == SECSuccess) {
140         rv = fips186Change_ReduceModQForDSA(w.data, q, qLen, dest);
141     }
142 
143     SECITEM_FreeItem(&w, PR_FALSE);
144     return rv;
145 }
146 
147 static void
translate_mpi_error(mp_err err)148 translate_mpi_error(mp_err err)
149 {
150     MP_TO_SEC_ERROR(err);
151 }
152 
153 static SECStatus
dsa_NewKeyExtended(const PQGParams * params,const SECItem * seed,DSAPrivateKey ** privKey)154 dsa_NewKeyExtended(const PQGParams *params, const SECItem *seed,
155                    DSAPrivateKey **privKey)
156 {
157     mp_int p, g;
158     mp_int x, y;
159     mp_err err;
160     PLArenaPool *arena;
161     DSAPrivateKey *key;
162     /* Check args. */
163     if (!params || !privKey || !seed || !seed->data) {
164         PORT_SetError(SEC_ERROR_INVALID_ARGS);
165         return SECFailure;
166     }
167     /* Initialize an arena for the DSA key. */
168     arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
169     if (!arena) {
170         PORT_SetError(SEC_ERROR_NO_MEMORY);
171         return SECFailure;
172     }
173     key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey));
174     if (!key) {
175         PORT_SetError(SEC_ERROR_NO_MEMORY);
176         PORT_FreeArena(arena, PR_TRUE);
177         return SECFailure;
178     }
179     key->params.arena = arena;
180     /* Initialize MPI integers. */
181     MP_DIGITS(&p) = 0;
182     MP_DIGITS(&g) = 0;
183     MP_DIGITS(&x) = 0;
184     MP_DIGITS(&y) = 0;
185     CHECK_MPI_OK(mp_init(&p));
186     CHECK_MPI_OK(mp_init(&g));
187     CHECK_MPI_OK(mp_init(&x));
188     CHECK_MPI_OK(mp_init(&y));
189     /* Copy over the PQG params */
190     CHECK_MPI_OK(SECITEM_CopyItem(arena, &key->params.prime,
191                                   &params->prime));
192     CHECK_MPI_OK(SECITEM_CopyItem(arena, &key->params.subPrime,
193                                   &params->subPrime));
194     CHECK_MPI_OK(SECITEM_CopyItem(arena, &key->params.base, &params->base));
195     /* Convert stored p, g, and received x into MPI integers. */
196     SECITEM_TO_MPINT(params->prime, &p);
197     SECITEM_TO_MPINT(params->base, &g);
198     OCTETS_TO_MPINT(seed->data, &x, seed->len);
199     /* Store x in private key */
200     SECITEM_AllocItem(arena, &key->privateValue, seed->len);
201     PORT_Memcpy(key->privateValue.data, seed->data, seed->len);
202     /* Compute public key y = g**x mod p */
203     CHECK_MPI_OK(mp_exptmod(&g, &x, &p, &y));
204     /* Store y in public key */
205     MPINT_TO_SECITEM(&y, &key->publicValue, arena);
206     *privKey = key;
207     key = NULL;
208 cleanup:
209     mp_clear(&p);
210     mp_clear(&g);
211     mp_clear(&x);
212     mp_clear(&y);
213     if (key) {
214         PORT_FreeArena(key->params.arena, PR_TRUE);
215     }
216     if (err) {
217         translate_mpi_error(err);
218         return SECFailure;
219     }
220     return SECSuccess;
221 }
222 
223 SECStatus
DSA_NewRandom(PLArenaPool * arena,const SECItem * q,SECItem * seed)224 DSA_NewRandom(PLArenaPool *arena, const SECItem *q, SECItem *seed)
225 {
226     int retries = 10;
227     unsigned int i;
228     PRBool good;
229 
230     if (q == NULL || q->data == NULL || q->len == 0 ||
231         (q->data[0] == 0 && q->len == 1)) {
232         PORT_SetError(SEC_ERROR_INVALID_ARGS);
233         return SECFailure;
234     }
235 
236     if (!SECITEM_AllocItem(arena, seed, q->len)) {
237         return SECFailure;
238     }
239 
240     do {
241         /* Generate seed bytes for x according to FIPS 186-1 appendix 3 */
242         if (dsa_GenerateGlobalRandomBytes(q, seed->data, &seed->len,
243                                           seed->len)) {
244             goto loser;
245         }
246         /* Disallow values of 0 and 1 for x. */
247         good = PR_FALSE;
248         for (i = 0; i < seed->len - 1; i++) {
249             if (seed->data[i] != 0) {
250                 good = PR_TRUE;
251                 break;
252             }
253         }
254         if (!good && seed->data[i] > 1) {
255             good = PR_TRUE;
256         }
257     } while (!good && --retries > 0);
258 
259     if (!good) {
260         PORT_SetError(SEC_ERROR_NEED_RANDOM);
261     loser:
262         if (arena != NULL) {
263             SECITEM_ZfreeItem(seed, PR_FALSE);
264         }
265         return SECFailure;
266     }
267 
268     return SECSuccess;
269 }
270 
271 /*
272 ** Generate and return a new DSA public and private key pair,
273 **  both of which are encoded into a single DSAPrivateKey struct.
274 **  "params" is a pointer to the PQG parameters for the domain
275 **  Uses a random seed.
276 */
277 SECStatus
DSA_NewKey(const PQGParams * params,DSAPrivateKey ** privKey)278 DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey)
279 {
280     SECItem seed;
281     SECStatus rv;
282 
283     rv = PQG_Check(params);
284     if (rv != SECSuccess) {
285         return rv;
286     }
287     seed.data = NULL;
288 
289     rv = DSA_NewRandom(NULL, &params->subPrime, &seed);
290     if (rv == SECSuccess) {
291         if (seed.len != PQG_GetLength(&params->subPrime)) {
292             PORT_SetError(SEC_ERROR_INVALID_ARGS);
293             rv = SECFailure;
294         } else {
295             rv = dsa_NewKeyExtended(params, &seed, privKey);
296         }
297     }
298     SECITEM_ZfreeItem(&seed, PR_FALSE);
299     return rv;
300 }
301 
302 /* For FIPS compliance testing. Seed must be exactly the size of subPrime  */
303 SECStatus
DSA_NewKeyFromSeed(const PQGParams * params,const unsigned char * seed,DSAPrivateKey ** privKey)304 DSA_NewKeyFromSeed(const PQGParams *params,
305                    const unsigned char *seed,
306                    DSAPrivateKey **privKey)
307 {
308     SECItem seedItem;
309     seedItem.data = (unsigned char *)seed;
310     seedItem.len = PQG_GetLength(&params->subPrime);
311     return dsa_NewKeyExtended(params, &seedItem, privKey);
312 }
313 
314 static SECStatus
dsa_SignDigest(DSAPrivateKey * key,SECItem * signature,const SECItem * digest,const unsigned char * kbytes)315 dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
316                const unsigned char *kbytes)
317 {
318     mp_int p, q, g; /* PQG parameters */
319     mp_int x, k;    /* private key & pseudo-random integer */
320     mp_int r, s;    /* tuple (r, s) is signature) */
321     mp_int t;       /* holding tmp values */
322     mp_int ar;      /* holding blinding values */
323     mp_digit fuzz;  /* blinding multiplier for q */
324     mp_err err = MP_OKAY;
325     SECStatus rv = SECSuccess;
326     unsigned int dsa_subprime_len, dsa_signature_len, offset;
327     SECItem localDigest;
328     unsigned char localDigestData[DSA_MAX_SUBPRIME_LEN];
329     SECItem t2 = { siBuffer, NULL, 0 };
330 
331     /* FIPS-compliance dictates that digest is a SHA hash. */
332     /* Check args. */
333     if (!key || !signature || !digest) {
334         PORT_SetError(SEC_ERROR_INVALID_ARGS);
335         return SECFailure;
336     }
337 
338     dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
339     dsa_signature_len = dsa_subprime_len * 2;
340     if ((signature->len < dsa_signature_len) ||
341         (digest->len > HASH_LENGTH_MAX) ||
342         (digest->len < SHA1_LENGTH)) {
343         PORT_SetError(SEC_ERROR_INVALID_ARGS);
344         return SECFailure;
345     }
346 
347     /* DSA accepts digests not equal to dsa_subprime_len, if the
348      * digests are greater, then they are truncated to the size of
349      * dsa_subprime_len, using the left most bits. If they are less
350      * then they are padded on the left.*/
351     PORT_Memset(localDigestData, 0, dsa_subprime_len);
352     offset = (digest->len < dsa_subprime_len) ? (dsa_subprime_len - digest->len) : 0;
353     PORT_Memcpy(localDigestData + offset, digest->data,
354                 dsa_subprime_len - offset);
355     localDigest.data = localDigestData;
356     localDigest.len = dsa_subprime_len;
357 
358     /* Initialize MPI integers. */
359     MP_DIGITS(&p) = 0;
360     MP_DIGITS(&q) = 0;
361     MP_DIGITS(&g) = 0;
362     MP_DIGITS(&x) = 0;
363     MP_DIGITS(&k) = 0;
364     MP_DIGITS(&r) = 0;
365     MP_DIGITS(&s) = 0;
366     MP_DIGITS(&t) = 0;
367     MP_DIGITS(&ar) = 0;
368     CHECK_MPI_OK(mp_init(&p));
369     CHECK_MPI_OK(mp_init(&q));
370     CHECK_MPI_OK(mp_init(&g));
371     CHECK_MPI_OK(mp_init(&x));
372     CHECK_MPI_OK(mp_init(&k));
373     CHECK_MPI_OK(mp_init(&r));
374     CHECK_MPI_OK(mp_init(&s));
375     CHECK_MPI_OK(mp_init(&t));
376     CHECK_MPI_OK(mp_init(&ar));
377 
378     /*
379     ** Convert stored PQG and private key into MPI integers.
380     */
381     SECITEM_TO_MPINT(key->params.prime, &p);
382     SECITEM_TO_MPINT(key->params.subPrime, &q);
383     SECITEM_TO_MPINT(key->params.base, &g);
384     SECITEM_TO_MPINT(key->privateValue, &x);
385     OCTETS_TO_MPINT(kbytes, &k, dsa_subprime_len);
386 
387     /* k blinding  create a single value that has the high bit set in
388      * the mp_digit*/
389     if (RNG_GenerateGlobalRandomBytes(&fuzz, sizeof(mp_digit)) != SECSuccess) {
390         PORT_SetError(SEC_ERROR_NEED_RANDOM);
391         rv = SECFailure;
392         goto cleanup;
393     }
394     fuzz |= 1ULL << ((sizeof(mp_digit) * PR_BITS_PER_BYTE - 1));
395     /*
396     ** FIPS 186-1, Section 5, Step 1
397     **
398     ** r = (g**k mod p) mod q
399     */
400     CHECK_MPI_OK(mp_mul_d(&q, fuzz, &t)); /* t = q*fuzz */
401     CHECK_MPI_OK(mp_add(&k, &t, &t));     /* t = k+q*fuzz */
402     /* length of t is now fixed, bits in k have been blinded */
403     CHECK_MPI_OK(mp_exptmod(&g, &t, &p, &r)); /* r = g**t mod p */
404     /* r is now g**(k+q*fuzz) == g**k mod p */
405     CHECK_MPI_OK(mp_mod(&r, &q, &r)); /* r = r mod q    */
406     /* make sure fuzz is cleared off the stack and not optimized away */
407     *(volatile mp_digit *)&fuzz = 0;
408 
409     /*
410     ** FIPS 186-1, Section 5, Step 2
411     **
412     ** s = (k**-1 * (HASH(M) + x*r)) mod q
413     */
414     if (DSA_NewRandom(NULL, &key->params.subPrime, &t2) != SECSuccess) {
415         PORT_SetError(SEC_ERROR_NEED_RANDOM);
416         rv = SECFailure;
417         goto cleanup;
418     }
419     SECITEM_TO_MPINT(t2, &t); /* t <-$ Zq */
420     SECITEM_ZfreeItem(&t2, PR_FALSE);
421     if (DSA_NewRandom(NULL, &key->params.subPrime, &t2) != SECSuccess) {
422         PORT_SetError(SEC_ERROR_NEED_RANDOM);
423         rv = SECFailure;
424         goto cleanup;
425     }
426     SECITEM_TO_MPINT(t2, &ar); /* ar <-$ Zq */
427     SECITEM_ZfreeItem(&t2, PR_FALSE);
428 
429     /* Using mp_invmod on k directly would leak bits from k. */
430     CHECK_MPI_OK(mp_mul(&k, &ar, &k));       /* k = k * ar */
431     CHECK_MPI_OK(mp_mulmod(&k, &t, &q, &k)); /* k = k * t mod q */
432     /* k is now k*t*ar */
433     CHECK_MPI_OK(mp_invmod(&k, &q, &k)); /* k = k**-1 mod q */
434     /* k is now (k*t*ar)**-1 */
435     CHECK_MPI_OK(mp_mulmod(&k, &t, &q, &k)); /* k = k * t mod q */
436     /* k is now (k*ar)**-1 */
437     SECITEM_TO_MPINT(localDigest, &s); /* s = HASH(M)     */
438     /* To avoid leaking secret bits here the addition is blinded. */
439     CHECK_MPI_OK(mp_mul(&x, &ar, &x)); /* x = x * ar */
440     /* x is now x*ar */
441     CHECK_MPI_OK(mp_mulmod(&x, &r, &q, &x)); /* x = x * r mod q */
442     /* x is now x*r*ar */
443     CHECK_MPI_OK(mp_mulmod(&s, &ar, &q, &t)); /* t = s * ar mod q */
444     /* t is now hash(M)*ar */
445     CHECK_MPI_OK(mp_add(&t, &x, &s)); /* s = t + x */
446     /* s is now (HASH(M)+x*r)*ar */
447     CHECK_MPI_OK(mp_mulmod(&s, &k, &q, &s)); /* s = s * k mod q */
448     /* s is now (HASH(M)+x*r)*ar*(k*ar)**-1 = (k**-1)*(HASH(M)+x*r) */
449 
450     /*
451     ** verify r != 0 and s != 0
452     ** mentioned as optional in FIPS 186-1.
453     */
454     if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) {
455         PORT_SetError(SEC_ERROR_NEED_RANDOM);
456         rv = SECFailure;
457         goto cleanup;
458     }
459     /*
460     ** Step 4
461     **
462     ** Signature is tuple (r, s)
463     */
464     err = mp_to_fixlen_octets(&r, signature->data, dsa_subprime_len);
465     if (err < 0)
466         goto cleanup;
467     err = mp_to_fixlen_octets(&s, signature->data + dsa_subprime_len,
468                               dsa_subprime_len);
469     if (err < 0)
470         goto cleanup;
471     err = MP_OKAY;
472     signature->len = dsa_signature_len;
473 cleanup:
474     PORT_Memset(localDigestData, 0, DSA_MAX_SUBPRIME_LEN);
475     mp_clear(&p);
476     mp_clear(&q);
477     mp_clear(&g);
478     mp_clear(&x);
479     mp_clear(&k);
480     mp_clear(&r);
481     mp_clear(&s);
482     mp_clear(&t);
483     mp_clear(&ar);
484     if (err) {
485         translate_mpi_error(err);
486         rv = SECFailure;
487     }
488     return rv;
489 }
490 
491 /* signature is caller-supplied buffer of at least 40 bytes.
492 ** On input,  signature->len == size of buffer to hold signature.
493 **            digest->len    == size of digest.
494 ** On output, signature->len == size of signature in buffer.
495 ** Uses a random seed.
496 */
497 SECStatus
DSA_SignDigest(DSAPrivateKey * key,SECItem * signature,const SECItem * digest)498 DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest)
499 {
500     SECStatus rv;
501     int retries = 10;
502     unsigned char kSeed[DSA_MAX_SUBPRIME_LEN];
503     unsigned int kSeedLen = 0;
504     unsigned int i;
505     unsigned int dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
506     PRBool good;
507 
508     PORT_SetError(0);
509     do {
510         rv = dsa_GenerateGlobalRandomBytes(&key->params.subPrime,
511                                            kSeed, &kSeedLen, sizeof kSeed);
512         if (rv != SECSuccess)
513             break;
514         if (kSeedLen != dsa_subprime_len) {
515             PORT_SetError(SEC_ERROR_INVALID_ARGS);
516             rv = SECFailure;
517             break;
518         }
519         /* Disallow a value of 0 for k. */
520         good = PR_FALSE;
521         for (i = 0; i < kSeedLen; i++) {
522             if (kSeed[i] != 0) {
523                 good = PR_TRUE;
524                 break;
525             }
526         }
527         if (!good) {
528             PORT_SetError(SEC_ERROR_NEED_RANDOM);
529             rv = SECFailure;
530             continue;
531         }
532         rv = dsa_SignDigest(key, signature, digest, kSeed);
533     } while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM &&
534              --retries > 0);
535     PORT_Memset(kSeed, 0, sizeof kSeed);
536     return rv;
537 }
538 
539 /* For FIPS compliance testing. Seed must be exactly 20 bytes. */
540 SECStatus
DSA_SignDigestWithSeed(DSAPrivateKey * key,SECItem * signature,const SECItem * digest,const unsigned char * seed)541 DSA_SignDigestWithSeed(DSAPrivateKey *key,
542                        SECItem *signature,
543                        const SECItem *digest,
544                        const unsigned char *seed)
545 {
546     SECStatus rv;
547     rv = dsa_SignDigest(key, signature, digest, seed);
548     return rv;
549 }
550 
551 /* signature is caller-supplied buffer of at least 20 bytes.
552 ** On input,  signature->len == size of buffer to hold signature.
553 **            digest->len    == size of digest.
554 */
555 SECStatus
DSA_VerifyDigest(DSAPublicKey * key,const SECItem * signature,const SECItem * digest)556 DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
557                  const SECItem *digest)
558 {
559     /* FIPS-compliance dictates that digest is a SHA hash. */
560     mp_int p, q, g;      /* PQG parameters */
561     mp_int r_, s_;       /* tuple (r', s') is received signature) */
562     mp_int u1, u2, v, w; /* intermediate values used in verification */
563     mp_int y;            /* public key */
564     mp_err err;
565     unsigned int dsa_subprime_len, dsa_signature_len, offset;
566     SECItem localDigest;
567     unsigned char localDigestData[DSA_MAX_SUBPRIME_LEN];
568     SECStatus verified = SECFailure;
569 
570     /* Check args. */
571     if (!key || !signature || !digest) {
572         PORT_SetError(SEC_ERROR_INVALID_ARGS);
573         return SECFailure;
574     }
575 
576     dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
577     dsa_signature_len = dsa_subprime_len * 2;
578     if ((signature->len != dsa_signature_len) ||
579         (digest->len > HASH_LENGTH_MAX) ||
580         (digest->len < SHA1_LENGTH)) {
581         PORT_SetError(SEC_ERROR_INVALID_ARGS);
582         return SECFailure;
583     }
584 
585     /* DSA accepts digests not equal to dsa_subprime_len, if the
586      * digests are greater, than they are truncated to the size of
587      * dsa_subprime_len, using the left most bits. If they are less
588      * then they are padded on the left.*/
589     PORT_Memset(localDigestData, 0, dsa_subprime_len);
590     offset = (digest->len < dsa_subprime_len) ? (dsa_subprime_len - digest->len) : 0;
591     PORT_Memcpy(localDigestData + offset, digest->data,
592                 dsa_subprime_len - offset);
593     localDigest.data = localDigestData;
594     localDigest.len = dsa_subprime_len;
595 
596     /* Initialize MPI integers. */
597     MP_DIGITS(&p) = 0;
598     MP_DIGITS(&q) = 0;
599     MP_DIGITS(&g) = 0;
600     MP_DIGITS(&y) = 0;
601     MP_DIGITS(&r_) = 0;
602     MP_DIGITS(&s_) = 0;
603     MP_DIGITS(&u1) = 0;
604     MP_DIGITS(&u2) = 0;
605     MP_DIGITS(&v) = 0;
606     MP_DIGITS(&w) = 0;
607     CHECK_MPI_OK(mp_init(&p));
608     CHECK_MPI_OK(mp_init(&q));
609     CHECK_MPI_OK(mp_init(&g));
610     CHECK_MPI_OK(mp_init(&y));
611     CHECK_MPI_OK(mp_init(&r_));
612     CHECK_MPI_OK(mp_init(&s_));
613     CHECK_MPI_OK(mp_init(&u1));
614     CHECK_MPI_OK(mp_init(&u2));
615     CHECK_MPI_OK(mp_init(&v));
616     CHECK_MPI_OK(mp_init(&w));
617     /*
618     ** Convert stored PQG and public key into MPI integers.
619     */
620     SECITEM_TO_MPINT(key->params.prime, &p);
621     SECITEM_TO_MPINT(key->params.subPrime, &q);
622     SECITEM_TO_MPINT(key->params.base, &g);
623     SECITEM_TO_MPINT(key->publicValue, &y);
624     /*
625     ** Convert received signature (r', s') into MPI integers.
626     */
627     OCTETS_TO_MPINT(signature->data, &r_, dsa_subprime_len);
628     OCTETS_TO_MPINT(signature->data + dsa_subprime_len, &s_, dsa_subprime_len);
629     /*
630     ** Verify that 0 < r' < q and 0 < s' < q
631     */
632     if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
633         mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0) {
634         /* err is zero here. */
635         PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
636         goto cleanup; /* will return verified == SECFailure */
637     }
638     /*
639     ** FIPS 186-1, Section 6, Step 1
640     **
641     ** w = (s')**-1 mod q
642     */
643     CHECK_MPI_OK(mp_invmod(&s_, &q, &w)); /* w = (s')**-1 mod q */
644     /*
645     ** FIPS 186-1, Section 6, Step 2
646     **
647     ** u1 = ((Hash(M')) * w) mod q
648     */
649     SECITEM_TO_MPINT(localDigest, &u1);        /* u1 = HASH(M')     */
650     CHECK_MPI_OK(mp_mulmod(&u1, &w, &q, &u1)); /* u1 = u1 * w mod q */
651     /*
652     ** FIPS 186-1, Section 6, Step 3
653     **
654     ** u2 = ((r') * w) mod q
655     */
656     CHECK_MPI_OK(mp_mulmod(&r_, &w, &q, &u2));
657     /*
658     ** FIPS 186-1, Section 6, Step 4
659     **
660     ** v = ((g**u1 * y**u2) mod p) mod q
661     */
662     CHECK_MPI_OK(mp_exptmod(&g, &u1, &p, &g)); /* g = g**u1 mod p */
663     CHECK_MPI_OK(mp_exptmod(&y, &u2, &p, &y)); /* y = y**u2 mod p */
664     CHECK_MPI_OK(mp_mulmod(&g, &y, &p, &v));   /* v = g * y mod p */
665     CHECK_MPI_OK(mp_mod(&v, &q, &v));          /* v = v mod q     */
666     /*
667     ** Verification:  v == r'
668     */
669     if (mp_cmp(&v, &r_)) {
670         PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
671         verified = SECFailure; /* Signature failed to verify. */
672     } else {
673         verified = SECSuccess; /* Signature verified. */
674     }
675 cleanup:
676     PORT_Memset(localDigestData, 0, sizeof localDigestData);
677     mp_clear(&p);
678     mp_clear(&q);
679     mp_clear(&g);
680     mp_clear(&y);
681     mp_clear(&r_);
682     mp_clear(&s_);
683     mp_clear(&u1);
684     mp_clear(&u2);
685     mp_clear(&v);
686     mp_clear(&w);
687     if (err) {
688         translate_mpi_error(err);
689     }
690     return verified;
691 }
692