- 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.
1502 lines
61 KiB
Diff
1502 lines
61 KiB
Diff
# 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, ¶ms->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, ¶ms->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 = ¶ms->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(¶ms->asymk.sig, 0, sizeof(bltestIO));
|
||
params->asymk.sig.mode = ioMode;
|
||
setupIO(cipherInfo->arena, ¶ms->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
|