OLD | NEW |
1 /* | 1 /* |
2 * | 2 * |
3 * This Source Code Form is subject to the terms of the Mozilla Public | 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 | 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/. */ | 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 $ */ | 6 /* $Id: dsa.c,v 1.23 2012/06/12 16:39:00 rrelyea%redhat.com Exp $ */ |
7 | 7 |
8 #ifdef FREEBL_NO_DEPEND | 8 #ifdef FREEBL_NO_DEPEND |
9 #include "stubs.h" | 9 #include "stubs.h" |
10 #endif | 10 #endif |
11 | 11 |
12 #include "prerror.h" | 12 #include "prerror.h" |
13 #include "secerr.h" | 13 #include "secerr.h" |
14 | 14 |
15 #include "prtypes.h" | 15 #include "prtypes.h" |
16 #include "prinit.h" | 16 #include "prinit.h" |
17 #include "blapi.h" | 17 #include "blapi.h" |
18 #include "nssilock.h" | 18 #include "nssilock.h" |
19 #include "secitem.h" | 19 #include "secitem.h" |
20 #include "blapi.h" | 20 #include "blapi.h" |
21 #include "mpi.h" | 21 #include "mpi.h" |
22 #include "secmpi.h" | 22 #include "secmpi.h" |
| 23 #include "pqg.h" |
23 | 24 |
24 /* XXX to be replaced by define in blapit.h */ | 25 /* XXX to be replaced by define in blapit.h */ |
25 #define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048 | 26 #define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048 |
26 | 27 |
27 /* | 28 /* |
28 * FIPS 186-2 requires result from random output to be reduced mod q when | 29 * FIPS 186-2 requires result from random output to be reduced mod q when |
29 * generating random numbers for DSA. | 30 * generating random numbers for DSA. |
30 * | 31 * |
31 * Input: w, 2*qLen bytes | 32 * Input: w, 2*qLen bytes |
32 * q, qLen bytes | 33 * q, qLen bytes |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 } | 73 } |
73 | 74 |
74 /* | 75 /* |
75 * FIPS 186-2 requires result from random output to be reduced mod q when | 76 * FIPS 186-2 requires result from random output to be reduced mod q when |
76 * generating random numbers for DSA. | 77 * generating random numbers for DSA. |
77 */ | 78 */ |
78 SECStatus | 79 SECStatus |
79 FIPS186Change_ReduceModQForDSA(const unsigned char *w, | 80 FIPS186Change_ReduceModQForDSA(const unsigned char *w, |
80 const unsigned char *q, | 81 const unsigned char *q, |
81 unsigned char *xj) { | 82 unsigned char *xj) { |
82 return fips186Change_ReduceModQForDSA(w, q, DSA_SUBPRIME_LEN, xj); | 83 return fips186Change_ReduceModQForDSA(w, q, DSA1_SUBPRIME_LEN, xj); |
83 } | 84 } |
84 | 85 |
85 /* | 86 /* |
86 * The core of Algorithm 1 of FIPS 186-2 Change Notice 1. | 87 * The core of Algorithm 1 of FIPS 186-2 Change Notice 1. |
87 * | 88 * |
88 * We no longer support FIPS 186-2 RNG. This function was exported | 89 * We no longer support FIPS 186-2 RNG. This function was exported |
89 * for power-up self tests and FIPS tests. Keep this stub, which fails, | 90 * for power-up self tests and FIPS tests. Keep this stub, which fails, |
90 * to prevent crashes, but also to signal to test code that FIPS 186-2 | 91 * to prevent crashes, but also to signal to test code that FIPS 186-2 |
91 * RNG is no longer supported. | 92 * RNG is no longer supported. |
92 */ | 93 */ |
(...skipping 27 matching lines...) Expand all Loading... |
120 SECItem w; | 121 SECItem w; |
121 const PRUint8 * q = qItem->data; | 122 const PRUint8 * q = qItem->data; |
122 unsigned int qLen = qItem->len; | 123 unsigned int qLen = qItem->len; |
123 | 124 |
124 if (*q == 0) { | 125 if (*q == 0) { |
125 ++q; | 126 ++q; |
126 --qLen; | 127 --qLen; |
127 } | 128 } |
128 if (maxDestLen < qLen) { | 129 if (maxDestLen < qLen) { |
129 /* This condition can occur when DSA_SignDigest is passed a group | 130 /* This condition can occur when DSA_SignDigest is passed a group |
130 with a subprime that is larger than DSA_SUBPRIME_LEN. */ | 131 with a subprime that is larger than DSA_MAX_SUBPRIME_LEN. */ |
131 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 132 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
132 return SECFailure; | 133 return SECFailure; |
133 } | 134 } |
134 w.data = NULL; /* otherwise SECITEM_AllocItem asserts */ | 135 w.data = NULL; /* otherwise SECITEM_AllocItem asserts */ |
135 if (!SECITEM_AllocItem(NULL, &w, 2*qLen)) { | 136 if (!SECITEM_AllocItem(NULL, &w, 2*qLen)) { |
136 return SECFailure; | 137 return SECFailure; |
137 } | 138 } |
138 *destLen = qLen; | 139 *destLen = qLen; |
139 | 140 |
140 rv = RNG_GenerateGlobalRandomBytes(w.data, w.len); | 141 rv = RNG_GenerateGlobalRandomBytes(w.data, w.len); |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 ** both of which are encoded into a single DSAPrivateKey struct. | 273 ** both of which are encoded into a single DSAPrivateKey struct. |
273 ** "params" is a pointer to the PQG parameters for the domain | 274 ** "params" is a pointer to the PQG parameters for the domain |
274 ** Uses a random seed. | 275 ** Uses a random seed. |
275 */ | 276 */ |
276 SECStatus | 277 SECStatus |
277 DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey) | 278 DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey) |
278 { | 279 { |
279 SECItem seed; | 280 SECItem seed; |
280 SECStatus rv; | 281 SECStatus rv; |
281 | 282 |
| 283 rv = PQG_Check(params); |
| 284 if (rv != SECSuccess) { |
| 285 return rv; |
| 286 } |
282 seed.data = NULL; | 287 seed.data = NULL; |
283 | 288 |
284 rv = DSA_NewRandom(NULL, ¶ms->subPrime, &seed); | 289 rv = DSA_NewRandom(NULL, ¶ms->subPrime, &seed); |
285 if (rv == SECSuccess) { | 290 if (rv == SECSuccess) { |
286 if (seed.len != DSA_SUBPRIME_LEN) { | 291 if (seed.len != PQG_GetLength(¶ms->subPrime)) { |
287 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 292 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
288 rv = SECFailure; | 293 rv = SECFailure; |
289 } else { | 294 } else { |
290 rv = dsa_NewKeyExtended(params, &seed, privKey); | 295 rv = dsa_NewKeyExtended(params, &seed, privKey); |
291 } | 296 } |
292 } | 297 } |
293 SECITEM_FreeItem(&seed, PR_FALSE); | 298 SECITEM_FreeItem(&seed, PR_FALSE); |
294 return rv; | 299 return rv; |
295 } | 300 } |
296 | 301 |
297 /* For FIPS compliance testing. Seed must be exactly 20 bytes long */ | 302 /* For FIPS compliance testing. Seed must be exactly the size of subPrime */ |
298 SECStatus | 303 SECStatus |
299 DSA_NewKeyFromSeed(const PQGParams *params, | 304 DSA_NewKeyFromSeed(const PQGParams *params, |
300 const unsigned char *seed, | 305 const unsigned char *seed, |
301 DSAPrivateKey **privKey) | 306 DSAPrivateKey **privKey) |
302 { | 307 { |
303 /* TODO: check Q size */ | |
304 SECItem seedItem; | 308 SECItem seedItem; |
305 seedItem.data = (unsigned char*) seed; | 309 seedItem.data = (unsigned char*) seed; |
306 seedItem.len = DSA_SUBPRIME_LEN; | 310 seedItem.len = PQG_GetLength(¶ms->subPrime); |
307 return dsa_NewKeyExtended(params, &seedItem, privKey); | 311 return dsa_NewKeyExtended(params, &seedItem, privKey); |
308 } | 312 } |
309 | 313 |
310 static SECStatus | 314 static SECStatus |
311 dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest, | 315 dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest, |
312 const unsigned char *kb) | 316 const unsigned char *kb) |
313 { | 317 { |
314 mp_int p, q, g; /* PQG parameters */ | 318 mp_int p, q, g; /* PQG parameters */ |
315 mp_int x, k; /* private key & pseudo-random integer */ | 319 mp_int x, k; /* private key & pseudo-random integer */ |
316 mp_int r, s; /* tuple (r, s) is signature) */ | 320 mp_int r, s; /* tuple (r, s) is signature) */ |
317 mp_err err = MP_OKAY; | 321 mp_err err = MP_OKAY; |
318 SECStatus rv = SECSuccess; | 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 |
319 | 327 |
320 /* FIPS-compliance dictates that digest is a SHA1 hash. */ | 328 /* FIPS-compliance dictates that digest is a SHA hash. */ |
321 /* Check args. */ | 329 /* Check args. */ |
322 if (!key || !signature || !digest || | 330 if (!key || !signature || !digest) { |
323 (signature->len < DSA_SIGNATURE_LEN) || | |
324 » (digest->len != SHA1_LENGTH)) { | |
325 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 331 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
326 return SECFailure; | 332 return SECFailure; |
327 } | 333 } |
328 | 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 |
329 /* Initialize MPI integers. */ | 356 /* Initialize MPI integers. */ |
330 MP_DIGITS(&p) = 0; | 357 MP_DIGITS(&p) = 0; |
331 MP_DIGITS(&q) = 0; | 358 MP_DIGITS(&q) = 0; |
332 MP_DIGITS(&g) = 0; | 359 MP_DIGITS(&g) = 0; |
333 MP_DIGITS(&x) = 0; | 360 MP_DIGITS(&x) = 0; |
334 MP_DIGITS(&k) = 0; | 361 MP_DIGITS(&k) = 0; |
335 MP_DIGITS(&r) = 0; | 362 MP_DIGITS(&r) = 0; |
336 MP_DIGITS(&s) = 0; | 363 MP_DIGITS(&s) = 0; |
337 CHECK_MPI_OK( mp_init(&p) ); | 364 CHECK_MPI_OK( mp_init(&p) ); |
338 CHECK_MPI_OK( mp_init(&q) ); | 365 CHECK_MPI_OK( mp_init(&q) ); |
339 CHECK_MPI_OK( mp_init(&g) ); | 366 CHECK_MPI_OK( mp_init(&g) ); |
340 CHECK_MPI_OK( mp_init(&x) ); | 367 CHECK_MPI_OK( mp_init(&x) ); |
341 CHECK_MPI_OK( mp_init(&k) ); | 368 CHECK_MPI_OK( mp_init(&k) ); |
342 CHECK_MPI_OK( mp_init(&r) ); | 369 CHECK_MPI_OK( mp_init(&r) ); |
343 CHECK_MPI_OK( mp_init(&s) ); | 370 CHECK_MPI_OK( mp_init(&s) ); |
344 /* | 371 /* |
345 ** Convert stored PQG and private key into MPI integers. | 372 ** Convert stored PQG and private key into MPI integers. |
346 */ | 373 */ |
347 SECITEM_TO_MPINT(key->params.prime, &p); | 374 SECITEM_TO_MPINT(key->params.prime, &p); |
348 SECITEM_TO_MPINT(key->params.subPrime, &q); | 375 SECITEM_TO_MPINT(key->params.subPrime, &q); |
349 SECITEM_TO_MPINT(key->params.base, &g); | 376 SECITEM_TO_MPINT(key->params.base, &g); |
350 SECITEM_TO_MPINT(key->privateValue, &x); | 377 SECITEM_TO_MPINT(key->privateValue, &x); |
351 OCTETS_TO_MPINT(kb, &k, DSA_SUBPRIME_LEN); | 378 OCTETS_TO_MPINT(kb, &k, dsa_subprime_len); |
352 /* | 379 /* |
353 ** FIPS 186-1, Section 5, Step 1 | 380 ** FIPS 186-1, Section 5, Step 1 |
354 ** | 381 ** |
355 ** r = (g**k mod p) mod q | 382 ** r = (g**k mod p) mod q |
356 */ | 383 */ |
357 CHECK_MPI_OK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */ | 384 CHECK_MPI_OK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */ |
358 CHECK_MPI_OK( mp_mod(&r, &q, &r) ); /* r = r mod q */ | 385 CHECK_MPI_OK( mp_mod(&r, &q, &r) ); /* r = r mod q */ |
359 /* | 386 /* |
360 ** FIPS 186-1, Section 5, Step 2 | 387 ** FIPS 186-1, Section 5, Step 2 |
361 ** | 388 ** |
362 ** s = (k**-1 * (SHA1(M) + x*r)) mod q | 389 ** s = (k**-1 * (HASH(M) + x*r)) mod q |
363 */ | 390 */ |
364 SECITEM_TO_MPINT(*digest, &s); /* s = SHA1(M) */ | 391 SECITEM_TO_MPINT(localDigest, &s); /* s = HASH(M) */ |
365 CHECK_MPI_OK( mp_invmod(&k, &q, &k) ); /* k = k**-1 mod q */ | 392 CHECK_MPI_OK( mp_invmod(&k, &q, &k) ); /* k = k**-1 mod q */ |
366 CHECK_MPI_OK( mp_mulmod(&x, &r, &q, &x) ); /* x = x * r mod q */ | 393 CHECK_MPI_OK( mp_mulmod(&x, &r, &q, &x) ); /* x = x * r mod q */ |
367 CHECK_MPI_OK( mp_addmod(&s, &x, &q, &s) ); /* s = s + x mod q */ | 394 CHECK_MPI_OK( mp_addmod(&s, &x, &q, &s) ); /* s = s + x mod q */ |
368 CHECK_MPI_OK( mp_mulmod(&s, &k, &q, &s) ); /* s = s * k mod q */ | 395 CHECK_MPI_OK( mp_mulmod(&s, &k, &q, &s) ); /* s = s * k mod q */ |
369 /* | 396 /* |
370 ** verify r != 0 and s != 0 | 397 ** verify r != 0 and s != 0 |
371 ** mentioned as optional in FIPS 186-1. | 398 ** mentioned as optional in FIPS 186-1. |
372 */ | 399 */ |
373 if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) { | 400 if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) { |
374 PORT_SetError(SEC_ERROR_NEED_RANDOM); | 401 PORT_SetError(SEC_ERROR_NEED_RANDOM); |
375 rv = SECFailure; | 402 rv = SECFailure; |
376 goto cleanup; | 403 goto cleanup; |
377 } | 404 } |
378 /* | 405 /* |
379 ** Step 4 | 406 ** Step 4 |
380 ** | 407 ** |
381 ** Signature is tuple (r, s) | 408 ** Signature is tuple (r, s) |
382 */ | 409 */ |
383 err = mp_to_fixlen_octets(&r, signature->data, DSA_SUBPRIME_LEN); | 410 err = mp_to_fixlen_octets(&r, signature->data, dsa_subprime_len); |
384 if (err < 0) goto cleanup; | 411 if (err < 0) goto cleanup; |
385 err = mp_to_fixlen_octets(&s, signature->data + DSA_SUBPRIME_LEN, | 412 err = mp_to_fixlen_octets(&s, signature->data + dsa_subprime_len, |
386 DSA_SUBPRIME_LEN); | 413 dsa_subprime_len); |
387 if (err < 0) goto cleanup; | 414 if (err < 0) goto cleanup; |
388 err = MP_OKAY; | 415 err = MP_OKAY; |
389 signature->len = DSA_SIGNATURE_LEN; | 416 signature->len = dsa_signature_len; |
390 cleanup: | 417 cleanup: |
| 418 PORT_Memset(localDigestData, 0, DSA_MAX_SUBPRIME_LEN); |
391 mp_clear(&p); | 419 mp_clear(&p); |
392 mp_clear(&q); | 420 mp_clear(&q); |
393 mp_clear(&g); | 421 mp_clear(&g); |
394 mp_clear(&x); | 422 mp_clear(&x); |
395 mp_clear(&k); | 423 mp_clear(&k); |
396 mp_clear(&r); | 424 mp_clear(&r); |
397 mp_clear(&s); | 425 mp_clear(&s); |
398 if (err) { | 426 if (err) { |
399 translate_mpi_error(err); | 427 translate_mpi_error(err); |
400 rv = SECFailure; | 428 rv = SECFailure; |
401 } | 429 } |
402 return rv; | 430 return rv; |
403 } | 431 } |
404 | 432 |
405 /* signature is caller-supplied buffer of at least 40 bytes. | 433 /* signature is caller-supplied buffer of at least 40 bytes. |
406 ** On input, signature->len == size of buffer to hold signature. | 434 ** On input, signature->len == size of buffer to hold signature. |
407 ** digest->len == size of digest. | 435 ** digest->len == size of digest. |
408 ** On output, signature->len == size of signature in buffer. | 436 ** On output, signature->len == size of signature in buffer. |
409 ** Uses a random seed. | 437 ** Uses a random seed. |
410 */ | 438 */ |
411 SECStatus | 439 SECStatus |
412 DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest) | 440 DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest) |
413 { | 441 { |
414 SECStatus rv; | 442 SECStatus rv; |
415 int retries = 10; | 443 int retries = 10; |
416 unsigned char kSeed[DSA_SUBPRIME_LEN]; | 444 unsigned char kSeed[DSA_MAX_SUBPRIME_LEN]; |
417 unsigned int kSeedLen = 0; | 445 unsigned int kSeedLen = 0; |
418 unsigned int i; | 446 unsigned int i; |
| 447 unsigned int dsa_subprime_len = PQG_GetLength(&key->params.subPrime); |
419 PRBool good; | 448 PRBool good; |
420 | 449 |
421 PORT_SetError(0); | 450 PORT_SetError(0); |
422 do { | 451 do { |
423 rv = dsa_GenerateGlobalRandomBytes(&key->params.subPrime, | 452 rv = dsa_GenerateGlobalRandomBytes(&key->params.subPrime, |
424 kSeed, &kSeedLen, sizeof kSeed); | 453 kSeed, &kSeedLen, sizeof kSeed); |
425 if (rv != SECSuccess) | 454 if (rv != SECSuccess) |
426 break; | 455 break; |
427 if (kSeedLen != DSA_SUBPRIME_LEN) { | 456 if (kSeedLen != dsa_subprime_len) { |
428 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 457 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
429 rv = SECFailure; | 458 rv = SECFailure; |
430 break; | 459 break; |
431 } | 460 } |
432 /* Disallow a value of 0 for k. */ | 461 /* Disallow a value of 0 for k. */ |
433 good = PR_FALSE; | 462 good = PR_FALSE; |
434 for (i = 0; i < kSeedLen; i++) { | 463 for (i = 0; i < kSeedLen; i++) { |
435 if (kSeed[i] != 0) { | 464 if (kSeed[i] != 0) { |
436 good = PR_TRUE; | 465 good = PR_TRUE; |
437 break; | 466 break; |
(...skipping 23 matching lines...) Expand all Loading... |
461 } | 490 } |
462 | 491 |
463 /* signature is caller-supplied buffer of at least 20 bytes. | 492 /* signature is caller-supplied buffer of at least 20 bytes. |
464 ** On input, signature->len == size of buffer to hold signature. | 493 ** On input, signature->len == size of buffer to hold signature. |
465 ** digest->len == size of digest. | 494 ** digest->len == size of digest. |
466 */ | 495 */ |
467 SECStatus | 496 SECStatus |
468 DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature, | 497 DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature, |
469 const SECItem *digest) | 498 const SECItem *digest) |
470 { | 499 { |
471 /* FIPS-compliance dictates that digest is a SHA1 hash. */ | 500 /* FIPS-compliance dictates that digest is a SHA hash. */ |
472 mp_int p, q, g; /* PQG parameters */ | 501 mp_int p, q, g; /* PQG parameters */ |
473 mp_int r_, s_; /* tuple (r', s') is received signature) */ | 502 mp_int r_, s_; /* tuple (r', s') is received signature) */ |
474 mp_int u1, u2, v, w; /* intermediate values used in verification */ | 503 mp_int u1, u2, v, w; /* intermediate values used in verification */ |
475 mp_int y; /* public key */ | 504 mp_int y; /* public key */ |
476 mp_err err; | 505 mp_err err; |
| 506 int dsa_subprime_len, dsa_signature_len, offset; |
| 507 SECItem localDigest; |
| 508 unsigned char localDigestData[DSA_MAX_SUBPRIME_LEN]; |
477 SECStatus verified = SECFailure; | 509 SECStatus verified = SECFailure; |
478 | 510 |
479 /* Check args. */ | 511 /* Check args. */ |
480 if (!key || !signature || !digest || | 512 if (!key || !signature || !digest ) { |
481 (signature->len != DSA_SIGNATURE_LEN) || | |
482 » (digest->len != SHA1_LENGTH)) { | |
483 PORT_SetError(SEC_ERROR_INVALID_ARGS); | 513 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
484 return SECFailure; | 514 return SECFailure; |
485 } | 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 |
486 /* Initialize MPI integers. */ | 538 /* Initialize MPI integers. */ |
487 MP_DIGITS(&p) = 0; | 539 MP_DIGITS(&p) = 0; |
488 MP_DIGITS(&q) = 0; | 540 MP_DIGITS(&q) = 0; |
489 MP_DIGITS(&g) = 0; | 541 MP_DIGITS(&g) = 0; |
490 MP_DIGITS(&y) = 0; | 542 MP_DIGITS(&y) = 0; |
491 MP_DIGITS(&r_) = 0; | 543 MP_DIGITS(&r_) = 0; |
492 MP_DIGITS(&s_) = 0; | 544 MP_DIGITS(&s_) = 0; |
493 MP_DIGITS(&u1) = 0; | 545 MP_DIGITS(&u1) = 0; |
494 MP_DIGITS(&u2) = 0; | 546 MP_DIGITS(&u2) = 0; |
495 MP_DIGITS(&v) = 0; | 547 MP_DIGITS(&v) = 0; |
(...skipping 11 matching lines...) Expand all Loading... |
507 /* | 559 /* |
508 ** Convert stored PQG and public key into MPI integers. | 560 ** Convert stored PQG and public key into MPI integers. |
509 */ | 561 */ |
510 SECITEM_TO_MPINT(key->params.prime, &p); | 562 SECITEM_TO_MPINT(key->params.prime, &p); |
511 SECITEM_TO_MPINT(key->params.subPrime, &q); | 563 SECITEM_TO_MPINT(key->params.subPrime, &q); |
512 SECITEM_TO_MPINT(key->params.base, &g); | 564 SECITEM_TO_MPINT(key->params.base, &g); |
513 SECITEM_TO_MPINT(key->publicValue, &y); | 565 SECITEM_TO_MPINT(key->publicValue, &y); |
514 /* | 566 /* |
515 ** Convert received signature (r', s') into MPI integers. | 567 ** Convert received signature (r', s') into MPI integers. |
516 */ | 568 */ |
517 OCTETS_TO_MPINT(signature->data, &r_, DSA_SUBPRIME_LEN); | 569 OCTETS_TO_MPINT(signature->data, &r_, dsa_subprime_len); |
518 OCTETS_TO_MPINT(signature->data + DSA_SUBPRIME_LEN, &s_, DSA_SUBPRIME_LEN); | 570 OCTETS_TO_MPINT(signature->data + dsa_subprime_len, &s_, dsa_subprime_len); |
519 /* | 571 /* |
520 ** Verify that 0 < r' < q and 0 < s' < q | 572 ** Verify that 0 < r' < q and 0 < s' < q |
521 */ | 573 */ |
522 if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 || | 574 if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 || |
523 mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0) { | 575 mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0) { |
524 /* err is zero here. */ | 576 /* err is zero here. */ |
525 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | 577 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
526 goto cleanup; /* will return verified == SECFailure */ | 578 goto cleanup; /* will return verified == SECFailure */ |
527 } | 579 } |
528 /* | 580 /* |
529 ** FIPS 186-1, Section 6, Step 1 | 581 ** FIPS 186-1, Section 6, Step 1 |
530 ** | 582 ** |
531 ** w = (s')**-1 mod q | 583 ** w = (s')**-1 mod q |
532 */ | 584 */ |
533 CHECK_MPI_OK( mp_invmod(&s_, &q, &w) ); /* w = (s')**-1 mod q */ | 585 CHECK_MPI_OK( mp_invmod(&s_, &q, &w) ); /* w = (s')**-1 mod q */ |
534 /* | 586 /* |
535 ** FIPS 186-1, Section 6, Step 2 | 587 ** FIPS 186-1, Section 6, Step 2 |
536 ** | 588 ** |
537 ** u1 = ((SHA1(M')) * w) mod q | 589 ** u1 = ((Hash(M')) * w) mod q |
538 */ | 590 */ |
539 SECITEM_TO_MPINT(*digest, &u1); /* u1 = SHA1(M') */ | 591 SECITEM_TO_MPINT(localDigest, &u1); /* u1 = HASH(M') */ |
540 CHECK_MPI_OK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */ | 592 CHECK_MPI_OK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */ |
541 /* | 593 /* |
542 ** FIPS 186-1, Section 6, Step 3 | 594 ** FIPS 186-1, Section 6, Step 3 |
543 ** | 595 ** |
544 ** u2 = ((r') * w) mod q | 596 ** u2 = ((r') * w) mod q |
545 */ | 597 */ |
546 CHECK_MPI_OK( mp_mulmod(&r_, &w, &q, &u2) ); | 598 CHECK_MPI_OK( mp_mulmod(&r_, &w, &q, &u2) ); |
547 /* | 599 /* |
548 ** FIPS 186-1, Section 6, Step 4 | 600 ** FIPS 186-1, Section 6, Step 4 |
549 ** | 601 ** |
(...skipping 21 matching lines...) Expand all Loading... |
571 mp_clear(&s_); | 623 mp_clear(&s_); |
572 mp_clear(&u1); | 624 mp_clear(&u1); |
573 mp_clear(&u2); | 625 mp_clear(&u2); |
574 mp_clear(&v); | 626 mp_clear(&v); |
575 mp_clear(&w); | 627 mp_clear(&w); |
576 if (err) { | 628 if (err) { |
577 translate_mpi_error(err); | 629 translate_mpi_error(err); |
578 } | 630 } |
579 return verified; | 631 return verified; |
580 } | 632 } |
OLD | NEW |