nss/nss-3.112-partial-pub-key-validate.patch
Robert Relyea 29ff4c3b89 Resolves: RHEL-127691
- fips update
 -   Fix indicators for the new post-quantum algorithms
 -   Fix the ML-KEM Self-tests
 -   Fix the ML-KEM zeroizaiton
 -   Add partial public validation before OAEP
- bug fixes
 -   add CKA_SEED to private attributes so they are updated on password change.
 -   mark CKA_PARAMETER_SET as CK_ULONG when storing into the database
 -   fix unrefrence read in leancrypto.
2025-11-26 11:08:41 -08:00

1502 lines
61 KiB
Diff
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# HG changeset patch
# User Robert Relyea <rrelyea@redhat.com>
# Date 1763508464 28800
# Tue Nov 18 15:27:44 2025 -0800
# Branch RHEL10
# Node ID d7226ed21acc227df5dfb0a73b99a31640fddcba
# Parent 6949dbcd6631ec0db3f53b3cf8957fac3a80da25
nss-3.112-partial-pub-key-validate.patch
diff --git a/cmd/bltest/blapitest.c b/cmd/bltest/blapitest.c
--- a/cmd/bltest/blapitest.c
+++ b/cmd/bltest/blapitest.c
@@ -27,28 +27,30 @@
SECStatus EC_DecodeParams(const SECItem *encodedParams,
ECParams **ecparams);
SECStatus EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
const ECParams *srcParams);
char *progName;
char *testdir = NULL;
+PRBool strictOAEP = PR_FALSE;
#define BLTEST_DEFAULT_CHUNKSIZE 4096
#define WORDSIZE sizeof(unsigned long)
-#define CHECKERROR(rv, ln) \
- if (rv) { \
+#define CHECKERROR(rv, erv, ln) \
+ if (rv != erv) { \
PRErrorCode prerror = PR_GetError(); \
PR_fprintf(PR_STDERR, "%s: ERR %d (%s) at line %d.\n", progName, \
prerror, PORT_ErrorToString(prerror), ln); \
exit(-1); \
- }
+ } \
+ rv = SECSuccess
/* Macros for performance timing. */
#define TIMESTART() \
time1 = PR_IntervalNow();
#define TIMEFINISH(time, reps) \
time2 = (PRIntervalTime)(PR_IntervalNow() - time1); \
time1 = PR_IntervalToMilliseconds(time2); \
@@ -112,16 +114,19 @@ Usage()
PRINTUSAGE("", "-m", "cipher mode to use");
PRINTUSAGE("", "-i", "file which contains input buffer");
PRINTUSAGE("", "-o", "file for output buffer");
PRINTUSAGE("", "-k", "file which contains key");
PRINTUSAGE("", "-v", "file which contains initialization vector");
PRINTUSAGE("", "-p", "do performance test");
PRINTUSAGE("", "-4", "run test in multithread mode. th_num number of parallel threads");
PRINTUSAGE("", "-5", "run test for specified time interval(in seconds)");
+ PRINTUSAGE("", "-6", "hash algorithm for RSA PSS or OAEP");
+ PRINTUSAGE("", "-7", "mask hash algorithm for RSA PSS or OAEP");
+ PRINTUSAGE("", "-8", "validate the public key for RSAOAEP Encrypt");
PRINTUSAGE("", "--aad", "File with contains additional auth data");
fprintf(stderr, "\n");
PRINTUSAGE(progName, "-H -m mode", "Hash a buffer");
PRINTUSAGE("", "", "[-i plaintext] [-o hash]");
PRINTUSAGE("", "", "[-b bufsize]");
PRINTUSAGE("", "", "[-p repetitions | -5 time_interval] [-4 th_num]");
PRINTUSAGE("", "-m", "cipher mode to use");
PRINTUSAGE("", "-i", "file which contains input buffer");
@@ -370,23 +375,23 @@ eckey_from_filedata(PLArenaPool *arena,
ECPrivateKey *key;
SECStatus rv;
ECParams *tmpECParams = NULL;
key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey));
/* read and convert params */
key->ecParams.arena = arena;
key_from_filedata(arena, &key->ecParams.DEREncoding, 0, 1, filedata);
rv = SECOID_Init();
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, SECSuccess, __LINE__);
rv = EC_DecodeParams(&key->ecParams.DEREncoding, &tmpECParams);
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, SECSuccess, __LINE__);
rv = EC_CopyParams(key->ecParams.arena, &key->ecParams, tmpECParams);
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, SECSuccess, __LINE__);
rv = SECOID_Shutdown();
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, SECSuccess, __LINE__);
PORT_FreeArena(tmpECParams->arena, PR_TRUE);
/* read key */
key_from_filedata(arena, &key->publicValue, 1, 3, filedata);
return key;
}
typedef struct curveNameTagPairStr {
char *curveName;
@@ -799,16 +804,17 @@ struct bltestCipherInfoStr {
} cipher;
/* performance testing */
int repetitionsToPerfom;
int seconds;
int repetitions;
int cxreps;
double cxtime;
double optime;
+ SECStatus expect;
};
PRBool
is_symmkeyCipher(bltestCipherMode mode)
{
/* change as needed! */
if (mode >= bltestDES_ECB && mode <= bltestCHACHA20_CTR)
return PR_TRUE;
@@ -836,16 +842,29 @@ is_authCipher(bltestCipherMode mode)
case bltestCHACHA20:
return PR_TRUE;
default:
return PR_FALSE;
}
}
PRBool
+is_rsaV2(bltestCipherMode mode)
+{
+ /* change as needed! */
+ switch (mode) {
+ case bltestRSA_OAEP:
+ case bltestRSA_PSS:
+ return PR_TRUE;
+ default:
+ return PR_FALSE;
+ }
+}
+
+PRBool
is_singleShotCipher(bltestCipherMode mode)
{
/* change as needed! */
switch (mode) {
case bltestAES_GCM:
case bltestAES_CTS:
case bltestCHACHA20_CTR:
case bltestCHACHA20:
@@ -1748,16 +1767,18 @@ bltest_rsa_init(bltestCipherInfo *cipher
/* Have to convert private key to public key. Memory
* is freed with private key's arena */
pubKey = (RSAPublicKey *)PORT_ArenaAlloc(privKey->arena,
sizeof(RSAPublicKey));
pubKey->modulus.len = privKey->modulus.len;
pubKey->modulus.data = privKey->modulus.data;
pubKey->publicExponent.len = privKey->publicExponent.len;
pubKey->publicExponent.data = privKey->publicExponent.data;
+ /* if structOAEP is set, exercise the oaep verify tests */
+ pubKey->needVerify = strictOAEP;
asymk->pubKey = (void *)pubKey;
}
switch (cipherInfo->mode) {
case bltestRSA:
cipherInfo->cipher.pubkeyCipher = encrypt ? rsa_PublicKeyOp
: rsa_PrivateKeyOp;
break;
case bltestRSA_PSS:
@@ -1785,20 +1806,20 @@ blapi_pqg_param_gen(unsigned int keysize
}
SECStatus
bltest_pqg_init(bltestDSAParams *dsap)
{
SECStatus rv, res;
PQGVerify *vfy = NULL;
rv = blapi_pqg_param_gen(dsap->keysize, &dsap->pqg, &vfy);
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, SECSuccess, __LINE__);
rv = PQG_VerifyParams(dsap->pqg, vfy, &res);
- CHECKERROR(res, __LINE__);
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(res, SECSuccess, __LINE__);
+ CHECKERROR(rv, SECSuccess, __LINE__);
return rv;
}
SECStatus
bltest_dsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
{
int i;
DSAPrivateKey **dummyKey;
@@ -2247,48 +2268,48 @@ pubkeyInitKey(bltestCipherInfo *cipherIn
case bltestDSA:
dsap = &asymk->cipherParams.dsa;
dsaKey = (DSAPrivateKey **)&asymk->privKey;
if (keysize > 0) {
dsap->keysize = keysize * 8;
if (!dsap->pqg)
bltest_pqg_init(dsap);
rv = DSA_NewKey(dsap->pqg, dsaKey);
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, cipherInfo->expect, __LINE__);
serialize_key(&(*dsaKey)->params.prime, 5, file);
} else {
setupIO(cipherInfo->arena, &asymk->key, file, NULL, 0);
*dsaKey = dsakey_from_filedata(cipherInfo->arena, &asymk->key.buf);
dsap->keysize = (*dsaKey)->params.prime.len * 8;
}
break;
case bltestECDSA:
ecKey = (ECPrivateKey **)&asymk->privKey;
if (curveName != NULL) {
tmpECParamsDER = getECParams(curveName);
rv = SECOID_Init();
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, SECSuccess, __LINE__);
rv = EC_DecodeParams(tmpECParamsDER, &tmpECParams) == SECFailure;
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, SECSuccess, __LINE__);
rv = EC_NewKey(tmpECParams, ecKey);
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, cipherInfo->expect, __LINE__);
ecSerialize[0].type = tmpECParamsDER->type;
ecSerialize[0].data = tmpECParamsDER->data;
ecSerialize[0].len = tmpECParamsDER->len;
ecSerialize[1].type = (*ecKey)->publicValue.type;
ecSerialize[1].data = (*ecKey)->publicValue.data;
ecSerialize[1].len = (*ecKey)->publicValue.len;
ecSerialize[2].type = (*ecKey)->privateValue.type;
ecSerialize[2].data = (*ecKey)->privateValue.data;
ecSerialize[2].len = (*ecKey)->privateValue.len;
serialize_key(&(ecSerialize[0]), 3, file);
SECITEM_FreeItem(tmpECParamsDER, PR_TRUE);
PORT_FreeArena(tmpECParams->arena, PR_TRUE);
rv = SECOID_Shutdown();
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, SECSuccess, __LINE__);
} else {
setupIO(cipherInfo->arena, &asymk->key, file, NULL, 0);
*ecKey = eckey_from_filedata(cipherInfo->arena, &asymk->key.buf);
}
break;
default:
return SECFailure;
}
@@ -2494,42 +2515,42 @@ cipherDoOp(bltestCipherInfo *cipherInfo)
: PR_MIN(cipherInfo->input.pBuf.len, 16);
unsigned char *output = cipherInfo->output.pBuf.data;
unsigned int outputLen = maxLen;
unsigned int totalOutputLen = 0;
TIMESTART();
rv = (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx,
output, &len, outputLen,
input, inputLen);
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, cipherInfo->expect, __LINE__);
totalOutputLen += len;
if (cipherInfo->input.pBuf.len > inputLen) {
input += inputLen;
inputLen = cipherInfo->input.pBuf.len - inputLen;
output += len;
outputLen -= len;
rv = (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx,
output, &len, outputLen,
input, inputLen);
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, cipherInfo->expect, __LINE__);
totalOutputLen += len;
}
cipherInfo->output.pBuf.len = totalOutputLen;
TIMEFINISH(cipherInfo->optime, 1.0);
cipherInfo->repetitions = 0;
if (cipherInfo->repetitionsToPerfom != 0) {
TIMESTART();
for (i = 0; i < cipherInfo->repetitionsToPerfom; i++,
cipherInfo->repetitions++) {
(*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx, dummyOut,
&len, maxLen,
cipherInfo->input.pBuf.data,
cipherInfo->input.pBuf.len);
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, cipherInfo->expect, __LINE__);
}
} else {
int opsBetweenChecks = 0;
TIMEMARK(cipherInfo->seconds);
while (!(TIMETOFINISH())) {
int j = 0;
for (; j < opsBetweenChecks; j++) {
(*cipherInfo->cipher.symmkeyCipher)(
@@ -2551,32 +2572,32 @@ cipherDoOp(bltestCipherInfo *cipherInfo)
TIMESTART();
rv = (*cipherInfo->cipher.aeadCipher)(
cipherInfo->cx,
output, &outputLen, maxLen,
input, inputLen,
sk->iv.buf.data, sk->iv.buf.len,
ask->aad.buf.data, ask->aad.buf.len);
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, cipherInfo->expect, __LINE__);
cipherInfo->output.pBuf.len = outputLen;
TIMEFINISH(cipherInfo->optime, 1.0);
cipherInfo->repetitions = 0;
if (cipherInfo->repetitionsToPerfom != 0) {
TIMESTART();
for (i = 0; i < cipherInfo->repetitionsToPerfom; i++,
cipherInfo->repetitions++) {
rv = (*cipherInfo->cipher.aeadCipher)(
cipherInfo->cx,
output, &outputLen, maxLen,
input, inputLen,
sk->iv.buf.data, sk->iv.buf.len,
ask->aad.buf.data, ask->aad.buf.len);
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, cipherInfo->expect, __LINE__);
}
} else {
int opsBetweenChecks = 0;
TIMEMARK(cipherInfo->seconds);
while (!(TIMETOFINISH())) {
int j = 0;
for (; j < opsBetweenChecks; j++) {
(*cipherInfo->cipher.aeadCipher)(
@@ -2591,74 +2612,74 @@ cipherDoOp(bltestCipherInfo *cipherInfo)
}
TIMEFINISH(cipherInfo->optime, 1.0);
} else if (is_pubkeyCipher(cipherInfo->mode)) {
TIMESTART();
rv = (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx,
&cipherInfo->output.pBuf,
&cipherInfo->input.pBuf);
TIMEFINISH(cipherInfo->optime, 1.0);
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, cipherInfo->expect, __LINE__);
cipherInfo->repetitions = 0;
if (cipherInfo->repetitionsToPerfom != 0) {
TIMESTART();
for (i = 0; i < cipherInfo->repetitionsToPerfom;
i++, cipherInfo->repetitions++) {
SECItem dummy;
dummy.data = dummyOut;
dummy.len = maxLen;
- (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx, &dummy,
- &cipherInfo->input.pBuf);
- CHECKERROR(rv, __LINE__);
+ rv = (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx, &dummy,
+ &cipherInfo->input.pBuf);
+ CHECKERROR(rv, cipherInfo->expect, __LINE__);
}
} else {
int opsBetweenChecks = 0;
TIMEMARK(cipherInfo->seconds);
while (!(TIMETOFINISH())) {
int j = 0;
for (; j < opsBetweenChecks; j++) {
SECItem dummy;
dummy.data = dummyOut;
dummy.len = maxLen;
- (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx, &dummy,
- &cipherInfo->input.pBuf);
- CHECKERROR(rv, __LINE__);
+ rv = (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx, &dummy,
+ &cipherInfo->input.pBuf);
+ CHECKERROR(rv, cipherInfo->expect, __LINE__);
}
cipherInfo->repetitions += j;
}
}
TIMEFINISH(cipherInfo->optime, 1.0);
} else if (is_hashCipher(cipherInfo->mode)) {
TIMESTART();
rv = (*cipherInfo->cipher.hashCipher)(cipherInfo->output.pBuf.data,
cipherInfo->input.pBuf.data,
cipherInfo->input.pBuf.len);
TIMEFINISH(cipherInfo->optime, 1.0);
- CHECKERROR(rv, __LINE__);
+ CHECKERROR(rv, cipherInfo->expect, __LINE__);
cipherInfo->repetitions = 0;
if (cipherInfo->repetitionsToPerfom != 0) {
TIMESTART();
for (i = 0; i < cipherInfo->repetitionsToPerfom;
i++, cipherInfo->repetitions++) {
- (*cipherInfo->cipher.hashCipher)(dummyOut,
- cipherInfo->input.pBuf.data,
- cipherInfo->input.pBuf.len);
- CHECKERROR(rv, __LINE__);
+ rv = (*cipherInfo->cipher.hashCipher)(dummyOut,
+ cipherInfo->input.pBuf.data,
+ cipherInfo->input.pBuf.len);
+ CHECKERROR(rv, cipherInfo->expect, __LINE__);
}
} else {
int opsBetweenChecks = 0;
TIMEMARK(cipherInfo->seconds);
while (!(TIMETOFINISH())) {
int j = 0;
for (; j < opsBetweenChecks; j++) {
bltestIO *input = &cipherInfo->input;
- (*cipherInfo->cipher.hashCipher)(dummyOut,
- input->pBuf.data,
- input->pBuf.len);
- CHECKERROR(rv, __LINE__);
+ rv = (*cipherInfo->cipher.hashCipher)(dummyOut,
+ input->pBuf.data,
+ input->pBuf.len);
+ CHECKERROR(rv, cipherInfo->expect, __LINE__);
}
cipherInfo->repetitions += j;
}
}
TIMEFINISH(cipherInfo->optime, 1.0);
}
PORT_Free(dummyOut);
return rv;
@@ -2996,29 +3017,20 @@ load_file_data(PLArenaPool *arena, bltes
file = PR_Open(fn, PR_RDONLY, 00660);
if (file) {
setupIO(arena, data, file, NULL, 0);
PR_Close(file);
}
}
HASH_HashType
-mode_str_to_hash_alg(const SECItem *modeStr)
+mode_string_to_hash_alg(const char *modeString)
{
bltestCipherMode mode;
- char *tempModeStr = NULL;
- if (!modeStr || modeStr->len == 0)
- return HASH_AlgNULL;
- tempModeStr = PORT_Alloc(modeStr->len + 1);
- if (!tempModeStr)
- return HASH_AlgNULL;
- memcpy(tempModeStr, modeStr->data, modeStr->len);
- tempModeStr[modeStr->len] = '\0';
- mode = get_mode(tempModeStr);
- PORT_Free(tempModeStr);
+ mode = get_mode(modeString);
switch (mode) {
case bltestMD2:
return HASH_AlgMD2;
case bltestMD5:
return HASH_AlgMD5;
case bltestSHA1:
return HASH_AlgSHA1;
case bltestSHA224:
@@ -3029,16 +3041,33 @@ mode_str_to_hash_alg(const SECItem *mode
return HASH_AlgSHA384;
case bltestSHA512:
return HASH_AlgSHA512;
default:
return HASH_AlgNULL;
}
}
+HASH_HashType
+mode_str_to_hash_alg(const SECItem *modeStr)
+{
+ HASH_HashType hashType;
+ char *tempModeStr = NULL;
+ if (!modeStr || modeStr->len == 0)
+ return HASH_AlgNULL;
+ tempModeStr = PORT_Alloc(modeStr->len + 1);
+ if (!tempModeStr)
+ return HASH_AlgNULL;
+ memcpy(tempModeStr, modeStr->data, modeStr->len);
+ tempModeStr[modeStr->len] = '\0';
+ hashType = mode_string_to_hash_alg(tempModeStr);
+ PORT_Free(tempModeStr);
+ return hashType;
+}
+
void
get_params(PLArenaPool *arena, bltestParams *params,
bltestCipherMode mode, int j)
{
char filename[256];
char *modestr = mode_strings[mode];
bltestIO tempIO;
@@ -3259,16 +3288,17 @@ blapi_selftest(bltestCipherMode *modes,
char filename[256];
PLArenaPool *arena;
SECItem item;
SECStatus rv = SECSuccess, srv;
PORT_Memset(&cipherInfo, 0, sizeof(cipherInfo));
arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
cipherInfo.arena = arena;
+ cipherInfo.expect = SECSuccess;
nummodes = (numModes == 0) ? NUMMODES : numModes;
for (i = 0; i < nummodes; i++) {
if (numModes > 0)
mode = modes[i];
else
mode = i;
if (mode == bltestINVALID) {
@@ -3299,31 +3329,41 @@ blapi_selftest(bltestCipherMode *modes,
"plaintext", j);
load_file_data(arena, &pt, filename,
is_sigCipher(mode) ? bltestBase64Encoded
: bltestBinary);
snprintf(filename, sizeof(filename), "%s/tests/%s/%s%d", testdir, modestr,
"ciphertext", j);
load_file_data(arena, &ct, filename, bltestBase64Encoded);
+ snprintf(filename, sizeof(filename), "%s/tests/%s/%s%s%s%d", testdir, modestr,
+ "result", encrypt? "-encrypt" : "-decrypt", strictOAEP ? "-strict":"", j);
+
+ cipherInfo.expect = SECSuccess;
+ if (PR_Access(filename, PR_ACCESS_EXISTS) == PR_SUCCESS) {
+ cipherInfo.expect = SECFailure;
+ }
+
get_params(arena, params, mode, j);
/* Forward Operation (Encrypt/Sign/Hash)
** Align the input buffer (plaintext) according to request
** then perform operation and compare to ciphertext
*/
if (encrypt) {
rv |= bltestCopyIO(arena, &cipherInfo.input, &pt);
misalignBuffer(arena, &cipherInfo.input, inoff);
memset(&cipherInfo.output.buf, 0, sizeof cipherInfo.output.buf);
rv |= cipherInit(&cipherInfo, PR_TRUE);
misalignBuffer(arena, &cipherInfo.output, outoff);
rv |= cipherDoOp(&cipherInfo);
rv |= cipherFinish(&cipherInfo);
- rv |= verify_self_test(&cipherInfo.output,
- &ct, mode, PR_TRUE, SECSuccess);
+ if (cipherInfo.expect == SECSuccess) {
+ rv |= verify_self_test(&cipherInfo.output,
+ &ct, mode, PR_TRUE, SECSuccess);
+ }
/* If testing hash, only one op to test */
if (is_hashCipher(mode))
continue;
if (is_sigCipher(mode)) {
/* Verify operations support detached signature files. For
** consistency between tests that run Sign/Verify back to
** back (eg: self-tests) and tests that are only running
** verify operations, copy the output into the sig buf,
@@ -3332,16 +3372,22 @@ blapi_selftest(bltestCipherMode *modes,
** verify-only operations, this ensures that the output
** buffer is properly configured
*/
rv |= bltestCopyIO(arena, &params->asymk.sig, &cipherInfo.output);
}
}
if (!decrypt)
continue;
+
+ /* If we expect the encrypt to fail, then don't do the decrypt */
+ if (cipherInfo.expect == SECFailure) {
+ continue;
+ }
+
/* Reverse Operation (Decrypt/Verify)
** Align the input buffer (ciphertext) according to request
** then perform operation and compare to plaintext
*/
if (is_sigCipher(mode)) {
rv |= bltestCopyIO(arena, &cipherInfo.input, &pt);
rv |= bltestCopyIO(arena, &cipherInfo.output, &params->asymk.sig);
} else {
@@ -3692,16 +3738,19 @@ enum {
opt_UseSigSeed,
opt_SeedFile,
opt_AAD,
opt_InputOffset,
opt_OutputOffset,
opt_MonteCarlo,
opt_ThreadNum,
opt_SecondsToRun,
+ opt_RSAHash,
+ opt_MaskHash,
+ opt_OAEPStrict,
opt_CmdLine
};
static secuCommandFlag bltest_commands[] = {
{ /* cmd_Decrypt */ 'D', PR_FALSE, 0, PR_FALSE },
{ /* cmd_Encrypt */ 'E', PR_FALSE, 0, PR_FALSE },
{ /* cmd_FIPS */ 'F', PR_FALSE, 0, PR_FALSE },
{ /* cmd_Hash */ 'H', PR_FALSE, 0, PR_FALSE },
@@ -3742,19 +3791,29 @@ static secuCommandFlag bltest_options[]
{ /* opt_UseSigSeed */ 'y', PR_FALSE, 0, PR_FALSE },
{ /* opt_SeedFile */ 'z', PR_FALSE, 0, PR_FALSE },
{ /* opt_AAD */ 0, PR_TRUE, 0, PR_FALSE, "aad" },
{ /* opt_InputOffset */ '1', PR_TRUE, 0, PR_FALSE },
{ /* opt_OutputOffset */ '2', PR_TRUE, 0, PR_FALSE },
{ /* opt_MonteCarlo */ '3', PR_FALSE, 0, PR_FALSE },
{ /* opt_ThreadNum */ '4', PR_TRUE, 0, PR_FALSE },
{ /* opt_SecondsToRun */ '5', PR_TRUE, 0, PR_FALSE },
+ { /* opt_RSAHash */ '6', PR_TRUE, 0, PR_FALSE },
+ { /* opt_MaskHash */ '7', PR_TRUE, 0, PR_FALSE },
+ { /* opt_OAEPStrict */ '8', PR_FALSE, 0, PR_FALSE },
{ /* opt_CmdLine */ '-', PR_FALSE, 0, PR_FALSE }
};
+unsigned int
+HashLen(HASH_HashType type)
+{
+ const SECHashObject *hashObj = HASH_GetRawHashObject(type);
+ return hashObj->length;
+}
+
int
main(int argc, char **argv)
{
SECStatus rv = SECFailure;
double totalTime = 0.0;
PRIntervalTime time1, time2;
PRFileDesc *outfile = NULL;
@@ -3832,16 +3891,17 @@ main(int argc, char **argv)
if (bltest.options[opt_InputOffset].activated)
inoff = PORT_Atoi(bltest.options[opt_InputOffset].arg);
if (bltest.options[opt_OutputOffset].activated)
outoff = PORT_Atoi(bltest.options[opt_OutputOffset].arg);
testdir = (bltest.options[opt_SelfTestDir].activated) ? strdup(bltest.options[opt_SelfTestDir].arg)
: ".";
+ strictOAEP= bltest.options[opt_OAEPStrict].activated;
/*
* Handle three simple cases first
*/
/* test the RSA_PopulatePrivateKey function with known vectors */
if (bltest.commands[cmd_RSAPopulateKV].activated) {
PORT_Free(cipherInfo);
return doRSAPopulateTestKV();
@@ -4145,16 +4205,84 @@ main(int argc, char **argv)
}
memset(&askp->aad, 0, sizeof askp->aad);
askp->aad.mode = ioMode;
setupIO(cipherInfo->arena, &askp->aad, file, aadstr, 0);
if (file) {
PR_Close(file);
}
}
+ /* set up rsaoaep and pss values */
+ if (is_rsaV2(cipherInfo->mode)) {
+ char *seedstr = NULL;
+ bltestRSAParams *rsakp;
+ bltestIO tempIO;
+ rsakp = &params->asymk.cipherParams.rsa;
+
+ /* hash */
+ if (bltest.options[opt_RSAHash].activated) {
+ if (bltest.options[opt_CmdLine].activated) {
+ rsakp->hashAlg = mode_string_to_hash_alg(
+ bltest.options[opt_RSAHash].arg);
+ } else {
+ load_file_data(arena, &tempIO,
+ bltest.options[opt_RSAHash].arg,
+ bltestBinary);
+ rsakp->hashAlg = mode_str_to_hash_alg(&tempIO.buf);
+ }
+ } else {
+ /* save the random iv for reference */
+ file = PR_Open("tmp.hash", PR_WRONLY | PR_CREATE_FILE, 00660);
+ PR_Write(file, "sha256\n", sizeof("sha256\n")-1);
+ rsakp->hashAlg = HASH_AlgSHA256;
+ PR_Close(file);
+
+ }
+ /* mask */
+ if (bltest.options[opt_RSAHash].activated) {
+ if (bltest.options[opt_CmdLine].activated) {
+ rsakp->maskHashAlg = mode_string_to_hash_alg(
+ bltest.options[opt_MaskHash].arg);
+ } else {
+ load_file_data(arena, &tempIO,
+ bltest.options[opt_MaskHash].arg,
+ bltestBinary);
+ rsakp->maskHashAlg = mode_str_to_hash_alg(&tempIO.buf);
+ }
+ } else {
+ /* save the random iv for reference */
+ file = PR_Open("tmp.maskhash", PR_WRONLY | PR_CREATE_FILE,
+ 00660);
+ PR_Write(file, "sha256\n", sizeof("sha256\n")-1);
+ rsakp->maskHashAlg = HASH_AlgSHA256;
+ PR_Close(file);
+
+ }
+ /* seed salt */
+ file = NULL;
+ if (bltest.options[opt_Seed].activated) {
+ if (bltest.options[opt_CmdLine].activated) {
+ seedstr = bltest.options[opt_Seed].arg;
+ } else {
+ file = PR_Open(bltest.options[opt_Seed].arg,
+ PR_RDONLY, 00660);
+ }
+ } else {
+ /* save the random seed for reference */
+ file = PR_Open("tmp.seed", PR_WRONLY | PR_CREATE_FILE, 00660);
+ }
+ memset(&rsakp->seed, 0, sizeof rsakp->seed);
+ rsakp->seed.mode = ioMode;
+ setupIO(cipherInfo->arena, &rsakp->seed, file, seedstr,
+ HashLen(rsakp->hashAlg));
+ if (file) {
+ PR_Close(file);
+ }
+ file = NULL;
+ }
if (bltest.commands[cmd_Verify].activated) {
file = PR_Open(bltest.options[opt_SigFile].arg, PR_RDONLY, 00660);
if (is_sigCipher(cipherInfo->mode)) {
memset(&params->asymk.sig, 0, sizeof(bltestIO));
params->asymk.sig.mode = ioMode;
setupIO(cipherInfo->arena, &params->asymk.sig, file, NULL, 0);
}
diff --git a/cmd/bltest/tests/rsa_oaep/ciphertext18 b/cmd/bltest/tests/rsa_oaep/ciphertext18
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/ciphertext18
@@ -0,0 +1,6 @@
+m8ZlOZEwDf3oapXT/tuBWS5Boa9rS08M/pFz1N2Y1GU0sYC4zcv79zxmjk2RjYLe
+VjCAM8gAGoVdpV7P53NvAwEZcEpXd/ewhCz1sopc19o96pEYqC01Ik9TW0H/41Rh
+O/KvWvVEoJ8s0TS6z+ViCK5iBjdxLhF7SKxwJXfcwZvOua3lr9yjgkljVzIYf7XA
+1ZkkuxB0PDPw6ud022rn/xKhjhL9GJObY9rNYZwyS6hSpUEM+ZV106X+7nISVgOr
+vP93jbTwg0ndqn3XJKOduJVZVTR/dEebqSuBnWW4TIGE3Tq84Xf+ySGpMtD3vRbG
+C5P6A7EyqXJOOwUvvZzAcw==
diff --git a/cmd/bltest/tests/rsa_oaep/ciphertext19 b/cmd/bltest/tests/rsa_oaep/ciphertext19
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/ciphertext19
@@ -0,0 +1,6 @@
+eNIFlfXIih5XqUTcmFUeW3WQdlrO8yeLkGBgYZcHkFCNXeEze26osWLzIpuRc+vY
+kdHVVxDWhcp4Q/3AWL8Ib67BYfZk/AQn+IJCDsd2tdVxg3/ifCtYYm+09KY8oNy/
+uWudjMEiS1FR7l+wb2QNHcQH6UjJqt5+z19nCcwyBfHH6E3u+U+Pq6uDdhSODu3e
+s0UxYjiDl0UUW5m7uJVq7MCrqAHgTkH3h+wWOMJaORZ7tk9tfCnvUt9AiAToyv0Y
+G9Ylbkll5bM+UO7R6JsXqm25cM6pshP5jy+aXbw+KqXLjxbgrDdZQZ1MXup7QT/z
+znUkc0USufg5BmymMoPP/A==
diff --git a/cmd/bltest/tests/rsa_oaep/ciphertext20 b/cmd/bltest/tests/rsa_oaep/ciphertext20
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/ciphertext20
@@ -0,0 +1,6 @@
+Ll4/kyqhXiKtf+rgK8vNrVpfqV+YOiARW1vCX5Mo28OEbUQHNeetPdpbQ8gnlkFa
+xWdVrUmeVSY4A3Nkv8f3ZvC2m08A1OCvSxhgTKUJvO8eW5DErFdj0irT4FKt4nsO
+G86+cOiEr5OuWNfZv+UI36TJaadgGXHNAD/keCl/tq65tiiw6EwWYSm3kypA5MN+
+2e5eBtdwZfFM+kouQZf75AUitcYYGCbnZLWIyZc8OfTyEgtcR8ERTz+BrT0Ub8va
+ML0MEc3+nIMApdXU9SWbyr/WA8Sz/wh5kyA+Yr6Xww0j36chjRgSh3Dn3ykZkYZX
+gwWtxqWTY6mWaatQXCfnHA==
diff --git a/cmd/bltest/tests/rsa_oaep/ciphertext21 b/cmd/bltest/tests/rsa_oaep/ciphertext21
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/ciphertext21
@@ -0,0 +1,6 @@
+gsKckbXuYtoxoGMVpkVsd1Nb2BMTqMuThlUXbzQB1qzJ1/PTbdpRWFtcDKsW202f
+tO4NPt7sCIHdiqdqwXVQxcTabrbwaUZICtwphbLUQDKMU/pwhicKHSH8hD0/FbwU
+4iYUgYKxkjsQUlW4Eq4Yh+2Vfk2+ae6PFAvdQE0EHEWsNUkbbbv5tNweLH0JmQGp
+W4k2MKm2LUu4+v+n8aQ4FwkuQKS2ZqddTjR+QRjM+hzsSVNPpvvCu4kK4xU3G0ru
+JWLCtmdmVGXpLlwiLUn0FomRUa1fqQOhp3W4/WvJf1kdcj2pPLzgHPKgivb+03o+
+4pHctkSM4dgC9vhMOLc8Tg==
diff --git a/cmd/bltest/tests/rsa_oaep/ciphertext22 b/cmd/bltest/tests/rsa_oaep/ciphertext22
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/ciphertext22
@@ -0,0 +1,6 @@
+agf+F8PWGOKXgZYUpqPZ2NT17bkElsyzUNXbmcuZKd1YHSo6TZZj+Jdd48QhlDHK
+fUIch1+QIgRnTWZ9Jpw6d7Agk1jz0yjg2ywrEmdT1aRwBonVn1r1rK3q2giCZLEd
+YhQ2fz/Iz89b084w7yjLDI2mbOi0Pbizn6IB6whkJYIKPjMLgekvwQ6EM4VvrsM6
+gHT9BGmICIpO+ipHYYwNhZiePpnZSck5p7lxmHLa/WWFeGrFJzNzab+8ToRw12hR
+oL4DBLfob5wvychGSkjGeWWRbFhbujalHOI8fOg92bUxSeaks3XDhRhv8eZmX1c6
+hpKbNFNI99e20O5riigz7Q==
diff --git a/cmd/bltest/tests/rsa_oaep/hash18 b/cmd/bltest/tests/rsa_oaep/hash18
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/hash18
@@ -0,0 +1,1 @@
+sha256
diff --git a/cmd/bltest/tests/rsa_oaep/hash19 b/cmd/bltest/tests/rsa_oaep/hash19
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/hash19
@@ -0,0 +1,1 @@
+sha256
diff --git a/cmd/bltest/tests/rsa_oaep/hash20 b/cmd/bltest/tests/rsa_oaep/hash20
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/hash20
@@ -0,0 +1,1 @@
+sha256
diff --git a/cmd/bltest/tests/rsa_oaep/hash21 b/cmd/bltest/tests/rsa_oaep/hash21
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/hash21
@@ -0,0 +1,1 @@
+sha256
diff --git a/cmd/bltest/tests/rsa_oaep/hash22 b/cmd/bltest/tests/rsa_oaep/hash22
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/hash22
@@ -0,0 +1,1 @@
+sha256
diff --git a/cmd/bltest/tests/rsa_oaep/key18 b/cmd/bltest/tests/rsa_oaep/key18
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/key18
@@ -0,0 +1,1 @@
+AAAAAQAAAAEA5UUoEM5A1qttdY2GGJiJ5ypWHjr6o+CISs8S+zs2npypQiFLjSaf37nacs1Vz7J5mSHwJhTRXm2uzUYPckEuN1TA/88v4zl3O20RY2IBvI+T9Gqb/ir8KmH+/xQivsBaN2qIu0u/ZNzHyDpQlB3rJu4iqJhTQC/CdKN19o3Ex9QRdSC4xAITKnMooImWbLlBcqx0M6G0DMraD9DRaKntHhYabmtI8ly3wbldjHXlLc4YFEm+/Mk5kzNZAUCQ/gZrU/C6ue45cHhiqJpJ2Wx4X+3EQveTh9+emJMtOz4sogvy67ow+0/0f3svgbiycwe4HL5gu4yOCsH6l6asfqIYdwAAAAMBAAEAAAEAdDQ+H256vJN80kUd/19pHgp+Rao9GUyXp9sW0tFrWK8stsDrayp1g87OYruiT7g1G6Fw98w7ZjIPlCl7cLyKsS66961Kp0+cGDmqw4WMPcdEBXD3iba9wrmSpjTNe4NA9q9/h/bXlka0185+wuP7KOswE+XI5FKQq8+h3Ypzf5kEFCq2m1o13qEpqVyzKn4nJvkzmGvQN1+lcLi1OuhNr58iXG7yNS07Uewi9ytWMoYv/DB4peVT0kEHTrQsCSS1x4DPE6gj4taRosU4wwPQa0a23/5d/1MfLlQCa/GSa7vEryfa5bXbxbVpGcXEZLs33RG9M7IE2H0DB1RKP5Dm9wAAAQDlRSgQzkDWq211jYYYmInnKlYeOvqj4IhKzxL7OzaenKlCIUuNJp/fudpyzVXPsnmZIfAmFNFeba7NRg9yQS43VMD/zy/jOXc7bRFjYgG8j5P0apv+KvwqYf7/FCK+wFo3aoi7S79k3MfIOlCUHesm7iKomFNAL8J0o3X2jcTH1BF1ILjEAhMqcyigiZZsuUFyrHQzobQMytoP0NFoqe0eFhpua0jyXLfBuV2MdeUtzhgUSb78yTmTM1kBQJD+BmtT8Lq57jlweGKomknZbHhf7cRC95OH356Yky07PiyiC/LrujD7T/R/ey+BuLJzB7gcvmC7jI4KwfqXpqx+ohh3AAAAAQEAAAEAdDQ+H256vJN80kUd/19pHgp+Rao9GUyXp9sW0tFrWK8stsDrayp1g87OYruiT7g1G6Fw98w7ZjIPlCl7cLyKsS66961Kp0+cGDmqw4WMPcdEBXD3iba9wrmSpjTNe4NA9q9/h/bXlka0185+wuP7KOswE+XI5FKQq8+h3Ypzf5kEFCq2m1o13qEpqVyzKn4nJvkzmGvQN1+lcLi1OuhNr58iXG7yNS07Uewi9ytWMoYv/DB4peVT0kEHTrQsCSS1x4DPE6gj4taRosU4wwPQa0a23/5d/1MfLlQCa/GSa7vEryfa5bXbxbVpGcXEZLs33RG9M7IE2H0DB1RKP5Dm9wAAAAEBAAAAAQE=
\ No newline at end of file
diff --git a/cmd/bltest/tests/rsa_oaep/key19 b/cmd/bltest/tests/rsa_oaep/key19
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/key19
@@ -0,0 +1,1 @@
+AAAAAQAAAAEAiEv3eeAtf4akF4xEo9sRDLbrulalIBrTmzTYl7Twlk18eUU2CvamKx03Ls8YRdJsJ+73F+03e5gXQuqaq3IArYzy3P09rghqgPW52/Sux49ajDLfWsOUbWa4bQSAHxLHi45ZipyPnWgqHqzE7tq5OL4XpN0JVEg/wvm4c8FBIt91Qq5xQFdFkr5WpsnCyLTvvpDtaFCzIAoN2LY2ijH13V3dMuN1dKhCj2L9INEHgxRIqq5iKmBrRqZMhXdvZAh83lOc8aBgAkZ7Puvjz2fSSHlVNb9xfl+JUxOoHy6uUw66ZA5P1yacOlqwra/9gbe1GjuU0GJJQS8sVtt0MgHcjQAAAAMBAAEAAAEAYYSKMAbXKeVK5YXVTz3hYM+w7zbmkWqCN+Gnn8wjUHDx5HUlJtxXV2sDRxxtv42rbRAm+67DhWugnOF/oVM2I/jMz1xCUTFp0VZwIMnSeIgl4AjgM3Fad6E9M+rWfaQnAAKekyT8okGLHGjRqJWC5xYenjSNq4LLCDOToz00RbYQu0GaHXawG26AJbarYRaZLeG1zWUSSVIWnL+F4mMVh0huiSlS9TWTe2YQrkKqFzslyJ3DCqXQDz1gyuOm7E/3zeNAmGFZXrzCwLJuTpFQY66Ohmt25rDQdTvPR/V+Lnev3acLdTvwuFyT4MYsZeqCJ6b5ocUy5sW6WzwntsGg0QAAAAAAAAAAAAAAAAAAAAAAAAAA
\ No newline at end of file
diff --git a/cmd/bltest/tests/rsa_oaep/key20 b/cmd/bltest/tests/rsa_oaep/key20
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/key20
@@ -0,0 +1,1 @@
+AAAAAQAAAAEAxpqCGNigv6qOWXo2iOvLLM35bPnp5JgaB3XnnbWOUqF0vbvvRP85giGkYYDj4poPGT0NRshTkz7fKbAVCHCs7HBFzzaxXisQsFd9mno+x+62nERyJ8Jx6XASVxN9IoyhE7xXS1eDPjccG9XlXktwaRsvC3HCxlqEPxNCE+l9RM8re859xMesjtML2Ww6U5tKci//84f/dKjAD5Hbdoj2JIwRhRl+2ACUml2rWrglSjKH19ZzJkbWFFJhecrt1FD/CFsx+hFAtZQtuqs7PFQvZSwU1OoVTyf/jMEXwhsDoRyf3+QQp8wAm4GztJxXTclXk2jNA+g9/UJ91ZxUwrIYoQAAAAMBAAEAAAEAi59wOvuA9352mR08XcI3koY0BpMkBhuQoRIZBVzwc9MieYk4S6+KxJvWLt4oV9SrLLkpLkwDxY774RjzkH12dCYsOzNs9nL23raqQ9xX1EZnJfdIlyoGJmeUJMYPTtH6ANYnlPoxozyJStPtr1wZGs/3X30XieVrd68yrMGedhZ6tej11vJS/a22DWG57NjZC7/enzBkYHtzVCFnDRk08Qxzcss85IF8khG8NpLz1tl4+9vKKkwa08d++SC3EAs2/d9y9RCxiYTcXEgaWTmINT6JpWBXwdJAUIjOr1ujequixnapB351UZODHGKBieU1hpc52NuKz/SCLuCQmxkM0QAAAAAAAAAAAAAAAAAAAAAAAAAA
\ No newline at end of file
diff --git a/cmd/bltest/tests/rsa_oaep/key21 b/cmd/bltest/tests/rsa_oaep/key21
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/key21
@@ -0,0 +1,1 @@
+AAAAAQAAAAEAhxOfLwr3NUmZUE50aKLO+KHw8Y4yOLd9wZKJq/9WcuHnOJJJw0uV35ugsUvaXAcRwszCOJTtu+cZ1zMvRoEB/EQGcltmULHF9ViHkK5b7gcaSP2ALIrZyF9/IN5vnUGqsg1719WmgAOee6Zo1nytdbq5+cJGmAC8a6CorCM68eR1UsdoB7RfVQpqzc9fjG+HZ2wv58mk/OEhJAHUJRf7xjbrbF9jZ3DeiMd8f/dxK+bEKCXt2XsYZoOquylOdNVxCBylGSelzJqFwUvHUeJzSsz3PvXHB3YBH0cABVufoMOjwRYaNJvryhRICmbnH0Gw9ai90A/lotbprv2bzuGKUQAAAAMBAAEAAAEAGLqQ4+3gABNvS/JxAU79ESukjrR3oUaGcU/AgIqIaxPMXuD5PBW0ZHF7Y7n9SefJap5N2En7k/DlHC60svWfRVCy955YhJ4NVYHwVwcWsOGFtFkVb/fLERuydu6t3m7ucrxk/tEuxgCEZSuO/kAHBD3ltlCDLQv2KYzP7kfzJEllSDVplfcSfIxi5VQTcHuLZFScYQSeeWdjprWZ1Bv/fyFzqioqyNb/3SyFEMnXubDR0KH5yAWfeRRNLCje+DDUa41ZGiyBzlVf8eRtoh8CUNfDq6MtbfBvzjyswVV4M/h2RCO7nGAaJ8OkpCjzW04czzR/hwA2SbzP49OPD+fj1QAAAAAAAAAAAAAAAAAAAAAAAAAA
\ No newline at end of file
diff --git a/cmd/bltest/tests/rsa_oaep/key22 b/cmd/bltest/tests/rsa_oaep/key22
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/key22
@@ -0,0 +1,1 @@
+AAAAAQAAAAEAgu9i5HnjEXoGUpZ1SMf6auSlz7+X6N4hQ6Yiicq4BC66QIyjY3IjEyhlJKHsX3//GzWd+6NCerSWb23j54IrFcLGNH1oWylxZXJtCIn2+gVDsw4D+RwbG/cY6B3U4Qs1HnlSqgxKVVYAQmQyeIKshXldD86aC5OnfDlguZBN3Qe641oqoAshOzAPzBQU0fo4dey5SVXftIKm4YE2+rVK7UmbQsNBCPYonT3obsGqspnx5MghuP1MMV2HkTyL4GJk/MwTFKlsd8Nq9PrrPfpbEtpITV57lTvRcKMqW/8WaaY7YfNKtIE/TppFyw5WcxP+iPffXA+s3/kZNn4/zEGowQAAAAMBAAEAAAEAVjyMiaatoykXWPW3sYPkrtqBSt8Jkloa1o9pWA+oOzj7euAmDK1z5H5Kf2IWaJ/IyYb60m2or2CZZDKgVC4rafexMGNlvguk9Ku6ETfjA09lizPg3NQEgn06oVNYy5xurEnXNGQEcys8Pkos+GOxHBv+eMd5msV0d4lSTsi2CkJHnKuwFphjYdCTQTBZK8zlKDkY6El6Dyfmy9lrg/T5NC6kE2eeCss2/hkWzIGMbDcE3UVZGhJJhrca9SUkUHbGwbicGYUOnEGlQho9IBCpHt7CP1XWSNwZFJkRcmBFKomghAaLSXM/bfm8tghsnqI+zAL6bTdAaZkDgw5Pc0Cr+QAAAAAAAAAAAAAAAAAAAAAAAAAA
\ No newline at end of file
diff --git a/cmd/bltest/tests/rsa_oaep/maskhash18 b/cmd/bltest/tests/rsa_oaep/maskhash18
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/maskhash18
@@ -0,0 +1,1 @@
+sha256
diff --git a/cmd/bltest/tests/rsa_oaep/maskhash19 b/cmd/bltest/tests/rsa_oaep/maskhash19
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/maskhash19
@@ -0,0 +1,1 @@
+sha256
diff --git a/cmd/bltest/tests/rsa_oaep/maskhash20 b/cmd/bltest/tests/rsa_oaep/maskhash20
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/maskhash20
@@ -0,0 +1,1 @@
+sha256
diff --git a/cmd/bltest/tests/rsa_oaep/maskhash21 b/cmd/bltest/tests/rsa_oaep/maskhash21
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/maskhash21
@@ -0,0 +1,1 @@
+sha256
diff --git a/cmd/bltest/tests/rsa_oaep/maskhash22 b/cmd/bltest/tests/rsa_oaep/maskhash22
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/maskhash22
@@ -0,0 +1,1 @@
+sha256
diff --git a/cmd/bltest/tests/rsa_oaep/numtests b/cmd/bltest/tests/rsa_oaep/numtests
--- a/cmd/bltest/tests/rsa_oaep/numtests
+++ b/cmd/bltest/tests/rsa_oaep/numtests
@@ -1,1 +1,1 @@
-18
+23
diff --git a/cmd/bltest/tests/rsa_oaep/plaintext18 b/cmd/bltest/tests/rsa_oaep/plaintext18
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/plaintext18
@@ -0,0 +1,1 @@
+i<>f<EFBFBD>2<EFBFBD>H<EFBFBD>&:<3A>?L<>ط<EFBFBD><0F><>8<EFBFBD>(<28><08>֪
\ No newline at end of file
diff --git a/cmd/bltest/tests/rsa_oaep/plaintext19 b/cmd/bltest/tests/rsa_oaep/plaintext19
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/plaintext19
@@ -0,0 +1,1 @@
+<2B> <09><>^=<3D><>.<2E><> F<><46>-<2D>T/4<<3C>/.<2E>O<EFBFBD>2%
\ No newline at end of file
diff --git a/cmd/bltest/tests/rsa_oaep/plaintext20 b/cmd/bltest/tests/rsa_oaep/plaintext20
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/plaintext20
@@ -0,0 +1,1 @@
+g<><10><14><><EFBFBD>8<>ڐ8<DA90><38>d<>ůd3<64><33><EFBFBD><EFBFBD>G<EFBFBD>
\ No newline at end of file
diff --git a/cmd/bltest/tests/rsa_oaep/plaintext21 b/cmd/bltest/tests/rsa_oaep/plaintext21
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/plaintext21
@@ -0,0 +1,1 @@
+)<29>7<QF<51>Y<EFBFBD><59>2ŕ8D<38><44><1D>Ǜ<EFBFBD>\l<><6C>2<EFBFBD><32>
\ No newline at end of file
diff --git a/cmd/bltest/tests/rsa_oaep/plaintext22 b/cmd/bltest/tests/rsa_oaep/plaintext22
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/plaintext22
@@ -0,0 +1,2 @@
+
+_A<5F><41>CW<43><57>i<EFBFBD>ML<4D><4C>T<1A>L&<26>9<EFBFBD><39><EFBFBD>FX:<3A>
\ No newline at end of file
diff --git a/cmd/bltest/tests/rsa_oaep/result-encrypt-strict18 b/cmd/bltest/tests/rsa_oaep/result-encrypt-strict18
new file mode 100644
diff --git a/cmd/bltest/tests/rsa_oaep/result-encrypt-strict19 b/cmd/bltest/tests/rsa_oaep/result-encrypt-strict19
new file mode 100644
diff --git a/cmd/bltest/tests/rsa_oaep/result-encrypt-strict20 b/cmd/bltest/tests/rsa_oaep/result-encrypt-strict20
new file mode 100644
diff --git a/cmd/bltest/tests/rsa_oaep/result-encrypt-strict21 b/cmd/bltest/tests/rsa_oaep/result-encrypt-strict21
new file mode 100644
diff --git a/cmd/bltest/tests/rsa_oaep/result-encrypt-strict22 b/cmd/bltest/tests/rsa_oaep/result-encrypt-strict22
new file mode 100644
diff --git a/cmd/bltest/tests/rsa_oaep/seed18 b/cmd/bltest/tests/rsa_oaep/seed18
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/seed18
@@ -0,0 +1,1 @@
+pEen2pQ7SPIZZcAUfx9c9OfvWK04xv/yLenDu7sR6RI=
diff --git a/cmd/bltest/tests/rsa_oaep/seed19 b/cmd/bltest/tests/rsa_oaep/seed19
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/seed19
@@ -0,0 +1,1 @@
+f8C1ECn7DX2XKYI+V+Pvc+jq8X2W4+k6kJT+wxxSLto=
diff --git a/cmd/bltest/tests/rsa_oaep/seed20 b/cmd/bltest/tests/rsa_oaep/seed20
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/seed20
@@ -0,0 +1,1 @@
+OK69y3CzpjGd8gcvjK635tleUxsYQQpcyA2o0J0fCvI=
diff --git a/cmd/bltest/tests/rsa_oaep/seed21 b/cmd/bltest/tests/rsa_oaep/seed21
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/seed21
@@ -0,0 +1,1 @@
+RH/jA0vCiCol1yr5NstmmmZgB4WkGLXZPUuf31uzgRs=
diff --git a/cmd/bltest/tests/rsa_oaep/seed22 b/cmd/bltest/tests/rsa_oaep/seed22
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/tests/rsa_oaep/seed22
@@ -0,0 +1,1 @@
+c4q+NoWLoTjV6lu7Bp9JLxV76NeDMoIPNrbIQX7aCH8=
diff --git a/lib/freebl/blapit.h b/lib/freebl/blapit.h
--- a/lib/freebl/blapit.h
+++ b/lib/freebl/blapit.h
@@ -306,16 +306,17 @@ typedef struct Blake2bContextStr BLAKE2B
** RSA Public and Private Key structures
*/
/* member names from PKCS#1, section 7.1 */
struct RSAPublicKeyStr {
PLArenaPool *arena;
SECItem modulus;
SECItem publicExponent;
+ PRBool needVerify;
};
typedef struct RSAPublicKeyStr RSAPublicKey;
/* member names from PKCS#1, section 7.2 */
struct RSAPrivateKeyStr {
PLArenaPool *arena;
SECItem version;
SECItem modulus;
diff --git a/lib/freebl/fipsfreebl.c b/lib/freebl/fipsfreebl.c
--- a/lib/freebl/fipsfreebl.c
+++ b/lib/freebl/fipsfreebl.c
@@ -1311,17 +1311,18 @@ freebl_fips_RSA_PowerUpSelfTest(void)
0x44, 0x54, 0xca, 0xbe, 0xa3, 0x0e, 0x5f, 0xef
};
static const RSAPublicKey bl_public_key = {
NULL,
{ FIPS_RSA_TYPE, (unsigned char *)rsa_modulus,
FIPS_RSA_MODULUS_LENGTH },
{ FIPS_RSA_TYPE, (unsigned char *)rsa_public_exponent,
- FIPS_RSA_PUBLIC_EXPONENT_LENGTH }
+ FIPS_RSA_PUBLIC_EXPONENT_LENGTH },
+ PR_FALSE,
};
static const RSAPrivateKey bl_private_key = {
NULL,
{ FIPS_RSA_TYPE, (unsigned char *)rsa_version,
FIPS_RSA_PRIVATE_VERSION_LENGTH },
{ FIPS_RSA_TYPE, (unsigned char *)rsa_modulus,
FIPS_RSA_MODULUS_LENGTH },
{ FIPS_RSA_TYPE, (unsigned char *)rsa_public_exponent,
diff --git a/lib/freebl/mpi/mpi.h b/lib/freebl/mpi/mpi.h
--- a/lib/freebl/mpi/mpi.h
+++ b/lib/freebl/mpi/mpi.h
@@ -40,16 +40,20 @@ SEC_BEGIN_PROTOS
#define MP_YES 0 /* yes (boolean result) */
#define MP_NO -1 /* no (boolean result) */
#define MP_MEM -2 /* out of memory */
#define MP_RANGE -3 /* argument out of range */
#define MP_BADARG -4 /* invalid parameter */
#define MP_UNDEF -5 /* answer is undefined */
#define MP_LAST_CODE MP_UNDEF
+/* miller-rabin extended */
+#define MP_PRIME 0
+#define MP_COMPOSITE 1
+#define MP_NOT_POWER 2
/* Comparison constants */
#define MP_LT -1
#define MP_EQ 0
#define MP_GT 1
typedef unsigned int mp_sign;
typedef unsigned int mp_size;
typedef int mp_err;
diff --git a/lib/freebl/mpi/mpprime.c b/lib/freebl/mpi/mpprime.c
--- a/lib/freebl/mpi/mpprime.c
+++ b/lib/freebl/mpi/mpprime.c
@@ -357,16 +357,170 @@ CLEANUP:
mp_clear(&m);
mp_clear(&z);
mp_clear(&x);
mp_clear(&amo);
return res;
} /* end mpp_pprime() */
+/*
+ mpp_pprime(a, nt)
+
+ Performs nt iteration of the extended Miller-Rabin probabilistic
+ primality test on a. Returns MP_PRIME if the tests indicates
+ a is probably prime, MP_COMPOSITE if the test fails with a possible
+ factor, MP_NOT_POWER if the function return MP_COMPOSITE we have a
+ factor and the composit is probably a power of a prime. If MP_NOT_POWER
+ is returned the number is definately a composite and definitely not
+ a power of a prime. If MP_PRIME is returned, the number is probably
+ a prime (but not guaranteed).
+ */
+mp_err
+mpp_pprime_or_power(mp_int *a, mp_int *factor, int nt)
+{
+ return mpp_pprime_or_power_ext_random(a, factor, nt, mpp_random_insecure);
+}
+
+mp_err
+mpp_pprime_or_power_ext_random(mp_int *a, mp_int *factor, int nt, mpp_random_fn random)
+{
+ mp_err res;
+ mp_int x, amo, m, z, xp, g; /* "amo" = "a minus one" */
+ int iter;
+ unsigned int jx;
+ mp_size b;
+
+ ARGCHK(a != NULL, MP_BADARG);
+
+ MP_DIGITS(&x) = 0;
+ MP_DIGITS(&amo) = 0;
+ MP_DIGITS(&m) = 0;
+ MP_DIGITS(&z) = 0;
+ MP_DIGITS(&xp) = 0;
+ MP_DIGITS(&g) = 0;
+
+ /* Initialize temporaries... */
+ MP_CHECKOK(mp_init(&amo));
+ /* Compute amo = a - 1 for what follows... */
+ MP_CHECKOK(mp_sub_d(a, 1, &amo));
+
+ b = mp_trailing_zeros(&amo);
+ if (!b) { /* a was even ? */
+ if (factor) {
+ mp_set_ulong(factor, 2UL);
+ }
+ res = MP_COMPOSITE;
+ goto CLEANUP;
+ }
+
+ MP_CHECKOK(mp_init_size(&x, MP_USED(a)));
+ MP_CHECKOK(mp_init(&z));
+ MP_CHECKOK(mp_init(&xp));
+ MP_CHECKOK(mp_init(&g));
+ MP_CHECKOK(mp_init(&m));
+ MP_CHECKOK(mp_div_2d(&amo, b, &m, 0));
+
+ /* Do the test nt times... */
+ for (iter = 0; iter < nt; iter++) {
+
+ /* Choose a random value for 1 < x < a */
+ MP_CHECKOK(s_mp_pad(&x, USED(a)));
+ MP_CHECKOK((*random)(&x));
+ MP_CHECKOK(mp_mod(&x, a, &x));
+ if (mp_cmp_d(&x, 1) <= 0) {
+ iter--; /* don't count this iteration */
+ continue; /* choose a new x */
+ }
+
+ /* g = GCD(x,a) */
+ MP_CHECKOK(mp_gcd(&x, a, &g));
+ /* if g > 1 , copy g-> factor, return MP_COMPOSITE */
+ if (mp_cmp_d(&g, 1) > 0) {
+ if (factor) {
+ mp_copy(&g, factor);
+ }
+ res = MP_COMPOSITE;
+ goto CLEANUP;
+ }
+
+ /* Compute z = (x ** m) mod a */
+ MP_CHECKOK(mp_exptmod(&x, &m, a, &z));
+
+ if (mp_cmp_d(&z, 1) == 0 || mp_cmp(&z, &amo) == 0) {
+ res = MP_PRIME;
+ continue;
+ }
+
+ res = MP_NOT_POWER; /* just in case the following for loop never executes. */
+ for (jx = 1; jx < b; jx++) {
+ /* xp = z */
+ MP_CHECKOK(mp_copy(&z, &xp));
+ /* z = z^2 (mod a) */
+ MP_CHECKOK(mp_sqrmod(&z, a, &z));
+ res = MP_NOT_POWER; /* previous line set res to MP_PRIME */
+
+ if (mp_cmp_d(&z, 1) == 0) {
+ res = MP_COMPOSITE;
+ break;
+ }
+ if (mp_cmp(&z, &amo) == 0) {
+ res = MP_PRIME;
+ break;
+ }
+ } /* end testing loop */
+
+ /* If the test passes, we will continue iterating, but a failed
+ test means the candidate is definitely NOT prime, so we will
+ immediately break out of this loop
+ */
+ if (res != MP_PRIME)
+ break;
+ } /* end iterations loop */
+
+ if (res == MP_PRIME) {
+ goto CLEANUP;
+ }
+
+ if (res == MP_NOT_POWER) {
+ /* xp = z */
+ MP_CHECKOK(mp_copy(&z, &xp));
+ /* z = z^2 (mod a) */
+ MP_CHECKOK(mp_sqrmod(&z, a, &z));
+ /* if z != 1 xp=z */
+ if (mp_cmp_d(&z, 1) != 0) {
+ MP_CHECKOK(mp_copy(&z, &xp));
+ }
+ }
+ res = MP_NOT_POWER;
+
+ /* g = GCD(xp-1,a) */
+ MP_CHECKOK(mp_sub_d(&xp, 1, &xp));
+ MP_CHECKOK(mp_gcd(&xp, a, &g));
+ /* if g > 1 , copy g-> factor, return MP_COMPOSITE */
+ if (mp_cmp_d(&g, 1) > 0) {
+ if (factor) {
+ mp_copy(&g, factor);
+ }
+ res = MP_COMPOSITE;
+ goto CLEANUP;
+ }
+ res = MP_NOT_POWER;
+
+CLEANUP:
+ mp_clear(&m);
+ mp_clear(&z);
+ mp_clear(&g);
+ mp_clear(&xp);
+ mp_clear(&x);
+ mp_clear(&amo);
+ return res;
+
+} /* end mpp_pprime() */
+
/* }}} */
/* Produce table of composites from list of primes and trial value.
** trial must be odd. List of primes must not include 2.
** sieve should have dimension >= MAXPRIME/2, where MAXPRIME is largest
** prime in list of primes. After this function is finished,
** if sieve[i] is non-zero, then (trial + 2*i) is composite.
** Each prime used in the sieve costs one division of trial, and eliminates
diff --git a/lib/freebl/mpi/mpprime.h b/lib/freebl/mpi/mpprime.h
--- a/lib/freebl/mpi/mpprime.h
+++ b/lib/freebl/mpi/mpprime.h
@@ -30,19 +30,21 @@ mp_err mpp_random_size(mp_int *a, mp_siz
typedef mp_err (*mpp_random_fn)(mp_int *);
/* Pseudo-primality testing */
mp_err mpp_divis_vector(mp_int *a, const mp_digit *vec, int size, int *which);
mp_err mpp_divis_primes(mp_int *a, mp_digit *np);
mp_err mpp_fermat(mp_int *a, mp_digit w);
mp_err mpp_fermat_list(mp_int *a, const mp_digit *primes, mp_size nPrimes);
mp_err mpp_pprime(mp_int *a, int nt);
+mp_err mpp_pprime_or_power(mp_int *a, mp_int *factor, int nt);
mp_err mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes,
unsigned char *sieve, mp_size nSieve);
mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong);
/* Pseudo-primality tests using a user-provided mpp_random implementation */
mp_err mpp_pprime_ext_random(mp_int *a, int nt, mpp_random_fn random);
+mp_err mpp_pprime_or_power_ext_random(mp_int *a, mp_int *f, int nt, mpp_random_fn random);
mp_err mpp_make_prime_ext_random(mp_int *start, mp_size nBits, mp_size strong, mpp_random_fn random);
SEC_END_PROTOS
#endif /* end _H_MP_PRIME_ */
diff --git a/lib/freebl/rsapkcs.c b/lib/freebl/rsapkcs.c
--- a/lib/freebl/rsapkcs.c
+++ b/lib/freebl/rsapkcs.c
@@ -10,16 +10,17 @@
#include "stubs.h"
#endif
#include "secerr.h"
#include "blapi.h"
#include "secitem.h"
#include "blapii.h"
+#include "secmpi.h"
#define RSA_BLOCK_MIN_PAD_LEN 8
#define RSA_BLOCK_FIRST_OCTET 0x00
#define RSA_BLOCK_PRIVATE_PAD_OCTET 0xff
#define RSA_BLOCK_AFTER_PAD_OCTET 0x00
/*
* RSA block types
@@ -795,16 +796,86 @@ eme_oaep_encode(unsigned char *em,
for (i = 0; i < hash->length; ++i)
em[1 + i] ^= mask[i];
PORT_ZFree(mask, dbMaskLen);
return SECSuccess;
}
SECStatus
+RSA_PartialVerify(RSAPublicKey *key)
+{
+ mp_int n, e, fact;
+ mp_err err;
+ SECStatus rv = SECSuccess;
+ mp_int small_primes_product;
+ /* this string is the NIST string *751, since the requirement is to detect up to prime 751
+ * inclusive */
+ const char *primes_product_decimal_string ="1090367704589007566035202161494385722019383400119651874476478760664145697976533387343668263403266024900638505861980470638958322454581550203448421495842767449796261170069732921897400657944793163960886418313690808872680411646815934535605444102983629208422567461571568587963766123806881456648026733413053968363611105";
+
+ /* modulus length check done by the FIPS indicator code */
+ /* validate public exponent this test only succeeds if the exponent e is
+ * 2^16 <= e < 2^256. e = 2^16 will be rejected below byte the iseven check */
+ if (!key->publicExponent.data[0] || (key->publicExponent.len < 3) || (key->publicExponent.len > 32)) {
+ PORT_SetError(SEC_ERROR_INVALID_KEY);
+ return SECFailure;
+ }
+ /* convert to mpi for more detailed tests */
+ MP_DIGITS(&n) = 0;
+ MP_DIGITS(&e) = 0;
+ MP_DIGITS(&fact) = 0;
+ MP_DIGITS(&small_primes_product) = 0;
+ CHECK_MPI_OK(mp_init(&n));
+ CHECK_MPI_OK(mp_init(&e));
+ CHECK_MPI_OK(mp_init(&small_primes_product));
+ CHECK_MPI_OK(mp_init(&fact));
+ SECITEM_TO_MPINT(key->modulus, &n);
+ SECITEM_TO_MPINT(key->publicExponent, &e);
+
+ /* reject even exponents and moduluses */
+ if (mp_iseven(&e) || mp_iseven(&n)) {
+ err = MP_BADARG;
+ goto cleanup;
+ }
+ /* check for componsite or power */
+ err = mpp_pprime_or_power_secure(&n, NULL, 4);
+ if (err != MP_NOT_POWER) {
+ /* prime check succeeded, therefore modulus is not composite */
+ /* or we found a factor, indicating that the modulus is probably
+ * a power of a prime */
+ err = MP_BADARG;
+ goto cleanup;
+ }
+ /* check for small factors using gcd */
+ CHECK_MPI_OK(mp_read_radix(&small_primes_product,
+ primes_product_decimal_string, 10));
+ CHECK_MPI_OK(mp_gcd(&n,&small_primes_product, &fact));
+ if (mp_cmp_d(&fact, 1) != 0) {
+ /* factor found, not a good modulus */
+ err = MP_BADARG;
+ goto cleanup;
+ }
+
+cleanup:
+ mp_clear(&n);
+ mp_clear(&e);
+ mp_clear(&small_primes_product);
+ mp_clear(&fact);
+ if (err) {
+ PORT_SetError(SEC_ERROR_INVALID_KEY);
+ rv = SECFailure;
+ } else {
+ /* if we are called again with this key, no need to verify
+ * again */
+ key->needVerify = PR_FALSE;
+ }
+ return rv;
+}
+
+SECStatus
RSA_EncryptOAEP(RSAPublicKey *key,
HASH_HashType hashAlg,
HASH_HashType maskHashAlg,
const unsigned char *label,
unsigned int labelLen,
const unsigned char *seed,
unsigned int seedLen,
unsigned char *output,
@@ -827,16 +898,25 @@ RSA_EncryptOAEP(RSAPublicKey *key,
return SECFailure;
}
if ((labelLen == 0 && label != NULL) ||
(labelLen > 0 && label == NULL)) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
}
+ /* we only need to verify public keys once, and only in FIPS mode
+ */
+ if (key->needVerify) {
+ rv = RSA_PartialVerify(key);
+ if (rv != SECSuccess) {
+ /* error code set by RSA_PartialVerify() */
+ return rv;
+ }
+ }
oaepEncoded = (unsigned char *)PORT_Alloc(modulusLen);
if (oaepEncoded == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return SECFailure;
}
rv = eme_oaep_encode(oaepEncoded, modulusLen, input, inputLen,
hashAlg, maskHashAlg, label, labelLen, seed, seedLen);
diff --git a/lib/freebl/secmpi.c b/lib/freebl/secmpi.c
--- a/lib/freebl/secmpi.c
+++ b/lib/freebl/secmpi.c
@@ -17,12 +17,18 @@ mpp_random_secure(mp_int *a)
mp_err
mpp_pprime_secure(mp_int *a, int nt)
{
return mpp_pprime_ext_random(a, nt, &mpp_random_secure);
}
mp_err
+mpp_pprime_or_power_secure(mp_int *a, mp_int *fact, int nt)
+{
+ return mpp_pprime_or_power_ext_random(a, fact, nt, &mpp_random_secure);
+}
+
+mp_err
mpp_make_prime_secure(mp_int *start, mp_size nBits, mp_size strong)
{
return mpp_make_prime_ext_random(start, nBits, strong, &mpp_random_secure);
}
diff --git a/lib/freebl/secmpi.h b/lib/freebl/secmpi.h
--- a/lib/freebl/secmpi.h
+++ b/lib/freebl/secmpi.h
@@ -54,10 +54,13 @@
}
/* Fill the `used` digits of an mp_int with random bits */
mp_err mpp_random_secure(mp_int *a);
/* Pseudo-primality testing using `mpp_random_secure` to choose Miller-Rabin base */
mp_err mpp_pprime_secure(mp_int *a, int nt);
+/* Pseudo-primality testing using `mpp_random_secure` to choose extended Miller-Rabin base */
+mp_err mpp_pprime_or_power_secure(mp_int *a, mp_int *fact, int nt);
+
/* Variant of `mpp_make_prime` using `mpp_random_secure` to choose Miller-Rabin base */
mp_err mpp_make_prime_secure(mp_int *start, mp_size nBits, mp_size strong);
diff --git a/lib/softoken/fipstest.c b/lib/softoken/fipstest.c
--- a/lib/softoken/fipstest.c
+++ b/lib/softoken/fipstest.c
@@ -470,17 +470,18 @@ sftk_fips_RSA_PowerUpSelfTest(void)
0x66, 0xa6, 0x5e, 0x30, 0x0c, 0x82, 0xd5, 0x81
};
static const RSAPublicKey bl_public_key = {
NULL,
{ FIPS_RSA_TYPE, (unsigned char *)rsa_modulus,
FIPS_RSA_MODULUS_LENGTH },
{ FIPS_RSA_TYPE, (unsigned char *)rsa_public_exponent,
- FIPS_RSA_PUBLIC_EXPONENT_LENGTH }
+ FIPS_RSA_PUBLIC_EXPONENT_LENGTH },
+ PR_FALSE,
};
static const RSAPrivateKey bl_private_key = {
NULL,
{ FIPS_RSA_TYPE, (unsigned char *)rsa_version,
FIPS_RSA_PRIVATE_VERSION_LENGTH },
{ FIPS_RSA_TYPE, (unsigned char *)rsa_modulus,
FIPS_RSA_MODULUS_LENGTH },
{ FIPS_RSA_TYPE, (unsigned char *)rsa_public_exponent,
diff --git a/lib/softoken/lowkey.c b/lib/softoken/lowkey.c
--- a/lib/softoken/lowkey.c
+++ b/lib/softoken/lowkey.c
@@ -309,16 +309,18 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPr
rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
&privk->u.rsa.modulus);
if (rv == SECSuccess) {
rv = SECITEM_CopyItem(arena, &pubk->u.rsa.publicExponent,
&privk->u.rsa.publicExponent);
if (rv == SECSuccess)
return pubk;
}
+ /* this key was already verified fully as a private key */
+ pubk->u.rsa.needVerify = PR_FALSE;
} else {
PORT_SetError(SEC_ERROR_NO_MEMORY);
}
break;
case NSSLOWKEYDSAKey:
pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
sizeof(NSSLOWKEYPublicKey));
if (pubk != NULL) {
diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c
--- a/lib/softoken/pkcs11.c
+++ b/lib/softoken/pkcs11.c
@@ -2030,16 +2030,19 @@ sftk_GetPubKey(SFTKObject *object, CK_KE
return NULL;
}
/* fill in the structure */
pubKey->arena = arena;
switch (key_type) {
case CKK_RSA:
pubKey->keyType = NSSLOWKEYRSAKey;
+ /* if we claim the object is fix, then make sure it's verified
+ * before we do an OAEP operation */
+ pubKey->u.rsa.needVerify = object->isFIPS;
crv = sftk_Attribute2SSecItem(arena, &pubKey->u.rsa.modulus,
object, CKA_MODULUS);
if (crv != CKR_OK)
break;
crv = sftk_Attribute2SSecItem(arena, &pubKey->u.rsa.publicExponent,
object, CKA_PUBLIC_EXPONENT);
break;
case CKK_DSA:
diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c
--- a/lib/softoken/pkcs11c.c
+++ b/lib/softoken/pkcs11c.c
@@ -7370,16 +7370,18 @@ mldsa_next:
crv = CKR_HOST_MEMORY;
goto loser;
}
rv = SECITEM_CopyItem(arena, &pubk.u.rsa.publicExponent, &lpk->u.rsa.publicExponent);
if (rv != SECSuccess) {
crv = CKR_HOST_MEMORY;
goto loser;
}
+ pubk.u.rsa.needVerify = PR_FALSE; /* We're just encoding the key from the
+ * private key */
if (SEC_ASN1EncodeItem(arena, &spki.subjectPublicKey,
&pubk, nsslowkey_RSAPublicKeyTemplate) == NULL) {
crv = CKR_HOST_MEMORY;
goto loser;
}
publicKeyInfo = SEC_ASN1EncodeItem(arena, NULL,
diff --git a/tests/cipher/cipher.sh b/tests/cipher/cipher.sh
--- a/tests/cipher/cipher.sh
+++ b/tests/cipher/cipher.sh
@@ -87,18 +87,18 @@ cipher_main()
cipher_without_offset
else
inOff=0
while [ $inOff -lt 8 ]
do
outOff=0
while [ $outOff -lt 8 ]
do
- echo "bltest -T -m $PARAM -d $CIPHERTESTDIR -1 $inOff -2 $outOff"
- ${PROFTOOL} ${BINDIR}/bltest${PROG_SUFFIX} -T -m $PARAM -d $CIPHERTESTDIR -1 $inOff -2 $outOff
+ echo "bltest -T -m $PARAM -d $CIPHERTESTDIR -1 $inOff -2 $outOff -8"
+ ${PROFTOOL} ${BINDIR}/bltest${PROG_SUFFIX} -T -m $PARAM -d $CIPHERTESTDIR -1 $inOff -2 $outOff -8
if [ $? -ne 0 ]; then
failedStr="$failedStr[$inOff:$outOff]"
fi
outOff=`expr $outOff + 1`
done
inOff=`expr $inOff + 1`
done
if [ -n "$failedStr" ]; then