diff -up ./nss/lib/freebl/mpi/mpprime.c.fips-186-4 ./nss/lib/freebl/mpi/mpprime.c --- ./nss/lib/freebl/mpi/mpprime.c.fips-186-4 2014-06-24 13:45:27.000000000 -0700 +++ ./nss/lib/freebl/mpi/mpprime.c 2014-10-16 09:54:02.787374811 -0700 @@ -410,31 +410,32 @@ mp_err mpp_make_prime(mp_int *start, mp_ MP_DIGITS(&q) = 0; MP_CHECKOK( mp_init(&trial) ); MP_CHECKOK( mp_init(&q) ); - /* values taken from table 4.4, HandBook of Applied Cryptography */ - if (nBits >= 1300) { - num_tests = 2; - } else if (nBits >= 850) { + /* values originally taken from table 4.4, + * HandBook of Applied Cryptography, augmented by FIPS-186 + * requirements, Table C.2 and C.3 */ + if (nBits >= 2000) { num_tests = 3; - } else if (nBits >= 650) { + } else if (nBits >= 1536) { num_tests = 4; - } else if (nBits >= 550) { + } else if (nBits >= 1024) { num_tests = 5; - } else if (nBits >= 450) { + } else if (nBits >= 550) { num_tests = 6; - } else if (nBits >= 400) { + } else if (nBits >= 450) { num_tests = 7; - } else if (nBits >= 350) { + } else if (nBits >= 400) { num_tests = 8; - } else if (nBits >= 300) { + } else if (nBits >= 350) { num_tests = 9; + } else if (nBits >= 300) { + num_tests = 10; } else if (nBits >= 250) { - num_tests = 12; + num_tests = 20; } else if (nBits >= 200) { - num_tests = 15; - } else if (nBits >= 150) { - num_tests = 18; + num_tests = 41; } else if (nBits >= 100) { - num_tests = 27; + num_tests = 38; /* funny anomaly in the FIPS tables, for aux primes, the + * required more iterations for larger aux primes */ } else num_tests = 50; diff -up ./nss/lib/freebl/rsa.c.fips-186-4 ./nss/lib/freebl/rsa.c --- ./nss/lib/freebl/rsa.c.fips-186-4 2014-10-16 09:54:02.784374761 -0700 +++ ./nss/lib/freebl/rsa.c 2014-10-16 15:08:33.946099491 -0700 @@ -138,7 +138,7 @@ rsa_build_from_primes(const mp_int *p, c CHECK_MPI_OK( mp_sub_d(p, 1, &psub1) ); CHECK_MPI_OK( mp_sub_d(q, 1, &qsub1) ); if (needPublicExponent || needPrivateExponent) { - CHECK_MPI_OK( mp_mul(&psub1, &qsub1, &phi) ); + CHECK_MPI_OK( mp_lcm(&psub1, &qsub1, &phi) ); /* 3. Compute d = e**-1 mod(phi) */ /* or e = d**-1 mod(phi) as necessary */ if (needPublicExponent) { @@ -226,6 +226,45 @@ cleanup: } /* + * make sure the key components meet fips186 requirements. + */ +static PRBool +rsa_fips186_verify(mp_int *p, mp_int *q, mp_int *d, int keySizeInBits) +{ + mp_int pq_diff; + mp_err err = MP_OKAY; + PRBool ret=PR_FALSE; + + if (keySizeInBits < 250) { + /* not a valid FIPS length, no point in our other tests */ + /* if you are here, and in FIPS mode, you are outside the security + * policy */ + return PR_TRUE; + } + + /* p & q are already known to be greater then sqrt(2)*2^(keySize/2-1) */ + /* we also know that gcd(p-1,e) = 1 and gcd(q-1,e) = 1 because the + * mp_invmod() function will fail. */ + /* now check p-q > 2^(keysize/2-100) */ + MP_DIGITS(&pq_diff) = 0; + CHECK_MPI_OK( mp_init(&pq_diff) ); + /* NSS always has p > q, so we know pq_diff is positive */ + CHECK_MPI_OK( mp_sub(p,q,&pq_diff) ); + if ((unsigned)mpl_significant_bits(&pq_diff) < (keySizeInBits/2 - 100)) { + goto cleanup; + } + /* now verify d is large enough*/ + if ((unsigned)mpl_significant_bits(d) < (keySizeInBits/2)) { + goto cleanup; + } + ret = PR_TRUE; + +cleanup: + mp_clear(&pq_diff); + return ret; +} + +/* ** Generate and return a new RSA public and private key. ** Both keys are encoded in a single RSAPrivateKey structure. ** "cx" is the random number generator context @@ -241,6 +280,7 @@ RSA_NewKey(int keySizeInBits, SECItem *p unsigned int primeLen; mp_int p, q, e, d; int kiter; + int max_attempts; mp_err err = MP_OKAY; SECStatus rv = SECSuccess; int prerr = 0; @@ -281,6 +321,7 @@ RSA_NewKey(int keySizeInBits, SECItem *p /* 3. Set the public exponent */ SECITEM_TO_MPINT(*publicExponent, &e); kiter = 0; + max_attempts = 5*(keySizeInBits/2); /* FIPS 186-4 B.3.3 steps 4.7 and 5.8 */ do { prerr = 0; PORT_SetError(0); @@ -298,12 +339,18 @@ RSA_NewKey(int keySizeInBits, SECItem *p &e, PR_FALSE, /* needPublicExponent=false */ &d, PR_TRUE, /* needPrivateExponent=true */ key, keySizeInBits); - if (rv == SECSuccess) - break; /* generated two good primes */ + if (rv == SECSuccess) { + if (rsa_fips186_verify(&p, &q, &d, keySizeInBits) ){ + break; + } + prerr = PORT_GetError(); + } else { + prerr = SEC_ERROR_NEED_RANDOM; /* retry with different values */ + } prerr = PORT_GetError(); kiter++; /* loop until have primes */ - } while (prerr == SEC_ERROR_NEED_RANDOM && kiter < MAX_KEY_GEN_ATTEMPTS); + } while (prerr == SEC_ERROR_NEED_RANDOM && kiter < max_attempts); if (prerr) goto cleanup; cleanup: