| Index: mozilla/security/nss/lib/freebl/dsa.c
|
| ===================================================================
|
| --- mozilla/security/nss/lib/freebl/dsa.c (revision 164196)
|
| +++ mozilla/security/nss/lib/freebl/dsa.c (working copy)
|
| @@ -20,6 +20,7 @@
|
| #include "blapi.h"
|
| #include "mpi.h"
|
| #include "secmpi.h"
|
| +#include "pqg.h"
|
|
|
| /* XXX to be replaced by define in blapit.h */
|
| #define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048
|
| @@ -79,7 +80,7 @@
|
| FIPS186Change_ReduceModQForDSA(const unsigned char *w,
|
| const unsigned char *q,
|
| unsigned char *xj) {
|
| - return fips186Change_ReduceModQForDSA(w, q, DSA_SUBPRIME_LEN, xj);
|
| + return fips186Change_ReduceModQForDSA(w, q, DSA1_SUBPRIME_LEN, xj);
|
| }
|
|
|
| /*
|
| @@ -127,7 +128,7 @@
|
| }
|
| if (maxDestLen < qLen) {
|
| /* This condition can occur when DSA_SignDigest is passed a group
|
| - with a subprime that is larger than DSA_SUBPRIME_LEN. */
|
| + with a subprime that is larger than DSA_MAX_SUBPRIME_LEN. */
|
| PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| return SECFailure;
|
| }
|
| @@ -279,11 +280,15 @@
|
| SECItem seed;
|
| SECStatus rv;
|
|
|
| + rv = PQG_Check(params);
|
| + if (rv != SECSuccess) {
|
| + return rv;
|
| + }
|
| seed.data = NULL;
|
|
|
| rv = DSA_NewRandom(NULL, ¶ms->subPrime, &seed);
|
| if (rv == SECSuccess) {
|
| - if (seed.len != DSA_SUBPRIME_LEN) {
|
| + if (seed.len != PQG_GetLength(¶ms->subPrime)) {
|
| PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| rv = SECFailure;
|
| } else {
|
| @@ -294,16 +299,15 @@
|
| return rv;
|
| }
|
|
|
| -/* For FIPS compliance testing. Seed must be exactly 20 bytes long */
|
| +/* For FIPS compliance testing. Seed must be exactly the size of subPrime */
|
| SECStatus
|
| DSA_NewKeyFromSeed(const PQGParams *params,
|
| const unsigned char *seed,
|
| DSAPrivateKey **privKey)
|
| {
|
| - /* TODO: check Q size */
|
| SECItem seedItem;
|
| seedItem.data = (unsigned char*) seed;
|
| - seedItem.len = DSA_SUBPRIME_LEN;
|
| + seedItem.len = PQG_GetLength(¶ms->subPrime);
|
| return dsa_NewKeyExtended(params, &seedItem, privKey);
|
| }
|
|
|
| @@ -316,16 +320,39 @@
|
| mp_int r, s; /* tuple (r, s) is signature) */
|
| mp_err err = MP_OKAY;
|
| SECStatus rv = SECSuccess;
|
| + unsigned int dsa_subprime_len, dsa_signature_len, offset;
|
| + SECItem localDigest;
|
| + unsigned char localDigestData[DSA_MAX_SUBPRIME_LEN];
|
| +
|
|
|
| - /* FIPS-compliance dictates that digest is a SHA1 hash. */
|
| + /* FIPS-compliance dictates that digest is a SHA hash. */
|
| /* Check args. */
|
| - if (!key || !signature || !digest ||
|
| - (signature->len < DSA_SIGNATURE_LEN) ||
|
| - (digest->len != SHA1_LENGTH)) {
|
| + if (!key || !signature || !digest) {
|
| PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| return SECFailure;
|
| }
|
|
|
| + dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
|
| + dsa_signature_len = dsa_subprime_len*2;
|
| + if ((signature->len < dsa_signature_len) ||
|
| + (digest->len > HASH_LENGTH_MAX) ||
|
| + (digest->len < SHA1_LENGTH)) {
|
| + PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| + return SECFailure;
|
| + }
|
| +
|
| + /* DSA accepts digests not equal to dsa_subprime_len, if the
|
| + * digests are greater, then they are truncated to the size of
|
| + * dsa_subprime_len, using the left most bits. If they are less
|
| + * then they are padded on the left.*/
|
| + PORT_Memset(localDigestData, 0, dsa_subprime_len);
|
| + offset = (digest->len < dsa_subprime_len) ?
|
| + (dsa_subprime_len - digest->len) : 0;
|
| + PORT_Memcpy(localDigestData+offset, digest->data,
|
| + dsa_subprime_len - offset);
|
| + localDigest.data = localDigestData;
|
| + localDigest.len = dsa_subprime_len;
|
| +
|
| /* Initialize MPI integers. */
|
| MP_DIGITS(&p) = 0;
|
| MP_DIGITS(&q) = 0;
|
| @@ -348,7 +375,7 @@
|
| SECITEM_TO_MPINT(key->params.subPrime, &q);
|
| SECITEM_TO_MPINT(key->params.base, &g);
|
| SECITEM_TO_MPINT(key->privateValue, &x);
|
| - OCTETS_TO_MPINT(kb, &k, DSA_SUBPRIME_LEN);
|
| + OCTETS_TO_MPINT(kb, &k, dsa_subprime_len);
|
| /*
|
| ** FIPS 186-1, Section 5, Step 1
|
| **
|
| @@ -359,9 +386,9 @@
|
| /*
|
| ** FIPS 186-1, Section 5, Step 2
|
| **
|
| - ** s = (k**-1 * (SHA1(M) + x*r)) mod q
|
| + ** s = (k**-1 * (HASH(M) + x*r)) mod q
|
| */
|
| - SECITEM_TO_MPINT(*digest, &s); /* s = SHA1(M) */
|
| + SECITEM_TO_MPINT(localDigest, &s); /* s = HASH(M) */
|
| CHECK_MPI_OK( mp_invmod(&k, &q, &k) ); /* k = k**-1 mod q */
|
| CHECK_MPI_OK( mp_mulmod(&x, &r, &q, &x) ); /* x = x * r mod q */
|
| CHECK_MPI_OK( mp_addmod(&s, &x, &q, &s) ); /* s = s + x mod q */
|
| @@ -380,14 +407,15 @@
|
| **
|
| ** Signature is tuple (r, s)
|
| */
|
| - err = mp_to_fixlen_octets(&r, signature->data, DSA_SUBPRIME_LEN);
|
| + err = mp_to_fixlen_octets(&r, signature->data, dsa_subprime_len);
|
| if (err < 0) goto cleanup;
|
| - err = mp_to_fixlen_octets(&s, signature->data + DSA_SUBPRIME_LEN,
|
| - DSA_SUBPRIME_LEN);
|
| + err = mp_to_fixlen_octets(&s, signature->data + dsa_subprime_len,
|
| + dsa_subprime_len);
|
| if (err < 0) goto cleanup;
|
| err = MP_OKAY;
|
| - signature->len = DSA_SIGNATURE_LEN;
|
| + signature->len = dsa_signature_len;
|
| cleanup:
|
| + PORT_Memset(localDigestData, 0, DSA_MAX_SUBPRIME_LEN);
|
| mp_clear(&p);
|
| mp_clear(&q);
|
| mp_clear(&g);
|
| @@ -413,9 +441,10 @@
|
| {
|
| SECStatus rv;
|
| int retries = 10;
|
| - unsigned char kSeed[DSA_SUBPRIME_LEN];
|
| + unsigned char kSeed[DSA_MAX_SUBPRIME_LEN];
|
| unsigned int kSeedLen = 0;
|
| unsigned int i;
|
| + unsigned int dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
|
| PRBool good;
|
|
|
| PORT_SetError(0);
|
| @@ -424,7 +453,7 @@
|
| kSeed, &kSeedLen, sizeof kSeed);
|
| if (rv != SECSuccess)
|
| break;
|
| - if (kSeedLen != DSA_SUBPRIME_LEN) {
|
| + if (kSeedLen != dsa_subprime_len) {
|
| PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| rv = SECFailure;
|
| break;
|
| @@ -468,21 +497,44 @@
|
| DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
|
| const SECItem *digest)
|
| {
|
| - /* FIPS-compliance dictates that digest is a SHA1 hash. */
|
| + /* FIPS-compliance dictates that digest is a SHA hash. */
|
| mp_int p, q, g; /* PQG parameters */
|
| mp_int r_, s_; /* tuple (r', s') is received signature) */
|
| mp_int u1, u2, v, w; /* intermediate values used in verification */
|
| mp_int y; /* public key */
|
| mp_err err;
|
| + int dsa_subprime_len, dsa_signature_len, offset;
|
| + SECItem localDigest;
|
| + unsigned char localDigestData[DSA_MAX_SUBPRIME_LEN];
|
| SECStatus verified = SECFailure;
|
|
|
| /* Check args. */
|
| - if (!key || !signature || !digest ||
|
| - (signature->len != DSA_SIGNATURE_LEN) ||
|
| - (digest->len != SHA1_LENGTH)) {
|
| + if (!key || !signature || !digest ) {
|
| PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| return SECFailure;
|
| }
|
| +
|
| + dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
|
| + dsa_signature_len = dsa_subprime_len*2;
|
| + if ((signature->len != dsa_signature_len) ||
|
| + (digest->len > HASH_LENGTH_MAX) ||
|
| + (digest->len < SHA1_LENGTH)) {
|
| + PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| + return SECFailure;
|
| + }
|
| +
|
| + /* DSA accepts digests not equal to dsa_subprime_len, if the
|
| + * digests are greater, than they are truncated to the size of
|
| + * dsa_subprime_len, using the left most bits. If they are less
|
| + * then they are padded on the left.*/
|
| + PORT_Memset(localDigestData, 0, dsa_subprime_len);
|
| + offset = (digest->len < dsa_subprime_len) ?
|
| + (dsa_subprime_len - digest->len) : 0;
|
| + PORT_Memcpy(localDigestData+offset, digest->data,
|
| + dsa_subprime_len - offset);
|
| + localDigest.data = localDigestData;
|
| + localDigest.len = dsa_subprime_len;
|
| +
|
| /* Initialize MPI integers. */
|
| MP_DIGITS(&p) = 0;
|
| MP_DIGITS(&q) = 0;
|
| @@ -514,8 +566,8 @@
|
| /*
|
| ** Convert received signature (r', s') into MPI integers.
|
| */
|
| - OCTETS_TO_MPINT(signature->data, &r_, DSA_SUBPRIME_LEN);
|
| - OCTETS_TO_MPINT(signature->data + DSA_SUBPRIME_LEN, &s_, DSA_SUBPRIME_LEN);
|
| + OCTETS_TO_MPINT(signature->data, &r_, dsa_subprime_len);
|
| + OCTETS_TO_MPINT(signature->data + dsa_subprime_len, &s_, dsa_subprime_len);
|
| /*
|
| ** Verify that 0 < r' < q and 0 < s' < q
|
| */
|
| @@ -534,9 +586,9 @@
|
| /*
|
| ** FIPS 186-1, Section 6, Step 2
|
| **
|
| - ** u1 = ((SHA1(M')) * w) mod q
|
| + ** u1 = ((Hash(M')) * w) mod q
|
| */
|
| - SECITEM_TO_MPINT(*digest, &u1); /* u1 = SHA1(M') */
|
| + SECITEM_TO_MPINT(localDigest, &u1); /* u1 = HASH(M') */
|
| CHECK_MPI_OK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */
|
| /*
|
| ** FIPS 186-1, Section 6, Step 3
|
|
|