| 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 |