security/nss/lib/freebl/dsa.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial