Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: mozilla/security/nss/lib/freebl/dsa.c

Issue 14249009: Change the NSS and NSPR source tree to the new directory structure to be (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « mozilla/security/nss/lib/freebl/drbg.c ('k') | mozilla/security/nss/lib/freebl/ec.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 /* $Id: dsa.c,v 1.23 2012/06/12 16:39:00 rrelyea%redhat.com Exp $ */
7
8 #ifdef FREEBL_NO_DEPEND
9 #include "stubs.h"
10 #endif
11
12 #include "prerror.h"
13 #include "secerr.h"
14
15 #include "prtypes.h"
16 #include "prinit.h"
17 #include "blapi.h"
18 #include "nssilock.h"
19 #include "secitem.h"
20 #include "blapi.h"
21 #include "mpi.h"
22 #include "secmpi.h"
23 #include "pqg.h"
24
25 /* XXX to be replaced by define in blapit.h */
26 #define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048
27
28 /*
29 * FIPS 186-2 requires result from random output to be reduced mod q when
30 * generating random numbers for DSA.
31 *
32 * Input: w, 2*qLen bytes
33 * q, qLen bytes
34 * Output: xj, qLen bytes
35 */
36 static SECStatus
37 fips186Change_ReduceModQForDSA(const PRUint8 *w, const PRUint8 *q,
38 unsigned int qLen, PRUint8 * xj)
39 {
40 mp_int W, Q, Xj;
41 mp_err err;
42 SECStatus rv = SECSuccess;
43
44 /* Initialize MPI integers. */
45 MP_DIGITS(&W) = 0;
46 MP_DIGITS(&Q) = 0;
47 MP_DIGITS(&Xj) = 0;
48 CHECK_MPI_OK( mp_init(&W) );
49 CHECK_MPI_OK( mp_init(&Q) );
50 CHECK_MPI_OK( mp_init(&Xj) );
51 /*
52 * Convert input arguments into MPI integers.
53 */
54 CHECK_MPI_OK( mp_read_unsigned_octets(&W, w, 2*qLen) );
55 CHECK_MPI_OK( mp_read_unsigned_octets(&Q, q, qLen) );
56
57 /*
58 * Algorithm 1 of FIPS 186-2 Change Notice 1, Step 3.3
59 *
60 * xj = (w0 || w1) mod q
61 */
62 CHECK_MPI_OK( mp_mod(&W, &Q, &Xj) );
63 CHECK_MPI_OK( mp_to_fixlen_octets(&Xj, xj, qLen) );
64 cleanup:
65 mp_clear(&W);
66 mp_clear(&Q);
67 mp_clear(&Xj);
68 if (err) {
69 MP_TO_SEC_ERROR(err);
70 rv = SECFailure;
71 }
72 return rv;
73 }
74
75 /*
76 * FIPS 186-2 requires result from random output to be reduced mod q when
77 * generating random numbers for DSA.
78 */
79 SECStatus
80 FIPS186Change_ReduceModQForDSA(const unsigned char *w,
81 const unsigned char *q,
82 unsigned char *xj) {
83 return fips186Change_ReduceModQForDSA(w, q, DSA1_SUBPRIME_LEN, xj);
84 }
85
86 /*
87 * The core of Algorithm 1 of FIPS 186-2 Change Notice 1.
88 *
89 * We no longer support FIPS 186-2 RNG. This function was exported
90 * for power-up self tests and FIPS tests. Keep this stub, which fails,
91 * to prevent crashes, but also to signal to test code that FIPS 186-2
92 * RNG is no longer supported.
93 */
94 SECStatus
95 FIPS186Change_GenerateX(PRUint8 *XKEY, const PRUint8 *XSEEDj,
96 PRUint8 *x_j)
97 {
98 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
99 return SECFailure;
100 }
101
102 /*
103 * Specialized RNG for DSA
104 *
105 * As per Algorithm 1 of FIPS 186-2 Change Notice 1, in step 3.3 the value
106 * Xj should be reduced mod q, a 160-bit prime number. Since this parameter
107 * is only meaningful in the context of DSA, the above RNG functions
108 * were implemented without it. They are re-implemented below for use
109 * with DSA.
110 */
111
112 /*
113 ** Generate some random bytes, using the global random number generator
114 ** object. In DSA mode, so there is a q.
115 */
116 static SECStatus
117 dsa_GenerateGlobalRandomBytes(const SECItem * qItem, PRUint8 * dest,
118 unsigned int * destLen, unsigned int maxDestLen)
119 {
120 SECStatus rv;
121 SECItem w;
122 const PRUint8 * q = qItem->data;
123 unsigned int qLen = qItem->len;
124
125 if (*q == 0) {
126 ++q;
127 --qLen;
128 }
129 if (maxDestLen < qLen) {
130 /* This condition can occur when DSA_SignDigest is passed a group
131 with a subprime that is larger than DSA_MAX_SUBPRIME_LEN. */
132 PORT_SetError(SEC_ERROR_INVALID_ARGS);
133 return SECFailure;
134 }
135 w.data = NULL; /* otherwise SECITEM_AllocItem asserts */
136 if (!SECITEM_AllocItem(NULL, &w, 2*qLen)) {
137 return SECFailure;
138 }
139 *destLen = qLen;
140
141 rv = RNG_GenerateGlobalRandomBytes(w.data, w.len);
142 if (rv == SECSuccess) {
143 rv = fips186Change_ReduceModQForDSA(w.data, q, qLen, dest);
144 }
145
146 SECITEM_FreeItem(&w, PR_FALSE);
147 return rv;
148 }
149
150 static void translate_mpi_error(mp_err err)
151 {
152 MP_TO_SEC_ERROR(err);
153 }
154
155 static SECStatus
156 dsa_NewKeyExtended(const PQGParams *params, const SECItem * seed,
157 DSAPrivateKey **privKey)
158 {
159 mp_int p, g;
160 mp_int x, y;
161 mp_err err;
162 PRArenaPool *arena;
163 DSAPrivateKey *key;
164 /* Check args. */
165 if (!params || !privKey || !seed || !seed->data) {
166 PORT_SetError(SEC_ERROR_INVALID_ARGS);
167 return SECFailure;
168 }
169 /* Initialize an arena for the DSA key. */
170 arena = PORT_NewArena(NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE);
171 if (!arena) {
172 PORT_SetError(SEC_ERROR_NO_MEMORY);
173 return SECFailure;
174 }
175 key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey));
176 if (!key) {
177 PORT_SetError(SEC_ERROR_NO_MEMORY);
178 PORT_FreeArena(arena, PR_TRUE);
179 return SECFailure;
180 }
181 key->params.arena = arena;
182 /* Initialize MPI integers. */
183 MP_DIGITS(&p) = 0;
184 MP_DIGITS(&g) = 0;
185 MP_DIGITS(&x) = 0;
186 MP_DIGITS(&y) = 0;
187 CHECK_MPI_OK( mp_init(&p) );
188 CHECK_MPI_OK( mp_init(&g) );
189 CHECK_MPI_OK( mp_init(&x) );
190 CHECK_MPI_OK( mp_init(&y) );
191 /* Copy over the PQG params */
192 CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.prime,
193 &params->prime) );
194 CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.subPrime,
195 &params->subPrime) );
196 CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.base, &params->base) );
197 /* Convert stored p, g, and received x into MPI integers. */
198 SECITEM_TO_MPINT(params->prime, &p);
199 SECITEM_TO_MPINT(params->base, &g);
200 OCTETS_TO_MPINT(seed->data, &x, seed->len);
201 /* Store x in private key */
202 SECITEM_AllocItem(arena, &key->privateValue, seed->len);
203 PORT_Memcpy(key->privateValue.data, seed->data, seed->len);
204 /* Compute public key y = g**x mod p */
205 CHECK_MPI_OK( mp_exptmod(&g, &x, &p, &y) );
206 /* Store y in public key */
207 MPINT_TO_SECITEM(&y, &key->publicValue, arena);
208 *privKey = key;
209 key = NULL;
210 cleanup:
211 mp_clear(&p);
212 mp_clear(&g);
213 mp_clear(&x);
214 mp_clear(&y);
215 if (key)
216 PORT_FreeArena(key->params.arena, PR_TRUE);
217 if (err) {
218 translate_mpi_error(err);
219 return SECFailure;
220 }
221 return SECSuccess;
222 }
223
224 SECStatus
225 DSA_NewRandom(PLArenaPool * arena, const SECItem * q, SECItem * seed)
226 {
227 int retries = 10;
228 unsigned int i;
229 PRBool good;
230
231 if (q == NULL || q->data == NULL || q->len == 0 ||
232 (q->data[0] == 0 && q->len == 1)) {
233 PORT_SetError(SEC_ERROR_INVALID_ARGS);
234 return SECFailure;
235 }
236
237 if (!SECITEM_AllocItem(arena, seed, q->len)) {
238 return SECFailure;
239 }
240
241 do {
242 /* Generate seed bytes for x according to FIPS 186-1 appendix 3 */
243 if (dsa_GenerateGlobalRandomBytes(q, seed->data, &seed->len,
244 seed->len)) {
245 goto loser;
246 }
247 /* Disallow values of 0 and 1 for x. */
248 good = PR_FALSE;
249 for (i = 0; i < seed->len-1; i++) {
250 if (seed->data[i] != 0) {
251 good = PR_TRUE;
252 break;
253 }
254 }
255 if (!good && seed->data[i] > 1) {
256 good = PR_TRUE;
257 }
258 } while (!good && --retries > 0);
259
260 if (!good) {
261 PORT_SetError(SEC_ERROR_NEED_RANDOM);
262 loser: if (arena != NULL) {
263 SECITEM_FreeItem(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
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_FreeItem(&seed, PR_FALSE);
299 return rv;
300 }
301
302 /* For FIPS compliance testing. Seed must be exactly the size of subPrime */
303 SECStatus
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
315 dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
316 const unsigned char *kb)
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_err err = MP_OKAY;
322 SECStatus rv = SECSuccess;
323 unsigned int dsa_subprime_len, dsa_signature_len, offset;
324 SECItem localDigest;
325 unsigned char localDigestData[DSA_MAX_SUBPRIME_LEN];
326
327
328 /* FIPS-compliance dictates that digest is a SHA hash. */
329 /* Check args. */
330 if (!key || !signature || !digest) {
331 PORT_SetError(SEC_ERROR_INVALID_ARGS);
332 return SECFailure;
333 }
334
335 dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
336 dsa_signature_len = dsa_subprime_len*2;
337 if ((signature->len < dsa_signature_len) ||
338 (digest->len > HASH_LENGTH_MAX) ||
339 (digest->len < SHA1_LENGTH)) {
340 PORT_SetError(SEC_ERROR_INVALID_ARGS);
341 return SECFailure;
342 }
343
344 /* DSA accepts digests not equal to dsa_subprime_len, if the
345 * digests are greater, then they are truncated to the size of
346 * dsa_subprime_len, using the left most bits. If they are less
347 * then they are padded on the left.*/
348 PORT_Memset(localDigestData, 0, dsa_subprime_len);
349 offset = (digest->len < dsa_subprime_len) ?
350 (dsa_subprime_len - digest->len) : 0;
351 PORT_Memcpy(localDigestData+offset, digest->data,
352 dsa_subprime_len - offset);
353 localDigest.data = localDigestData;
354 localDigest.len = dsa_subprime_len;
355
356 /* Initialize MPI integers. */
357 MP_DIGITS(&p) = 0;
358 MP_DIGITS(&q) = 0;
359 MP_DIGITS(&g) = 0;
360 MP_DIGITS(&x) = 0;
361 MP_DIGITS(&k) = 0;
362 MP_DIGITS(&r) = 0;
363 MP_DIGITS(&s) = 0;
364 CHECK_MPI_OK( mp_init(&p) );
365 CHECK_MPI_OK( mp_init(&q) );
366 CHECK_MPI_OK( mp_init(&g) );
367 CHECK_MPI_OK( mp_init(&x) );
368 CHECK_MPI_OK( mp_init(&k) );
369 CHECK_MPI_OK( mp_init(&r) );
370 CHECK_MPI_OK( mp_init(&s) );
371 /*
372 ** Convert stored PQG and private key into MPI integers.
373 */
374 SECITEM_TO_MPINT(key->params.prime, &p);
375 SECITEM_TO_MPINT(key->params.subPrime, &q);
376 SECITEM_TO_MPINT(key->params.base, &g);
377 SECITEM_TO_MPINT(key->privateValue, &x);
378 OCTETS_TO_MPINT(kb, &k, dsa_subprime_len);
379 /*
380 ** FIPS 186-1, Section 5, Step 1
381 **
382 ** r = (g**k mod p) mod q
383 */
384 CHECK_MPI_OK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */
385 CHECK_MPI_OK( mp_mod(&r, &q, &r) ); /* r = r mod q */
386 /*
387 ** FIPS 186-1, Section 5, Step 2
388 **
389 ** s = (k**-1 * (HASH(M) + x*r)) mod q
390 */
391 SECITEM_TO_MPINT(localDigest, &s); /* s = HASH(M) */
392 CHECK_MPI_OK( mp_invmod(&k, &q, &k) ); /* k = k**-1 mod q */
393 CHECK_MPI_OK( mp_mulmod(&x, &r, &q, &x) ); /* x = x * r mod q */
394 CHECK_MPI_OK( mp_addmod(&s, &x, &q, &s) ); /* s = s + x mod q */
395 CHECK_MPI_OK( mp_mulmod(&s, &k, &q, &s) ); /* s = s * k mod q */
396 /*
397 ** verify r != 0 and s != 0
398 ** mentioned as optional in FIPS 186-1.
399 */
400 if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) {
401 PORT_SetError(SEC_ERROR_NEED_RANDOM);
402 rv = SECFailure;
403 goto cleanup;
404 }
405 /*
406 ** Step 4
407 **
408 ** Signature is tuple (r, s)
409 */
410 err = mp_to_fixlen_octets(&r, signature->data, dsa_subprime_len);
411 if (err < 0) goto cleanup;
412 err = mp_to_fixlen_octets(&s, signature->data + dsa_subprime_len,
413 dsa_subprime_len);
414 if (err < 0) goto cleanup;
415 err = MP_OKAY;
416 signature->len = dsa_signature_len;
417 cleanup:
418 PORT_Memset(localDigestData, 0, DSA_MAX_SUBPRIME_LEN);
419 mp_clear(&p);
420 mp_clear(&q);
421 mp_clear(&g);
422 mp_clear(&x);
423 mp_clear(&k);
424 mp_clear(&r);
425 mp_clear(&s);
426 if (err) {
427 translate_mpi_error(err);
428 rv = SECFailure;
429 }
430 return rv;
431 }
432
433 /* signature is caller-supplied buffer of at least 40 bytes.
434 ** On input, signature->len == size of buffer to hold signature.
435 ** digest->len == size of digest.
436 ** On output, signature->len == size of signature in buffer.
437 ** Uses a random seed.
438 */
439 SECStatus
440 DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest)
441 {
442 SECStatus rv;
443 int retries = 10;
444 unsigned char kSeed[DSA_MAX_SUBPRIME_LEN];
445 unsigned int kSeedLen = 0;
446 unsigned int i;
447 unsigned int dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
448 PRBool good;
449
450 PORT_SetError(0);
451 do {
452 rv = dsa_GenerateGlobalRandomBytes(&key->params.subPrime,
453 kSeed, &kSeedLen, sizeof kSeed);
454 if (rv != SECSuccess)
455 break;
456 if (kSeedLen != dsa_subprime_len) {
457 PORT_SetError(SEC_ERROR_INVALID_ARGS);
458 rv = SECFailure;
459 break;
460 }
461 /* Disallow a value of 0 for k. */
462 good = PR_FALSE;
463 for (i = 0; i < kSeedLen; i++) {
464 if (kSeed[i] != 0) {
465 good = PR_TRUE;
466 break;
467 }
468 }
469 if (!good) {
470 PORT_SetError(SEC_ERROR_NEED_RANDOM);
471 rv = SECFailure;
472 continue;
473 }
474 rv = dsa_SignDigest(key, signature, digest, kSeed);
475 } while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM &&
476 --retries > 0);
477 return rv;
478 }
479
480 /* For FIPS compliance testing. Seed must be exactly 20 bytes. */
481 SECStatus
482 DSA_SignDigestWithSeed(DSAPrivateKey * key,
483 SECItem * signature,
484 const SECItem * digest,
485 const unsigned char * seed)
486 {
487 SECStatus rv;
488 rv = dsa_SignDigest(key, signature, digest, seed);
489 return rv;
490 }
491
492 /* signature is caller-supplied buffer of at least 20 bytes.
493 ** On input, signature->len == size of buffer to hold signature.
494 ** digest->len == size of digest.
495 */
496 SECStatus
497 DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
498 const SECItem *digest)
499 {
500 /* FIPS-compliance dictates that digest is a SHA hash. */
501 mp_int p, q, g; /* PQG parameters */
502 mp_int r_, s_; /* tuple (r', s') is received signature) */
503 mp_int u1, u2, v, w; /* intermediate values used in verification */
504 mp_int y; /* public key */
505 mp_err err;
506 int dsa_subprime_len, dsa_signature_len, offset;
507 SECItem localDigest;
508 unsigned char localDigestData[DSA_MAX_SUBPRIME_LEN];
509 SECStatus verified = SECFailure;
510
511 /* Check args. */
512 if (!key || !signature || !digest ) {
513 PORT_SetError(SEC_ERROR_INVALID_ARGS);
514 return SECFailure;
515 }
516
517 dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
518 dsa_signature_len = dsa_subprime_len*2;
519 if ((signature->len != dsa_signature_len) ||
520 (digest->len > HASH_LENGTH_MAX) ||
521 (digest->len < SHA1_LENGTH)) {
522 PORT_SetError(SEC_ERROR_INVALID_ARGS);
523 return SECFailure;
524 }
525
526 /* DSA accepts digests not equal to dsa_subprime_len, if the
527 * digests are greater, than they are truncated to the size of
528 * dsa_subprime_len, using the left most bits. If they are less
529 * then they are padded on the left.*/
530 PORT_Memset(localDigestData, 0, dsa_subprime_len);
531 offset = (digest->len < dsa_subprime_len) ?
532 (dsa_subprime_len - digest->len) : 0;
533 PORT_Memcpy(localDigestData+offset, digest->data,
534 dsa_subprime_len - offset);
535 localDigest.data = localDigestData;
536 localDigest.len = dsa_subprime_len;
537
538 /* Initialize MPI integers. */
539 MP_DIGITS(&p) = 0;
540 MP_DIGITS(&q) = 0;
541 MP_DIGITS(&g) = 0;
542 MP_DIGITS(&y) = 0;
543 MP_DIGITS(&r_) = 0;
544 MP_DIGITS(&s_) = 0;
545 MP_DIGITS(&u1) = 0;
546 MP_DIGITS(&u2) = 0;
547 MP_DIGITS(&v) = 0;
548 MP_DIGITS(&w) = 0;
549 CHECK_MPI_OK( mp_init(&p) );
550 CHECK_MPI_OK( mp_init(&q) );
551 CHECK_MPI_OK( mp_init(&g) );
552 CHECK_MPI_OK( mp_init(&y) );
553 CHECK_MPI_OK( mp_init(&r_) );
554 CHECK_MPI_OK( mp_init(&s_) );
555 CHECK_MPI_OK( mp_init(&u1) );
556 CHECK_MPI_OK( mp_init(&u2) );
557 CHECK_MPI_OK( mp_init(&v) );
558 CHECK_MPI_OK( mp_init(&w) );
559 /*
560 ** Convert stored PQG and public key into MPI integers.
561 */
562 SECITEM_TO_MPINT(key->params.prime, &p);
563 SECITEM_TO_MPINT(key->params.subPrime, &q);
564 SECITEM_TO_MPINT(key->params.base, &g);
565 SECITEM_TO_MPINT(key->publicValue, &y);
566 /*
567 ** Convert received signature (r', s') into MPI integers.
568 */
569 OCTETS_TO_MPINT(signature->data, &r_, dsa_subprime_len);
570 OCTETS_TO_MPINT(signature->data + dsa_subprime_len, &s_, dsa_subprime_len);
571 /*
572 ** Verify that 0 < r' < q and 0 < s' < q
573 */
574 if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
575 mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0) {
576 /* err is zero here. */
577 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
578 goto cleanup; /* will return verified == SECFailure */
579 }
580 /*
581 ** FIPS 186-1, Section 6, Step 1
582 **
583 ** w = (s')**-1 mod q
584 */
585 CHECK_MPI_OK( mp_invmod(&s_, &q, &w) ); /* w = (s')**-1 mod q */
586 /*
587 ** FIPS 186-1, Section 6, Step 2
588 **
589 ** u1 = ((Hash(M')) * w) mod q
590 */
591 SECITEM_TO_MPINT(localDigest, &u1); /* u1 = HASH(M') */
592 CHECK_MPI_OK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */
593 /*
594 ** FIPS 186-1, Section 6, Step 3
595 **
596 ** u2 = ((r') * w) mod q
597 */
598 CHECK_MPI_OK( mp_mulmod(&r_, &w, &q, &u2) );
599 /*
600 ** FIPS 186-1, Section 6, Step 4
601 **
602 ** v = ((g**u1 * y**u2) mod p) mod q
603 */
604 CHECK_MPI_OK( mp_exptmod(&g, &u1, &p, &g) ); /* g = g**u1 mod p */
605 CHECK_MPI_OK( mp_exptmod(&y, &u2, &p, &y) ); /* y = y**u2 mod p */
606 CHECK_MPI_OK( mp_mulmod(&g, &y, &p, &v) ); /* v = g * y mod p */
607 CHECK_MPI_OK( mp_mod(&v, &q, &v) ); /* v = v mod q */
608 /*
609 ** Verification: v == r'
610 */
611 if (mp_cmp(&v, &r_)) {
612 PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
613 verified = SECFailure; /* Signature failed to verify. */
614 } else {
615 verified = SECSuccess; /* Signature verified. */
616 }
617 cleanup:
618 mp_clear(&p);
619 mp_clear(&q);
620 mp_clear(&g);
621 mp_clear(&y);
622 mp_clear(&r_);
623 mp_clear(&s_);
624 mp_clear(&u1);
625 mp_clear(&u2);
626 mp_clear(&v);
627 mp_clear(&w);
628 if (err) {
629 translate_mpi_error(err);
630 }
631 return verified;
632 }
OLDNEW
« no previous file with comments | « mozilla/security/nss/lib/freebl/drbg.c ('k') | mozilla/security/nss/lib/freebl/ec.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698