File nss-CAVS-fixes.patch of Package mozilla-nss.754
# HG changeset patch
# Parent 2706b90296a4137a738f19ea81f378fc2dcce465
extend CAVS test to provide what it takes for certification
diff --git a/cmd/fipstest/dsa.sh b/cmd/fipstest/dsa.sh
--- a/cmd/fipstest/dsa.sh
+++ b/cmd/fipstest/dsa.sh
@@ -17,17 +17,17 @@ response=`echo $request | sed -e "s/req/
echo $request $response
fipstest dsa keypair $request > $response
request=PQGGen.req
response=`echo $request | sed -e "s/req/rsp/"`
echo $request $response
fipstest dsa pqggen $request > $response
-request=PQGVer.req
+request=PQGVer1863.req
response=`echo $request | sed -e "s/req/rsp/"`
echo $request $response
fipstest dsa pqgver $request > $response
request=SigGen.req
response=`echo $request | sed -e "s/req/rsp/"`
echo $request $response
fipstest dsa siggen $request > $response
diff --git a/cmd/fipstest/fipstest.c b/cmd/fipstest/fipstest.c
--- a/cmd/fipstest/fipstest.c
+++ b/cmd/fipstest/fipstest.c
@@ -1,28 +1,31 @@
/* 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/. */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
+#include <dlfcn.h>
#include "secitem.h"
#include "blapi.h"
#include "nssutil.h"
#include "secerr.h"
#include "secder.h"
#include "secdig.h"
#include "secoid.h"
#include "ec.h"
#include "hasht.h"
#include "lowkeyi.h"
#include "softoken.h"
+#include "../../lib/freebl/fips.h"
+
#if 0
#include "../../lib/freebl/mpi/mpi.h"
#endif
#ifndef NSS_DISABLE_ECC
extern SECStatus
EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
extern SECStatus
@@ -34,16 +37,26 @@ EC_CopyParams(PLArenaPool *arena, ECPara
#define DECRYPT 0
#define BYTE unsigned char
#define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
#define RSA_MAX_TEST_MODULUS_BITS 4096
#define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS/8
#define RSA_MAX_TEST_EXPONENT_BYTES 8
#define PQG_TEST_SEED_BYTES 20
+/* Function pointers for dynamically loaded functions */
+void *(*FREEBL_GetGlobalVar_p) (int which, void *data);
+SECStatus (*FREEBL_Test_PQG_ParamGenV3_p) (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_p) (unsigned int L, unsigned int N, unsigned int seedBytes,
+ PQGParams **pParams, PQGVerify **pVfy,
+ int shanum, const SECItem *P, const SECItem *Q);
+
SECStatus
hex_to_byteval(const char *c2, unsigned char *byteval)
{
int i;
unsigned char offset;
*byteval = 0;
for (i=0; i<2; i++) {
if (c2[i] >= '0' && c2[i] <= '9') {
@@ -93,16 +106,34 @@ to_hex_str_cap(char *str, const unsigned
{
unsigned int i;
for (i=0; i<len; i++) {
byteval_to_hex(buf[i], &str[2*i], 'A');
}
str[2*len] = '\0';
}
+void
+to_hex_str_pad (char *str, const unsigned char *buf, unsigned int len, unsigned int padlen)
+{
+ unsigned int i, j;
+
+ for (j = 0; len < padlen; padlen--)
+ {
+ str [j++] = '0';
+ str [j++] = '0';
+ }
+
+ for (i=0; i<len; i++, j += 2) {
+ byteval_to_hex(buf[i], &str[j], 'a');
+ }
+
+ str[j] = '\0';
+}
+
/*
* Convert a string of hex digits (str) to an array (buf) of len bytes.
* Return PR_TRUE if the hex string can fit in the byte array. Return
* PR_FALSE if the hex string is empty or is too long.
*/
PRBool
from_hex_str(unsigned char *buf, unsigned int len, const char *str)
{
@@ -147,16 +178,181 @@ from_hex_str(unsigned char *buf, unsigne
} else {
hex_to_byteval(&str[j], &buf[i]);
j += 2;
}
}
return PR_TRUE;
}
+/*
+ * Convert a string of hex digits (str) to an array (buf) of maxlen bytes.
+ * Return length of resulting output in buf, or 0 on error.
+ */
+int
+from_hex_str_varlen (unsigned char *buf, unsigned int maxlen, const char *str)
+{
+ unsigned int nxdigit; /* number of hex digits in str */
+ unsigned int i; /* index into buf */
+ unsigned int j; /* index into str */
+
+ /* count the hex digits */
+ nxdigit = 0;
+ for (nxdigit = 0; isxdigit (str [nxdigit]); nxdigit++) {
+ /* empty body */
+ }
+ if (nxdigit == 0) {
+ return 0;
+ }
+
+ for (i = 0, j = 0; j < nxdigit; i++) {
+ if ((nxdigit - j) % 2 == 1) {
+ char tmp [2];
+ tmp [0] = '0';
+ tmp [1] = str [j];
+ hex_to_byteval (tmp, &buf [i]);
+ j++;
+ } else {
+ hex_to_byteval (&str [j], &buf [i]);
+ j += 2;
+ }
+ }
+ return i;
+}
+
+/*
+ * HASH_ functions are available to full NSS apps and internally inside
+ * freebl, but not exported to users of freebl. Create short stubs to
+ * replace the functionality for fipstest.
+ */
+SECStatus
+fips_hashBuf(HASH_HashType type, unsigned char *hashBuf,
+ unsigned char *msg, int len)
+{
+ SECStatus rv = SECFailure;
+
+ switch (type) {
+ case HASH_AlgSHA1:
+ rv = SHA1_HashBuf(hashBuf, msg, len);
+ break;
+ case HASH_AlgSHA224:
+ rv = SHA224_HashBuf(hashBuf, msg, len);
+ break;
+ case HASH_AlgSHA256:
+ rv = SHA256_HashBuf(hashBuf, msg, len);
+ break;
+ case HASH_AlgSHA384:
+ rv = SHA384_HashBuf(hashBuf, msg, len);
+ break;
+ case HASH_AlgSHA512:
+ rv = SHA512_HashBuf(hashBuf, msg, len);
+ break;
+ default:
+ break;
+ }
+ return rv;
+}
+
+int
+fips_hashLen(HASH_HashType type)
+{
+ int len = 0;
+
+ switch (type) {
+ case HASH_AlgSHA1:
+ len = SHA1_LENGTH;
+ break;
+ case HASH_AlgSHA224:
+ len = SHA224_LENGTH;
+ break;
+ case HASH_AlgSHA256:
+ len = SHA256_LENGTH;
+ break;
+ case HASH_AlgSHA384:
+ len = SHA384_LENGTH;
+ break;
+ case HASH_AlgSHA512:
+ len = SHA512_LENGTH;
+ break;
+ default:
+ break;
+ }
+ return len;
+}
+
+SECOidTag
+fips_hashOid(HASH_HashType type)
+{
+ SECOidTag oid = SEC_OID_UNKNOWN;
+
+ switch (type) {
+ case HASH_AlgSHA1:
+ oid = SEC_OID_SHA1;
+ break;
+ case HASH_AlgSHA224:
+ oid = SEC_OID_SHA224;
+ break;
+ case HASH_AlgSHA256:
+ oid = SEC_OID_SHA256;
+ break;
+ case HASH_AlgSHA384:
+ oid = SEC_OID_SHA384;
+ break;
+ case HASH_AlgSHA512:
+ oid = SEC_OID_SHA512;
+ break;
+ default:
+ break;
+ }
+ return oid;
+}
+
+HASH_HashType
+sha_get_hashType(int hashbits)
+{
+ HASH_HashType hashType = HASH_AlgNULL;
+
+ switch (hashbits) {
+ case 1:
+ case (SHA1_LENGTH*PR_BITS_PER_BYTE):
+ hashType = HASH_AlgSHA1;
+ break;
+ case (SHA224_LENGTH*PR_BITS_PER_BYTE):
+ hashType = HASH_AlgSHA224;
+ break;
+ case (SHA256_LENGTH*PR_BITS_PER_BYTE):
+ hashType = HASH_AlgSHA256;
+ break;
+ case (SHA384_LENGTH*PR_BITS_PER_BYTE):
+ hashType = HASH_AlgSHA384;
+ break;
+ case (SHA512_LENGTH*PR_BITS_PER_BYTE):
+ hashType = HASH_AlgSHA512;
+ break;
+ default:
+ break;
+ }
+ return hashType;
+}
+
+/*
+ * Calculate the SHA Message Digest
+ *
+ * MD = Message digest
+ * MDLen = length of Message Digest and SHA_Type
+ * msg = message to digest
+ * msgLen = length of message to digest
+ */
+SECStatus sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen)
+{
+ HASH_HashType hashType = sha_get_hashType(MDLen*PR_BITS_PER_BYTE);
+
+ return fips_hashBuf(hashType, MD, msg, msgLen);
+}
+
SECStatus
tdea_encrypt_buf(
int mode,
const unsigned char *key,
const unsigned char *iv,
unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
const unsigned char *input, unsigned int inputlen)
{
@@ -2001,22 +2197,22 @@ ecdsa_keypair_test(char *reqfn)
int i;
unsigned int len;
ecdsareq = fopen(reqfn, "r");
ecdsaresp = stdout;
strcpy(curve, "nist");
while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
/* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
+ if (buf[0] == '#' || buf[0] == '\n' || buf [0] == '\r') {
fputs(buf, ecdsaresp);
continue;
}
/* [X-ddd] */
- if (buf[0] == '[') {
+ if (buf[0] == '[' && buf [1] != '\0' && buf [2] == '-') {
const char *src;
char *dst;
SECItem *encodedparams;
src = &buf[1];
dst = &curve[4];
*dst++ = tolower(*src);
src += 2; /* skip the hyphen */
@@ -2030,16 +2226,21 @@ ecdsa_keypair_test(char *reqfn)
}
if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
goto loser;
}
SECITEM_FreeItem(encodedparams, PR_TRUE);
fputs(buf, ecdsaresp);
continue;
}
+ /* [...] */
+ if (buf [0] == '[') {
+ fputs(buf, ecdsaresp);
+ continue;
+ }
/* N = x */
if (buf[0] == 'N') {
if (sscanf(buf, "N = %d", &N) != 1) {
goto loser;
}
for (i = 0; i < N; i++) {
ECPrivateKey *ecpriv;
@@ -2216,20 +2417,23 @@ ecdsa_siggen_test(char *reqfn)
* needs to be large enough to hold the longest
* line "Msg = <256 hex digits>\n".
*/
FILE *ecdsareq; /* input stream from the REQUEST file */
FILE *ecdsaresp; /* output stream to the RESPONSE file */
char curve[16]; /* "nistxddd" */
ECParams *ecparams = NULL;
int i, j;
+ char c;
+ int curvenum;
+ int shanum;
unsigned int len;
unsigned char msg[512]; /* message to be signed (<= 128 bytes) */
unsigned int msglen;
- unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
+ unsigned char md[SHA512_LENGTH];
unsigned char sig[2*MAX_ECKEY_LEN];
SECItem signature, digest;
ecdsareq = fopen(reqfn, "r");
ecdsaresp = stdout;
strcpy(curve, "nist");
while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
/* a comment or blank line */
@@ -2238,16 +2442,19 @@ ecdsa_siggen_test(char *reqfn)
continue;
}
/* [X-ddd] */
if (buf[0] == '[') {
const char *src;
char *dst;
SECItem *encodedparams;
+ if (sscanf (buf, "[%c-%d,SHA-%d]", &c, &curvenum, &shanum) != 3)
+ goto loser;
+
src = &buf[1];
dst = &curve[4];
*dst++ = tolower(*src);
src += 2; /* skip the hyphen */
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
*dst = '\0';
@@ -2273,17 +2480,17 @@ ecdsa_siggen_test(char *reqfn)
i = 3;
while (isspace(buf[i]) || buf[i] == '=') {
i++;
}
for (j=0; isxdigit(buf[i]); i+=2,j++) {
hex_to_byteval(&buf[i], &msg[j]);
}
msglen = j;
- if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
+ if (fips_hashBuf(sha_get_hashType(shanum), md, msg, msglen) != SECSuccess) {
goto loser;
}
fputs(buf, ecdsaresp);
if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
goto loser;
}
if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
@@ -2303,18 +2510,18 @@ ecdsa_siggen_test(char *reqfn)
fputs(buf, ecdsaresp);
fputc('\n', ecdsaresp);
fputs("Qy = ", ecdsaresp);
to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
fputs(buf, ecdsaresp);
fputc('\n', ecdsaresp);
digest.type = siBuffer;
- digest.data = sha1;
- digest.len = sizeof sha1;
+ digest.data = md;
+ digest.len = fips_hashLen (sha_get_hashType (shanum));
signature.type = siBuffer;
signature.data = sig;
signature.len = sizeof sig;
if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) {
goto loser;
}
len = signature.len;
if (len%2 != 0) {
@@ -2355,21 +2562,24 @@ ecdsa_sigver_test(char *reqfn)
* needs to be large enough to hold the longest
* line "Msg = <256 hex digits>\n".
*/
FILE *ecdsareq; /* input stream from the REQUEST file */
FILE *ecdsaresp; /* output stream to the RESPONSE file */
char curve[16]; /* "nistxddd" */
ECPublicKey ecpub;
unsigned int i, j;
+ char c;
+ int curvenum;
+ int shanum;
unsigned int flen; /* length in bytes of the field size */
unsigned int olen; /* length in bytes of the base point order */
unsigned char msg[512]; /* message that was signed (<= 128 bytes) */
unsigned int msglen;
- unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
+ unsigned char md[SHA512_LENGTH];
unsigned char sig[2*MAX_ECKEY_LEN];
SECItem signature, digest;
PRBool keyvalid = PR_TRUE;
PRBool sigvalid = PR_TRUE;
ecdsareq = fopen(reqfn, "r");
ecdsaresp = stdout;
ecpub.ecParams.arena = NULL;
@@ -2382,16 +2592,19 @@ ecdsa_sigver_test(char *reqfn)
}
/* [X-ddd] */
if (buf[0] == '[') {
const char *src;
char *dst;
SECItem *encodedparams;
ECParams *ecparams;
+ if (sscanf (buf, "[%c-%d,SHA-%d]", &c, &curvenum, &shanum) != 3)
+ goto loser;
+
src = &buf[1];
dst = &curve[4];
*dst++ = tolower(*src);
src += 2; /* skip the hyphen */
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
*dst = '\0';
@@ -2437,24 +2650,24 @@ ecdsa_sigver_test(char *reqfn)
i = 3;
while (isspace(buf[i]) || buf[i] == '=') {
i++;
}
for (j=0; isxdigit(buf[i]); i+=2,j++) {
hex_to_byteval(&buf[i], &msg[j]);
}
msglen = j;
- if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
+ if (fips_hashBuf(sha_get_hashType(shanum), md, msg, msglen) != SECSuccess) {
goto loser;
}
fputs(buf, ecdsaresp);
digest.type = siBuffer;
- digest.data = sha1;
- digest.len = sizeof sha1;
+ digest.data = md;
+ digest.len = fips_hashLen (sha_get_hashType (shanum));
continue;
}
/* Qx = ... */
if (strncmp(buf, "Qx", 2) == 0) {
fputs(buf, ecdsaresp);
i = 2;
while (isspace(buf[i]) || buf[i] == '=') {
@@ -2603,19 +2816,19 @@ drbg(char *reqfn)
unsigned char *nonce = NULL;
int nonceLen = 0;
unsigned char *personalizationString = NULL;
int personalizationStringLen = 0;
unsigned char *additionalInput = NULL;
int additionalInputLen = 0;
unsigned char *entropyInput = NULL;
int entropyInputLen = 0;
- unsigned char predictedreturn_bytes[SHA256_LENGTH];
- unsigned char return_bytes[SHA256_LENGTH];
- int return_bytes_len = SHA256_LENGTH;
+ unsigned char *predictedreturn_bytes = NULL;
+ unsigned char *return_bytes = NULL;
+ int return_bytes_len = 0;
enum { NONE, INSTANTIATE, GENERATE, RESEED, RESULT } command =
NONE;
PRBool genResult = PR_FALSE;
SECStatus rv;
rngreq = fopen(reqfn, "r");
rngresp = stdout;
while (fgets(buf, sizeof buf, rngreq) != NULL) {
@@ -2804,16 +3017,41 @@ drbg(char *reqfn)
additionalInputLen = additionalInputLen/8;
if (additionalInputLen > 0) {
additionalInput = PORT_Alloc(additionalInputLen);
}
fputs(buf, rngresp);
continue;
}
+ if (strncmp(buf, "[ReturnedBitsLen", 16) == 0) {
+ if (return_bytes) {
+ PORT_ZFree(return_bytes, return_bytes_len);
+ return_bytes = NULL;
+ }
+
+ if (predictedreturn_bytes) {
+ PORT_ZFree(predictedreturn_bytes, return_bytes_len);
+ predictedreturn_bytes = NULL;
+ }
+
+ return_bytes_len = 0;
+
+ if (sscanf(buf, "[ReturnedBitsLen = %d]", &return_bytes_len) != 1) {
+ goto loser;
+ }
+ return_bytes_len = return_bytes_len/8;
+ if (return_bytes_len > 0) {
+ return_bytes = PORT_Alloc(return_bytes_len);
+ predictedreturn_bytes = PORT_Alloc(return_bytes_len);
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+
if (strncmp(buf, "COUNT", 5) == 0) {
/* zeroize the variables for the test with this data set */
if (entropyInput) {
memset(entropyInput, 0, entropyInputLen);
}
if (nonce) {
memset(nonce, 0, nonceLen);
}
@@ -2954,17 +3192,17 @@ drbg(char *reqfn)
to_hex_str(buf, predictedreturn_bytes,
return_bytes_len);
fputs(buf, stderr);
fputs("\n actual = ", stderr);
fputs(buf2, stderr);
fputc('\n', stderr);
}
}
- memset(predictedreturn_bytes, 0 , sizeof predictedreturn_bytes);
+ memset(predictedreturn_bytes, 0, return_bytes_len);
continue;
}
}
loser:
fclose(rngreq);
}
@@ -3213,146 +3451,16 @@ rng_mct(char *reqfn)
continue;
}
}
loser:
fclose(rngreq);
}
/*
- * HASH_ functions are available to full NSS apps and internally inside
- * freebl, but not exported to users of freebl. Create short stubs to
- * replace the functionality for fipstest.
- */
-SECStatus
-fips_hashBuf(HASH_HashType type, unsigned char *hashBuf,
- unsigned char *msg, int len)
-{
- SECStatus rv = SECFailure;
-
- switch (type) {
- case HASH_AlgSHA1:
- rv = SHA1_HashBuf(hashBuf, msg, len);
- break;
- case HASH_AlgSHA224:
- rv = SHA224_HashBuf(hashBuf, msg, len);
- break;
- case HASH_AlgSHA256:
- rv = SHA256_HashBuf(hashBuf, msg, len);
- break;
- case HASH_AlgSHA384:
- rv = SHA384_HashBuf(hashBuf, msg, len);
- break;
- case HASH_AlgSHA512:
- rv = SHA512_HashBuf(hashBuf, msg, len);
- break;
- default:
- break;
- }
- return rv;
-}
-
-int
-fips_hashLen(HASH_HashType type)
-{
- int len = 0;
-
- switch (type) {
- case HASH_AlgSHA1:
- len = SHA1_LENGTH;
- break;
- case HASH_AlgSHA224:
- len = SHA224_LENGTH;
- break;
- case HASH_AlgSHA256:
- len = SHA256_LENGTH;
- break;
- case HASH_AlgSHA384:
- len = SHA384_LENGTH;
- break;
- case HASH_AlgSHA512:
- len = SHA512_LENGTH;
- break;
- default:
- break;
- }
- return len;
-}
-
-SECOidTag
-fips_hashOid(HASH_HashType type)
-{
- SECOidTag oid = SEC_OID_UNKNOWN;
-
- switch (type) {
- case HASH_AlgSHA1:
- oid = SEC_OID_SHA1;
- break;
- case HASH_AlgSHA224:
- oid = SEC_OID_SHA224;
- break;
- case HASH_AlgSHA256:
- oid = SEC_OID_SHA256;
- break;
- case HASH_AlgSHA384:
- oid = SEC_OID_SHA384;
- break;
- case HASH_AlgSHA512:
- oid = SEC_OID_SHA512;
- break;
- default:
- break;
- }
- return oid;
-}
-
-HASH_HashType
-sha_get_hashType(int hashbits)
-{
- HASH_HashType hashType = HASH_AlgNULL;
-
- switch (hashbits) {
- case 1:
- case (SHA1_LENGTH*PR_BITS_PER_BYTE):
- hashType = HASH_AlgSHA1;
- break;
- case (SHA224_LENGTH*PR_BITS_PER_BYTE):
- hashType = HASH_AlgSHA224;
- break;
- case (SHA256_LENGTH*PR_BITS_PER_BYTE):
- hashType = HASH_AlgSHA256;
- break;
- case (SHA384_LENGTH*PR_BITS_PER_BYTE):
- hashType = HASH_AlgSHA384;
- break;
- case (SHA512_LENGTH*PR_BITS_PER_BYTE):
- hashType = HASH_AlgSHA512;
- break;
- default:
- break;
- }
- return hashType;
-}
-
-/*
- * Calculate the SHA Message Digest
- *
- * MD = Message digest
- * MDLen = length of Message Digest and SHA_Type
- * msg = message to digest
- * msgLen = length of message to digest
- */
-SECStatus sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen)
-{
- HASH_HashType hashType = sha_get_hashType(MDLen*PR_BITS_PER_BYTE);
-
- return fips_hashBuf(hashType, MD, msg, msgLen);
-}
-
-/*
* Perform the SHA Monte Carlo Test
*
* MDLen = length of Message Digest and SHA_Type
* seed = input seed value
* resp = is the output response file.
*/
SECStatus sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp)
{
@@ -3414,17 +3522,17 @@ SECStatus sha_mct_test(unsigned int MDLe
* The output RESPONSE file is written to stdout.
*/
void sha_test(char *reqfn)
{
unsigned int i, j;
unsigned int MDlen; /* the length of the Message Digest in Bytes */
unsigned int msgLen; /* the length of the input Message in Bytes */
unsigned char *msg = NULL; /* holds the message to digest.*/
- size_t bufSize = 25608; /*MAX buffer size */
+ size_t bufSize = 102400; /*MAX buffer size */
char *buf = NULL; /* holds one line from the input REQUEST file.*/
unsigned char seed[HASH_LENGTH_MAX]; /* max size of seed 64 bytes */
unsigned char MD[HASH_LENGTH_MAX]; /* message digest */
FILE *req = NULL; /* input stream from the REQUEST file */
FILE *resp; /* output stream to the RESPONSE file */
buf = PORT_ZAlloc(bufSize);
@@ -3721,17 +3829,17 @@ void hmac_test(char *reqfn)
hex_to_byteval(&buf[i], &msg[j]);
}
fputs(buf, resp);
/* calculate the HMAC and output */
if (hmac_calc(HMAC, HMACLen, key, keyLen,
msg, msgLen, hash_alg) != SECSuccess) {
goto loser;
}
- fputs("MAC = ", resp);
+ fputs("Mac = ", resp);
to_hex_str(buf, HMAC, TLen);
fputs(buf, resp);
fputc('\n', resp);
continue;
}
}
loser:
if (req) {
@@ -3868,16 +3976,17 @@ loser:
/*
* pqg generation type
*/
typedef enum {
FIPS186_1,/* Generate/Verify P,Q & G according to FIPS 186-1 */
A_1_1_2, /* Generate Probable P & Q */
A_1_1_3, /* Verify Probable P & Q */
+ A_1_2_1, /* Generate Provable P & Q */
A_1_2_2, /* Verify Provable P & Q */
A_2_1, /* Generate Unverifiable G */
A_2_2, /* Assure Unverifiable G */
A_2_3, /* Generate Verifiable G */
A_2_4 /* Verify Verifiable G */
} dsa_pqg_type;
/*
@@ -3906,17 +4015,17 @@ dsa_pqgver_test(char *reqfn)
dsareq = fopen(reqfn, "r");
dsaresp = stdout;
memset(&pqg, 0, sizeof(pqg));
memset(&vfy, 0, sizeof(vfy));
while (fgets(buf, sizeof buf, dsareq) != NULL) {
/* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
+ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
fputs(buf, dsaresp);
continue;
}
/* [A.xxxxx ] */
if (buf[0] == '[' && buf[1] == 'A') {
if (strncmp(&buf[1],"A.1.1.3",7) == 0) {
@@ -4119,17 +4228,16 @@ dsa_pqgver_test(char *reqfn)
if (rv != SECSuccess) {
goto loser;
}
if (result == SECSuccess) {
fprintf(dsaresp, "Result = P\n");
} else {
fprintf(dsaresp, "Result = F\n");
}
- fprintf(dsaresp, "\n");
}
continue;
}
if (strncmp(buf,"pgen_counter", 12) == 0) {
if (sscanf(buf, "pgen_counter = %u", &vfy.counter) != 1) {
goto loser;
}
fputs(buf, dsaresp);
@@ -4144,17 +4252,16 @@ dsa_pqgver_test(char *reqfn)
if (rv != SECSuccess) {
goto loser;
}
if (result == SECSuccess) {
fprintf(dsaresp, "Result = P\n");
} else {
fprintf(dsaresp, "Result = F\n");
}
- fprintf(dsaresp, "\n");
}
continue;
}
/* H = ... */
if (buf[0] == 'H') {
SECStatus rv, result = SECFailure;
i = 1;
@@ -4182,17 +4289,16 @@ dsa_pqgver_test(char *reqfn)
if (rv != SECSuccess) {
goto loser;
}
if (result == SECSuccess) {
fprintf(dsaresp, "Result = P\n");
} else {
fprintf(dsaresp, "Result = F\n");
}
- fprintf(dsaresp, "\n");
continue;
}
}
loser:
fclose(dsareq);
if (pqg.prime.data) { /* P */
SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
}
@@ -4226,61 +4332,63 @@ dsa_pqggen_test(char *reqfn)
* 800 to hold seed = (384 public key (x2 for HEX)
*/
FILE *dsareq; /* input stream from the REQUEST file */
FILE *dsaresp; /* output stream to the RESPONSE file */
int count; /* number of times to generate parameters */
int N;
int L;
int i;
+ int shanum = 0;
unsigned int j;
PQGParams *pqg = NULL;
PQGVerify *vfy = NULL;
+ SECItem P, Q;
unsigned int keySizeIndex;
dsa_pqg_type type = FIPS186_1;
dsareq = fopen(reqfn, "r");
dsaresp = stdout;
while (fgets(buf, sizeof buf, dsareq) != NULL) {
/* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
+ if (buf[0] == '#' || buf[0] == '\n' || buf [0] == '\r') {
fputs(buf, dsaresp);
continue;
}
/* [A.xxxxx ] */
if (buf[0] == '[' && buf[1] == 'A') {
if (strncmp(&buf[1],"A.1.1.2",7) == 0) {
type = A_1_1_2;
} else if (strncmp(&buf[1],"A.2.1",5) == 0) {
- fprintf(stderr, "NSS only Generates G with P&Q\n");
- exit(1);
+ type = A_2_1;
} else if (strncmp(&buf[1],"A.2.3",5) == 0) {
fprintf(stderr, "NSS only Generates G with P&Q\n");
exit(1);
} else if (strncmp(&buf[1],"A.1.2.1",7) == 0) {
- fprintf(stderr, "NSS does not support Shawe-Taylor Primes\n");
- exit(1);
+ type = A_1_2_1;
} else {
fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]);
exit(1);
}
fputs(buf, dsaresp);
continue;
}
/* [Mod = ... ] */
if (buf[0] == '[') {
+ shanum = 0;
if (type == FIPS186_1) {
N=160;
if (sscanf(buf, "[mod = %d]", &L) != 1) {
goto loser;
}
- } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
+ } else if (sscanf (buf, "[mod = L=%d, N=%d, SHA-%d", &L, &N, &shanum) != 3 &&
+ sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
goto loser;
}
fputs(buf, dsaresp);
fputc('\n', dsaresp);
if (type == FIPS186_1) {
/************************************************************
@@ -4292,71 +4400,151 @@ dsa_pqggen_test(char *reqfn)
fprintf(dsaresp,
"DSA key size must be a multiple of 64 between 512 "
"and 1024, inclusive");
goto loser;
}
}
continue;
}
- /* N = ... */
- if (buf[0] == 'N') {
- if (sscanf(buf, "N = %d", &count) != 1) {
+ /* Num = ... */
+ if (strncmp(buf, "Num", 3) == 0) {
+ if (sscanf(buf, "Num = %d", &count) != 1) {
goto loser;
}
for (i = 0; i < count; i++) {
+ int pgen_counter, qgen_counter;
+ SECItem firstseed = { 0 }, qseed = { 0 }, pseed = { 0 };
SECStatus rv;
if (type == FIPS186_1) {
rv = PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
&pqg, &vfy);
+ } else if (type == A_1_2_1) {
+ rv = FREEBL_Test_PQG_ParamGenV3_p(L, N, 0, &pqg, &vfy,
+ shanum, &pgen_counter, &qgen_counter,
+ &firstseed, &pseed, &qseed);
+ } else if (type == A_1_1_2) {
+ rv = PQG_ParamGenV2(L, N, 0, &pqg, &vfy);
} else {
- rv = PQG_ParamGenV2(L, N, N, &pqg, &vfy);
+ /* A_2_1 -- Generate G when P and Q have been read */
+ continue;
}
+
if (rv != SECSuccess) {
fprintf(dsaresp,
"ERROR: Unable to generate PQG parameters");
goto loser;
}
to_hex_str(buf, pqg->prime.data, pqg->prime.len);
fprintf(dsaresp, "P = %s\n", buf);
to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
fprintf(dsaresp, "Q = %s\n", buf);
- to_hex_str(buf, pqg->base.data, pqg->base.len);
- fprintf(dsaresp, "G = %s\n", buf);
if (type == FIPS186_1) {
+ to_hex_str(buf, pqg->base.data, pqg->base.len);
+ fprintf(dsaresp, "G = %s\n", buf);
to_hex_str(buf, vfy->seed.data, vfy->seed.len);
fprintf(dsaresp, "Seed = %s\n", buf);
fprintf(dsaresp, "c = %d\n", vfy->counter);
to_hex_str(buf, vfy->h.data, vfy->h.len);
fputs("H = ", dsaresp);
for (j=vfy->h.len; j< pqg->prime.len; j++) {
fprintf(dsaresp, "00");
}
fprintf(dsaresp, "%s\n", buf);
+ } else if (type == A_1_2_1) {
+ to_hex_str(buf, firstseed.data, firstseed.len);
+ fprintf(dsaresp, "firstseed = %s\n", buf);
+ to_hex_str(buf, pseed.data, pseed.len);
+ fprintf(dsaresp, "pseed = %s\n", buf);
+ to_hex_str(buf, qseed.data, qseed.len);
+ fprintf(dsaresp, "qseed = %s\n", buf);
+ fprintf(dsaresp, "pgen_counter = %d\n", pgen_counter);
+ fprintf(dsaresp, "qgen_counter = %d\n", qgen_counter);
} else {
+ to_hex_str(buf, pqg->base.data, pqg->base.len);
+ fprintf(dsaresp, "G = %s\n", buf);
fprintf(dsaresp, "counter = %d\n", vfy->counter);
fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]);
to_hex_str(buf, vfy->seed.data, vfy->seed.len);
fprintf(dsaresp, "domain_parameter_seed = %s\n", buf);
}
+
fputc('\n', dsaresp);
+
if(pqg!=NULL) {
PQG_DestroyParams(pqg);
pqg = NULL;
}
if(vfy!=NULL) {
PQG_DestroyVerify(vfy);
vfy = NULL;
}
+
+ if (firstseed.data) {
+ SECITEM_FreeItem(&firstseed, PR_FALSE);
+ firstseed.data = NULL;
+ }
+ if (pseed.data) {
+ SECITEM_FreeItem(&pseed, PR_FALSE);
+ pseed.data = NULL;
+ }
+ if (qseed.data) {
+ SECITEM_FreeItem(&qseed, PR_FALSE);
+ qseed.data = NULL;
+ }
}
continue;
}
+ /* P = ... */
+ if (buf[0] == 'P') {
+ unsigned char databuf [1024];
+ int len;
+
+ fputs(buf, dsaresp);
+
+ for (i = 1; isspace (buf [i]) || buf [i] == '='; i++)
+ ;
+
+ len = from_hex_str_varlen (databuf, 1024, &buf [i]);
+
+ P.type = siBuffer;
+ P.data = NULL;
+ P.len = 0;
+ SECITEM_AllocItem (NULL, &P, len);
+ memcpy (P.data, databuf, len);
+ }
+
+ /* Q = ... */
+ if (buf[0] == 'Q') {
+ unsigned char databuf [1024];
+ char hexbuf [1024];
+ int len;
+
+ fputs(buf, dsaresp);
+
+ for (i = 1; isspace (buf [i]) || buf [i] == '='; i++)
+ ;
+
+ len = from_hex_str_varlen (databuf, 1024, &buf [i]);
+
+ Q.type = siBuffer;
+ Q.data = NULL;
+ Q.len = 0;
+ SECITEM_AllocItem (NULL, &Q, len);
+ memcpy (Q.data, databuf, len);
+
+ /* Generate G from P and Q according to FIPS 186-3 A2.1 */
+ FREEBL_Test_PQG_GenerateG_p (L, N, 0, &pqg, &vfy, shanum, &P, &Q);
+
+ to_hex_str((char *) hexbuf, pqg->base.data, pqg->base.len);
+ fprintf(dsaresp, "G = %s\n", hexbuf);
+ }
}
loser:
fclose(dsareq);
if(pqg!=NULL) {
PQG_DestroyParams(pqg);
}
if(vfy!=NULL) {
PQG_DestroyVerify(vfy);
@@ -4395,17 +4583,17 @@ dsa_siggen_test(char *reqfn)
HASH_HashType hashType = HASH_AlgNULL;
int hashNum = 0;
dsareq = fopen(reqfn, "r");
dsaresp = stdout;
while (fgets(buf, sizeof buf, dsareq) != NULL) {
/* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
+ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
fputs(buf, dsaresp);
continue;
}
/* [Mod = x] */
if (buf[0] == '[') {
if(pqg!=NULL) {
PQG_DestroyParams(pqg);
@@ -4424,17 +4612,16 @@ dsa_siggen_test(char *reqfn)
&hashNum) != 3) {
use_dsa1 = PR_TRUE;
hashNum = 1;
if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
goto loser;
}
}
fputs(buf, dsaresp);
- fputc('\n', dsaresp);
/****************************************************************
* PQG_ParamGenSeedLen doesn't take a key size, it takes an index
* that points to a valid key size.
*/
if (use_dsa1) {
keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
@@ -4452,16 +4639,17 @@ dsa_siggen_test(char *reqfn)
}
} else {
if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
fprintf(dsaresp,
"ERROR: Unable to generate PQG parameters");
goto loser;
}
}
+
to_hex_str(buf, pqg->prime.data, pqg->prime.len);
fprintf(dsaresp, "P = %s\n", buf);
to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
fprintf(dsaresp, "Q = %s\n", buf);
to_hex_str(buf, pqg->base.data, pqg->base.len);
fprintf(dsaresp, "G = %s\n", buf);
/* create DSA Key */
@@ -4526,17 +4714,16 @@ dsa_siggen_test(char *reqfn)
fputs(buf, dsaresp);
to_hex_str(buf, dsakey->publicValue.data,
dsakey->publicValue.len);
fprintf(dsaresp, "Y = %s\n", buf);
to_hex_str(buf, &signature.data[0], len);
fprintf(dsaresp, "R = %s\n", buf);
to_hex_str(buf, &signature.data[len], len);
fprintf(dsaresp, "S = %s\n", buf);
- fputc('\n', dsaresp);
continue;
}
}
loser:
fclose(dsareq);
if(pqg != NULL) {
PQG_DestroyParams(pqg);
@@ -4580,17 +4767,17 @@ dsa_sigver_test(char *reqfn)
int hashNum = 0;
dsareq = fopen(reqfn, "r");
dsaresp = stdout;
memset(&pubkey, 0, sizeof(pubkey));
while (fgets(buf, sizeof buf, dsareq) != NULL) {
/* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
+ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
fputs(buf, dsaresp);
continue;
}
/* [Mod = x] */
if (buf[0] == '[') {
if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d]", &L, & N,
@@ -4762,17 +4949,16 @@ dsa_sigver_test(char *reqfn)
signature.data = sig;
signature.len = pubkey.params.subPrime.len*2;
if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) {
fprintf(dsaresp, "Result = P\n");
} else {
fprintf(dsaresp, "Result = F\n");
}
- fprintf(dsaresp, "\n");
continue;
}
}
loser:
fclose(dsareq);
if (pubkey.params.prime.data) { /* P */
SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
}
@@ -4783,16 +4969,140 @@ loser:
SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
}
if (pubkey.publicValue.data) { /* Y */
SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
}
}
/*
+ * Perform the RSA Provable-prime key generation test
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+rsa_keygen_probable_test(char *reqfn)
+{
+ char buf[2*RSA_MAX_TEST_MODULUS_BYTES+1];
+ /* buf holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * 2x for HEX output + 1 for \n
+ */
+ FILE *rsareq; /* input stream from the REQUEST file */
+ FILE *rsaresp; /* output stream to the RESPONSE file */
+ int i;
+ int modulus; /* the Modulus size */
+ int publicExponent = DEFAULT_RSA_PUBLIC_EXPONENT;
+ SECItem pe = {0, 0, 0 };
+ unsigned char pubEx[4];
+ int peCount = 0;
+ RSAPrivateKey *rsaBlapiPrivKey = NULL; /* holds RSA private and
+ * public keys */
+
+ rsareq = fopen(reqfn, "r");
+ rsaresp = stdout;
+
+ /* calculate the exponent */
+ for (i=0; i < 4; i++) {
+ if (peCount || (publicExponent &
+ ((unsigned long)0xff000000L >> (i*8)))) {
+ pubEx[peCount] =
+ (unsigned char)((publicExponent >> (3-i)*8) & 0xff);
+ peCount++;
+ }
+ }
+ pe.len = peCount;
+ pe.data = &pubEx[0];
+ pe.type = siBuffer;
+
+ while (fgets(buf, sizeof buf, rsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n' || buf [0] == '\r') {
+ fputs(buf, rsaresp);
+ continue;
+ }
+
+ /* [PrimeMethod = ...] */
+ if (strncmp (buf, "[PrimeMethod", 4) == 0) {
+ /* PrimeMethod is always ProvRP */
+ fputs(buf, rsaresp);
+ }
+
+ /* [Table = ...] */
+ if (strncmp (buf, "[Table", 4) == 0) {
+ /* M-R Test table */
+ fputs(buf, rsaresp);
+ }
+
+ /* [mod = ...] */
+ if (strncmp (buf, "[mod", 4) == 0) {
+ if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
+ goto loser;
+ }
+ if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
+ fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
+ goto loser;
+ }
+
+ fputs(buf, rsaresp);
+ }
+
+ if (strncmp (buf, "N", 1) == 0) {
+ int count;
+ int i;
+
+ if (sscanf(buf, "N = %d", &count) != 1) {
+ goto loser;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (rsaBlapiPrivKey != NULL) {
+ PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
+ rsaBlapiPrivKey = NULL;
+ }
+
+ rsaBlapiPrivKey = RSA_NewKey(modulus, &pe);
+ if (rsaBlapiPrivKey == NULL) {
+ fprintf(rsaresp, "Error unable to create RSA key\n");
+ goto loser;
+ }
+
+ to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data,
+ rsaBlapiPrivKey->publicExponent.len);
+ fprintf(rsaresp, "e = %s\n", buf);
+ to_hex_str(buf, rsaBlapiPrivKey->prime1.data,
+ rsaBlapiPrivKey->prime1.len);
+ fprintf(rsaresp, "p = %s\n", buf);
+ to_hex_str(buf, rsaBlapiPrivKey->prime2.data,
+ rsaBlapiPrivKey->prime2.len);
+ fprintf(rsaresp, "q = %s\n", buf);
+
+ to_hex_str(buf, rsaBlapiPrivKey->modulus.data,
+ rsaBlapiPrivKey->modulus.len);
+ fprintf(rsaresp, "n = %s\n", buf);
+ to_hex_str_pad(buf, rsaBlapiPrivKey->privateExponent.data,
+ rsaBlapiPrivKey->privateExponent.len,
+ modulus / 8);
+ fprintf(rsaresp, "d = %s\n\n", buf);
+ }
+ }
+ }
+loser:
+ fclose(rsareq);
+
+ if (rsaBlapiPrivKey != NULL) {
+ /* frees private and public key */
+ PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
+ rsaBlapiPrivKey = NULL;
+ }
+}
+
+/*
* Perform the RSA Signature Generation Test.
*
* reqfn is the pathname of the REQUEST file.
*
* The output RESPONSE file is written to stdout.
*/
void
rsa_siggen_test(char *reqfn)
@@ -4832,17 +5142,17 @@ rsa_siggen_test(char *reqfn)
}
}
pe.len = peCount;
pe.data = &pubEx[0];
pe.type = siBuffer;
while (fgets(buf, sizeof buf, rsareq) != NULL) {
/* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
+ if (buf[0] == '#' || buf[0] == '\n' || buf [0] == '\r') {
fputs(buf, rsaresp);
continue;
}
/* [mod = ...] */
if (buf[0] == '[') {
if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
@@ -5030,17 +5340,17 @@ rsa_sigver_test(char *reqfn)
RSAPublicKey rsaBlapiPublicKey; /* hold RSA public key */
rsareq = fopen(reqfn, "r");
rsaresp = stdout;
memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey));
while (fgets(buf, sizeof buf, rsareq) != NULL) {
/* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
+ if (buf[0] == '#' || buf[0] == '\n' || buf [0] == '\r') {
fputs(buf, rsaresp);
continue;
}
/* [Mod = ...] */
if (buf[0] == '[') {
unsigned int flen; /* length in bytes of the field size */
@@ -5101,16 +5411,17 @@ rsa_sigver_test(char *reqfn)
} else if (strncmp(&buf[i], "SHA384", 6) == 0) {
shaAlg = HASH_AlgSHA384;
} else if (strncmp(&buf[i], "SHA512", 6) == 0) {
shaAlg = HASH_AlgSHA512;
} else {
fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
goto loser;
}
+ shaOid = fips_hashOid(shaAlg);
fputs(buf, rsaresp);
continue;
}
/* e = ... public Key */
if (buf[0] == 'e') {
unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES];
unsigned char t;
@@ -5228,22 +5539,57 @@ loser:
if (rsaBlapiPublicKey.modulus.data) { /* n */
SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
}
if (rsaBlapiPublicKey.publicExponent.data) { /* e */
SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
}
}
+static void
+init_functions (void)
+{
+ void *freebl_so;
+
+ freebl_so = dlopen ("libfreebl3.so", RTLD_LAZY);
+ if (freebl_so == NULL)
+ {
+ fprintf (stderr, "Failed to load libfreebl3.so.");
+ exit (1);
+ }
+
+ FREEBL_GetGlobalVar_p = dlsym (freebl_so, "FREEBL_GetGlobalVar");
+ FREEBL_Test_PQG_ParamGenV3_p = dlsym (freebl_so, "FREEBL_Test_PQG_ParamGenV3");
+ FREEBL_Test_PQG_GenerateG_p = dlsym (freebl_so, "FREEBL_Test_PQG_GenerateG");
+
+ if (FREEBL_GetGlobalVar_p == NULL)
+ {
+ fprintf (stderr, "Failed to bind FREEBL_GetGlobalVar.");
+ exit (1);
+ }
+ if (FREEBL_Test_PQG_ParamGenV3_p == NULL)
+ {
+ fprintf (stderr, "Failed to bind FREEBL_TEST_PQG_ParamGenV3.");
+ exit (1);
+ }
+ if (FREEBL_Test_PQG_GenerateG_p == NULL)
+ {
+ fprintf (stderr, "Failed to bind FREEBL_TEST_PQG_GenerateG.");
+ exit (1);
+ }
+}
+
int main(int argc, char **argv)
{
if (argc < 2) exit (-1);
+ init_functions ();
RNG_RNGInit();
SECOID_Init();
+ BL_Init();
/*************/
/* TDEA */
/*************/
if (strcmp(argv[1], "tdea") == 0) {
/* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */
if (strcmp(argv[2], "kat") == 0) {
/* Known Answer Test (KAT) */
@@ -5294,16 +5640,19 @@ int main(int argc, char **argv)
/* argv[2]=siggen|sigver */
/* argv[3]=<test name>.req */
if (strcmp(argv[2], "siggen") == 0) {
/* Signature Generation Test */
rsa_siggen_test(argv[3]);
} else if (strcmp(argv[2], "sigver") == 0) {
/* Signature Verification Test */
rsa_sigver_test(argv[3]);
+ } else if (strcmp(argv[2], "keygen") == 0) {
+ /* Key Generation Test with probable primes */
+ rsa_keygen_probable_test(argv[3]);
}
/*************/
/* HMAC */
/*************/
} else if (strcmp(argv[1], "hmac") == 0) {
hmac_test(argv[2]);
/*************/
/* DSA */
diff --git a/cmd/fipstest/rng.sh b/cmd/fipstest/rng.sh
old mode 100644
new mode 100755
--- a/cmd/fipstest/rng.sh
+++ b/cmd/fipstest/rng.sh
@@ -8,16 +8,16 @@
#
# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
# variables appropriately so that the fipstest command and the NSPR and NSS
# shared libraries/DLLs are on the search path. Then run this script in the
# directory where the REQUEST (.req) files reside. The script generates the
# RESPONSE (.rsp) files in the same directory.
drbg_requests="
-SHA256_DRBG.req
+Hash_DRBG.req
"
for request in $drbg_requests; do
response=`echo $request | sed -e "s/req/rsp/"`
echo $request $response
fipstest drbg $request > $response
done
diff --git a/cmd/fipstest/rsa.sh b/cmd/fipstest/rsa.sh
old mode 100644
new mode 100755
--- a/cmd/fipstest/rsa.sh
+++ b/cmd/fipstest/rsa.sh
@@ -8,17 +8,22 @@
#
# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
# variables appropriately so that the fipstest command and the NSPR and NSS
# shared libraries/DLLs are on the search path. Then run this script in the
# directory where the REQUEST (.req) files reside. The script generates the
# RESPONSE (.rsp) files in the same directory.
-request=SigGen15.req
+request=SigGen15_186-3.req
response=`echo $request | sed -e "s/req/rsp/"`
echo $request $response
fipstest rsa siggen $request > $response
-request=SigVer15.req
+request=SigVer15_186-3.req
response=`echo $request | sed -e "s/req/rsp/"`
echo $request $response
fipstest rsa sigver $request > $response
+
+request=KeyGen_RandomProbablyPrime3_3.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest rsa keygen $request > $response
diff --git a/cmd/fipstest/sha.sh b/cmd/fipstest/sha.sh
old mode 100644
new mode 100755
--- a/cmd/fipstest/sha.sh
+++ b/cmd/fipstest/sha.sh
@@ -9,30 +9,33 @@
# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
# variables appropriately so that the fipstest command and the NSPR and NSS
# shared libraries/DLLs are on the search path. Then run this script in the
# directory where the REQUEST (.req) files reside. The script generates the
# RESPONSE (.rsp) files in the same directory.
sha_ShortMsg_requests="
SHA1ShortMsg.req
+SHA224ShortMsg.req
SHA256ShortMsg.req
SHA384ShortMsg.req
SHA512ShortMsg.req
"
sha_LongMsg_requests="
SHA1LongMsg.req
+SHA224LongMsg.req
SHA256LongMsg.req
SHA384LongMsg.req
SHA512LongMsg.req
"
sha_Monte_requests="
SHA1Monte.req
+SHA224Monte.req
SHA256Monte.req
SHA384Monte.req
SHA512Monte.req
"
for request in $sha_ShortMsg_requests; do
response=`echo $request | sed -e "s/req/rsp/"`
echo $request $response
fipstest sha $request > $response
diff --git a/cmd/pk11gcmtest/pk11gcmtest.c b/cmd/pk11gcmtest/pk11gcmtest.c
--- a/cmd/pk11gcmtest/pk11gcmtest.c
+++ b/cmd/pk11gcmtest/pk11gcmtest.c
@@ -28,16 +28,42 @@ hex_to_byteval(const char *c2, unsigned
*byteval |= (offset + 10) << 4*(1-i);
} else {
return SECFailure;
}
}
return SECSuccess;
}
+SECStatus
+byteval_to_hex(unsigned char byteval, char *c2, char a)
+{
+ int i;
+ unsigned char offset;
+ for (i=0; i<2; i++) {
+ offset = (byteval >> 4*(1-i)) & 0x0f;
+ if (offset < 10) {
+ c2[i] = '0' + offset;
+ } else {
+ c2[i] = a + offset - 10;
+ }
+ }
+ return SECSuccess;
+}
+
+void
+to_hex_str(char *str, const unsigned char *buf, unsigned int len)
+{
+ unsigned int i;
+ for (i=0; i<len; i++) {
+ byteval_to_hex(buf[i], &str[2*i], 'a');
+ }
+ str[2*len] = '\0';
+}
+
static SECStatus
aes_encrypt_buf(
const unsigned char *key, unsigned int keysize,
const unsigned char *iv, unsigned int ivsize,
unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
const unsigned char *input, unsigned int inputlen,
const unsigned char *aad, unsigned int aadlen, unsigned int tagsize)
{
@@ -117,17 +143,19 @@ aes_decrypt_buf(
key_item.data = (unsigned char *) key; /* const cast */
key_item.len = keysize;
slot = PK11_GetInternalSlot();
symKey = PK11_ImportSymKey(slot, CKM_AES_GCM, PK11_OriginUnwrap,
CKA_DECRYPT, &key_item, NULL);
PK11_FreeSlot(slot);
slot = NULL;
if (!symKey) {
+#if 0
fprintf(stderr, "PK11_ImportSymKey failed\n");
+#endif
goto loser;
}
gcm_params.pIv = (unsigned char *) iv;
gcm_params.ulIvLen = ivsize;
gcm_params.pAAD = (unsigned char *) aad;
gcm_params.ulAADLen = aadlen;
gcm_params.ulTagBits = tagsize * 8;
@@ -149,26 +177,27 @@ loser:
PK11_FreeSymKey(symKey);
}
return rv;
}
/*
* Perform the AES Known Answer Test (KAT) in Galois Counter Mode (GCM).
*
- * respfn is the pathname of the RESPONSE file.
+ * reqfn is the pathname of the RESPONSE file.
*/
static void
-aes_gcm_kat(const char *respfn)
+aes_gcm_kat(const char *reqfn)
{
char buf[512]; /* holds one line from the input REQUEST file.
* needs to be large enough to hold the longest
* line "CIPHERTEXT = <320 hex digits>\n".
*/
- FILE *aesresp; /* input stream from the RESPONSE file */
+ FILE *aesreq; /* input stream from the REQUEST file */
+ FILE *aesresp; /* output stream to the RESPONSE file */
int i, j;
unsigned int test_group = 0;
unsigned int num_tests;
PRBool is_encrypt;
unsigned char key[32]; /* 128, 192, or 256 bits */
unsigned int keysize;
unsigned char iv[10*16]; /* 1 to 10 blocks */
unsigned int ivsize;
@@ -185,32 +214,34 @@ aes_gcm_kat(const char *respfn)
unsigned int expected_keylen = 0;
unsigned int expected_ivlen = 0;
unsigned int expected_ptlen = 0;
unsigned int expected_aadlen = 0;
unsigned int expected_taglen = 0;
SECStatus rv;
- if (strstr(respfn, "Encrypt") != NULL) {
+ if (strstr(reqfn, "Encrypt") != NULL) {
is_encrypt = PR_TRUE;
- } else if (strstr(respfn, "Decrypt") != NULL) {
+ } else if (strstr(reqfn, "Decrypt") != NULL) {
is_encrypt = PR_FALSE;
} else {
fprintf(stderr, "Input file name must contain Encrypt or Decrypt\n");
exit(1);
}
- aesresp = fopen(respfn, "r");
- if (aesresp == NULL) {
- fprintf(stderr, "Cannot open input file %s\n", respfn);
+ aesreq = fopen(reqfn, "r");
+ if (aesreq == NULL) {
+ fprintf(stderr, "Cannot open input file %s\n", reqfn);
exit(1);
}
- while (fgets(buf, sizeof buf, aesresp) != NULL) {
+ aesresp = stdout;
+ while (fgets(buf, sizeof buf, aesreq) != NULL) {
/* a comment or blank line */
- if (buf[0] == '#' || buf[0] == '\n') {
+ if (buf[0] == '#' || buf[0] == '\n' || buf [0] == '\r') {
+ fputs(buf, aesresp);
continue;
}
/* [Keylen = ...], [IVlen = ...], etc. */
if (buf[0] == '[') {
if (strncmp(&buf[1], "Keylen = ", 9) == 0) {
expected_keylen = atoi(&buf[10]);
} else if (strncmp(&buf[1], "IVlen = ", 8) == 0) {
expected_ivlen = atoi(&buf[9]);
@@ -218,38 +249,43 @@ aes_gcm_kat(const char *respfn)
expected_ptlen = atoi(&buf[9]);
} else if (strncmp(&buf[1], "AADlen = ", 9) == 0) {
expected_aadlen = atoi(&buf[10]);
} else if (strncmp(&buf[1], "Taglen = ", 9) == 0) {
expected_taglen = atoi(&buf[10]);
test_group++;
if (test_group > 1) {
+#if 0
/* Report num_tests for the previous test group. */
printf("%u tests\n", num_tests);
+#endif
}
num_tests = 0;
+#if 0
printf("Keylen = %u, IVlen = %u, PTlen = %u, AADlen = %u, "
"Taglen = %u: ", expected_keylen, expected_ivlen,
expected_ptlen, expected_aadlen, expected_taglen);
+#endif
/* Convert lengths in bits to lengths in bytes. */
PORT_Assert(expected_keylen % 8 == 0);
expected_keylen /= 8;
PORT_Assert(expected_ivlen % 8 == 0);
expected_ivlen /= 8;
PORT_Assert(expected_ptlen % 8 == 0);
expected_ptlen /= 8;
PORT_Assert(expected_aadlen % 8 == 0);
expected_aadlen /= 8;
PORT_Assert(expected_taglen % 8 == 0);
expected_taglen /= 8;
} else {
fprintf(stderr, "Unexpected input line: %s\n", buf);
exit(1);
}
+ fputs(buf, aesresp);
continue;
}
/* "Count = x" begins a new data set */
if (strncmp(buf, "Count", 5) == 0) {
/* zeroize the variables for the test with this data set */
memset(key, 0, sizeof key);
keysize = 0;
memset(iv, 0, sizeof iv);
@@ -258,16 +294,17 @@ aes_gcm_kat(const char *respfn)
plaintextlen = 0;
memset(aad, 0, sizeof aad);
aadlen = 0;
memset(ciphertext, 0, sizeof ciphertext);
ciphertextlen = 0;
memset(output, 0, sizeof output);
outputlen = 0;
num_tests++;
+ fputs(buf, aesresp);
continue;
}
/* Key = ... */
if (strncmp(buf, "Key", 3) == 0) {
i = 3;
while (isspace(buf[i]) || buf[i] == '=') {
i++;
}
@@ -275,16 +312,17 @@ aes_gcm_kat(const char *respfn)
hex_to_byteval(&buf[i], &key[j]);
}
keysize = j;
if (keysize != expected_keylen) {
fprintf(stderr, "Unexpected key length: %u vs. %u\n",
keysize, expected_keylen);
exit(1);
}
+ fputs(buf, aesresp);
continue;
}
/* IV = ... */
if (strncmp(buf, "IV", 2) == 0) {
i = 2;
while (isspace(buf[i]) || buf[i] == '=') {
i++;
}
@@ -292,16 +330,17 @@ aes_gcm_kat(const char *respfn)
hex_to_byteval(&buf[i], &iv[j]);
}
ivsize = j;
if (ivsize != expected_ivlen) {
fprintf(stderr, "Unexpected IV length: %u vs. %u\n",
ivsize, expected_ivlen);
exit(1);
}
+ fputs(buf, aesresp);
continue;
}
/* PT = ... */
if (strncmp(buf, "PT", 2) == 0) {
i = 2;
while (isspace(buf[i]) || buf[i] == '=') {
i++;
}
@@ -310,33 +349,17 @@ aes_gcm_kat(const char *respfn)
}
plaintextlen = j;
if (plaintextlen != expected_ptlen) {
fprintf(stderr, "Unexpected PT length: %u vs. %u\n",
plaintextlen, expected_ptlen);
exit(1);
}
- if (!is_encrypt) {
- rv = aes_decrypt_buf(key, keysize, iv, ivsize,
- output, &outputlen, sizeof output,
- ciphertext, ciphertextlen, aad, aadlen, tag, tagsize);
- if (rv != SECSuccess) {
- fprintf(stderr, "aes_decrypt_buf failed\n");
- goto loser;
- }
- if (outputlen != plaintextlen) {
- fprintf(stderr, "aes_decrypt_buf: wrong output size\n");
- goto loser;
- }
- if (memcmp(output, plaintext, plaintextlen) != 0) {
- fprintf(stderr, "aes_decrypt_buf: wrong plaintext\n");
- goto loser;
- }
- }
+ fputs(buf, aesresp);
continue;
}
/* FAIL */
if (strncmp(buf, "FAIL", 4) == 0) {
plaintextlen = 0;
PORT_Assert(!is_encrypt);
rv = aes_decrypt_buf(key, keysize, iv, ivsize,
@@ -363,16 +386,56 @@ aes_gcm_kat(const char *respfn)
hex_to_byteval(&buf[i], &aad[j]);
}
aadlen = j;
if (aadlen != expected_aadlen) {
fprintf(stderr, "Unexpected AAD length: %u vs. %u\n",
aadlen, expected_aadlen);
exit(1);
}
+
+ fputs(buf, aesresp);
+
+ if (is_encrypt) {
+ rv = aes_encrypt_buf(key, keysize, iv, ivsize,
+ output, &outputlen, sizeof output,
+ plaintext, plaintextlen, aad, aadlen, expected_taglen);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "aes_encrypt_buf failed\n");
+ goto loser;
+ }
+ if (outputlen != plaintextlen + expected_taglen) {
+ fprintf(stderr, "aes_encrypt_buf: wrong output size\n");
+ goto loser;
+ }
+#if 0
+ /* XXX Don't try to compare the ciphertext, as there is none
+ * to compare with. Just output the resulting CT. */
+ if (memcmp(output, ciphertext, plaintextlen) != 0) {
+ fprintf(stderr, "aes_encrypt_buf: wrong ciphertext\n");
+ goto loser;
+ }
+
+ if (memcmp(output + plaintextlen, tag, tagsize) != 0) {
+ fprintf(stderr, "aes_encrypt_buf: wrong tag\n");
+ goto loser;
+ }
+#endif
+
+ fputs ("CT = ", aesresp);
+ to_hex_str (buf, output, plaintextlen);
+ fputs (buf, aesresp);
+ fputc ('\n', aesresp);
+
+ fputs ("Tag = ", aesresp);
+ to_hex_str (buf, output + plaintextlen, expected_taglen);
+ fputs (buf, aesresp);
+ fputc ('\n', aesresp);
+ }
+
continue;
}
/* CT = ... */
if (strncmp(buf, "CT", 2) == 0) {
i = 2;
while (isspace(buf[i]) || buf[i] == '=') {
i++;
}
@@ -380,16 +443,18 @@ aes_gcm_kat(const char *respfn)
hex_to_byteval(&buf[i], &ciphertext[j]);
}
ciphertextlen = j;
if (ciphertextlen != expected_ptlen) {
fprintf(stderr, "Unexpected CT length: %u vs. %u\n",
ciphertextlen, expected_ptlen);
exit(1);
}
+
+ fputs(buf, aesresp);
continue;
}
/* Tag = ... */
if (strncmp(buf, "Tag", 3) == 0) {
i = 3;
while (isspace(buf[i]) || buf[i] == '=') {
i++;
}
@@ -398,46 +463,54 @@ aes_gcm_kat(const char *respfn)
}
tagsize = j;
if (tagsize != expected_taglen) {
fprintf(stderr, "Unexpected tag length: %u vs. %u\n",
tagsize, expected_taglen);
exit(1);
}
- if (is_encrypt) {
- rv = aes_encrypt_buf(key, keysize, iv, ivsize,
+ fputs(buf, aesresp);
+
+ if (!is_encrypt) {
+ rv = aes_decrypt_buf(key, keysize, iv, ivsize,
output, &outputlen, sizeof output,
- plaintext, plaintextlen, aad, aadlen, tagsize);
- if (rv != SECSuccess) {
- fprintf(stderr, "aes_encrypt_buf failed\n");
+ ciphertext, ciphertextlen, aad, aadlen, tag, tagsize);
+ if (rv != SECSuccess || outputlen < expected_ptlen) {
+ fputs ("FAIL\n", aesresp);
+ } else {
+ fputs ("PT = ", aesresp);
+ to_hex_str (buf, output, expected_ptlen);
+ fputs (buf, aesresp);
+ fputc ('\n', aesresp);
+ }
+
+#if 0
+ /* XXX Nothing to compare against */
+
+ if (memcmp(output, plaintext, plaintextlen) != 0) {
+ fprintf(stderr, "aes_decrypt_buf: wrong plaintext\n");
goto loser;
}
- if (outputlen != plaintextlen + tagsize) {
- fprintf(stderr, "aes_encrypt_buf: wrong output size\n");
- goto loser;
- }
- if (memcmp(output, ciphertext, plaintextlen) != 0) {
- fprintf(stderr, "aes_encrypt_buf: wrong ciphertext\n");
- goto loser;
- }
- if (memcmp(output + plaintextlen, tag, tagsize) != 0) {
- fprintf(stderr, "aes_encrypt_buf: wrong tag\n");
- goto loser;
- }
+#endif
}
+
continue;
}
}
+
+#if 0
/* Report num_tests for the last test group. */
printf("%u tests\n", num_tests);
printf("%u test groups\n", test_group);
printf("PASS\n");
+#endif
+
loser:
- fclose(aesresp);
+ fclose(aesreq);
}
int main(int argc, char **argv)
{
if (argc < 2) exit(1);
NSS_NoDB_Init(NULL);
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,17 +1223,21 @@ 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 b; /* 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 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;
@@ -1247,17 +1251,16 @@ pqg_ParamGen(unsigned int L, unsigned in
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);
@@ -1298,20 +1301,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: b = L -1 - (n*outlen); (same as n = (L-1) mod outlen) */
b = (L - 1) % outlen;
seedlen = seedBytes * PR_BITS_PER_BYTE; /* bits in seed */
step_5:
@@ -1375,16 +1385,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
@@ -1494,16 +1509,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);
@@ -1533,53 +1556,102 @@ 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)
+{
+ int rv;
+
+ /* 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,