File nss-CAVS-fixes.patch of Package mozilla-nss.2738
# HG changeset patch
# Parent 27661bdc65050f356ed2603821400839950eb01b
extend CAVS test to provide what it takes for certification
diff --git a/lib/freebl/fips.h b/lib/freebl/fips.h
--- a/lib/freebl/fips.h
+++ b/lib/freebl/fips.h
@@ -3,27 +3,35 @@
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef FIPS_H
#define FIPS_H
+#include "blapit.h"
#include "hasht.h"
-#include "secerr.h"
#define IN_FIPS_RETURN(rv) \
do { \
if (FIPS_mode()) { \
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); \
return rv; \
} \
} while (0)
int FIPS_mode(void);
char* FIPS_rngDev(void);
PRBool FIPS_hashAlgApproved(HASH_HashType hashAlg);
void* FREEBL_GetGlobalVar(int which, void *data);
+SECStatus FREEBL_Test_PQG_ParamGenV3 (unsigned int L, unsigned int N, unsigned int seedBytes,
+ PQGParams **pParams, PQGVerify **pVfy,
+ int shanum, int *pgen_counter, int *qgen_counter,
+ SECItem *firstseed, SECItem *pseed, SECItem *qseed);
+SECStatus FREEBL_Test_PQG_GenerateG (unsigned int L, unsigned int N, unsigned int seedBytes,
+ PQGParams **pParams, PQGVerify **pVfy,
+ int shanum, const SECItem *P, const SECItem *Q);
+
#endif
diff --git a/lib/freebl/freebl.def b/lib/freebl/freebl.def
--- a/lib/freebl/freebl.def
+++ b/lib/freebl/freebl.def
@@ -17,11 +17,13 @@
;+# directives are hidden behind ";", ";+", and ";-"
;+
;+NSSprivate_3.11 { # NSS 3.11 release
;+ global:
LIBRARY freebl3 ;-
EXPORTS ;-
FREEBL_GetVector;
FREEBL_GetGlobalVar;
+FREEBL_Test_PQG_GenerateG;
+FREEBL_Test_PQG_ParamGenV3;
;+ local:
;+ *;
;+};
diff --git a/lib/freebl/freebl_hash.def b/lib/freebl/freebl_hash.def
--- a/lib/freebl/freebl_hash.def
+++ b/lib/freebl/freebl_hash.def
@@ -17,16 +17,18 @@
;+# directives are hidden behind ";", ";+", and ";-"
;+
;+NSSprivate_3.11 { # NSS 3.11 release
;+ global:
LIBRARY freebl3 ;-
EXPORTS ;-
FREEBL_GetVector;
FREEBL_GetGlobalVar;
+FREEBL_Test_PQG_GenerateG;
+FREEBL_Test_PQG_ParamGenV3;
;+ local:
;+ *;
;+};
;+NSSRAWHASH_3.12.3 { # NSS 3.12.3 release
;+ global:
NSSLOW_Init;
NSSLOW_Shutdown;
NSSLOWHASH_Length;
diff --git a/lib/freebl/pqg.c b/lib/freebl/pqg.c
--- a/lib/freebl/pqg.c
+++ b/lib/freebl/pqg.c
@@ -1223,40 +1223,43 @@ cleanup:
/* This code uses labels and gotos, so that it can follow the numbered
** steps in the algorithms from FIPS 186-3 appendix A.1.1.2 very closely,
** and so that the correctness of this code can be easily verified.
** So, please forgive the ugly c code.
**/
static SECStatus
pqg_ParamGen(unsigned int L, unsigned int N, pqgGenType type,
- unsigned int seedBytes, PQGParams **pParams, PQGVerify **pVfy)
+ unsigned int seedBytes, PQGParams **pParams, PQGVerify **pVfy,
+ const SECItem *P_in, const SECItem *Q_in,
+ int minHashLen, int *pgen_counter_out,
+ int *qgen_counter_out, SECItem *firstseed_out,
+ SECItem *pseed_out, SECItem *qseed_out)
{
unsigned int n; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
unsigned int seedlen; /* Per FIPS 186-3 app A.1.1.2 (was 'g' 186-1)*/
- unsigned int counter; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
+ unsigned int counter = 0; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
unsigned int offset; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
unsigned int outlen; /* Per FIPS 186-3, appendix A.1.1.2. */
unsigned int maxCount;
- HASH_HashType hashtype;
+ HASH_HashType hashtype = HASH_AlgNULL;
SECItem *seed; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
PLArenaPool *arena = NULL;
PQGParams *params = NULL;
PQGVerify *verify = NULL;
PRBool passed;
SECItem hit = { 0, 0, 0 };
SECItem firstseed = { 0, 0, 0 };
SECItem qseed = { 0, 0, 0 };
SECItem pseed = { 0, 0, 0 };
mp_int P, Q, G, H, l, p0;
mp_err err = MP_OKAY;
SECStatus rv = SECFailure;
int iterations = 0;
-
/* Step 1. L and N already checked by caller*/
/* Step 2. if (seedlen < N) return INVALID; */
if (seedBytes < N/PR_BITS_PER_BYTE || !pParams || !pVfy) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* Initialize an arena for the params. */
arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
@@ -1297,20 +1300,27 @@ pqg_ParamGen(unsigned int L, unsigned in
MP_DIGITS(&p0) = 0;
CHECK_MPI_OK( mp_init(&P) );
CHECK_MPI_OK( mp_init(&Q) );
CHECK_MPI_OK( mp_init(&G) );
CHECK_MPI_OK( mp_init(&H) );
CHECK_MPI_OK( mp_init(&l) );
CHECK_MPI_OK( mp_init(&p0) );
+ if (P_in && Q_in && P_in->data && Q_in->data &&
+ P_in->len > 0 && Q_in->len > 0) {
+ SECITEM_TO_MPINT(*P_in, &P);
+ SECITEM_TO_MPINT(*Q_in, &Q);
+ goto generate_G;
+ }
+
/* Select Hash and Compute lengths. */
/* getFirstHash gives us the smallest acceptable hash for this key
* strength */
- hashtype = getFirstHash(L,N);
+ hashtype = getFirstHash(L, minHashLen > N ? minHashLen : N);
outlen = HASH_ResultLen(hashtype)*PR_BITS_PER_BYTE;
/* Step 3: n = Ceil(L/outlen)-1; (same as n = Floor((L-1)/outlen)) */
n = (L - 1) / outlen;
/* Step 4: (skipped since we don't use b): b = L -1 - (n*outlen); */
seedlen = seedBytes * PR_BITS_PER_BYTE; /* bits in seed */
step_5:
/* ******************************************************************
@@ -1373,16 +1383,21 @@ step_5:
if (seed->data == NULL) {
goto cleanup;
}
PORT_Memcpy(seed->data, firstseed.data, firstseed.len);
PORT_Memcpy(seed->data+firstseed.len, pseed.data, pseed.len);
PORT_Memcpy(seed->data+firstseed.len+pseed.len, qseed.data, qseed.len);
counter = 0 ; /* (qgen_counter << 16) | pgen_counter; */
+ if (pgen_counter_out)
+ *pgen_counter_out = pgen_counter;
+ if (qgen_counter_out)
+ *qgen_counter_out = qgen_counter;
+
/* we've generated both P and Q now, skip to generating G */
goto generate_G;
}
/* ******************************************************************
** Step 8. (Step 4 in 186-1)
** "Use a robust primality testing algorithm to test whether q is prime."
**
** Appendix 2.1 states that a Rabin test with at least 50 iterations
@@ -1492,16 +1507,24 @@ generate_G:
}
/* All generation is done. Now, save the PQG params. */
MPINT_TO_SECITEM(&P, ¶ms->prime, params->arena);
MPINT_TO_SECITEM(&Q, ¶ms->subPrime, params->arena);
MPINT_TO_SECITEM(&G, ¶ms->base, params->arena);
verify->counter = counter;
*pParams = params;
*pVfy = verify;
+
+ if (firstseed_out)
+ SECITEM_CopyItem (NULL, firstseed_out, &firstseed);
+ if (qseed_out)
+ SECITEM_CopyItem (NULL, qseed_out, &qseed);
+ if (pseed_out)
+ SECITEM_CopyItem (NULL, pseed_out, &pseed);
+
cleanup:
if (pseed.data) {
PORT_Free(pseed.data);
}
if (qseed.data) {
PORT_Free(qseed.data);
}
mp_clear(&P);
@@ -1531,53 +1554,100 @@ PQG_ParamGen(unsigned int j, PQGParams *
unsigned int seedBytes;
if (j > 8 || !pParams || !pVfy) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
L = 512 + (j * 64); /* bits in P */
seedBytes = L/8;
- return pqg_ParamGen(L, DSA1_Q_BITS, FIPS186_1_TYPE, seedBytes,
- pParams, pVfy);
+ return pqg_ParamGen(L, DSA1_Q_BITS, FIPS186_1_TYPE, seedBytes, pParams, pVfy,
+ NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
}
SECStatus
PQG_ParamGenSeedLen(unsigned int j, unsigned int seedBytes,
PQGParams **pParams, PQGVerify **pVfy)
{
unsigned int L; /* Length of P in bits. Per FIPS 186. */
if (j > 8 || !pParams || !pVfy) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
L = 512 + (j * 64); /* bits in P */
- return pqg_ParamGen(L, DSA1_Q_BITS, FIPS186_1_TYPE, seedBytes,
- pParams, pVfy);
+ return pqg_ParamGen(L, DSA1_Q_BITS, FIPS186_1_TYPE, seedBytes, pParams, pVfy,
+ NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
}
SECStatus
PQG_ParamGenV2(unsigned int L, unsigned int N, unsigned int seedBytes,
- PQGParams **pParams, PQGVerify **pVfy)
+ PQGParams **pParams, PQGVerify **pVfy)
{
if (N == 0) {
N = pqg_get_default_N(L);
}
if (seedBytes == 0) {
/* seedBytes == L/8 for probable primes, N/8 for Shawe-Taylor Primes */
seedBytes = N/8;
}
if (pqg_validate_dsa2(L,N) != SECSuccess) {
/* error code already set */
return SECFailure;
}
- return pqg_ParamGen(L, N, FIPS186_3_ST_TYPE, seedBytes, pParams, pVfy);
+ return pqg_ParamGen(L, N, FIPS186_3_ST_TYPE, seedBytes, pParams, pVfy,
+ NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
}
+SECStatus
+FREEBL_Test_PQG_ParamGenV3(unsigned int L, unsigned int N, unsigned int seedBytes,
+ PQGParams **pParams, PQGVerify **pVfy,
+ int shanum, int *pgen_counter, int *qgen_counter,
+ SECItem *firstseed, SECItem *pseed, SECItem *qseed)
+{
+ if (N == 0) {
+ N = pqg_get_default_N(L);
+ }
+ if (seedBytes == 0) {
+ /* seedBytes == L/8 for probable primes, N/8 for Shawe-Taylor Primes */
+ seedBytes = N/8;
+ }
+ if (pqg_validate_dsa2(L,N) != SECSuccess) {
+ /* error code already set */
+ return SECFailure;
+ }
+
+ return pqg_ParamGen(L, N, FIPS186_3_ST_TYPE, seedBytes, pParams, pVfy,
+ NULL, NULL, shanum, pgen_counter, qgen_counter, firstseed, pseed, qseed);
+}
+
+/* Only to be used by FIPS tests */
+SECStatus
+FREEBL_Test_PQG_GenerateG (unsigned int L, unsigned int N, unsigned int seedBytes,
+ PQGParams **pParams, PQGVerify **pVfy,
+ int shanum, const SECItem *P, const SECItem *Q)
+{
+ /* Generate G from P and Q according to FIPS 186-3 A2.1 */
+
+ if (N == 0) {
+ N = pqg_get_default_N(L);
+ }
+
+ if (seedBytes == 0) {
+ /* seedBytes == L/8 for probable primes, N/8 for Shawe-Taylor Primes */
+ seedBytes = N/8;
+ }
+ if (pqg_validate_dsa2(L,N) != SECSuccess) {
+ /* error code already set */
+ return SECFailure;
+ }
+
+ return pqg_ParamGen (L, N, FIPS186_1_TYPE, seedBytes, pParams, pVfy,
+ P, Q, shanum, NULL, NULL, NULL, NULL, NULL);
+}
/*
* verify can use vfy structures returned from either FIPS186-1 or
* FIPS186-2, and can handle differences in selected Hash functions to
* generate the parameters.
*/
SECStatus
PQG_VerifyParams(const PQGParams *params,
@@ -1586,17 +1656,17 @@ PQG_VerifyParams(const PQGParams *params
SECStatus rv = SECSuccess;
unsigned int g, n, L, N, offset, outlen;
mp_int p0, P, Q, G, P_, Q_, G_, r, h;
mp_err err = MP_OKAY;
int j;
unsigned int counter_max = 0; /* handle legacy L < 1024 */
unsigned int qseed_len;
SECItem pseed_ = {0, 0, 0};
- HASH_HashType hashtype;
+ HASH_HashType hashtype = HASH_AlgNULL;
pqgGenType type;
#define CHECKPARAM(cond) \
if (!(cond)) { \
*result = SECFailure; \
goto cleanup; \
}
if (!params || !vfy || !result) {