Merge commit '0982e5a8d8fc2d7585083d28800a84f6a75a133a' into pm27100-vc2010

This commit is contained in:
2024-07-24 10:58:27 +08:00
551 changed files with 1515565 additions and 963 deletions
+4 -1
View File
@@ -21,10 +21,12 @@ tasks:
$if: 'repository.url[-1] == "/"'
then: {$eval: 'repository.url[:-1]'}
else: {$eval: 'repository.url'}
# scheduler id
schedulerId: 'nss-level-${repository.level}'
in:
taskId: '${ownTaskId}'
taskGroupId: '${ownTaskId}'
schedulerId: 'nss-level-${repository.level}'
schedulerId: '${schedulerId}'
created: {$fromNow: ''}
deadline: {$fromNow: '1 day'}
expires: {$fromNow: '14 days'}
@@ -56,6 +58,7 @@ tasks:
TC_OWNER: "${push.owner}"
TC_SOURCE: "${repository.url}"
TC_PROJECT: ${repository.project}
TC_SCHEDULER_ID: "${schedulerId}"
NSS_PUSHLOG_ID: '${push.pushlog_id}'
NSS_HEAD_REPOSITORY: '${repository.url}'
NSS_HEAD_REVISION: '${push.revision}'
+2 -2
View File
@@ -87,10 +87,10 @@ ifdef NS_USE_GCC
NSPR_CONFIGURE_ENV = CC=gcc CXX=g++
endif
ifdef CC
NSPR_CONFIGURE_ENV = CC=$(CC)
NSPR_CONFIGURE_ENV = CC="$(CC)"
endif
ifdef CCC
NSPR_CONFIGURE_ENV += CXX=$(CCC)
NSPR_CONFIGURE_ENV += CXX="$(CCC)"
endif
# Remove -arch definitions. NSPR can't handle that.
NSPR_CONFIGURE_ENV := $(filter-out -arch x86_64,$(NSPR_CONFIGURE_ENV))
@@ -1,5 +1,21 @@
1 Added function:
'function SECOidTag HASH_GetHashOidTagByHashType(HASH_HashType)' {HASH_GetHashOidTagByHashType@@NSS_3.43}
'function SECStatus CERT_GetCertificateDer(const CERTCertificate*, SECItem*)' {CERT_GetCertificateDer@@NSS_3.44}
1 function with some indirect sub-type change:
[C]'function SECStatus CERT_AddOCSPAcceptableResponses(CERTOCSPRequest*, SECOidTag, ...)' at ocsp.c:2203:1 has some indirect sub-type changes:
parameter 2 of type 'typedef SECOidTag' has sub-type changes:
underlying type 'enum __anonymous_enum__' at secoidt.h:34:1 changed:
type size hasn't changed
3 enumerator insertions:
'__anonymous_enum__::SEC_OID_EXT_KEY_USAGE_IPSEC_END' value '361'
'__anonymous_enum__::SEC_OID_EXT_KEY_USAGE_IPSEC_TUNNEL' value '362'
'__anonymous_enum__::SEC_OID_EXT_KEY_USAGE_IPSEC_USER' value '363'
1 enumerator change:
'__anonymous_enum__::SEC_OID_TOTAL' from value '361' to '364' at secoidt.h:34:1
@@ -0,0 +1,17 @@
1 function with some indirect sub-type change:
[C]'function SECStatus NSS_GetAlgorithmPolicy(SECOidTag, PRUint32*)' at secoid.c:2234:1 has some indirect sub-type changes:
parameter 1 of type 'typedef SECOidTag' has sub-type changes:
underlying type 'enum __anonymous_enum__' at secoidt.h:34:1 changed:
type size hasn't changed
3 enumerator insertions:
'__anonymous_enum__::SEC_OID_EXT_KEY_USAGE_IPSEC_END' value '361'
'__anonymous_enum__::SEC_OID_EXT_KEY_USAGE_IPSEC_TUNNEL' value '362'
'__anonymous_enum__::SEC_OID_EXT_KEY_USAGE_IPSEC_USER' value '363'
1 enumerator change:
'__anonymous_enum__::SEC_OID_TOTAL' from value '361' to '364' at secoidt.h:34:1
@@ -0,0 +1,47 @@
1 function with some indirect sub-type change:
[C]'function PK11SymKey* NSS_CMSContentInfo_GetBulkKey(NSSCMSContentInfo*)' at cmscinfo.c:426:1 has some indirect sub-type changes:
parameter 1 of type 'NSSCMSContentInfo*' has sub-type changes:
in pointed to type 'typedef NSSCMSContentInfo' at cmst.h:54:1:
underlying type 'struct NSSCMSContentInfoStr' at cmst.h:126:1 changed:
type size hasn't changed
1 data member changes (2 filtered):
type of 'NSSCMSContent NSSCMSContentInfoStr::content' changed:
underlying type 'union NSSCMSContentUnion' at cmst.h:113:1 changed:
type size hasn't changed
1 data member changes (3 filtered):
type of 'NSSCMSEncryptedData* NSSCMSContentUnion::encryptedData' changed:
in pointed to type 'typedef NSSCMSEncryptedData' at cmst.h:65:1:
underlying type 'struct NSSCMSEncryptedDataStr' at cmst.h:463:1 changed:
type size hasn't changed
1 data member changes (1 filtered):
type of 'NSSCMSAttribute** NSSCMSEncryptedDataStr::unprotectedAttr' changed:
in pointed to type 'NSSCMSAttribute*':
in pointed to type 'typedef NSSCMSAttribute' at cmst.h:69:1:
underlying type 'struct NSSCMSAttributeStr' at cmst.h:482:1 changed:
type size hasn't changed
1 data member change:
type of 'SECOidData* NSSCMSAttributeStr::typeTag' changed:
in pointed to type 'typedef SECOidData' at secoidt.h:16:1:
underlying type 'struct SECOidDataStr' at secoidt.h:518:1 changed:
type size hasn't changed
1 data member change:
type of 'SECOidTag SECOidDataStr::offset' changed:
underlying type 'enum __anonymous_enum__' at secoidt.h:34:1 changed:
type size hasn't changed
3 enumerator insertions:
'__anonymous_enum__::SEC_OID_EXT_KEY_USAGE_IPSEC_END' value '361'
'__anonymous_enum__::SEC_OID_EXT_KEY_USAGE_IPSEC_TUNNEL' value '362'
'__anonymous_enum__::SEC_OID_EXT_KEY_USAGE_IPSEC_USER' value '363'
1 enumerator change:
'__anonymous_enum__::SEC_OID_TOTAL' from value '361' to '364' at secoidt.h:34:1
@@ -1,20 +0,0 @@
2 functions with some indirect sub-type change:
[C]'function SECStatus SSL_GetCipherSuiteInfo(PRUint16, SSLCipherSuiteInfo*, PRUintn)' at sslinfo.c:326:1 has some indirect sub-type changes:
parameter 2 of type 'SSLCipherSuiteInfo*' has sub-type changes:
in pointed to type 'typedef SSLCipherSuiteInfo' at sslt.h:433:1:
underlying type 'struct SSLCipherSuiteInfoStr' at sslt.h:366:1 changed:
type size changed from 768 to 832 (in bits)
1 data member insertion:
'SSLHashType SSLCipherSuiteInfoStr::kdfHash', at offset 768 (in bits) at sslt.h:429:1
[C]'function SECStatus SSL_GetPreliminaryChannelInfo(PRFileDesc*, SSLPreliminaryChannelInfo*, PRUintn)' at sslinfo.c:111:1 has some indirect sub-type changes:
parameter 2 of type 'SSLPreliminaryChannelInfo*' has sub-type changes:
in pointed to type 'typedef SSLPreliminaryChannelInfo' at sslt.h:379:1:
underlying type 'struct SSLPreliminaryChannelInfoStr' at sslt.h:333:1 changed:
type size changed from 160 to 192 (in bits)
1 data member insertion:
'PRUint16 SSLPreliminaryChannelInfoStr::zeroRttCipherSuite', at offset 160 (in bits) at sslt.h:375:1
@@ -1 +1 @@
NSS_3_42_BRANCH
NSS_3_43_BRANCH
@@ -924,9 +924,13 @@ async function scheduleWindows(name, base, build_script) {
function scheduleTests(task_build, task_cert, test_base) {
test_base = merge(test_base, {kind: "test"});
// Schedule tests that do NOT need certificates.
let no_cert_base = merge(test_base, {parent: task_build});
let cert_base = merge(test_base, {parent: task_cert});
let cert_base_long = merge(cert_base, {maxRunTime: 7200});
// Schedule tests that do NOT need certificates. This is defined as
// the test itself not needing certs AND not running under the upgradedb
// cycle (which itself needs certs). If cycle is not defined, default is all.
queue.scheduleTask(merge(no_cert_base, {
name: "Gtests", symbol: "Gtest", tests: "ssl_gtests gtests", cycle: "standard"
}));
@@ -947,46 +951,45 @@ function scheduleTests(task_build, task_cert, test_base) {
queue.scheduleTask(merge(no_cert_base, {
name: "tlsfuzzer tests", symbol: "tlsfuzzer", tests: "tlsfuzzer", cycle: "standard"
}));
queue.scheduleTask(merge(no_cert_base, {
queue.scheduleTask(merge(cert_base, {
name: "Chains tests", symbol: "Chains", tests: "chains"
}));
queue.scheduleTask(merge(no_cert_base, {
queue.scheduleTask(merge(cert_base_long, {
name: "Cipher tests", symbol: "Default", tests: "cipher", group: "Cipher"
}));
queue.scheduleTask(merge(no_cert_base, {
queue.scheduleTask(merge(cert_base_long, {
name: "Cipher tests", symbol: "NoAESNI", tests: "cipher",
env: {NSS_DISABLE_HW_AES: "1"}, group: "Cipher"
}));
queue.scheduleTask(merge(no_cert_base, {
queue.scheduleTask(merge(cert_base_long, {
name: "Cipher tests", symbol: "NoPCLMUL", tests: "cipher",
env: {NSS_DISABLE_PCLMUL: "1"}, group: "Cipher"
}));
queue.scheduleTask(merge(no_cert_base, {
queue.scheduleTask(merge(cert_base_long, {
name: "Cipher tests", symbol: "NoAVX", tests: "cipher",
env: {NSS_DISABLE_AVX: "1"}, group: "Cipher"
}));
queue.scheduleTask(merge(no_cert_base, {
queue.scheduleTask(merge(cert_base_long, {
name: "Cipher tests", symbol: "NoSSSE3|NEON", tests: "cipher",
env: {
NSS_DISABLE_ARM_NEON: "1",
NSS_DISABLE_SSSE3: "1"
}, group: "Cipher"
}));
queue.scheduleTask(merge(no_cert_base, {
queue.scheduleTask(merge(cert_base, {
name: "EC tests", symbol: "EC", tests: "ec"
}));
queue.scheduleTask(merge(no_cert_base, {
queue.scheduleTask(merge(cert_base, {
name: "Lowhash tests", symbol: "Lowhash", tests: "lowhash"
}));
queue.scheduleTask(merge(no_cert_base, {
queue.scheduleTask(merge(cert_base, {
name: "SDR tests", symbol: "SDR", tests: "sdr"
}));
queue.scheduleTask(merge(no_cert_base, {
queue.scheduleTask(merge(cert_base, {
name: "Policy tests", symbol: "Policy", tests: "policy"
}));
// Schedule tests that need certificates.
let cert_base = merge(test_base, {parent: task_cert});
queue.scheduleTask(merge(cert_base, {
name: "CRMF tests", symbol: "CRMF", tests: "crmf"
}));
@@ -135,7 +135,8 @@ function convertTask(def) {
return {
provisionerId: def.provisioner || "aws-provisioner-v1",
workerType: def.workerType || "hg-worker",
schedulerId: "task-graph-scheduler",
schedulerId: process.env.TC_SCHEDULER_ID,
taskGroupId: process.env.TASK_ID,
scopes,
created: fromNow(0),
@@ -167,7 +167,7 @@ export async function initFilter() {
let comment = await getCommitComment();
// Check for try syntax in changeset comment.
let match = comment.match(/^\s*try:\s*(.*)\s*$/);
let match = comment.match(/\btry:\s*(.*)\s*$/m);
// Add try syntax filter.
if (match) {
@@ -103,6 +103,7 @@ abi_diff()
cat ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt \
| grep -v "^Functions changes summary:" \
| grep -v "^Variables changes summary:" \
| sed -e 's/__anonymous_enum__[0-9]*/__anonymous_enum__/g' \
> ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt
rm -f ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt
+6 -1
View File
@@ -50,6 +50,7 @@ fuzz=0
fuzz_tls=0
fuzz_oss=0
no_local_nspr=0
sslkeylogfile=1
gyp_params=(--depth="$cwd" --generator-output=".")
ninja_params=()
@@ -94,7 +95,8 @@ while [ $# -gt 0 ]; do
--sancov=?*) enable_sancov "${1#*=}" ;;
--emit-llvm) gyp_params+=(-Demit_llvm=1 -Dsign_libs=0) ;;
--no-zdefs) gyp_params+=(-Dno_zdefs=1) ;;
--test) gyp_params+=(-Dtest_build=1) ;;
--test) gyp_params+=(-Dtest_build=1 -Dstatic_libs=1) ;;
--static) gyp_params+=(-Dstatic_libs=1) ;;
--ct-verif) gyp_params+=(-Dct_verif=1) ;;
--nspr) nspr_clean; rebuild_nspr=1 ;;
--with-nspr=?*) set_nspr_path "${1#*=}"; no_local_nspr=1 ;;
@@ -103,6 +105,7 @@ while [ $# -gt 0 ]; do
--enable-fips) gyp_params+=(-Ddisable_fips=0) ;;
--enable-libpkix) gyp_params+=(-Ddisable_libpkix=0) ;;
--mozpkix-only) gyp_params+=(-Dmozpkix_only=1 -Ddisable_tests=1 -Dsign_libs=0) ;;
--disable-keylog) sslkeylogfile=0 ;;
-D*) gyp_params+=("$1") ;;
*) show_help; exit 2 ;;
esac
@@ -117,6 +120,8 @@ else
target=Debug
fi
#gyp_params+=(-Denable_sslkeylogfile="$sslkeylogfile")
# Do special setup.
if [ "$fuzz" = 1 ]; then
source "$cwd"/coreconf/fuzz.sh
+2 -3
View File
@@ -120,6 +120,7 @@ main(int argc, char **argv)
/* Parse command line arguments */
optstate = PL_CreateOptState(argc, argv, "i:o:w:");
PORT_Assert(optstate);
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
switch (optstate->option) {
default:
@@ -203,9 +204,7 @@ main(int argc, char **argv)
}
exitCode = 0;
loser:
if (optstate) {
PL_DestroyOptState(optstate);
}
PL_DestroyOptState(optstate);
if (inFile && closeIn) {
fclose(inFile);
}
+50
View File
@@ -497,6 +497,13 @@ static const char *const
"ocspResponder",
"stepUp",
"msTrustListSigning",
"x509Any",
"ipsecIKE",
"ipsecIKEEnd",
"ipsecIKEIntermediate",
"ipsecEnd",
"ipsecTunnel",
"ipsecUser",
NULL };
static SECStatus
@@ -517,6 +524,10 @@ AddExtKeyUsage(void *extHandle, const char *userSuppliedValue)
while (1) {
if (!userSuppliedValue) {
/*
* none of the 'new' extended key usage options work with the prompted menu. This is so
* old scripts can continue to work.
*/
if (PrintChoicesAndGetAnswer(
"\t\t0 - Server Auth\n"
"\t\t1 - Client Auth\n"
@@ -572,6 +583,45 @@ AddExtKeyUsage(void *extHandle, const char *userSuppliedValue)
case 7:
rv = AddOidToSequence(os, SEC_OID_MS_EXT_KEY_USAGE_CTL_SIGNING);
break;
/*
* These new usages can only be added explicitly by the userSuppliedValues. This allows old
* scripts which used '>7' as an exit value to continue to work.
*/
case 8:
if (!userSuppliedValue)
goto endloop;
rv = AddOidToSequence(os, SEC_OID_X509_ANY_EXT_KEY_USAGE);
break;
case 9:
if (!userSuppliedValue)
goto endloop;
rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_IPSEC_IKE);
break;
case 10:
if (!userSuppliedValue)
goto endloop;
rv = AddOidToSequence(os, SEC_OID_IPSEC_IKE_END);
break;
case 11:
if (!userSuppliedValue)
goto endloop;
rv = AddOidToSequence(os, SEC_OID_IPSEC_IKE_INTERMEDIATE);
break;
case 12:
if (!userSuppliedValue)
goto endloop;
rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_IPSEC_END);
break;
case 13:
if (!userSuppliedValue)
goto endloop;
rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_IPSEC_TUNNEL);
break;
case 14:
if (!userSuppliedValue)
goto endloop;
rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_IPSEC_USER);
break;
default:
goto endloop;
}
+6 -3
View File
@@ -1362,8 +1362,11 @@ luC(enum usage_level ul, const char *command)
"%-20s Create extended key usage extension. Possible keywords:\n"
"%-20s \"serverAuth\", \"clientAuth\",\"codeSigning\",\n"
"%-20s \"emailProtection\", \"timeStamp\",\"ocspResponder\",\n"
"%-20s \"stepUp\", \"msTrustListSign\", \"critical\"\n",
" -6 | --extKeyUsage keyword,keyword,...", "", "", "", "");
"%-20s \"stepUp\", \"msTrustListSign\", \"x509Any\",\n"
"%-20s \"ipsecIKE\", \"ipsecIKEEnd\", \"ipsecIKEIntermediate\",\n"
"%-20s \"ipsecEnd\", \"ipsecTunnel\", \"ipsecUser\",\n"
"%-20s \"critical\"\n",
" -6 | --extKeyUsage keyword,keyword,...", "", "", "", "", "", "", "");
FPS "%-20s Create an email subject alt name extension\n",
" -7 emailAddrs");
FPS "%-20s Create an dns subject alt name extension\n",
@@ -3120,7 +3123,7 @@ certutil_main(int argc, char **argv, PRBool initialize)
PR_fprintf(PR_STDERR,
"%s -%c: specify a nickname (-n) or\n"
" a key ID (-k).\n",
commandToRun, progName);
progName, commandToRun);
return 255;
}
+1
View File
@@ -0,0 +1 @@
The scripts have been moved to tests/fips/cavs_scripts
File diff suppressed because it is too large Load Diff
@@ -185,7 +185,7 @@ cleanup:
}
static const char *const usageInfo[] = {
"pk11import - test PK11_PrivateKeyImport()"
"pk11import - test PK11_PrivateKeyImport()",
"Options:",
" -d certdir directory containing cert database",
" -k keysize size of the rsa, dh, and dsa key to test (default 1024)",
+42 -11
View File
@@ -233,7 +233,9 @@ PrintParameterUsage()
" ecdsa_secp521r1_sha512,\n"
" rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512,\n"
" rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512,\n"
"-Z enable 0-RTT (for TLS 1.3; also use -u)\n",
"-Z enable 0-RTT (for TLS 1.3; also use -u)\n"
"-E enable post-handshake authentication\n"
" (for TLS 1.3; only has an effect with 3 or more -r options)\n",
stderr);
}
@@ -804,6 +806,7 @@ PRBool failedToNegotiateName = PR_FALSE;
PRBool enableExtendedMasterSecret = PR_FALSE;
PRBool zeroRTT = PR_FALSE;
PRBool enableALPN = PR_FALSE;
PRBool enablePostHandshakeAuth = PR_FALSE;
SSLNamedGroup *enabledGroups = NULL;
unsigned int enabledGroupsCount = 0;
const SSLSignatureScheme *enabledSigSchemes = NULL;
@@ -1431,15 +1434,28 @@ handle_connection(PRFileDesc *tcp_sock, PRFileDesc *model_sock)
errWarn("second SSL_OptionSet SSL_REQUIRE_CERTIFICATE");
break;
}
rv = SSL_ReHandshake(ssl_sock, PR_TRUE);
if (rv != 0) {
errWarn("SSL_ReHandshake");
break;
}
rv = SSL_ForceHandshake(ssl_sock);
if (rv < 0) {
errWarn("SSL_ForceHandshake");
break;
if (enablePostHandshakeAuth) {
rv = SSL_SendCertificateRequest(ssl_sock);
if (rv != SECSuccess) {
errWarn("SSL_SendCertificateRequest");
break;
}
rv = SSL_ForceHandshake(ssl_sock);
if (rv != SECSuccess) {
errWarn("SSL_ForceHandshake");
break;
}
} else {
rv = SSL_ReHandshake(ssl_sock, PR_TRUE);
if (rv != 0) {
errWarn("SSL_ReHandshake");
break;
}
rv = SSL_ForceHandshake(ssl_sock);
if (rv < 0) {
errWarn("SSL_ForceHandshake");
break;
}
}
}
}
@@ -1948,6 +1964,16 @@ server_main(
}
}
if (enablePostHandshakeAuth) {
if (enabledVersions.max < SSL_LIBRARY_VERSION_TLS_1_3) {
errExit("You tried enabling post-handshake auth without enabling TLS 1.3!");
}
rv = SSL_OptionSet(model_sock, SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE);
if (rv != SECSuccess) {
errExit("error enabling post-handshake auth");
}
}
if (enableALPN) {
PRUint8 alpnVal[] = { 0x08,
0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 };
@@ -2223,7 +2249,7 @@ main(int argc, char **argv)
** in 3.28, please leave some time before resuing those.
** 'z' was removed in 3.39. */
optstate = PL_CreateOptState(argc, argv,
"2:A:C:DGH:I:J:L:M:NP:QRS:T:U:V:W:YZa:bc:d:e:f:g:hi:jk:lmn:op:rst:uvw:y");
"2:A:C:DEGH:I:J:L:M:NP:QRS:T:U:V:W:YZa:bc:d:e:f:g:hi:jk:lmn:op:rst:uvw:y");
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
++optionsFound;
switch (optstate->option) {
@@ -2243,6 +2269,11 @@ main(int argc, char **argv)
case 'D':
noDelay = PR_TRUE;
break;
case 'E':
enablePostHandshakeAuth = PR_TRUE;
break;
case 'H':
configureDHE = (PORT_Atoi(optstate->value) != 0);
break;
+24 -2
View File
@@ -221,7 +221,7 @@ PrintUsageHeader()
fprintf(stderr,
"Usage: %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n"
" [-D | -d certdir] [-C] [-b | -R root-module] \n"
" [-n nickname] [-Bafosvx] [-c ciphers] [-Y] [-Z]\n"
" [-n nickname] [-Bafosvx] [-c ciphers] [-Y] [-Z] [-E]\n"
" [-V [min-version]:[max-version]] [-K] [-T] [-U]\n"
" [-r N] [-w passwd] [-W pwfile] [-q [-t seconds]]\n"
" [-I groups] [-J signatureschemes]\n"
@@ -311,6 +311,9 @@ PrintParameterUsage()
fprintf(stderr, "%-20s Use DTLS\n", "-P {client, server}");
fprintf(stderr, "%-20s Exit after handshake\n", "-Q");
fprintf(stderr, "%-20s Encrypted SNI Keys\n", "-N");
fprintf(stderr, "%-20s Enable post-handshake authentication\n"
"%-20s for TLS 1.3; need to specify -n\n",
"-E", "");
}
static void
@@ -989,6 +992,7 @@ PRBool requestToExit = PR_FALSE;
char *versionString = NULL;
PRBool handshakeComplete = PR_FALSE;
char *encryptedSNIKeys = NULL;
PRBool enablePostHandshakeAuth = PR_FALSE;
static int
writeBytesToServer(PRFileDesc *s, const PRUint8 *buf, int nb)
@@ -1410,6 +1414,15 @@ run()
goto done;
}
if (enablePostHandshakeAuth) {
rv = SSL_OptionSet(s, SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE);
if (rv != SECSuccess) {
SECU_PrintError(progName, "error enabling post-handshake auth");
error = 1;
goto done;
}
}
if (enabledGroups) {
rv = SSL_NamedGroupConfig(s, enabledGroups, enabledGroupsCount);
if (rv < 0) {
@@ -1707,7 +1720,7 @@ main(int argc, char **argv)
* Please leave some time before reusing these.
*/
optstate = PL_CreateOptState(argc, argv,
"46A:CDFGHI:J:KL:M:N:OP:QR:STUV:W:X:YZa:bc:d:fgh:m:n:op:qr:st:uvw:");
"46A:CDEFGHI:J:KL:M:N:OP:QR:STUV:W:X:YZa:bc:d:fgh:m:n:op:qr:st:uvw:");
while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
switch (optstate->option) {
case '?':
@@ -1738,6 +1751,10 @@ main(int argc, char **argv)
openDB = PR_FALSE;
break;
case 'E':
enablePostHandshakeAuth = PR_TRUE;
break;
case 'F':
if (serverCertAuth.testFreshStatusFromSideChannel) {
/* parameter given twice or more */
@@ -1988,6 +2005,11 @@ main(int argc, char **argv)
exit(1);
}
if (enablePostHandshakeAuth && !nickname) {
fprintf(stderr, "%s: -E requires the use of -n\n", progName);
exit(1);
}
PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
PK11_SetPasswordFunc(SECU_GetModulePassword);
+4
View File
@@ -135,6 +135,10 @@ ifeq ($(KERNEL),Linux)
endif
OS_LIBS = $(OS_PTHREAD) -ldl -lc
ifeq ($(OS_TARGET),Android)
OS_LIBS += -llog
endif
ifdef USE_PTHREADS
DEFINES += -D_REENTRANT
endif
@@ -5,17 +5,18 @@ import subprocess
import sys
def main():
if sys.platform == 'win32':
if sys.platform == 'win32' or len(sys.argv) < 2:
print(0)
else:
cc = os.environ.get('CC', 'cc')
try:
cc_is_clang = 'clang' in subprocess.check_output(
cc_is_arg = sys.argv[1] in subprocess.check_output(
[cc, '--version'], universal_newlines=True)
except OSError:
# We probably just don't have CC/cc.
cc_is_clang = False
print(int(cc_is_clang))
cc_is_arg = False
print(int(cc_is_arg))
if __name__ == '__main__':
main()
+41 -11
View File
@@ -19,6 +19,8 @@
'conditions': [
['OS=="android"', {
'target_arch%': 'arm',
}, 'OS=="ios"', {
'target_arch%': 'arm64',
}, {
# Default architecture we're building for is the architecture we're
# building on.
@@ -35,7 +37,7 @@
},{
'use_system_sqlite%': 0,
}],
['OS=="mac" or OS=="win"', {
['OS=="mac" or OS=="ios" or OS=="win"', {
'cc_use_gnu_ld%': 0,
}, {
'cc_use_gnu_ld%': 1,
@@ -54,7 +56,7 @@
'zlib_libs%': ['-lz'],
'dll_prefix': 'lib',
'conditions': [
['OS=="mac"', {
['OS=="mac" or OS=="ios"', {
'moz_debug_flags%': '-gdwarf-2 -gfull',
'dll_suffix': 'dylib',
}, {
@@ -64,10 +66,15 @@
],
}],
['"<(GENERATOR)"=="ninja"', {
'cc_is_clang%': '<!(<(python) <(DEPTH)/coreconf/check_cc_clang.py)',
'cc_is_clang%': '<!(<(python) <(DEPTH)/coreconf/check_cc.py clang)',
}, {
'cc_is_clang%': '0',
}],
['"<(GENERATOR)"=="ninja"', {
'cc_is_gcc%': '<!(<(python) <(DEPTH)/coreconf/check_cc.py gcc)',
}, {
'cc_is_gcc%': '0',
}],
],
},
# Copy conditionally-set variables out one scope.
@@ -86,6 +93,7 @@
'dll_suffix': '<(dll_suffix)',
'freebl_name': '<(freebl_name)',
'cc_is_clang%': '<(cc_is_clang)',
'cc_is_gcc%': '<(cc_is_gcc)',
'cc_use_gnu_ld%': '<(cc_use_gnu_ld)',
# Some defaults
'disable_tests%': 0,
@@ -99,6 +107,7 @@
'moz_folded_library_name%': '',
'sanitizer_flags%': 0,
'test_build%': 0,
'static_libs%': 0,
'no_zdefs%': 0,
'fuzz%': 0,
'fuzz_tls%': 0,
@@ -122,6 +131,7 @@
'variables': {
'mapfile%': '',
'test_build%': 0,
'static_libs%': 0,
'debug_optimization_level%': '0',
'release_optimization_level%': '2',
},
@@ -142,7 +152,12 @@
'NSS_NO_INIT_SUPPORT',
],
}],
[ 'OS!="android" and OS!="mac" and OS!="win"', {
[ 'static_libs==1', {
'variables': {
'standalone_static_library': '1',
},
}],
[ 'OS!="android" and OS!="mac" and OS!="ios" and OS!="win"', {
'libraries': [
'-lpthread',
],
@@ -153,6 +168,11 @@
'-lc',
],
}],
[ 'OS=="android"', {
'libraries': [
'-llog',
],
}],
[ 'fuzz==1', {
'variables': {
'debug_optimization_level%': '1',
@@ -257,7 +277,7 @@
}],
}]
],
}, 'test_build==1 and _type=="shared_library"', {
}, 'static_libs==1 and _type=="shared_library"', {
# When linking a shared lib against a static one, XCode doesn't
# export the latter's symbols by default. -all_load fixes that.
'xcode_settings': {
@@ -355,7 +375,7 @@
'OPENBSD',
],
}],
['OS=="mac" or OS=="dragonfly" or OS=="freebsd" or OS=="netbsd" or OS=="openbsd"', {
['OS=="mac" or OS=="ios" or OS=="dragonfly" or OS=="freebsd" or OS=="netbsd" or OS=="openbsd"', {
'defines': [
'HAVE_BSD_FLOCK',
],
@@ -367,7 +387,7 @@
'_REENTRANT',
],
}],
[ 'OS!="mac" and OS!="win"', {
[ 'OS!="mac" and OS!="ios" and OS!="win"', {
'cflags': [
'-fPIC',
'-pipe',
@@ -393,7 +413,7 @@
}],
[ 'use_pprof==1 and OS!="android" and OS!="win"', {
'conditions': [
[ 'OS=="mac"', {
[ 'OS=="mac" or OS=="ios"', {
'xcode_settings': {
'OTHER_LDFLAGS': [ '-lprofiler' ],
},
@@ -453,7 +473,7 @@
'ANDROID',
],
}],
[ 'OS=="mac"', {
[ 'OS=="mac" or OS=="ios"', {
'defines': [
'DARWIN',
],
@@ -468,8 +488,18 @@
'ARCHS': ['x86_64'],
},
}],
[ 'target_arch=="arm64"', {
'xcode_settings': {
'ARCHS': ['arm64'],
},
}],
],
}],
[ 'OS=="ios"', {
'xcode_settings': {
'IPHONEOS_DEPLOYMENT_TARGET': '<(iphone_deployment_target)',
},
}],
[ 'OS=="win"', {
'defines': [
'_WINDOWS',
@@ -537,7 +567,7 @@
'Debug': {
'inherit_from': ['Common'],
'conditions': [
[ 'OS!="mac" and OS!="win"', {
[ 'OS!="mac" and OS!="ios" and OS!="win"', {
'cflags': [
'-g',
'<(moz_debug_flags)',
@@ -607,7 +637,7 @@
'process_map_file': ['/bin/sh', '-c', '/usr/bin/env grep -v ";-" >(mapfile) | sed -e "s,;+,," -e "s; DATA ;;" -e "s,;;,," -e "s,;.*,;," > >@(_outputs)'],
},
}],
[ 'OS=="mac"', {
[ 'OS=="mac" or OS=="ios"', {
'variables': {
'process_map_file': ['/bin/sh', '-c', '/usr/bin/grep -v ";+" >(mapfile) | grep -v ";-" | sed -e "s; DATA ;;" -e "s,;;,," -e "s,;.*,," -e "s,^,_," > >@(_outputs)'],
},
+1 -1
View File
@@ -14,7 +14,7 @@ if [ -z "$CC" ]; then
export CXX=clang++
fi
gyp_params+=(-Dtest_build=1 -Dfuzz=1 -Dsign_libs=0)
gyp_params+=(-Dtest_build=1 -Dstatic_libs=1 -Dfuzz=1 -Dsign_libs=0)
# Add debug symbols even for opt builds.
nspr_params+=(--enable-debug-symbols)
+1
View File
@@ -52,6 +52,7 @@ const uint8_t kTlsAlertInappropriateFallback = 86;
const uint8_t kTlsAlertMissingExtension = 109;
const uint8_t kTlsAlertUnsupportedExtension = 110;
const uint8_t kTlsAlertUnrecognizedName = 112;
const uint8_t kTlsAlertCertificateRequired = 116;
const uint8_t kTlsAlertNoApplicationProtocol = 120;
const uint8_t kTlsFakeChangeCipherSpec[] = {
+38
View File
@@ -427,6 +427,9 @@ of the attribute codes:
</listitem>
<listitem>
<para><command>J</command> (as an object signer)</para>
</listitem>
<listitem>
<para><command>I</command> (as an IPSEC user)</para>
</listitem>
</itemizedlist></listitem>
</varlistentry>
@@ -662,6 +665,41 @@ of the attribute codes:
critical
</para>
</listitem>
<listitem>
<para>
x509Any
</para>
</listitem>
<listitem>
<para>
ipsecIKE
</para>
</listitem>
<listitem>
<para>
ipsecIKEEnd
</para>
</listitem>
<listitem>
<para>
ipsecIKEIntermediate
</para>
</listitem>
<listitem>
<para>
ipsecEnd
</para>
</listitem>
<listitem>
<para>
ipsecTunnel
</para>
</listitem>
<listitem>
<para>
ipsecUser
</para>
</listitem>
</itemizedlist>
<para>X.509 certificate extensions are described in RFC 5280.</para></listitem>
</varlistentry>
@@ -12,6 +12,8 @@
'type': 'executable',
'sources': [
'alg1485_unittest.cc',
'cert_unittest.cc',
'decode_certs_unittest.cc',
'<(DEPTH)/gtests/common/gtests.cc'
],
'dependencies': [
@@ -20,6 +22,7 @@
'<(DEPTH)/lib/util/util.gyp:nssutil3',
'<(DEPTH)/lib/ssl/ssl.gyp:ssl3',
'<(DEPTH)/lib/nss/nss.gyp:nss3',
'<(DEPTH)/lib/smime/smime.gyp:smime3',
]
}
],
@@ -8,6 +8,8 @@ MODULE = nss
CPPSRCS = \
alg1485_unittest.cc \
cert_unittest.cc \
decode_certs_unittest.cc \
$(NULL)
INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \
@@ -40,6 +40,13 @@
'freebl_gtest_deps',
'<(DEPTH)/exports.gyp:nss_exports',
],
'conditions': [
[ 'cc_is_gcc==1 and (target_arch=="ia32" or target_arch=="x64")', {
'cflags_cc': [
'-msse2',
],
}],
],
},
{
'target_name': 'prng_gtest',
@@ -6,6 +6,7 @@
#include <stdint.h>
#include <string.h>
#include <memory>
#ifdef __MACH__
#include <mach/clock.h>
@@ -27,7 +28,7 @@ void gettime(struct timespec* tp) {
tp->tv_sec = mts.tv_sec;
tp->tv_nsec = mts.tv_nsec;
#else
clock_gettime(CLOCK_MONOTONIC, tp);
ASSERT_NE(0, timespec_get(tp, TIME_UTC));
#endif
}
@@ -84,8 +85,9 @@ class MPITest : public ::testing::Test {
mp_int a;
ASSERT_EQ(MP_OKAY, mp_init(&a));
ASSERT_EQ(MP_OKAY, mp_read_unsigned_octets(&a, ref.data(), ref.size()));
uint8_t buf[len];
ASSERT_EQ(MP_OKAY, mp_to_fixlen_octets(&a, buf, len));
std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
ASSERT_NE(buf, nullptr);
ASSERT_EQ(MP_OKAY, mp_to_fixlen_octets(&a, buf.get(), len));
size_t compare;
if (len > ref.size()) {
for (size_t i = 0; i < len - ref.size(); ++i) {
@@ -96,9 +98,9 @@ class MPITest : public ::testing::Test {
compare = len;
}
dump("value", ref.data(), ref.size());
dump("output", buf, len);
ASSERT_EQ(0, memcmp(buf + len - compare, ref.data() + ref.size() - compare,
compare))
dump("output", buf.get(), len);
ASSERT_EQ(0, memcmp(buf.get() + len - compare,
ref.data() + ref.size() - compare, compare))
<< "comparing " << compare << " octets";
mp_clear(&a);
}
@@ -5,6 +5,7 @@
#include "gtest/gtest.h"
#include <stdint.h>
#include <memory>
#include "blapi.h"
#include "secitem.h"
@@ -359,6 +359,7 @@ TEST_F(pkixder_input_tests, Skip_WrapAroundPointer)
// but this should catch the problem on at least some compilers, if not all of
// them.
const uint8_t* der = nullptr;
// coverity[FORWARD_NULL]
--der;
Input buf;
ASSERT_EQ(Success, buf.Init(der, 0));
@@ -8,6 +8,7 @@ MODULE = nss
CPPSRCS = \
pk11_aeskeywrap_unittest.cc \
pk11_aes_gcm_unittest.cc \
pk11_chacha20poly1305_unittest.cc \
pk11_curve25519_unittest.cc \
pk11_ecdsa_unittest.cc \
@@ -8,6 +8,7 @@
#include "nss.h"
#include "pk11pub.h"
#include "sechash.h"
#include "secerr.h"
#include "cpputil.h"
#include "nss_scoped_ptrs.h"
@@ -17,10 +18,17 @@
namespace nss_test {
static const CK_MECHANISM_TYPE kMech = CKM_NSS_CHACHA20_POLY1305;
static const CK_MECHANISM_TYPE kMechXor = CKM_NSS_CHACHA20_CTR;
// Some test data for simple tests.
static const uint8_t kKeyData[32] = {'k'};
static const uint8_t kCtrNonce[16] = {'c', 0, 0, 0, 'n'};
static const uint8_t kData[16] = {'d'};
class Pkcs11ChaCha20Poly1305Test
: public ::testing::TestWithParam<chacha_testvector> {
public:
void EncryptDecrypt(PK11SymKey* symKey, const bool invalid_iv,
void EncryptDecrypt(const ScopedPK11SymKey& key, const bool invalid_iv,
const bool invalid_tag, const uint8_t* data,
size_t data_len, const uint8_t* aad, size_t aad_len,
const uint8_t* iv, size_t iv_len,
@@ -39,7 +47,7 @@ class Pkcs11ChaCha20Poly1305Test
// Encrypt.
unsigned int outputLen = 0;
std::vector<uint8_t> output(data_len + aead_params.ulTagLen);
SECStatus rv = PK11_Encrypt(symKey, mech, &params, output.data(),
SECStatus rv = PK11_Encrypt(key.get(), kMech, &params, output.data(),
&outputLen, output.size(), data, data_len);
// Return if encryption failure was expected due to invalid IV.
@@ -60,8 +68,9 @@ class Pkcs11ChaCha20Poly1305Test
// Decrypt.
unsigned int decryptedLen = 0;
std::vector<uint8_t> decrypted(data_len);
rv = PK11_Decrypt(symKey, mech, &params, decrypted.data(), &decryptedLen,
decrypted.size(), output.data(), outputLen);
rv =
PK11_Decrypt(key.get(), kMech, &params, decrypted.data(), &decryptedLen,
decrypted.size(), output.data(), outputLen);
EXPECT_EQ(rv, SECSuccess);
// Check the plaintext.
@@ -73,8 +82,9 @@ class Pkcs11ChaCha20Poly1305Test
if (outputLen != 0) {
std::vector<uint8_t> bogusCiphertext(output);
bogusCiphertext[0] ^= 0xff;
rv = PK11_Decrypt(symKey, mech, &params, decrypted.data(), &decryptedLen,
decrypted.size(), bogusCiphertext.data(), outputLen);
rv = PK11_Decrypt(key.get(), kMech, &params, decrypted.data(),
&decryptedLen, decrypted.size(), bogusCiphertext.data(),
outputLen);
EXPECT_NE(rv, SECSuccess);
}
@@ -83,8 +93,9 @@ class Pkcs11ChaCha20Poly1305Test
if (outputLen != 0) {
std::vector<uint8_t> bogusTag(output);
bogusTag[outputLen - 1] ^= 0xff;
rv = PK11_Decrypt(symKey, mech, &params, decrypted.data(), &decryptedLen,
decrypted.size(), bogusTag.data(), outputLen);
rv = PK11_Decrypt(key.get(), kMech, &params, decrypted.data(),
&decryptedLen, decrypted.size(), bogusTag.data(),
outputLen);
EXPECT_NE(rv, SECSuccess);
}
@@ -100,7 +111,7 @@ class Pkcs11ChaCha20Poly1305Test
bogusAeadParams.pNonce = toUcharPtr(bogusIV.data());
bogusIV[0] ^= 0xff;
rv = PK11_Decrypt(symKey, mech, &bogusParams, decrypted.data(),
rv = PK11_Decrypt(key.get(), kMech, &bogusParams, decrypted.data(),
&decryptedLen, data_len, output.data(), outputLen);
EXPECT_NE(rv, SECSuccess);
}
@@ -117,7 +128,7 @@ class Pkcs11ChaCha20Poly1305Test
bogusAeadParams.pAAD = toUcharPtr(bogusAAD.data());
bogusAAD[0] ^= 0xff;
rv = PK11_Decrypt(symKey, mech, &bogusParams, decrypted.data(),
rv = PK11_Decrypt(key.get(), kMech, &bogusParams, decrypted.data(),
&decryptedLen, data_len, output.data(), outputLen);
EXPECT_NE(rv, SECSuccess);
}
@@ -125,16 +136,16 @@ class Pkcs11ChaCha20Poly1305Test
void EncryptDecrypt(const chacha_testvector testvector) {
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
SECItem keyItem = {siBuffer, toUcharPtr(testvector.Key.data()),
static_cast<unsigned int>(testvector.Key.size())};
SECItem key_item = {siBuffer, toUcharPtr(testvector.Key.data()),
static_cast<unsigned int>(testvector.Key.size())};
// Import key.
ScopedPK11SymKey symKey(PK11_ImportSymKey(
slot.get(), mech, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, nullptr));
EXPECT_TRUE(!!symKey);
ScopedPK11SymKey key(PK11_ImportSymKey(slot.get(), kMech, PK11_OriginUnwrap,
CKA_ENCRYPT, &key_item, nullptr));
EXPECT_TRUE(!!key);
// Check.
EncryptDecrypt(symKey.get(), testvector.invalid_iv, testvector.invalid_tag,
EncryptDecrypt(key, testvector.invalid_iv, testvector.invalid_tag,
testvector.Data.data(), testvector.Data.size(),
testvector.AAD.data(), testvector.AAD.size(),
testvector.IV.data(), testvector.IV.size(),
@@ -142,14 +153,13 @@ class Pkcs11ChaCha20Poly1305Test
}
protected:
CK_MECHANISM_TYPE mech = CKM_NSS_CHACHA20_POLY1305;
};
TEST_F(Pkcs11ChaCha20Poly1305Test, GenerateEncryptDecrypt) {
// Generate a random key.
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ScopedPK11SymKey symKey(PK11_KeyGen(slot.get(), mech, nullptr, 32, nullptr));
EXPECT_TRUE(!!symKey);
ScopedPK11SymKey key(PK11_KeyGen(slot.get(), kMech, nullptr, 32, nullptr));
EXPECT_TRUE(!!key);
// Generate random data.
std::vector<uint8_t> data(512);
@@ -168,8 +178,85 @@ TEST_F(Pkcs11ChaCha20Poly1305Test, GenerateEncryptDecrypt) {
EXPECT_EQ(rv, SECSuccess);
// Check.
EncryptDecrypt(symKey.get(), false, false, data.data(), data.size(),
aad.data(), aad.size(), iv.data(), iv.size());
EncryptDecrypt(key, false, false, data.data(), data.size(), aad.data(),
aad.size(), iv.data(), iv.size());
}
TEST_F(Pkcs11ChaCha20Poly1305Test, Xor) {
static const uint8_t kExpected[sizeof(kData)] = {
0xd8, 0x15, 0xd3, 0xb3, 0xe9, 0x34, 0x3b, 0x7a,
0x24, 0xf6, 0x5f, 0xd7, 0x95, 0x3d, 0xd3, 0x51};
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
SECItem keyItem = {siBuffer, toUcharPtr(kKeyData),
static_cast<unsigned int>(sizeof(kKeyData))};
ScopedPK11SymKey key(PK11_ImportSymKey(
slot.get(), kMechXor, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, nullptr));
EXPECT_TRUE(!!key);
SECItem ctr_nonce_item = {siBuffer, toUcharPtr(kCtrNonce),
static_cast<unsigned int>(sizeof(kCtrNonce))};
uint8_t output[sizeof(kData)];
unsigned int output_len = 88; // This should be overwritten.
SECStatus rv =
PK11_Encrypt(key.get(), kMechXor, &ctr_nonce_item, output, &output_len,
sizeof(output), kData, sizeof(kData));
ASSERT_EQ(SECSuccess, rv);
ASSERT_EQ(sizeof(kExpected), static_cast<size_t>(output_len));
EXPECT_EQ(0, memcmp(kExpected, output, sizeof(kExpected)));
// Decrypting has the same effect.
rv = PK11_Decrypt(key.get(), kMechXor, &ctr_nonce_item, output, &output_len,
sizeof(output), kData, sizeof(kData));
ASSERT_EQ(SECSuccess, rv);
ASSERT_EQ(sizeof(kData), static_cast<size_t>(output_len));
EXPECT_EQ(0, memcmp(kExpected, output, sizeof(kExpected)));
// Operating in reverse too.
rv = PK11_Encrypt(key.get(), kMechXor, &ctr_nonce_item, output, &output_len,
sizeof(output), kExpected, sizeof(kExpected));
ASSERT_EQ(SECSuccess, rv);
ASSERT_EQ(sizeof(kExpected), static_cast<size_t>(output_len));
EXPECT_EQ(0, memcmp(kData, output, sizeof(kData)));
}
// This test just ensures that a key can be generated for use with the XOR
// function. The result is random and therefore cannot be checked.
TEST_F(Pkcs11ChaCha20Poly1305Test, GenerateXor) {
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ScopedPK11SymKey key(PK11_KeyGen(slot.get(), kMech, nullptr, 32, nullptr));
EXPECT_TRUE(!!key);
SECItem ctr_nonce_item = {siBuffer, toUcharPtr(kCtrNonce),
static_cast<unsigned int>(sizeof(kCtrNonce))};
uint8_t output[sizeof(kData)];
unsigned int output_len = 88; // This should be overwritten.
SECStatus rv =
PK11_Encrypt(key.get(), kMechXor, &ctr_nonce_item, output, &output_len,
sizeof(output), kData, sizeof(kData));
ASSERT_EQ(SECSuccess, rv);
ASSERT_EQ(sizeof(kData), static_cast<size_t>(output_len));
}
TEST_F(Pkcs11ChaCha20Poly1305Test, XorInvalidParams) {
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ScopedPK11SymKey key(PK11_KeyGen(slot.get(), kMech, nullptr, 32, nullptr));
EXPECT_TRUE(!!key);
SECItem ctr_nonce_item = {siBuffer, toUcharPtr(kCtrNonce),
static_cast<unsigned int>(sizeof(kCtrNonce)) - 1};
uint8_t output[sizeof(kData)];
unsigned int output_len = 88;
SECStatus rv =
PK11_Encrypt(key.get(), kMechXor, &ctr_nonce_item, output, &output_len,
sizeof(output), kData, sizeof(kData));
EXPECT_EQ(SECFailure, rv);
ctr_nonce_item.data = nullptr;
rv = PK11_Encrypt(key.get(), kMechXor, &ctr_nonce_item, output, &output_len,
sizeof(output), kData, sizeof(kData));
EXPECT_EQ(SECFailure, rv);
EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
}
TEST_P(Pkcs11ChaCha20Poly1305Test, TestVectors) { EncryptDecrypt(GetParam()); }
@@ -40,6 +40,9 @@ class Pkcs11Curve25519Test
ScopedCERTSubjectPublicKeyInfo certSpki(
SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiItem));
if (!expect_success && !certSpki) {
return;
}
ASSERT_TRUE(certSpki);
ScopedSECKEYPublicKey pubKey(SECKEY_ExtractPublicKey(certSpki.get()));
@@ -29,20 +29,20 @@
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/lib/util/util.gyp:nssutil3',
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
'<(DEPTH)/lib/util/util.gyp:nssutil3',
],
'conditions': [
[ 'test_build==1', {
[ 'static_libs==1', {
'dependencies': [
'<(DEPTH)/lib/base/base.gyp:nssb',
'<(DEPTH)/lib/certdb/certdb.gyp:certdb',
'<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
'<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
'<(DEPTH)/lib/dev/dev.gyp:nssdev',
'<(DEPTH)/lib/nss/nss.gyp:nss_static',
'<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
'<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
'<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
'<(DEPTH)/lib/certdb/certdb.gyp:certdb',
'<(DEPTH)/lib/base/base.gyp:nssb',
'<(DEPTH)/lib/dev/dev.gyp:nssdev',
'<(DEPTH)/lib/pki/pki.gyp:nsspki',
'<(DEPTH)/lib/ssl/ssl.gyp:ssl',
],
@@ -48,8 +48,15 @@ class Pk11KeyImportTestBase : public ::testing::Test {
ScopedSECKEYEncryptedPrivateKeyInfo key_info;
ScopedSECItem public_value;
GenerateAndExport(&key_type, &key_info, &public_value);
ASSERT_NE(nullptr, key_info);
ASSERT_NE(nullptr, public_value);
// Note: NSS is currently unable export wrapped DH keys, so this doesn't
// test
// CKM_DH_PKCS_KEY_PAIR_GEN beyond generate and verify
if (key_type == dhKey) {
return;
}
ASSERT_NE(nullptr, key_info);
// Now import the encrypted key.
static const uint8_t nick[] = "nick";
@@ -78,17 +85,41 @@ class Pk11KeyImportTestBase : public ::testing::Test {
CK_MECHANISM_TYPE mech_;
private:
SECItem GetPublicComponent(ScopedSECKEYPublicKey& pub_key) {
SECItem null = {siBuffer, NULL, 0};
switch (SECKEY_GetPublicKeyType(pub_key.get())) {
case rsaKey:
case rsaPssKey:
case rsaOaepKey:
return pub_key->u.rsa.modulus;
case keaKey:
return pub_key->u.kea.publicValue;
case dsaKey:
return pub_key->u.dsa.publicValue;
case dhKey:
return pub_key->u.dh.publicValue;
case ecKey:
return pub_key->u.ec.publicValue;
case fortezzaKey: /* depricated */
case nullKey:
/* didn't use default here so we can catch new key types at compile time
*/
break;
}
return null;
}
void CheckForPublicKey(const ScopedSECKEYPrivateKey& priv_key,
const SECItem* expected_public) {
// Verify the public key exists.
StackSECItem priv_id;
KeyType type = SECKEY_GetPrivateKeyType(priv_key.get());
SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, priv_key.get(),
CKA_ID, &priv_id);
ASSERT_EQ(SECSuccess, rv) << "Couldn't read CKA_ID from private key: "
<< PORT_ErrorToName(PORT_GetError());
CK_ATTRIBUTE_TYPE value_type = CKA_VALUE;
switch (SECKEY_GetPrivateKeyType(priv_key.get())) {
switch (type) {
case rsaKey:
value_type = CKA_MODULUS;
break;
@@ -106,6 +137,8 @@ class Pk11KeyImportTestBase : public ::testing::Test {
FAIL() << "unknown key type";
}
// Scan public key objects until we find one with the same CKA_ID as
// priv_key
std::unique_ptr<PK11GenericObject, PK11GenericObjectsDeleter> objs(
PK11_FindGenericObjects(slot_.get(), CKO_PUBLIC_KEY));
ASSERT_NE(nullptr, objs);
@@ -128,20 +161,44 @@ class Pk11KeyImportTestBase : public ::testing::Test {
ASSERT_EQ(1U, token.len);
ASSERT_NE(0, token.data[0]);
StackSECItem value;
rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, value_type, &value);
StackSECItem raw_value;
SECItem decoded_value;
rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, value_type, &raw_value);
ASSERT_EQ(SECSuccess, rv);
SECItem value = raw_value;
// Decode the EC_POINT and check the output against expected.
// CKA_EC_POINT isn't stable, see Bug 1520649.
ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
ASSERT_TRUE(arena);
if (value_type == CKA_EC_POINT) {
continue;
// If this fails due to the noted inconsistency, we may need to
// check the whole raw_value, or remove a leading UNCOMPRESSED_POINT tag
rv = SEC_QuickDERDecodeItem(arena.get(), &decoded_value,
SEC_ASN1_GET(SEC_OctetStringTemplate),
&raw_value);
ASSERT_EQ(SECSuccess, rv);
value = decoded_value;
}
ASSERT_TRUE(SECITEM_ItemsAreEqual(expected_public, &value))
<< "expected: "
<< DataBuffer(expected_public->data, expected_public->len)
<< std::endl
<< "actual: " << DataBuffer(value.data, value.len) << std::endl;
// Finally, convert the private to public and ensure it matches.
ScopedSECKEYPublicKey pub_key(SECKEY_ConvertToPublicKey(priv_key.get()));
ASSERT_TRUE(pub_key);
SECItem converted_public = GetPublicComponent(pub_key);
ASSERT_TRUE(converted_public.len != 0);
ASSERT_TRUE(SECITEM_ItemsAreEqual(expected_public, &converted_public))
<< "expected: "
<< DataBuffer(expected_public->data, expected_public->len)
<< std::endl
<< "actual: "
<< DataBuffer(converted_public.data, converted_public.len)
<< std::endl;
}
}
@@ -160,13 +217,6 @@ class Pk11KeyImportTestBase : public ::testing::Test {
ScopedSECKEYPublicKey pub_key(pub_tmp);
ASSERT_NE(nullptr, pub_key);
// Wrap and export the key.
ScopedSECKEYEncryptedPrivateKeyInfo epki(PK11_ExportEncryptedPrivKeyInfo(
slot_.get(), SEC_OID_AES_256_CBC, password_.get(), priv_key.get(), 1,
nullptr));
ASSERT_NE(nullptr, epki) << "PK11_ExportEncryptedPrivKeyInfo failed: "
<< PORT_ErrorToName(PORT_GetError());
// Save the public value, which we will need on import */
SECItem* pub_val;
KeyType t = SECKEY_GetPublicKeyType(pub_key.get());
@@ -190,8 +240,22 @@ class Pk11KeyImportTestBase : public ::testing::Test {
CheckForPublicKey(priv_key, pub_val);
*key_type = t;
key_info->swap(epki);
public_value->reset(SECITEM_DupItem(pub_val));
// Note: NSS is currently unable export wrapped DH keys, so this doesn't
// test
// CKM_DH_PKCS_KEY_PAIR_GEN beyond generate and verify
if (mech_ == CKM_DH_PKCS_KEY_PAIR_GEN) {
return;
}
// Wrap and export the key.
ScopedSECKEYEncryptedPrivateKeyInfo epki(PK11_ExportEncryptedPrivKeyInfo(
slot_.get(), SEC_OID_AES_256_CBC, password_.get(), priv_key.get(), 1,
nullptr));
ASSERT_NE(nullptr, epki) << "PK11_ExportEncryptedPrivKeyInfo failed: "
<< PORT_ErrorToName(PORT_GetError());
key_info->swap(epki);
}
ScopedPK11SlotInfo slot_;
@@ -281,9 +345,8 @@ TEST_P(Pk11KeyImportTest, GenerateExportImport) { Test(); }
INSTANTIATE_TEST_CASE_P(Pk11KeyImportTest, Pk11KeyImportTest,
::testing::Values(CKM_RSA_PKCS_KEY_PAIR_GEN,
CKM_DSA_KEY_PAIR_GEN));
// Note: NSS is currently unable export wrapped DH keys, so this doesn't test
// CKM_DH_PKCS_KEY_PAIR_GEN.
CKM_DSA_KEY_PAIR_GEN,
CKM_DH_PKCS_KEY_PAIR_GEN));
class Pk11KeyImportTestEC : public Pk11KeyImportTestBase,
public ::testing::WithParamInterface<SECOidTag> {
@@ -19,7 +19,7 @@
'<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
],
'conditions': [
[ 'test_build==1', {
[ 'static_libs==1', {
'dependencies': [
'<(DEPTH)/lib/nss/nss.gyp:nss_static',
'<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
+6
View File
@@ -36,6 +36,12 @@ CPPSRCS := $(filter-out $(shell grep -l '^TEST_F' $(CPPSRCS)), $(CPPSRCS))
CFLAGS += -DNSS_DISABLE_TLS_1_3
endif
ifdef NSS_ALLOW_SSLKEYLOGFILE
SSLKEYLOGFILE_FILES = ssl_keylog_unittest.cc
else
SSLKEYLOGFILE_FILES = $(NULL)
endif
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
+1 -1
View File
@@ -31,7 +31,6 @@ CPPSRCS = \
ssl_gather_unittest.cc \
ssl_gtest.cc \
ssl_hrr_unittest.cc \
ssl_keylog_unittest.cc \
ssl_keyupdate_unittest.cc \
ssl_loopback_unittest.cc \
ssl_misc_unittest.cc \
@@ -55,6 +54,7 @@ CPPSRCS = \
tls_filter.cc \
tls_protect.cc \
tls_esni_unittest.cc \
$(SSLKEYLOGFILE_FILES) \
$(NULL)
INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \
@@ -649,6 +649,227 @@ TEST_P(TlsConnectTls13, ZeroRttOrdering) {
EXPECT_EQ(2U, step);
}
// Early data remains available after the handshake completes for TLS.
TEST_F(TlsConnectStreamTls13, ZeroRttLateReadTls) {
SetupForZeroRtt();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
ExpectResumption(RESUME_TICKET);
client_->Handshake(); // ClientHello
// Write some early data.
const uint8_t data[] = {1, 2, 3, 4, 5, 6, 7, 8};
PRInt32 rv = PR_Write(client_->ssl_fd(), data, sizeof(data));
EXPECT_EQ(static_cast<PRInt32>(sizeof(data)), rv);
// Consume the ClientHello and generate ServerHello..Finished.
server_->Handshake();
// Read some of the data.
std::vector<uint8_t> small_buffer(1 + sizeof(data) / 2);
rv = PR_Read(server_->ssl_fd(), small_buffer.data(), small_buffer.size());
EXPECT_EQ(static_cast<PRInt32>(small_buffer.size()), rv);
EXPECT_EQ(0, memcmp(data, small_buffer.data(), small_buffer.size()));
Handshake(); // Complete the handshake.
ExpectEarlyDataAccepted(true);
CheckConnected();
// After the handshake, it should be possible to read the remainder.
uint8_t big_buf[100];
rv = PR_Read(server_->ssl_fd(), big_buf, sizeof(big_buf));
EXPECT_EQ(static_cast<PRInt32>(sizeof(data) - small_buffer.size()), rv);
EXPECT_EQ(0, memcmp(&data[small_buffer.size()], big_buf,
sizeof(data) - small_buffer.size()));
// And that's all there is to read.
rv = PR_Read(server_->ssl_fd(), big_buf, sizeof(big_buf));
EXPECT_GT(0, rv);
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
}
// Early data that arrives before the handshake can be read after the handshake
// is complete.
TEST_F(TlsConnectDatagram13, ZeroRttLateReadDtls) {
SetupForZeroRtt();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
ExpectResumption(RESUME_TICKET);
client_->Handshake(); // ClientHello
// Write some early data.
const uint8_t data[] = {1, 2, 3};
PRInt32 written = PR_Write(client_->ssl_fd(), data, sizeof(data));
EXPECT_EQ(static_cast<PRInt32>(sizeof(data)), written);
Handshake(); // Complete the handshake.
ExpectEarlyDataAccepted(true);
CheckConnected();
// Reading at the server should return the early data, which was buffered.
uint8_t buf[sizeof(data) + 1] = {0};
PRInt32 read = PR_Read(server_->ssl_fd(), buf, sizeof(buf));
EXPECT_EQ(static_cast<PRInt32>(sizeof(data)), read);
EXPECT_EQ(0, memcmp(data, buf, sizeof(data)));
}
class PacketHolder : public PacketFilter {
public:
PacketHolder() = default;
virtual Action Filter(const DataBuffer& input, DataBuffer* output) {
packet_ = input;
Disable();
return DROP;
}
const DataBuffer& packet() const { return packet_; }
private:
DataBuffer packet_;
};
// Early data that arrives late is discarded for DTLS.
TEST_F(TlsConnectDatagram13, ZeroRttLateArrivalDtls) {
SetupForZeroRtt();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
ExpectResumption(RESUME_TICKET);
client_->Handshake(); // ClientHello
// Write some early data. Twice, so that we can read bits of it.
const uint8_t data[] = {1, 2, 3};
PRInt32 written = PR_Write(client_->ssl_fd(), data, sizeof(data));
EXPECT_EQ(static_cast<PRInt32>(sizeof(data)), written);
// Block and capture the next packet.
auto holder = std::make_shared<PacketHolder>();
client_->SetFilter(holder);
written = PR_Write(client_->ssl_fd(), data, sizeof(data));
EXPECT_EQ(static_cast<PRInt32>(sizeof(data)), written);
EXPECT_FALSE(holder->enabled()) << "the filter should disable itself";
// Consume the ClientHello and generate ServerHello..Finished.
server_->Handshake();
// Read some of the data.
std::vector<uint8_t> small_buffer(sizeof(data));
PRInt32 read =
PR_Read(server_->ssl_fd(), small_buffer.data(), small_buffer.size());
EXPECT_EQ(static_cast<PRInt32>(small_buffer.size()), read);
EXPECT_EQ(0, memcmp(data, small_buffer.data(), small_buffer.size()));
Handshake(); // Complete the handshake.
ExpectEarlyDataAccepted(true);
CheckConnected();
server_->SendDirect(holder->packet());
// Reading now should return nothing, even though a valid packet was
// delivered.
read = PR_Read(server_->ssl_fd(), small_buffer.data(), small_buffer.size());
EXPECT_GT(0, read);
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
}
// Early data reads in TLS should be coalesced.
TEST_F(TlsConnectStreamTls13, ZeroRttCoalesceReadTls) {
SetupForZeroRtt();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
ExpectResumption(RESUME_TICKET);
client_->Handshake(); // ClientHello
// Write some early data. In two writes.
const uint8_t data[] = {1, 2, 3, 4, 5, 6};
PRInt32 written = PR_Write(client_->ssl_fd(), data, 1);
EXPECT_EQ(1, written);
written = PR_Write(client_->ssl_fd(), data + 1, sizeof(data) - 1);
EXPECT_EQ(static_cast<PRInt32>(sizeof(data) - 1), written);
// Consume the ClientHello and generate ServerHello..Finished.
server_->Handshake();
// Read all of the data.
std::vector<uint8_t> buffer(sizeof(data));
PRInt32 read = PR_Read(server_->ssl_fd(), buffer.data(), buffer.size());
EXPECT_EQ(static_cast<PRInt32>(sizeof(data)), read);
EXPECT_EQ(0, memcmp(data, buffer.data(), sizeof(data)));
Handshake(); // Complete the handshake.
ExpectEarlyDataAccepted(true);
CheckConnected();
}
// Early data reads in DTLS should not be coalesced.
TEST_F(TlsConnectDatagram13, ZeroRttNoCoalesceReadDtls) {
SetupForZeroRtt();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
ExpectResumption(RESUME_TICKET);
client_->Handshake(); // ClientHello
// Write some early data. In two writes.
const uint8_t data[] = {1, 2, 3, 4, 5, 6};
PRInt32 written = PR_Write(client_->ssl_fd(), data, 1);
EXPECT_EQ(1, written);
written = PR_Write(client_->ssl_fd(), data + 1, sizeof(data) - 1);
EXPECT_EQ(static_cast<PRInt32>(sizeof(data) - 1), written);
// Consume the ClientHello and generate ServerHello..Finished.
server_->Handshake();
// Try to read all of the data.
std::vector<uint8_t> buffer(sizeof(data));
PRInt32 read = PR_Read(server_->ssl_fd(), buffer.data(), buffer.size());
EXPECT_EQ(1, read);
EXPECT_EQ(0, memcmp(data, buffer.data(), 1));
// Read the remainder.
read = PR_Read(server_->ssl_fd(), buffer.data(), buffer.size());
EXPECT_EQ(static_cast<PRInt32>(sizeof(data) - 1), read);
EXPECT_EQ(0, memcmp(data + 1, buffer.data(), sizeof(data) - 1));
Handshake(); // Complete the handshake.
ExpectEarlyDataAccepted(true);
CheckConnected();
}
// Early data reads in DTLS should fail if the buffer is too small.
TEST_F(TlsConnectDatagram13, ZeroRttShortReadDtls) {
SetupForZeroRtt();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
ExpectResumption(RESUME_TICKET);
client_->Handshake(); // ClientHello
// Write some early data. In two writes.
const uint8_t data[] = {1, 2, 3, 4, 5, 6};
PRInt32 written = PR_Write(client_->ssl_fd(), data, sizeof(data));
EXPECT_EQ(static_cast<PRInt32>(sizeof(data)), written);
// Consume the ClientHello and generate ServerHello..Finished.
server_->Handshake();
// Try to read all of the data into a small buffer.
std::vector<uint8_t> buffer(sizeof(data));
PRInt32 read = PR_Read(server_->ssl_fd(), buffer.data(), 1);
EXPECT_GT(0, read);
EXPECT_EQ(SSL_ERROR_RX_SHORT_DTLS_READ, PORT_GetError());
// Read again with more space.
read = PR_Read(server_->ssl_fd(), buffer.data(), buffer.size());
EXPECT_EQ(static_cast<PRInt32>(sizeof(data)), read);
EXPECT_EQ(0, memcmp(data, buffer.data(), sizeof(data)));
Handshake(); // Complete the handshake.
ExpectEarlyDataAccepted(true);
CheckConnected();
}
#ifndef NSS_DISABLE_TLS_1_3
INSTANTIATE_TEST_CASE_P(Tls13ZeroRttReplayTest, TlsZeroRttReplayTest,
TlsConnectTestBase::kTlsVariantsAll);
@@ -320,6 +320,46 @@ TEST_F(TlsConnectStreamTls13, PostHandshakeAuthConcurrent) {
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
}
TEST_F(TlsConnectStreamTls13, PostHandshakeAuthBeforeKeyUpdate) {
client_->SetupClientAuth();
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE));
Connect();
// Send CertificateRequest.
EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
<< "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
// Send KeyUpdate.
EXPECT_EQ(SECFailure, SSL_KeyUpdate(server_->ssl_fd(), PR_TRUE));
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
}
TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDuringClientKeyUpdate) {
client_->SetupClientAuth();
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE));
Connect();
CheckEpochs(3, 3);
// Send CertificateRequest from server.
EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
<< "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
// Send KeyUpdate from client.
EXPECT_EQ(SECSuccess, SSL_KeyUpdate(client_->ssl_fd(), PR_TRUE));
server_->SendData(50); // server sends CertificateRequest
client_->SendData(50); // client sends KeyUpdate
server_->ReadBytes(50); // server receives KeyUpdate and defers response
CheckEpochs(4, 3);
client_->ReadBytes(50); // client receives CertificateRequest
client_->SendData(
50); // client sends Certificate, CertificateVerify, Finished
server_->ReadBytes(
50); // server receives Certificate, CertificateVerify, Finished
client_->CheckEpochs(3, 4);
server_->CheckEpochs(4, 4);
server_->SendData(50); // server sends KeyUpdate
client_->ReadBytes(50); // client receives KeyUpdate
client_->CheckEpochs(4, 4);
}
TEST_F(TlsConnectStreamTls13, PostHandshakeAuthMissingExtension) {
client_->SetupClientAuth();
Connect();
@@ -454,6 +494,9 @@ TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDecline) {
client_->SetupClientAuth();
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE));
EXPECT_EQ(SECSuccess,
SSL_OptionSet(server_->ssl_fd(), SSL_REQUIRE_CERTIFICATE,
SSL_REQUIRE_ALWAYS));
// Client to decline the certificate request.
EXPECT_EQ(SECSuccess,
SSL_GetClientAuthDataHook(
@@ -472,10 +515,13 @@ TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDecline) {
// Send CertificateRequest.
EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
<< "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
server_->SendData(50);
client_->ReadBytes(50);
client_->SendData(50);
server_->ReadBytes(50);
server_->SendData(50); // send Certificate Request
client_->ReadBytes(50); // read Certificate Request
client_->SendData(50); // send empty Certificate+Finished
server_->ExpectSendAlert(kTlsAlertCertificateRequired);
server_->ReadBytes(50); // read empty Certificate+Finished
server_->ExpectReadWriteError();
server_->SendData(50); // send alert
// AuthCertificateCallback is not called, because the client sends
// an empty certificate_list.
EXPECT_EQ(0U, called);
@@ -655,6 +701,44 @@ TEST_P(TlsConnectTls12, ClientAuthInconsistentPssSignatureScheme) {
ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
}
TEST_P(TlsConnectTls13, ClientAuthPkcs1SignatureScheme) {
static const SSLSignatureScheme kSignatureScheme[] = {
ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pss_rsae_sha256};
Reset(TlsAgent::kServerRsa, "rsa");
client_->SetSignatureSchemes(kSignatureScheme,
PR_ARRAY_SIZE(kSignatureScheme));
server_->SetSignatureSchemes(kSignatureScheme,
PR_ARRAY_SIZE(kSignatureScheme));
client_->SetupClientAuth();
server_->RequestClientAuth(true);
auto capture_cert_verify = MakeTlsFilter<TlsHandshakeRecorder>(
client_, kTlsHandshakeCertificateVerify);
capture_cert_verify->EnableDecryption();
Connect();
CheckSigScheme(capture_cert_verify, 0, server_, ssl_sig_rsa_pss_rsae_sha256,
1024);
}
TEST_P(TlsConnectTls13, ClientAuthPkcs1SignatureSchemeOnly) {
static const SSLSignatureScheme kSignatureScheme[] = {
ssl_sig_rsa_pkcs1_sha256};
Reset(TlsAgent::kServerRsa, "rsa");
client_->SetSignatureSchemes(kSignatureScheme,
PR_ARRAY_SIZE(kSignatureScheme));
server_->SetSignatureSchemes(kSignatureScheme,
PR_ARRAY_SIZE(kSignatureScheme));
client_->SetupClientAuth();
server_->RequestClientAuth(true);
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
}
class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter {
public:
TlsZeroCertificateRequestSigAlgsFilter(const std::shared_ptr<TlsAgent>& a)
@@ -887,7 +971,7 @@ TEST_P(TlsConnectTls13, InconsistentSignatureSchemeAlert) {
client_->CheckErrorCode(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
}
TEST_P(TlsConnectTls12Plus, RequestClientAuthWithSha384) {
TEST_P(TlsConnectTls12, RequestClientAuthWithSha384) {
server_->SetSignatureSchemes(kSignatureSchemeRsaSha384,
PR_ARRAY_SIZE(kSignatureSchemeRsaSha384));
server_->RequestClientAuth(false);
@@ -1349,12 +1433,21 @@ TEST_P(TlsSignatureSchemeConfiguration, SignatureSchemeConfigBoth) {
INSTANTIATE_TEST_CASE_P(
SignatureSchemeRsa, TlsSignatureSchemeConfiguration,
::testing::Combine(
TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV12Plus,
TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV12,
::testing::Values(TlsAgent::kServerRsaSign),
::testing::Values(ssl_auth_rsa_sign),
::testing::Values(ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pkcs1_sha384,
ssl_sig_rsa_pkcs1_sha512, ssl_sig_rsa_pss_rsae_sha256,
ssl_sig_rsa_pss_rsae_sha384)));
// RSASSA-PKCS1-v1_5 is not allowed to be used in TLS 1.3
INSTANTIATE_TEST_CASE_P(
SignatureSchemeRsaTls13, TlsSignatureSchemeConfiguration,
::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
TlsConnectTestBase::kTlsV13,
::testing::Values(TlsAgent::kServerRsaSign),
::testing::Values(ssl_auth_rsa_sign),
::testing::Values(ssl_sig_rsa_pss_rsae_sha256,
ssl_sig_rsa_pss_rsae_sha384)));
// PSS with SHA-512 needs a bigger key to work.
INSTANTIATE_TEST_CASE_P(
SignatureSchemeBigRsa, TlsSignatureSchemeConfiguration,
@@ -68,12 +68,6 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase {
virtual void SetupCertificate() {
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
switch (sig_scheme_) {
case ssl_sig_rsa_pkcs1_sha256:
case ssl_sig_rsa_pkcs1_sha384:
case ssl_sig_rsa_pkcs1_sha512:
Reset(TlsAgent::kServerRsaSign);
auth_type_ = ssl_auth_rsa_sign;
break;
case ssl_sig_rsa_pss_rsae_sha256:
case ssl_sig_rsa_pss_rsae_sha384:
Reset(TlsAgent::kServerRsaSign);
@@ -330,6 +324,12 @@ static SSLSignatureScheme kSignatureSchemesParamsArr[] = {
ssl_sig_rsa_pss_pss_sha256, ssl_sig_rsa_pss_pss_sha384,
ssl_sig_rsa_pss_pss_sha512};
static SSLSignatureScheme kSignatureSchemesParamsArrTls13[] = {
ssl_sig_ecdsa_secp256r1_sha256, ssl_sig_ecdsa_secp384r1_sha384,
ssl_sig_rsa_pss_rsae_sha256, ssl_sig_rsa_pss_rsae_sha384,
ssl_sig_rsa_pss_rsae_sha512, ssl_sig_rsa_pss_pss_sha256,
ssl_sig_rsa_pss_pss_sha384, ssl_sig_rsa_pss_pss_sha512};
INSTANTIATE_CIPHER_TEST_P(RC4, Stream, V10ToV12, kDummyNamedGroupParams,
kDummySignatureSchemesParams,
TLS_RSA_WITH_RC4_128_SHA,
@@ -394,7 +394,7 @@ INSTANTIATE_CIPHER_TEST_P(
#ifndef NSS_DISABLE_TLS_1_3
INSTANTIATE_CIPHER_TEST_P(TLS13, All, V13,
::testing::ValuesIn(kFasterDHEGroups),
::testing::ValuesIn(kSignatureSchemesParamsArr),
::testing::ValuesIn(kSignatureSchemesParamsArrTls13),
TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256,
TLS_AES_256_GCM_SHA384);
INSTANTIATE_CIPHER_TEST_P(TLS13AllGroups, All, V13,
@@ -1,53 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <cstdlib>
#include <fstream>
#include <sstream>
#include "gtest_utils.h"
#include "tls_connect.h"
namespace nss_test {
extern "C" {
extern FILE* ssl_trace_iob;
#ifdef NSS_ALLOW_SSLKEYLOGFILE
extern FILE* ssl_keylog_iob;
#endif
}
// These tests ensure that when the associated environment variables are unset
// that the lazily-initialized defaults are what they are supposed to be.
#ifdef DEBUG
TEST_P(TlsConnectGeneric, DebugEnvTraceFileNotSet) {
char* ev = PR_GetEnvSecure("SSLDEBUGFILE");
if (ev && ev[0]) {
// note: should use GTEST_SKIP when GTest gets updated to support it
return;
}
Connect();
EXPECT_EQ(stderr, ssl_trace_iob);
}
#endif
#ifdef NSS_ALLOW_SSLKEYLOGFILE
TEST_P(TlsConnectGeneric, DebugEnvKeylogFileNotSet) {
char* ev = PR_GetEnvSecure("SSLKEYLOGFILE");
if (ev && ev[0]) {
// note: should use GTEST_SKIP when GTest gets updated to support it
return;
}
Connect();
EXPECT_EQ(nullptr, ssl_keylog_iob);
}
#endif
} // namespace nss_test
@@ -436,14 +436,14 @@ TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsOddLength) {
}
TEST_F(TlsExtensionTest13Stream, SignatureAlgorithmsPrecedingGarbage) {
// 31 unknown signature algorithms followed by sha-256, rsa
// 31 unknown signature algorithms followed by sha-256, rsa-pss
const uint8_t val[] = {
0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0x01};
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x04};
DataBuffer extension(val, sizeof(val));
MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_signature_algorithms_xtn,
extension);
@@ -482,6 +482,73 @@ TEST_P(TlsExtensionTestGeneric, SupportedCurvesTrailingData) {
client_, ssl_elliptic_curves_xtn, extension));
}
TEST_P(TlsExtensionTest12, SupportedCurvesDisableX25519) {
// Disable session resumption.
ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
// Ensure that we can enable its use in the key exchange.
SECStatus rv =
NSS_SetAlgorithmPolicy(SEC_OID_CURVE25519, NSS_USE_ALG_IN_SSL_KX, 0);
ASSERT_EQ(SECSuccess, rv);
rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL,
0);
ASSERT_EQ(SECSuccess, rv);
auto capture1 =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_elliptic_curves_xtn);
Connect();
EXPECT_TRUE(capture1->captured());
const DataBuffer& ext1 = capture1->extension();
uint32_t count;
ASSERT_TRUE(ext1.Read(0, 2, &count));
// Whether or not we've seen x25519 offered in this handshake.
bool seen1_x25519 = false;
for (size_t offset = 2; offset <= count; offset++) {
uint32_t val;
ASSERT_TRUE(ext1.Read(offset, 2, &val));
if (val == ssl_grp_ec_curve25519) {
seen1_x25519 = true;
break;
}
}
ASSERT_TRUE(seen1_x25519);
// Ensure that we can disable its use in the key exchange.
rv = NSS_SetAlgorithmPolicy(SEC_OID_CURVE25519, 0, NSS_USE_ALG_IN_SSL_KX);
ASSERT_EQ(SECSuccess, rv);
rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL,
0);
ASSERT_EQ(SECSuccess, rv);
// Clean up after the last run.
Reset();
auto capture2 =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_elliptic_curves_xtn);
Connect();
EXPECT_TRUE(capture2->captured());
const DataBuffer& ext2 = capture2->extension();
ASSERT_TRUE(ext2.Read(0, 2, &count));
// Whether or not we've seen x25519 offered in this handshake.
bool seen2_x25519 = false;
for (size_t offset = 2; offset <= count; offset++) {
uint32_t val;
ASSERT_TRUE(ext2.Read(offset, 2, &val));
if (val == ssl_grp_ec_curve25519) {
seen2_x25519 = true;
break;
}
}
ASSERT_FALSE(seen2_x25519);
}
TEST_P(TlsExtensionTestPre13, SupportedPointsEmpty) {
const uint8_t val[] = {0x00};
DataBuffer extension(val, sizeof(val));
+9 -2
View File
@@ -32,7 +32,6 @@
'ssl_gather_unittest.cc',
'ssl_gtest.cc',
'ssl_hrr_unittest.cc',
'ssl_keylog_unittest.cc',
'ssl_keyupdate_unittest.cc',
'ssl_loopback_unittest.cc',
'ssl_misc_unittest.cc',
@@ -76,7 +75,7 @@
'<(DEPTH)/lib/libpkix/libpkix.gyp:libpkix',
],
'conditions': [
[ 'test_build==1', {
[ 'static_libs==1', {
'dependencies': [
'<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
],
@@ -93,6 +92,14 @@
'<(DEPTH)/lib/dbm/src/src.gyp:dbm',
],
}],
[ 'enable_sslkeylogfile==1 and sanitizer_flags==0', {
'sources': [
'ssl_keylog_unittest.cc',
],
'defines': [
'NSS_ALLOW_SSLKEYLOGFILE',
],
}],
],
}
],
@@ -4,8 +4,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef NSS_ALLOW_SSLKEYLOGFILE
#include <cstdlib>
#include <fstream>
#include <sstream>
@@ -114,5 +112,3 @@ INSTANTIATE_TEST_CASE_P(
#endif
} // namespace nss_test
#endif // NSS_ALLOW_SSLKEYLOGFILE
@@ -52,6 +52,7 @@ class AeadTest : public ::testing::Test {
static const size_t kMaxSize = 32;
ASSERT_GE(kMaxSize, ciphertext_len);
ASSERT_LT(0U, ciphertext_len);
uint8_t output[kMaxSize];
unsigned int output_len = 0;
@@ -191,7 +192,7 @@ TEST_F(AeadTest, AeadAes128Gcm) {
}
TEST_F(AeadTest, AeadAes256Gcm) {
SSLAeadContext *ctxInit;
SSLAeadContext *ctxInit = nullptr;
ASSERT_EQ(SECSuccess,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_256_GCM_SHA384,
secret_.get(), kLabel, strlen(kLabel), &ctxInit));
@@ -176,6 +176,7 @@ class BadPrSocket : public DummyIOLayerMethods {
// NSPR method vtable with the ones from this object.
dummy_layer_ =
PR_GetIdentitiesLayer(agent->ssl_fd(), DummyPrSocket::LayerId());
EXPECT_TRUE(dummy_layer_);
original_methods_ = dummy_layer_->methods;
original_secret_ = dummy_layer_->secret;
dummy_layer_->methods = fd_->methods;
@@ -442,6 +443,48 @@ TEST_P(TlsConnectStream, ReplaceRecordLayerAsyncLateAuth) {
SendForwardReceive(client_, client_stage, server_);
}
TEST_F(TlsConnectStreamTls13, ReplaceRecordLayerAsyncPostHandshake) {
StartConnect();
client_->SetServerKeyBits(server_->server_key_bits());
BadPrSocket bad_layer_client(client_);
BadPrSocket bad_layer_server(server_);
StagedRecords client_stage(client_);
StagedRecords server_stage(server_);
client_->SetAuthCertificateCallback(AuthCompleteBlock);
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING);
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING);
ASSERT_TRUE(client_stage.empty());
client_->Handshake();
ASSERT_TRUE(client_stage.empty());
EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state());
// Now declare the certificate good.
EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
client_->Handshake();
ASSERT_FALSE(client_stage.empty());
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state());
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
} else {
client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED);
server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED);
}
CheckKeys();
// Reading and writing application data should work.
SendForwardReceive(client_, client_stage, server_);
// Post-handshake messages should work here.
EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), nullptr, 0));
SendForwardReceive(server_, server_stage, client_);
}
// This test ensures that data is correctly forwarded when the handshake is
// resumed after asynchronous server certificate authentication, when
// SSL_AuthCertificateComplete() is called. The logic for resuming the
+3 -1
View File
@@ -33,9 +33,11 @@ class PacketFilter {
CHANGE, // change the packet to a different value
DROP // drop the packet
};
PacketFilter(bool enabled = true) : enabled_(enabled) {}
explicit PacketFilter(bool on = true) : enabled_(on) {}
virtual ~PacketFilter() {}
bool enabled() const { return enabled_; }
virtual Action Process(const DataBuffer& input, DataBuffer* output) {
if (!enabled_) {
return KEEP;
@@ -250,6 +250,7 @@ void TlsConnectTestBase::Reset(const std::string& server_name,
server_->SkipVersionChecks();
}
std::cerr << "Reset" << std::endl;
Init();
}
+2 -1
View File
@@ -156,7 +156,8 @@ class TlsConnectTestBase : public ::testing::Test {
// around test cases. In particular, DSA is checked in
// ssl_extension_unittest.cc.
const std::vector<SECOidTag> algorithms_ = {SEC_OID_APPLY_SSL_POLICY,
SEC_OID_ANSIX9_DSA_SIGNATURE};
SEC_OID_ANSIX9_DSA_SIGNATURE,
SEC_OID_CURVE25519};
std::vector<std::tuple<SECOidTag, uint32_t>> saved_policies_;
private:
@@ -70,7 +70,7 @@ static void GenerateEsniKey(time_t windowStart, SSLNamedGroup group,
ASSERT_NE(nullptr, priv);
SECITEM_FreeItem(&ecParams, PR_FALSE);
PRUint8 encoded[1024];
unsigned int encoded_len;
unsigned int encoded_len = 0;
SECStatus rv = SSL_EncodeESNIKeys(
&cipher_suites[0], cipher_suites.size(), group, pub, 100, windowStart,
@@ -375,11 +375,13 @@ TEST_P(TlsConnectTls13, ConnectEsniCSMismatch) {
GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record,
&pub, &priv);
PRUint8 encoded[1024];
unsigned int encoded_len;
unsigned int encoded_len = 0;
SECStatus rv = SSL_EncodeESNIKeys(
&kChaChaSuite[0], kChaChaSuite.size(), ssl_grp_ec_curve25519, pub.get(),
100, time(0), time(0) + 10, encoded, &encoded_len, sizeof(encoded));
ASSERT_EQ(SECSuccess, rv);
ASSERT_LT(0U, encoded_len);
rv = SSL_SetESNIKeyPair(server_->ssl_fd(), priv.get(), encoded, encoded_len);
ASSERT_EQ(SECSuccess, rv);
rv = SSL_EnableESNI(client_->ssl_fd(), record.data(), record.len(), "");
+2 -2
View File
@@ -549,9 +549,9 @@ class SelectiveDropFilter : public PacketFilter {
class SelectiveRecordDropFilter : public TlsRecordFilter {
public:
SelectiveRecordDropFilter(const std::shared_ptr<TlsAgent>& a,
uint32_t pattern, bool enabled = true)
uint32_t pattern, bool on = true)
: TlsRecordFilter(a), pattern_(pattern), counter_(0) {
if (!enabled) {
if (!on) {
Disable();
}
}
+3
View File
@@ -40,6 +40,7 @@ NSS build tool options:
(requires the gold linker, use clang-3.8 for SAW)
--no-zdefs don't set -Wl,-z,defs
--test ignore map files and export everything we have
--static create static libraries and use static linking
--ct-verif build with valgrind for ct-verif
--nspr force a rebuild of NSPR
--with-nspr use the NSPR build at the given locations
@@ -51,4 +52,6 @@ NSS build tool options:
--enable-libpkix make libpkix part of the build
--mozpkix-only build only static mozpkix and mozpkix-test libraries
support for this build option is limited
--disable-keylog disable support for logging key data to a file specified
by the SSLKEYLOGFILE environment variable
-D<gyp-option> pass an option directly to gyp
+6
View File
@@ -215,6 +215,12 @@ extern void CERT_DestroyCertificate(CERTCertificate *cert);
*/
extern CERTCertificate *CERT_DupCertificate(CERTCertificate *c);
/* Access the DER of the certificate. This only creates a reference to the DER
* in the outparam not a copy. To avoid the pointer becoming invalid, use
* CERT_DupCertificate() and keep a reference to the duplicate alive.
*/
extern SECStatus CERT_GetCertificateDer(const CERTCertificate *c, SECItem *der);
/*
** Create a new certificate request. This result must be wrapped with an
** CERTSignedData to create a signed certificate request.
+57 -87
View File
@@ -447,71 +447,39 @@ cert_GetCertType(CERTCertificate *cert)
}
PRBool
cert_EKUAllowsIPsecIKE(CERTCertificate *cert, PRBool *isCritical)
cert_IsIPsecOID(CERTOidSequence *extKeyUsage)
{
SECStatus rv;
SECItem encodedExtKeyUsage;
CERTOidSequence *extKeyUsage = NULL;
PRBool result = PR_FALSE;
rv = CERT_GetExtenCriticality(cert->extensions,
SEC_OID_X509_EXT_KEY_USAGE,
isCritical);
if (rv != SECSuccess) {
*isCritical = PR_FALSE;
if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_EXT_KEY_USAGE_IPSEC_IKE) == SECSuccess) {
return PR_TRUE;
}
encodedExtKeyUsage.data = NULL;
rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE,
&encodedExtKeyUsage);
if (rv != SECSuccess) {
/* EKU not present, allowed. */
result = PR_TRUE;
goto done;
if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_IPSEC_IKE_END) == SECSuccess) {
return PR_TRUE;
}
extKeyUsage = CERT_DecodeOidSequence(&encodedExtKeyUsage);
if (!extKeyUsage) {
/* failure */
goto done;
if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_IPSEC_IKE_INTERMEDIATE) == SECSuccess) {
return PR_TRUE;
}
if (findOIDinOIDSeqByTagNum(extKeyUsage,
SEC_OID_X509_ANY_EXT_KEY_USAGE) ==
SECSuccess) {
result = PR_TRUE;
goto done;
/* these are now deprecated, but may show up. Treat them the same as IKE */
if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_EXT_KEY_USAGE_IPSEC_END) == SECSuccess) {
return PR_TRUE;
}
if (findOIDinOIDSeqByTagNum(extKeyUsage,
SEC_OID_EXT_KEY_USAGE_IPSEC_IKE) ==
SECSuccess) {
result = PR_TRUE;
goto done;
if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_EXT_KEY_USAGE_IPSEC_TUNNEL) == SECSuccess) {
return PR_TRUE;
}
if (findOIDinOIDSeqByTagNum(extKeyUsage,
SEC_OID_IPSEC_IKE_END) ==
SECSuccess) {
result = PR_TRUE;
goto done;
if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_EXT_KEY_USAGE_IPSEC_USER) == SECSuccess) {
return PR_TRUE;
}
if (findOIDinOIDSeqByTagNum(extKeyUsage,
SEC_OID_IPSEC_IKE_INTERMEDIATE) ==
SECSuccess) {
result = PR_TRUE;
goto done;
/* this one should probably be in cert_ComputeCertType and set all usages? */
if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_X509_ANY_EXT_KEY_USAGE) == SECSuccess) {
return PR_TRUE;
}
done:
if (encodedExtKeyUsage.data != NULL) {
PORT_Free(encodedExtKeyUsage.data);
}
if (extKeyUsage != NULL) {
CERT_DestroyOidSequence(extKeyUsage);
}
return result;
return PR_FALSE;
}
PRUint32
@@ -521,9 +489,9 @@ cert_ComputeCertType(CERTCertificate *cert)
SECItem tmpitem;
SECItem encodedExtKeyUsage;
CERTOidSequence *extKeyUsage = NULL;
PRBool basicConstraintPresent = PR_FALSE;
CERTBasicConstraints basicConstraint;
PRUint32 nsCertType = 0;
PRBool isCA = PR_FALSE;
tmpitem.data = NULL;
CERT_FindNSCertTypeExtension(cert, &tmpitem);
@@ -535,7 +503,7 @@ cert_ComputeCertType(CERTCertificate *cert)
}
rv = CERT_FindBasicConstraintExten(cert, &basicConstraint);
if (rv == SECSuccess) {
basicConstraintPresent = PR_TRUE;
isCA = basicConstraint.isCA;
}
if (tmpitem.data != NULL || extKeyUsage != NULL) {
if (tmpitem.data == NULL) {
@@ -571,19 +539,11 @@ cert_ComputeCertType(CERTCertificate *cert)
if (findOIDinOIDSeqByTagNum(extKeyUsage,
SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT) ==
SECSuccess) {
if (basicConstraintPresent == PR_TRUE && (basicConstraint.isCA)) {
nsCertType |= NS_CERT_TYPE_EMAIL_CA;
} else {
nsCertType |= NS_CERT_TYPE_EMAIL;
}
nsCertType |= isCA ? NS_CERT_TYPE_EMAIL_CA : NS_CERT_TYPE_EMAIL;
}
if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH) == SECSuccess) {
if (basicConstraintPresent == PR_TRUE && (basicConstraint.isCA)) {
nsCertType |= NS_CERT_TYPE_SSL_CA;
} else {
nsCertType |= NS_CERT_TYPE_SSL_SERVER;
}
nsCertType |= isCA ? NS_CERT_TYPE_SSL_CA : NS_CERT_TYPE_SSL_SERVER;
}
/*
* Treat certs with step-up OID as also having SSL server type.
@@ -592,27 +552,18 @@ cert_ComputeCertType(CERTCertificate *cert)
if (findOIDinOIDSeqByTagNum(extKeyUsage,
SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) ==
SECSuccess) {
if (basicConstraintPresent == PR_TRUE && (basicConstraint.isCA)) {
nsCertType |= NS_CERT_TYPE_SSL_CA;
} else {
nsCertType |= NS_CERT_TYPE_SSL_SERVER;
}
nsCertType |= isCA ? NS_CERT_TYPE_SSL_CA : NS_CERT_TYPE_SSL_SERVER;
}
if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH) == SECSuccess) {
if (basicConstraintPresent == PR_TRUE && (basicConstraint.isCA)) {
nsCertType |= NS_CERT_TYPE_SSL_CA;
} else {
nsCertType |= NS_CERT_TYPE_SSL_CLIENT;
}
nsCertType |= isCA ? NS_CERT_TYPE_SSL_CA : NS_CERT_TYPE_SSL_CLIENT;
}
if (cert_IsIPsecOID(extKeyUsage)) {
nsCertType |= isCA ? NS_CERT_TYPE_IPSEC_CA : NS_CERT_TYPE_IPSEC;
}
if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_EXT_KEY_USAGE_CODE_SIGN) == SECSuccess) {
if (basicConstraintPresent == PR_TRUE && (basicConstraint.isCA)) {
nsCertType |= NS_CERT_TYPE_OBJECT_SIGNING_CA;
} else {
nsCertType |= NS_CERT_TYPE_OBJECT_SIGNING;
}
nsCertType |= isCA ? NS_CERT_TYPE_OBJECT_SIGNING_CA : NS_CERT_TYPE_OBJECT_SIGNING;
}
if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_EXT_KEY_USAGE_TIME_STAMP) == SECSuccess) {
@@ -629,7 +580,7 @@ cert_ComputeCertType(CERTCertificate *cert)
nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER;
/* if the basic constraint extension says the cert is a CA, then
allow SSL CA and EMAIL CA and Status Responder */
if (basicConstraintPresent && basicConstraint.isCA) {
if (isCA) {
nsCertType |= (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA |
EXT_KEY_USAGE_STATUS_RESPONDER);
}
@@ -638,6 +589,14 @@ cert_ComputeCertType(CERTCertificate *cert)
NS_CERT_TYPE_EMAIL;
}
/* IPSEC is allowed to use SSL client and server certs as well as email certs */
if (nsCertType & (NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_SSL_SERVER | NS_CERT_TYPE_EMAIL)) {
nsCertType |= NS_CERT_TYPE_IPSEC;
}
if (nsCertType & (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA)) {
nsCertType |= NS_CERT_TYPE_IPSEC_CA;
}
if (encodedExtKeyUsage.data != NULL) {
PORT_Free(encodedExtKeyUsage.data);
}
@@ -1153,7 +1112,7 @@ CERT_KeyUsageAndTypeForCertUsage(SECCertUsage usage, PRBool ca,
break;
case certUsageIPsec:
requiredKeyUsage = KU_KEY_CERT_SIGN;
requiredCertType = NS_CERT_TYPE_SSL_CA;
requiredCertType = NS_CERT_TYPE_IPSEC_CA;
break;
case certUsageSSLCA:
requiredKeyUsage = KU_KEY_CERT_SIGN;
@@ -1200,7 +1159,7 @@ CERT_KeyUsageAndTypeForCertUsage(SECCertUsage usage, PRBool ca,
case certUsageIPsec:
/* RFC 4945 Section 5.1.3.2 */
requiredKeyUsage = KU_DIGITAL_SIGNATURE_OR_NON_REPUDIATION;
requiredCertType = 0;
requiredCertType = NS_CERT_TYPE_IPSEC;
break;
case certUsageSSLServerWithStepUp:
requiredKeyUsage =
@@ -1314,6 +1273,17 @@ CERT_DupCertificate(CERTCertificate *c)
return c;
}
SECStatus
CERT_GetCertificateDer(const CERTCertificate *c, SECItem *der)
{
if (!c || !der) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
*der = c->derCert;
return SECSuccess;
}
/*
* Allow use of default cert database, so that apps(such as mozilla) don't
* have to pass the handle all over the place.
+18 -4
View File
@@ -416,6 +416,19 @@ struct CERTDistNamesStr {
void *head; /* private */
};
/*
* NS_CERT_TYPE defines are used in two areas:
* 1) The old NSS Cert Type Extension, which is a certificate extension in the
* actual cert. It was created before the x509 Extended Key Usage Extension,
* which has now taken over it's function. This field is only 8 bits wide
* 2) The nsCertType entry in the CERTCertificate structure. This field is
* 32 bits wide.
* Any entries in this table greater than 0x80 will not be able to be encoded
* in an NSS Cert Type Extension, but can still be represented internally in
* the nsCertType field.
*/
#define NS_CERT_TYPE_IPSEC_CA (0x200) /* outside the NS Cert Type Extenstion */
#define NS_CERT_TYPE_IPSEC (0x100) /* outside the NS Cert Type Extenstion */
#define NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */
#define NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */
#define NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */
@@ -430,11 +443,12 @@ struct CERTDistNamesStr {
#define NS_CERT_TYPE_APP \
(NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_SSL_SERVER | NS_CERT_TYPE_EMAIL | \
NS_CERT_TYPE_OBJECT_SIGNING)
NS_CERT_TYPE_IPSEC | NS_CERT_TYPE_OBJECT_SIGNING)
#define NS_CERT_TYPE_CA \
(NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA | \
NS_CERT_TYPE_OBJECT_SIGNING_CA | EXT_KEY_USAGE_STATUS_RESPONDER)
#define NS_CERT_TYPE_CA \
(NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA | \
NS_CERT_TYPE_OBJECT_SIGNING_CA | EXT_KEY_USAGE_STATUS_RESPONDER | \
NS_CERT_TYPE_IPSEC_CA)
typedef enum SECCertUsageEnum {
certUsageSSLClient = 0,
certUsageSSLServer = 1,
+1 -14
View File
@@ -1401,7 +1401,6 @@ CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
for (i = 1; i <= certificateUsageHighest &&
(SECSuccess == valid || returnedUsages || log);) {
PRBool typeAndEKUAllowed = PR_TRUE;
PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE;
if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) {
NEXT_USAGE();
@@ -1451,19 +1450,7 @@ CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
LOG_ERROR(log, cert, 0, requiredKeyUsage);
INVALID_USAGE();
}
if (certUsage != certUsageIPsec) {
if (!(certType & requiredCertType)) {
typeAndEKUAllowed = PR_FALSE;
}
} else {
PRBool isCritical;
PRBool allowed = cert_EKUAllowsIPsecIKE(cert, &isCritical);
/* If the extension isn't critical, we allow any EKU value. */
if (isCritical && !allowed) {
typeAndEKUAllowed = PR_FALSE;
}
}
if (!typeAndEKUAllowed) {
if (!(certType & requiredCertType)) {
if (PR_TRUE == requiredUsage) {
PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
}
+96 -5
View File
@@ -639,6 +639,11 @@ seckey_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki)
return pubk;
break;
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
/* A basic sanity check on inputs. */
if (spki->algorithm.parameters.len == 0 || newOs.len == 0) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
break;
}
pubk->keyType = ecKey;
pubk->u.ec.size = 0;
@@ -1206,6 +1211,37 @@ SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk)
return NULL;
}
/*
* Use the private key to find a public key handle. The handle will be on
* the same slot as the private key.
*/
static CK_OBJECT_HANDLE
seckey_FindPublicKeyHandle(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk)
{
CK_OBJECT_HANDLE keyID;
/* this helper function is only used below. If we want to make this more
* general, we would need to free up any already cached handles if the
* slot doesn't match up with the private key slot */
PORT_Assert(pubk->pkcs11ID == CK_INVALID_HANDLE);
/* first look for a matching public key */
keyID = PK11_MatchItem(privk->pkcs11Slot, privk->pkcs11ID, CKO_PUBLIC_KEY);
if (keyID != CK_INVALID_HANDLE) {
return keyID;
}
/* none found, create a temp one, make the pubk the owner */
pubk->pkcs11ID = PK11_DerivePubKeyFromPrivKey(privk);
if (pubk->pkcs11ID == CK_INVALID_HANDLE) {
/* end of the road. Token doesn't have matching public key, nor can
* token regenerate a new public key from and existing private key. */
return CK_INVALID_HANDLE;
}
pubk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot);
return pubk->pkcs11ID;
}
SECKEYPublicKey *
SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
{
@@ -1213,6 +1249,8 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
PLArenaPool *arena;
CERTCertificate *cert;
SECStatus rv;
CK_OBJECT_HANDLE pubKeyHandle;
SECItem decodedPoint;
/*
* First try to look up the cert.
@@ -1243,11 +1281,47 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
switch (privk->keyType) {
case nullKey:
case dhKey:
case dsaKey:
/* Nothing to query, if the cert isn't there, we're done -- no way
* to get the public key */
break;
case dsaKey:
pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk);
if (pubKeyHandle == CK_INVALID_HANDLE)
break;
rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
CKA_BASE, arena, &pubk->u.dsa.params.base);
if (rv != SECSuccess)
break;
rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
CKA_PRIME, arena, &pubk->u.dsa.params.prime);
if (rv != SECSuccess)
break;
rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
CKA_SUBPRIME, arena, &pubk->u.dsa.params.subPrime);
if (rv != SECSuccess)
break;
rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
CKA_VALUE, arena, &pubk->u.dsa.publicValue);
if (rv != SECSuccess)
break;
return pubk;
case dhKey:
pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk);
if (pubKeyHandle == CK_INVALID_HANDLE)
break;
rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
CKA_BASE, arena, &pubk->u.dh.base);
if (rv != SECSuccess)
break;
rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
CKA_PRIME, arena, &pubk->u.dh.prime);
if (rv != SECSuccess)
break;
rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
CKA_VALUE, arena, &pubk->u.dh.publicValue);
if (rv != SECSuccess)
break;
return pubk;
case rsaKey:
rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
CKA_MODULUS, arena, &pubk->u.rsa.modulus);
@@ -1258,7 +1332,6 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
if (rv != SECSuccess)
break;
return pubk;
break;
case ecKey:
rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
CKA_EC_PARAMS, arena, &pubk->u.ec.DEREncodedParams);
@@ -1268,7 +1341,23 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
CKA_EC_POINT, arena, &pubk->u.ec.publicValue);
if (rv != SECSuccess || pubk->u.ec.publicValue.len == 0) {
break;
pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk);
if (pubKeyHandle == CK_INVALID_HANDLE)
break;
rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
CKA_EC_POINT, arena, &pubk->u.ec.publicValue);
if (rv != SECSuccess)
break;
}
/* ec.publicValue should be decoded, PKCS #11 defines CKA_EC_POINT
* as encoded, but it's not always. try do decoded it and if it
* succeeds store the decoded value */
rv = SEC_QuickDERDecodeItem(arena, &decodedPoint,
SEC_ASN1_GET(SEC_OctetStringTemplate), &pubk->u.ec.publicValue);
if (rv == SECSuccess) {
/* both values are in the public key arena, so it's safe to
* overwrite the old value */
pubk->u.ec.publicValue = decodedPoint;
}
pubk->u.ec.encoding = ECPoint_Undefined;
return pubk;
@@ -1276,7 +1365,9 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
break;
}
PORT_FreeArena(arena, PR_FALSE);
/* must use Destroy public key here, because some paths create temporary
* PKCS #11 objects which need to be freed */
SECKEY_DestroyPublicKey(pubk);
return NULL;
}
+4
View File
@@ -1013,6 +1013,10 @@ extern SECStatus ChaCha20Poly1305_Open(
const unsigned char *nonce, unsigned int nonceLen,
const unsigned char *ad, unsigned int adLen);
extern SECStatus ChaCha20_Xor(
unsigned char *output, const unsigned char *block, unsigned int len,
const unsigned char *k, const unsigned char *nonce, PRUint32 ctr);
/******************************************/
/*
** MD5 secure hash function
+56 -12
View File
@@ -98,23 +98,32 @@ CheckX86CPUSupport()
#endif /* NSS_X86_OR_X64 */
/* clang-format off */
#if (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__)
#if defined(__aarch64__) || defined(__arm__)
#ifndef __has_include
#define __has_include(x) 0
#endif
#if (__has_include(<sys/auxv.h>) || defined(__linux__)) && \
defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)
/* This might be conflict with host compiler */
#if !defined(__ANDROID__)
#include <sys/auxv.h>
#endif
extern unsigned long getauxval(unsigned long type) __attribute__((weak));
#else
static unsigned long (*getauxval)(unsigned long) = NULL;
#define AT_HWCAP2 0
#define AT_HWCAP 0
#endif /* defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)*/
#endif /* (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__) */
#ifndef AT_HWCAP2
#define AT_HWCAP2 26
#endif
#ifndef AT_HWCAP
#define AT_HWCAP 16
#endif
#endif /* defined(__aarch64__) || defined(__arm__) */
/* clang-format on */
#if defined(__aarch64__) && !defined(__ANDROID__)
#if defined(__aarch64__)
// Defines from hwcap.h in Linux kernel - ARM64
#ifndef HWCAP_AES
#define HWCAP_AES (1 << 3)
@@ -144,9 +153,9 @@ CheckARMSupport()
/* aarch64 must support NEON. */
arm_neon_support_ = disable_arm_neon == NULL;
}
#endif /* defined(__aarch64__) && !defined(__ANDROID__) */
#endif /* defined(__aarch64__) */
#if defined(__arm__) && !defined(__ANDROID__)
#if defined(__arm__)
// Defines from hwcap.h in Linux kernel - ARM
/*
* HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
@@ -171,23 +180,58 @@ CheckARMSupport()
#define HWCAP2_SHA2 (1 << 3)
#endif
PRBool
GetNeonSupport()
{
char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON");
if (disable_arm_neon) {
return PR_FALSE;
}
#if defined(__ARM_NEON) || defined(__ARM_NEON__)
// Compiler generates NEON instruction as default option.
// If no getauxval, compiler generate NEON instruction by default,
// we should allow NOEN support.
return PR_TRUE;
#elif !defined(__ANDROID__)
// Android's cpu-features.c detects features by the following logic
//
// - Call getauxval(AT_HWCAP)
// - Parse /proc/self/auxv if getauxval is nothing or returns 0
// - Parse /proc/cpuinfo if both cannot detect features
//
// But we don't use it for Android since Android document
// (https://developer.android.com/ndk/guides/cpu-features) says
// one problem with AT_HWCAP sometimes devices (Nexus 4 and emulator)
// are mistaken for IDIV.
if (getauxval) {
return (getauxval(AT_HWCAP) & HWCAP_NEON);
}
#endif /* defined(__ARM_NEON) || defined(__ARM_NEON__) */
return PR_FALSE;
}
void
CheckARMSupport()
{
char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON");
char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES");
if (getauxval) {
// Android's cpu-features.c uses AT_HWCAP2 for newer features.
// AT_HWCAP2 is implemented on newer devices / kernel, so we can trust
// it since cpu-features.c doesn't have workaround / fallback.
// Also, AT_HWCAP2 is supported by glibc 2.18+ on Linux/arm, If
// AT_HWCAP2 isn't supported by glibc or Linux kernel, getauxval will
// returns 0.
long hwcaps = getauxval(AT_HWCAP2);
arm_aes_support_ = hwcaps & HWCAP2_AES && disable_hw_aes == NULL;
arm_pmull_support_ = hwcaps & HWCAP2_PMULL;
arm_sha1_support_ = hwcaps & HWCAP2_SHA1;
arm_sha2_support_ = hwcaps & HWCAP2_SHA2;
arm_neon_support_ = hwcaps & HWCAP_NEON && disable_arm_neon == NULL;
}
arm_neon_support_ = GetNeonSupport();
}
#endif /* defined(__arm__) && !defined(__ANDROID__) */
#endif /* defined(__arm__) */
// Enable when Firefox can use it.
// Enable when Firefox can use it for Android API 16 and 17.
// #if defined(__ANDROID__) && (defined(__arm__) || defined(__aarch64__))
// #include <cpu-features.h>
// void
@@ -268,7 +312,7 @@ FreeblInit(void)
{
#ifdef NSS_X86_OR_X64
CheckX86CPUSupport();
#elif (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__)
#elif (defined(__aarch64__) || defined(__arm__))
CheckARMSupport();
#endif
return PR_SUCCESS;
@@ -157,6 +157,7 @@ ChaCha20Poly1305_DestroyContext(ChaCha20Poly1305Context *ctx, PRBool freeit)
#endif
}
#ifndef NSS_DISABLE_CHACHAPOLY
void
ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k,
uint8_t *nonce, uint32_t ctr)
@@ -167,6 +168,25 @@ ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k,
Hacl_Chacha20_chacha20(output, block, len, k, nonce, ctr);
}
}
#endif /* NSS_DISABLE_CHACHAPOLY */
SECStatus
ChaCha20_Xor(unsigned char *output, const unsigned char *block, unsigned int len,
const unsigned char *k, const unsigned char *nonce, PRUint32 ctr)
{
#ifdef NSS_DISABLE_CHACHAPOLY
return SECFailure;
#else
// ChaCha has a 64 octet block, with a 32-bit block counter.
if (sizeof(len) > 4 && len >= (1ULL << (6 + 32))) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
ChaCha20Xor(output, (uint8_t *)block, len, (uint8_t *)k,
(uint8_t *)nonce, ctr);
return SECSuccess;
#endif
}
SECStatus
ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output,
@@ -185,6 +205,11 @@ ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output,
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
// ChaCha has a 64 octet block, with a 32-bit block counter.
if (sizeof(inputLen) > 4 && inputLen >= (1ULL << (6 + 32))) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
*outputLen = inputLen + ctx->tagLen;
if (maxOutputLen < *outputLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+1 -1
View File
@@ -22,7 +22,7 @@ swap8b(PRUint64 value)
return (value);
}
#elif !defined(_MSC_VER)
#elif defined(IS_LITTLE_ENDIAN) && !defined(_MSC_VER) && !__has_builtin(__builtin_bswap64) && !((defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))))
PRUint64
swap8b(PRUint64 x)
+16 -1
View File
@@ -11,6 +11,11 @@
#include <stdlib.h>
#include "prtypes.h"
/* For non-clang platform */
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
/* Unfortunately this isn't always set when it should be. */
#if defined(HAVE_LONG_LONG)
@@ -29,11 +34,17 @@
/*
* FREEBL_HTONLL(x): swap bytes in a 64-bit integer.
*/
#if defined(IS_LITTLE_ENDIAN)
#if defined(_MSC_VER)
#pragma intrinsic(_byteswap_uint64)
#define FREEBL_HTONLL(x) _byteswap_uint64(x)
/* gcc doesn't have __has_builtin, but it does have __builtin_bswap64 */
#elif __has_builtin(__builtin_bswap64) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
#define FREEBL_HTONLL(x) __builtin_bswap64(x)
#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__x86_64))
PRUint64 swap8b(PRUint64 value);
@@ -48,4 +59,8 @@ PRUint64 swap8b(PRUint64 x);
#endif /* _MSC_VER */
#endif /* HAVE_LONG_LONG */
#else /* IS_LITTLE_ENDIAN */
#define FREEBL_HTONLL(x) (x)
#endif
#endif /* HAVE_LONG_LONG */
+2 -1
View File
@@ -210,7 +210,8 @@ DH_Derive(SECItem *publicValue,
unsigned int len = 0;
unsigned int nb;
unsigned char *secret = NULL;
if (!publicValue || !prime || !privateValue || !derivedSecret) {
if (!publicValue || !publicValue->len || !prime || !prime->len ||
!privateValue || !privateValue->len || !derivedSecret) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
+8 -6
View File
@@ -202,8 +202,8 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
#endif
MP_DIGITS(&k) = 0;
if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0) ||
!ecParams->name) {
if (!ecParams || ecParams->name == ECCurve_noName ||
!privKey || !privKeyBytes || privKeyLen <= 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
@@ -391,7 +391,7 @@ EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey)
int len;
unsigned char *privKeyBytes = NULL;
if (!ecParams) {
if (!ecParams || ecParams->name == ECCurve_noName || !privKey) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
@@ -430,7 +430,8 @@ EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue)
mp_err err = MP_OKAY;
int len;
if (!ecParams || !publicValue || !ecParams->name) {
if (!ecParams || ecParams->name == ECCurve_noName ||
!publicValue || !publicValue->len) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
@@ -536,8 +537,9 @@ ECDH_Derive(SECItem *publicValue,
int i;
#endif
if (!publicValue || !ecParams || !privateValue || !derivedSecret ||
!ecParams->name) {
if (!publicValue || !publicValue->len ||
!ecParams || ecParams->name == ECCurve_noName ||
!privateValue || !privateValue->len || !derivedSecret) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
+3
View File
@@ -115,6 +115,9 @@ ec_Curve25519_pt_mul(SECItem *X, SECItem *k, SECItem *P)
}
px = P->data;
}
if (k->len != 32) {
return SECFailure;
}
rv = ec_Curve25519_mul(X->data, k->data, px);
if (NSS_SecureMemcmpZero(X->data, X->len) == 0) {
+326 -18
View File
@@ -15,8 +15,10 @@
#include "seccomon.h" /* Required for RSA and DSA. */
#include "secerr.h"
#include "prtypes.h"
#include "secitem.h"
#include "pkcs11t.h"
#include "ec.h" /* Required for ECDSA */
#include "ec.h" /* Required for EC */
/*
* different platforms have different ways of calling and initial entry point
@@ -288,6 +290,8 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
/* AES Known Plaintext (128-bits). (blocksize is 128-bits) */
static const PRUint8 aes_known_plaintext[] = { "NetscapeepacsteN" };
static const PRUint8 aes_gcm_known_aad[] = { "MozillaallizoM" };
/* AES Known Ciphertext (128-bit key). */
static const PRUint8 aes_ecb128_known_ciphertext[] = {
0x3c, 0xa5, 0x96, 0xf3, 0x34, 0x6a, 0x96, 0xc1,
@@ -299,6 +303,13 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0x15, 0x54, 0x14, 0x1d, 0x4e, 0xd8, 0xd5, 0xea
};
static const PRUint8 aes_gcm128_known_ciphertext[] = {
0x63, 0xf4, 0x95, 0x28, 0xe6, 0x78, 0xee, 0x6e,
0x4f, 0xe0, 0xfc, 0x8d, 0xd7, 0xa2, 0xb1, 0xff,
0x0c, 0x97, 0x1b, 0x0a, 0xdd, 0x97, 0x75, 0xed,
0x8b, 0xde, 0xbf, 0x16, 0x5e, 0x57, 0x6b, 0x4f
};
/* AES Known Ciphertext (192-bit key). */
static const PRUint8 aes_ecb192_known_ciphertext[] = {
0xa0, 0x18, 0x62, 0xed, 0x88, 0x19, 0xcb, 0x62,
@@ -310,6 +321,13 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0x07, 0xbc, 0x43, 0x2f, 0x6d, 0xad, 0x29, 0xe1
};
static const PRUint8 aes_gcm192_known_ciphertext[] = {
0xc1, 0x0b, 0x92, 0x1d, 0x68, 0x21, 0xf4, 0x25,
0x41, 0x61, 0x20, 0x2d, 0x59, 0x7f, 0x53, 0xde,
0x93, 0x39, 0xab, 0x09, 0x76, 0x41, 0x57, 0x2b,
0x90, 0x2e, 0x44, 0xbb, 0x52, 0x03, 0xe9, 0x07
};
/* AES Known Ciphertext (256-bit key). */
static const PRUint8 aes_ecb256_known_ciphertext[] = {
0xdb, 0xa6, 0x52, 0x01, 0x8a, 0x70, 0xae, 0x66,
@@ -321,18 +339,29 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0xc5, 0xc5, 0x68, 0x71, 0x6e, 0x34, 0x40, 0x16
};
static const PRUint8 aes_gcm256_known_ciphertext[] = {
0x5d, 0x9e, 0xd2, 0xa2, 0x74, 0x9c, 0xd9, 0x1c,
0xd1, 0xc9, 0xee, 0x5d, 0xb6, 0xf2, 0xc9, 0xb6,
0x79, 0x27, 0x53, 0x02, 0xa3, 0xdc, 0x22, 0xce,
0xf4, 0xb0, 0xc1, 0x8c, 0x86, 0x51, 0xf5, 0xa1
};
const PRUint8 *aes_ecb_known_ciphertext =
(aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_ecb128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_ecb192_known_ciphertext : aes_ecb256_known_ciphertext;
const PRUint8 *aes_cbc_known_ciphertext =
(aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_cbc128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_cbc192_known_ciphertext : aes_cbc256_known_ciphertext;
const PRUint8 *aes_gcm_known_ciphertext =
(aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_gcm128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_gcm192_known_ciphertext : aes_gcm256_known_ciphertext;
/* AES variables. */
PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH];
PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH];
PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH * 2];
PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH * 2];
AESContext *aes_context;
unsigned int aes_bytes_encrypted;
unsigned int aes_bytes_decrypted;
CK_GCM_PARAMS gcmParams;
SECStatus aes_status;
/*check if aes_key_size is 128, 192, or 256 bits */
@@ -455,6 +484,69 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
return (SECFailure);
}
/******************************************************/
/* AES-GCM Single-Round Known Answer Encryption Test. */
/******************************************************/
gcmParams.pIv = (PRUint8 *)aes_cbc_known_initialization_vector;
gcmParams.ulIvLen = FIPS_AES_BLOCK_SIZE;
gcmParams.pAAD = (PRUint8 *)aes_gcm_known_aad;
gcmParams.ulAADLen = sizeof(aes_gcm_known_aad);
gcmParams.ulTagBits = FIPS_AES_BLOCK_SIZE * 8;
aes_context = AES_CreateContext(aes_known_key,
(PRUint8 *)&gcmParams,
NSS_AES_GCM, PR_TRUE, aes_key_size,
FIPS_AES_BLOCK_SIZE);
if (aes_context == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return (SECFailure);
}
aes_status = AES_Encrypt(aes_context, aes_computed_ciphertext,
&aes_bytes_encrypted, FIPS_AES_ENCRYPT_LENGTH * 2,
aes_known_plaintext,
FIPS_AES_DECRYPT_LENGTH);
AES_DestroyContext(aes_context, PR_TRUE);
if ((aes_status != SECSuccess) ||
(aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH * 2) ||
(PORT_Memcmp(aes_computed_ciphertext, aes_gcm_known_ciphertext,
FIPS_AES_ENCRYPT_LENGTH * 2) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
/******************************************************/
/* AES-GCM Single-Round Known Answer Decryption Test. */
/******************************************************/
aes_context = AES_CreateContext(aes_known_key,
(PRUint8 *)&gcmParams,
NSS_AES_GCM, PR_FALSE, aes_key_size,
FIPS_AES_BLOCK_SIZE);
if (aes_context == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return (SECFailure);
}
aes_status = AES_Decrypt(aes_context, aes_computed_plaintext,
&aes_bytes_decrypted, FIPS_AES_DECRYPT_LENGTH * 2,
aes_gcm_known_ciphertext,
FIPS_AES_ENCRYPT_LENGTH * 2);
AES_DestroyContext(aes_context, PR_TRUE);
if ((aes_status != SECSuccess) ||
(aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
(PORT_Memcmp(aes_computed_plaintext, aes_known_plaintext,
FIPS_AES_DECRYPT_LENGTH) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
return (SECSuccess);
}
@@ -1094,7 +1186,7 @@ freebl_fips_ECDSA_Test(ECParams *ecparams,
"Firefox and ThunderBird are awesome!"
};
unsigned char sha1[SHA1_LENGTH]; /* SHA-1 hash (160 bits) */
unsigned char sha256[SHA256_LENGTH]; /* SHA-256 hash (256 bits) */
unsigned char sig[2 * MAX_ECKEY_LEN];
SECItem signature, digest;
ECPrivateKey *ecdsa_private_key = NULL;
@@ -1136,13 +1228,13 @@ freebl_fips_ECDSA_Test(ECParams *ecparams,
/* ECDSA Single-Round Known Answer Signature Test. */
/***************************************************/
ecdsaStatus = SHA1_HashBuf(sha1, msg, sizeof msg);
ecdsaStatus = SHA256_HashBuf(sha256, msg, sizeof msg);
if (ecdsaStatus != SECSuccess) {
goto loser;
}
digest.type = siBuffer;
digest.data = sha1;
digest.len = SHA1_LENGTH;
digest.data = sha256;
digest.len = SHA256_LENGTH;
memset(sig, 0, sizeof sig);
signature.type = siBuffer;
@@ -1181,10 +1273,83 @@ loser:
}
static SECStatus
freebl_fips_ECDSA_PowerUpSelfTest()
freebl_fips_ECDH_Test(ECParams *ecparams)
{
/* ECDSA Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
/* ECDH Known result (reused old CAVS vector) */
static const PRUint8 ecdh_known_pub_key_1[] = {
EC_POINT_FORM_UNCOMPRESSED,
/* pubX */
0x16, 0x81, 0x32, 0x86, 0xc8, 0xe4, 0x3a, 0x1f,
0x5d, 0xe3, 0x06, 0x22, 0x8b, 0x99, 0x14, 0x25,
0xf7, 0x9c, 0x5b, 0x1e, 0x96, 0x84, 0x85, 0x3b,
0x17, 0xfe, 0xf3, 0x1c, 0x0e, 0xed, 0xc4, 0xce,
/* pubY */
0x7a, 0x44, 0xfe, 0xbd, 0x91, 0x71, 0x7d, 0x73,
0xd9, 0x45, 0xea, 0xae, 0x66, 0x78, 0xfa, 0x6e,
0x46, 0xcd, 0xfa, 0x95, 0x15, 0x47, 0x62, 0x5d,
0xbb, 0x1b, 0x9f, 0xe6, 0x39, 0xfc, 0xfd, 0x47
};
static const PRUint8 ecdh_known_priv_key_2[] = {
0xb4, 0x2a, 0xe3, 0x69, 0x19, 0xec, 0xf0, 0x42,
0x6d, 0x45, 0x8c, 0x94, 0x4a, 0x26, 0xa7, 0x5c,
0xea, 0x9d, 0xd9, 0x0f, 0x59, 0xe0, 0x1a, 0x9d,
0x7c, 0xb7, 0x1c, 0x04, 0x53, 0xb8, 0x98, 0x5a
};
static const PRUint8 ecdh_known_hash_result[] = {
0x16, 0xf3, 0x85, 0xa2, 0x41, 0xf3, 0x7f, 0xc4,
0x0b, 0x56, 0x47, 0xee, 0xa7, 0x74, 0xb9, 0xdb,
0xe1, 0xfa, 0x22, 0xe9, 0x04, 0xf1, 0xb6, 0x12,
0x4b, 0x44, 0x8a, 0xbb, 0xbc, 0x08, 0x2b, 0xa7,
};
SECItem ecdh_priv_2, ecdh_pub_1;
SECItem ZZ = { 0, 0, 0 };
SECStatus ecdhStatus = SECSuccess;
PRUint8 computed_hash_result[HASH_LENGTH_MAX];
ecdh_priv_2.data = (PRUint8 *)ecdh_known_priv_key_2;
ecdh_priv_2.len = sizeof(ecdh_known_priv_key_2);
ecdh_pub_1.data = (PRUint8 *)ecdh_known_pub_key_1;
ecdh_pub_1.len = sizeof(ecdh_known_pub_key_1);
/* Generates a new EC key pair. The private key is a supplied
* random value (in seed) and the public key is the result of
* performing a scalar point multiplication of that value with
* the curve's base point.
*/
ecdhStatus = ECDH_Derive(&ecdh_pub_1, ecparams, &ecdh_priv_2, PR_FALSE, &ZZ);
if (ecdhStatus != SECSuccess) {
goto loser;
}
ecdhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
if (ecdhStatus != SECSuccess) {
goto loser;
}
if (PORT_Memcmp(computed_hash_result, ecdh_known_hash_result,
sizeof(ecdh_known_hash_result)) != 0) {
ecdhStatus = SECFailure;
goto loser;
}
loser:
if (ZZ.data) {
SECITEM_FreeItem(&ZZ, PR_FALSE);
}
if (ecdhStatus != SECSuccess) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
return (SECSuccess);
}
static SECStatus
freebl_fips_EC_PowerUpSelfTest()
{
/* EC Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
static const unsigned char p256_prime[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -1217,7 +1382,7 @@ freebl_fips_ECDSA_PowerUpSelfTest()
static const unsigned char p256_encoding[] = {
0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
};
static const ECParams ecdsa_known_P256_Params = {
static const ECParams ec_known_P256_Params = {
NULL, ec_params_named, /* arena, type */
/* fieldID */
{ 256, ec_field_GFp, /* size and type */
@@ -1250,10 +1415,10 @@ freebl_fips_ECDSA_PowerUpSelfTest()
0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff,
0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f,
0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5,
0x59, 0x6a, 0x62, 0x49, 0x3d, 0x50, 0xc9, 0xe1,
0x27, 0x3b, 0xff, 0x9b, 0x13, 0x66, 0x67, 0xdd,
0x7d, 0xd1, 0x0d, 0x2d, 0x7c, 0x44, 0x04, 0x1b,
0x16, 0x21, 0x12, 0xc5, 0xcb, 0xbd, 0x9e, 0x75
0xa7, 0xd2, 0x20, 0xdd, 0x45, 0xf9, 0x2b, 0xdd,
0xda, 0x98, 0x99, 0x5b, 0x1c, 0x02, 0x3a, 0x27,
0x8b, 0x7d, 0xb6, 0xed, 0x0e, 0xe0, 0xa7, 0xac,
0xaa, 0x36, 0x2c, 0xfa, 0x1a, 0xdf, 0x0d, 0xe1,
};
ECParams ecparams;
@@ -1261,13 +1426,18 @@ freebl_fips_ECDSA_PowerUpSelfTest()
SECStatus rv;
/* ECDSA GF(p) prime field curve test */
ecparams = ecdsa_known_P256_Params;
ecparams = ec_known_P256_Params;
rv = freebl_fips_ECDSA_Test(&ecparams,
ecdsa_known_P256_signature,
sizeof ecdsa_known_P256_signature);
if (rv != SECSuccess) {
return (SECFailure);
}
/* ECDH GF(p) prime field curve test */
rv = freebl_fips_ECDH_Test(&ecparams);
if (rv != SECSuccess) {
return (SECFailure);
}
return (SECSuccess);
}
@@ -1417,6 +1587,138 @@ freebl_fips_DSA_PowerUpSelfTest(void)
return (SECSuccess);
}
static SECStatus
freebl_fips_DH_PowerUpSelfTest(void)
{
/* DH Known P (2048-bits) */
static const PRUint8 dh_known_P[] = {
0xc2, 0x79, 0xbb, 0x76, 0x32, 0x0d, 0x43, 0xfd,
0x1b, 0x8c, 0xa2, 0x3c, 0x00, 0xdd, 0x6d, 0xef,
0xf8, 0x1a, 0xd9, 0xc1, 0xa2, 0xf5, 0x73, 0x2b,
0xdb, 0x1a, 0x3e, 0x84, 0x90, 0xeb, 0xe7, 0x8e,
0x5f, 0x5c, 0x6b, 0xb6, 0x61, 0x89, 0xd1, 0x03,
0xb0, 0x5f, 0x91, 0xe4, 0xd2, 0x82, 0x90, 0xfc,
0x3c, 0x49, 0x69, 0x59, 0xc1, 0x51, 0x6a, 0x85,
0x71, 0xe7, 0x5d, 0x72, 0x5a, 0x45, 0xad, 0x01,
0x6f, 0x82, 0xae, 0xec, 0x91, 0x08, 0x2e, 0x7c,
0x64, 0x93, 0x46, 0x1c, 0x68, 0xef, 0xc2, 0x03,
0x28, 0x1d, 0x75, 0x3a, 0xeb, 0x9c, 0x46, 0xf0,
0xc9, 0xdb, 0x99, 0x95, 0x13, 0x66, 0x4d, 0xd5,
0x1a, 0x78, 0x92, 0x51, 0x89, 0x72, 0x28, 0x7f,
0x20, 0x70, 0x41, 0x49, 0xa2, 0x86, 0xe9, 0xf9,
0x78, 0x5f, 0x8d, 0x2e, 0x5d, 0xfa, 0xdb, 0x57,
0xd4, 0x71, 0xdf, 0x66, 0xe3, 0x9e, 0x88, 0x70,
0xa4, 0x21, 0x44, 0x6a, 0xc7, 0xae, 0x30, 0x2c,
0x9c, 0x1f, 0x91, 0x57, 0xc8, 0x24, 0x34, 0x2d,
0x7a, 0x4a, 0x43, 0xc2, 0x5f, 0xab, 0x64, 0x2e,
0xaa, 0x28, 0x32, 0x95, 0x42, 0x7b, 0xa0, 0xcc,
0xdf, 0xfd, 0x22, 0xc8, 0x56, 0x84, 0xc1, 0x62,
0x15, 0xb2, 0x77, 0x86, 0x81, 0xfc, 0xa5, 0x12,
0x3c, 0xca, 0x28, 0x17, 0x8f, 0x03, 0x16, 0x6e,
0xb8, 0x24, 0xfa, 0x1b, 0x15, 0x02, 0xfd, 0x8b,
0xb6, 0x0a, 0x1a, 0xf7, 0x47, 0x41, 0xc5, 0x2b,
0x37, 0x3e, 0xa1, 0xbf, 0x68, 0xda, 0x1c, 0x55,
0x44, 0xc3, 0xee, 0xa1, 0x63, 0x07, 0x11, 0x3b,
0x5f, 0x00, 0x84, 0xb4, 0xc4, 0xe4, 0xa7, 0x97,
0x29, 0xf8, 0xce, 0xab, 0xfc, 0x27, 0x3e, 0x34,
0xe4, 0xc7, 0x81, 0x52, 0x32, 0x0e, 0x27, 0x3c,
0xa6, 0x70, 0x3f, 0x4a, 0x54, 0xda, 0xdd, 0x60,
0x26, 0xb3, 0x6e, 0x45, 0x26, 0x19, 0x41, 0x6f
};
static const PRUint8 dh_known_Y_1[] = {
0xb4, 0xc7, 0x85, 0xba, 0xa6, 0x98, 0xb3, 0x77,
0x41, 0x2b, 0xd9, 0x9a, 0x72, 0x90, 0xa4, 0xac,
0xc4, 0xf7, 0xc2, 0x23, 0x9a, 0x68, 0xe2, 0x7d,
0x3a, 0x54, 0x45, 0x91, 0xc1, 0xd7, 0x8a, 0x17,
0x54, 0xd3, 0x37, 0xaa, 0x0c, 0xcd, 0x0b, 0xe2,
0xf2, 0x34, 0x0f, 0x17, 0xa8, 0x07, 0x88, 0xaf,
0xed, 0xc1, 0x02, 0xd4, 0xdb, 0xdc, 0x0f, 0x22,
0x51, 0x23, 0x40, 0xb9, 0x65, 0x6d, 0x39, 0xf4,
0xe1, 0x8b, 0x57, 0x7d, 0xb6, 0xd3, 0xf2, 0x6b,
0x02, 0xa9, 0x36, 0xf0, 0x0d, 0xe3, 0xdb, 0x9a,
0xbf, 0x20, 0x00, 0x4d, 0xec, 0x6f, 0x68, 0x95,
0xee, 0x59, 0x4e, 0x3c, 0xb6, 0xda, 0x7b, 0x19,
0x08, 0x9a, 0xef, 0x61, 0x43, 0xf5, 0xfb, 0x25,
0x70, 0x19, 0xc1, 0x5f, 0x0e, 0x0f, 0x6a, 0x63,
0x44, 0xe9, 0xcf, 0x33, 0xce, 0x13, 0x4f, 0x34,
0x3c, 0x94, 0x40, 0x8d, 0xf2, 0x65, 0x42, 0xef,
0x70, 0x54, 0xdd, 0x5f, 0xc1, 0xd7, 0x0b, 0xa6,
0x06, 0xd5, 0xa6, 0x47, 0xae, 0x2c, 0x1f, 0x5a,
0xa6, 0xb3, 0xc1, 0x38, 0x3a, 0x3b, 0x60, 0x94,
0xa2, 0x95, 0xab, 0xb2, 0x86, 0x82, 0xc5, 0x3b,
0xb8, 0x6f, 0x3e, 0x55, 0x86, 0x84, 0xe0, 0x00,
0xe5, 0xef, 0xca, 0x5c, 0xec, 0x7e, 0x38, 0x0f,
0x82, 0xa2, 0xb1, 0xee, 0x48, 0x1b, 0x32, 0xbb,
0x5a, 0x33, 0xa5, 0x01, 0xba, 0xca, 0xa6, 0x64,
0x61, 0xb6, 0xe5, 0x5c, 0x0e, 0x5f, 0x2c, 0x66,
0x0d, 0x01, 0x6a, 0x20, 0x04, 0x70, 0x68, 0x82,
0x93, 0x29, 0x15, 0x3b, 0x7a, 0x06, 0xb2, 0x92,
0x61, 0xcd, 0x7e, 0xa4, 0xc1, 0x15, 0x64, 0x3b,
0x3c, 0x51, 0x10, 0x4c, 0x87, 0xa6, 0xaf, 0x07,
0xce, 0x46, 0x82, 0x75, 0xf3, 0x90, 0xf3, 0x21,
0x55, 0x74, 0xc2, 0xe4, 0x96, 0x7d, 0xc3, 0xe6,
0x33, 0xa5, 0xc6, 0x51, 0xef, 0xec, 0x90, 0x08
};
static const PRUint8 dh_known_x_2[] = {
0x9e, 0x9b, 0xc3, 0x25, 0x53, 0xf9, 0xfc, 0x92,
0xb6, 0xae, 0x54, 0x8e, 0x23, 0x4c, 0x94, 0xba,
0x41, 0xe6, 0x29, 0x33, 0xb9, 0xdb, 0xff, 0x6d,
0xa8, 0xb8, 0x48, 0x49, 0x66, 0x11, 0xa6, 0x13
};
static const PRUint8 dh_known_hash_result[] = {
0x93, 0xa2, 0x89, 0x1c, 0x8a, 0xc3, 0x70, 0xbf,
0xa7, 0xdf, 0xb6, 0xd7, 0x82, 0xfb, 0x87, 0x81,
0x09, 0x47, 0xf3, 0x9f, 0x5a, 0xbf, 0x4f, 0x3f,
0x8e, 0x5e, 0x06, 0xca, 0x30, 0xa7, 0xaf, 0x10
};
/* DH variables. */
SECStatus dhStatus;
SECItem dh_prime;
SECItem dh_pub_key_1;
SECItem dh_priv_key_2;
SECItem ZZ = { 0, 0, 0 };
PRUint8 computed_hash_result[HASH_LENGTH_MAX];
dh_prime.data = (PRUint8 *)dh_known_P;
dh_prime.len = sizeof(dh_known_P);
dh_pub_key_1.data = (PRUint8 *)dh_known_Y_1;
dh_pub_key_1.len = sizeof(dh_known_Y_1);
dh_priv_key_2.data = (PRUint8 *)dh_known_x_2;
dh_priv_key_2.len = sizeof(dh_known_x_2);
/* execute the derive */
dhStatus = DH_Derive(&dh_pub_key_1, &dh_prime, &dh_priv_key_2, &ZZ, dh_prime.len);
if (dhStatus != SECSuccess) {
goto loser;
}
dhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
if (dhStatus != SECSuccess) {
goto loser;
}
if (PORT_Memcmp(computed_hash_result, dh_known_hash_result,
sizeof(dh_known_hash_result)) != 0) {
dhStatus = SECFailure;
goto loser;
}
loser:
if (ZZ.data) {
SECITEM_FreeItem(&ZZ, PR_FALSE);
}
if (dhStatus != SECSuccess) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
return (SECSuccess);
}
static SECStatus
freebl_fips_RNG_PowerUpSelfTest(void)
{
@@ -1541,7 +1843,7 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
return rv;
/* NOTE: RSA can only be tested in full freebl. It requires access to
* the locking primitives */
* the locking primitives */
/* RSA Power-Up SelfTest(s). */
rv = freebl_fips_RSA_PowerUpSelfTest();
@@ -1554,8 +1856,14 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
if (rv != SECSuccess)
return rv;
/* ECDSA Power-Up SelfTest(s). */
rv = freebl_fips_ECDSA_PowerUpSelfTest();
/* DH Power-Up SelfTest(s). */
rv = freebl_fips_DH_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;
/* EC Power-Up SelfTest(s). */
rv = freebl_fips_EC_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;
+6 -6
View File
@@ -76,11 +76,11 @@
'__SSSE3__',
],
}],
[ 'OS=="android"', {
# On Android we can't use any of the hardware acceleration :(
'defines!': [
'__ARM_NEON__',
'__ARM_NEON',
[ 'target_arch=="arm"', {
# Gecko doesn't support non-NEON platform on Android, but tier-3
# platform such as Linux/arm will need it
'cflags_mozilla': [
'-mfpu=neon'
],
}],
],
@@ -107,7 +107,7 @@
],
}],
# macOS build doesn't use cflags.
[ 'OS=="mac"', {
[ 'OS=="mac" or OS=="ios"', {
'xcode_settings': {
'OTHER_CFLAGS': [
'-mpclmul', '-maes'
+1
View File
@@ -143,6 +143,7 @@ loser:
void
intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit)
{
PORT_Memset(gcm, 0, sizeof(intel_AES_GCMContext));
if (freeit) {
PORT_Free(gcm);
}
+5 -1
View File
@@ -313,10 +313,14 @@ static const struct FREEBLVectorStr vector =
BLAKE2B_End,
BLAKE2B_FlattenSize,
BLAKE2B_Flatten,
BLAKE2B_Resurrect
BLAKE2B_Resurrect,
/* End of Version 3.020 */
ChaCha20_Xor
/* End of version 3.021 */
};
const FREEBLVector*
+10
View File
@@ -2060,6 +2060,16 @@ EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
return (vector->p_EC_CopyParams)(arena, dstParams, srcParams);
}
SECStatus
ChaCha20_Xor(unsigned char *output, const unsigned char *block, unsigned int len,
const unsigned char *k, const unsigned char *nonce, PRUint32 ctr)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return SECFailure;
}
return (vector->p_ChaCha20_Xor)(output, block, len, k, nonce, ctr);
}
SECStatus
ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx,
const unsigned char *key, unsigned int keyLen,
+7 -1
View File
@@ -10,7 +10,7 @@
#include "blapi.h"
#define FREEBL_VERSION 0x0314
#define FREEBL_VERSION 0x0315
struct FREEBLVectorStr {
@@ -759,6 +759,12 @@ struct FREEBLVectorStr {
/* Version 3.020 came to here */
SECStatus (*p_ChaCha20_Xor)(unsigned char *output, const unsigned char *block,
unsigned int len, const unsigned char *k,
const unsigned char *nonce, PRUint32 ctr);
/* Version 3.021 came to here */
/* Add new function pointers at the end of this struct and bump
* FREEBL_VERSION at the beginning of this file. */
};
+4 -1
View File
@@ -2063,7 +2063,10 @@ s_mp_almost_inverse(const mp_int *a, const mp_int *p, mp_int *c)
}
}
if (res >= 0) {
while (MP_SIGN(c) != MP_ZPOS) {
if (mp_cmp_mag(c, p) >= 0) {
MP_CHECKOK(mp_div(c, p, NULL, c));
}
if (MP_SIGN(c) != MP_ZPOS) {
MP_CHECKOK(mp_add(c, p, c));
}
res = k;
+76 -42
View File
@@ -491,11 +491,11 @@ cleanup:
** This implments steps 4 thorough 22 of FIPS 186-3 A.1.2.1 and
** steps 16 through 34 of FIPS 186-2 C.6
*/
#define MAX_ST_SEED_BITS (HASH_LENGTH_MAX * PR_BITS_PER_BYTE)
static SECStatus
makePrimefromPrimesShaweTaylor(
HASH_HashType hashtype, /* selected Hashing algorithm */
unsigned int length, /* input. Length of prime in bits. */
unsigned int seedlen, /* input seed length in bits */
mp_int *c0, /* seed prime */
mp_int *q, /* sub prime, can be 1 */
mp_int *prime, /* output. */
@@ -557,7 +557,7 @@ makePrimefromPrimesShaweTaylor(
old_counter = *prime_gen_counter;
/*
** Comment: Generate a pseudorandom integer x in the interval
** [2**(lenght-1), 2**length].
** [2**(length-1), 2**length].
**
** Step 6/18 x = 0
*/
@@ -569,11 +569,10 @@ makePrimefromPrimesShaweTaylor(
for (i = 0; i < iterations; i++) {
/* is bigger than prime_seed should get to */
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
seedlen, &x[(iterations - i - 1) * hashlen]));
}
/* Step 8/20 prime_seed = prime_seed + iterations + 1 */
CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
prime_seed));
CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
/*
** Step 9/21 x = 2 ** (length-1) + x mod 2 ** (length-1)
**
@@ -595,7 +594,7 @@ makePrimefromPrimesShaweTaylor(
x[offset] = (mask & x[offset]) | bit;
/*
** Comment: Generate a candidate prime c in the interval
** [2**(lenght-1), 2**length].
** [2**(length-1), 2**length].
**
** Step 10 t = ceiling(x/(2q(p0)))
** Step 22 t = ceiling(x/(2(c0)))
@@ -624,7 +623,7 @@ step_23:
/* t = 2**(length-1) + 2qc0 -1 */
CHECK_MPI_OK(mp_add(&two_length_minus_1, &t, &t));
/* t = floor((2**(length-1)+2qc0 -1)/2qco)
* = ceil(2**(lenght-2)/2qc0) */
* = ceil(2**(length-2)/2qc0) */
CHECK_MPI_OK(mp_div(&t, &c0_2, &t, NULL));
CHECK_MPI_OK(mp_mul(&t, &c0_2, &c));
CHECK_MPI_OK(mp_add_d(&c, (mp_digit)1, &c)); /* c= 2tqc0 + 1*/
@@ -645,13 +644,11 @@ step_23:
** NOTE: we reuse the x array for 'a' initially.
*/
for (i = 0; i < iterations; i++) {
/* MAX_ST_SEED_BITS is bigger than prime_seed should get to */
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
seedlen, &x[(iterations - i - 1) * hashlen]));
}
/* Step 16/28 prime_seed = prime_seed + iterations + 1 */
CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
prime_seed));
CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
/* Step 17/29 a = 2 + (a mod (c-3)). */
CHECK_MPI_OK(mp_read_unsigned_octets(&a, x, iterations * hashlen));
CHECK_MPI_OK(mp_sub_d(&c, (mp_digit)3, &z)); /* z = c -3 */
@@ -742,6 +739,7 @@ makePrimefromSeedShaweTaylor(
int hashlen = HASH_ResultLen(hashtype);
int outlen = hashlen * PR_BITS_PER_BYTE;
int offset;
int seedlen = input_seed->len * 8; /*seedlen is in bits */
unsigned char bit, mask;
unsigned char x[HASH_LENGTH_MAX * 2];
mp_digit dummy;
@@ -775,7 +773,7 @@ makePrimefromSeedShaweTaylor(
goto cleanup;
}
/* Steps 16-34 */
rv = makePrimefromPrimesShaweTaylor(hashtype, length, &c0, &one,
rv = makePrimefromPrimesShaweTaylor(hashtype, length, seedlen, &c0, &one,
prime, prime_seed, prime_gen_counter);
goto cleanup; /* we're done, one way or the other */
}
@@ -787,8 +785,7 @@ makePrimefromSeedShaweTaylor(
step_5:
/* Step 5 c = Hash(prime_seed) xor Hash(prime_seed+1). */
CHECK_SEC_OK(HASH_HashBuf(hashtype, x, prime_seed->data, prime_seed->len));
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1,
MAX_ST_SEED_BITS, &x[hashlen]));
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1, seedlen, &x[hashlen]));
for (i = 0; i < hashlen; i++) {
x[i] = x[i] ^ x[i + hashlen];
}
@@ -817,7 +814,7 @@ step_5:
/* Step 8 prime_gen_counter = prime_gen_counter + 1 */
(*prime_gen_counter)++;
/* Step 9 prime_seed = prime_seed + 2 */
CHECK_SEC_OK(addToSeed(prime_seed, 2, MAX_ST_SEED_BITS, prime_seed));
CHECK_SEC_OK(addToSeed(prime_seed, 2, seedlen, prime_seed));
/* Step 10 Perform deterministic primality test on c. For example, since
** c is small, it's primality can be tested by trial division, See
** See Appendic C.7.
@@ -890,7 +887,8 @@ findQfromSeed(
mp_int *Q_, /* output. */
unsigned int *qseed_len, /* output */
HASH_HashType *hashtypePtr, /* output. Hash uses */
pqgGenType *typePtr) /* output. Generation Type used */
pqgGenType *typePtr, /* output. Generation Type used */
unsigned int *qgen_counter) /* output. q_counter */
{
HASH_HashType hashtype;
SECItem firstseed = { 0, 0, 0 };
@@ -964,6 +962,7 @@ findQfromSeed(
*qseed_len = qseed.len;
*hashtypePtr = hashtype;
*typePtr = FIPS186_3_ST_TYPE;
*qgen_counter = count;
SECITEM_FreeItem(&qseed, PR_FALSE);
return SECSuccess;
}
@@ -1388,19 +1387,26 @@ step_5:
CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
&qseed, &p0, &pseed, &pgen_counter));
/* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, seedBytes * 8,
&p0, &Q, &P, &pseed, &pgen_counter));
/* combine all the seeds */
seed->len = firstseed.len + qseed.len + pseed.len;
if ((qseed.len > firstseed.len) || (pseed.len > firstseed.len)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); /* shouldn't happen */
goto cleanup;
}
/* If the seed overflows, then pseed and qseed may have leading zeros which the mpl code clamps.
* we want to make sure those are added back in so the individual seed lengths are predictable from
* the overall seed length */
seed->len = firstseed.len * 3;
seed->data = PORT_ArenaZAlloc(verify->arena, seed->len);
if (seed->data == NULL) {
goto cleanup;
}
PORT_Memcpy(seed->data, firstseed.data, firstseed.len);
PORT_Memcpy(seed->data + firstseed.len, pseed.data, pseed.len);
PORT_Memcpy(seed->data + firstseed.len + pseed.len, qseed.data, qseed.len);
counter = 0; /* (qgen_counter << 16) | pgen_counter; */
PORT_Memcpy(seed->data + 2 * firstseed.len - pseed.len, pseed.data, pseed.len);
PORT_Memcpy(seed->data + 3 * firstseed.len - qseed.len, qseed.data, qseed.len);
counter = (qgen_counter << 16) | pgen_counter;
/* we've generated both P and Q now, skip to generating G */
goto generate_G;
@@ -1620,6 +1626,7 @@ PQG_VerifyParams(const PQGParams *params,
int j;
unsigned int counter_max = 0; /* handle legacy L < 1024 */
unsigned int qseed_len;
unsigned int qgen_counter_ = 0;
SECItem pseed_ = { 0, 0, 0 };
HASH_HashType hashtype;
pqgGenType type;
@@ -1699,48 +1706,55 @@ PQG_VerifyParams(const PQGParams *params,
/* Steps 7-12 are done only if the optional PQGVerify is supplied. */
/* continue processing P */
/* 7. counter < 4*L */
CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
/* 8. g >= N and g < 2*L (g is length of seed in bits) */
g = vfy->seed.len * 8;
CHECKPARAM(g >= N && g < counter_max / 2);
/* step 7 and 8 are delayed until we determine which type of generation
* was used */
/* 9. Q generated from SEED matches Q in PQGParams. */
/* This function checks all possible hash and generation types to
* find a Q_ which matches Q. */
g = vfy->seed.len * 8;
CHECKPARAM(findQfromSeed(L, N, g, &vfy->seed, &Q, &Q_, &qseed_len,
&hashtype, &type) == SECSuccess);
&hashtype, &type, &qgen_counter_) == SECSuccess);
CHECKPARAM(mp_cmp(&Q, &Q_) == 0);
/* now we can do steps 7 & 8*/
if ((type == FIPS186_1_TYPE) || (type == FIPS186_3_TYPE)) {
CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
CHECKPARAM(g >= N && g < counter_max / 2);
}
if (type == FIPS186_3_ST_TYPE) {
SECItem qseed = { 0, 0, 0 };
SECItem pseed = { 0, 0, 0 };
unsigned int first_seed_len;
unsigned int pgen_counter = 0;
unsigned int pgen_counter_ = 0;
unsigned int qgen_counter = (vfy->counter >> 16) & 0xffff;
unsigned int pgen_counter = (vfy->counter) & 0xffff;
/* extract pseed and qseed from domain_parameter_seed, which is
* first_seed || pseed || qseed. qseed is first_seed + small_integer
* pseed is qseed + small_integer. This means most of the time
* mod the length of first_seed. pseed is qseed + small_integer mod
* the length of first_seed. This means most of the time
* first_seed.len == qseed.len == pseed.len. Rarely qseed.len and/or
* pseed.len will be one greater than first_seed.len, so we can
* depend on the fact that
* first_seed.len = floor(domain_parameter_seed.len/3).
* findQfromSeed returned qseed.len, so we can calculate pseed.len as
* pseed.len = domain_parameter_seed.len - first_seed.len - qseed.len
* this is probably over kill, since 99.999% of the time they will all
* be equal.
*
* With the lengths, we can now find the offsets;
* pseed.len will be smaller because mpi clamps them. pqgGen
* automatically adds the zero pad back though, so we can depend
* domain_parameter_seed.len to be a multiple of three. We only have
* to deal with the fact that the returned seeds from our functions
* could be shorter.
* first_seed.len = domain_parameter_seed.len/3
* We can now find the offsets;
* first_seed.data = domain_parameter_seed.data + 0
* pseed.data = domain_parameter_seed.data + first_seed.len
* qseed.data = domain_parameter_seed.data
* + domain_paramter_seed.len - qseed.len
*
* We deal with pseed possibly having zero pad in the pseed check later.
*/
first_seed_len = vfy->seed.len / 3;
CHECKPARAM(qseed_len < vfy->seed.len);
CHECKPARAM(first_seed_len * 8 > N - 1);
CHECKPARAM(first_seed_len + qseed_len < vfy->seed.len);
CHECKPARAM(first_seed_len * 8 < counter_max / 2);
CHECKPARAM(first_seed_len >= qseed_len);
qseed.len = qseed_len;
qseed.data = vfy->seed.data + vfy->seed.len - qseed.len;
pseed.len = vfy->seed.len - (first_seed_len + qseed_len);
pseed.len = first_seed_len;
pseed.data = vfy->seed.data + first_seed_len;
/*
@@ -1752,14 +1766,34 @@ PQG_VerifyParams(const PQGParams *params,
** (ST_Random_Prime((ceil(length/2)+1, input_seed)
*/
CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
&qseed, &p0, &pseed_, &pgen_counter));
&qseed, &p0, &pseed_, &pgen_counter_));
/* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
&p0, &Q_, &P_, &pseed_, &pgen_counter));
CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, first_seed_len * 8,
&p0, &Q_, &P_, &pseed_, &pgen_counter_));
CHECKPARAM(mp_cmp(&P, &P_) == 0);
/* make sure pseed wasn't tampered with (since it is part of
* calculating G) */
if (pseed.len > pseed_.len) {
/* handle the case of zero pad for pseed */
int extra = pseed.len - pseed_.len;
int i;
for (i = 0; i < extra; i++) {
if (pseed.data[i] != 0) {
*result = SECFailure;
goto cleanup;
}
}
pseed.data += extra;
pseed.len -= extra;
/* the rest is handled in the normal compare below */
}
CHECKPARAM(SECITEM_CompareItem(&pseed, &pseed_) == SECEqual);
if (vfy->counter != -1) {
CHECKPARAM(pgen_counter < counter_max);
CHECKPARAM(qgen_counter < counter_max);
CHECKPARAM((pgen_counter_ == pgen_counter));
CHECKPARAM((qgen_counter_ == qgen_counter));
}
} else if (vfy->counter == -1) {
/* If counter is set to -1, we are really only verifying G, skip
* the remainder of the checks for P */
+7 -1
View File
@@ -1032,13 +1032,19 @@ AES_CreateContext(const unsigned char *key, const unsigned char *iv,
void
AES_DestroyContext(AESContext *cx, PRBool freeit)
{
void *mem = cx->mem;
if (cx->worker_cx && cx->destroy) {
(*cx->destroy)(cx->worker_cx, PR_TRUE);
cx->worker_cx = NULL;
cx->destroy = NULL;
}
PORT_Memset(cx, 0, sizeof(AESContext));
if (freeit) {
PORT_Free(cx->mem);
PORT_Free(mem);
} else {
/* if we are not freeing the context, restore mem, We may get called
* again to actually free the context */
cx->mem = mem;
}
}
@@ -3002,17 +3002,8 @@ PKIX_PL_Cert_VerifyCertAndKeyType(
if (CERT_CheckKeyUsage(cert->nssCert, requiredKeyUsage) != SECSuccess) {
PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED);
}
if (certUsage != certUsageIPsec) {
if (!(certType & requiredCertType)) {
PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED);
}
} else {
PRBool isCritical;
PRBool allowed = cert_EKUAllowsIPsecIKE(cert->nssCert, &isCritical);
/* If the extension isn't critical, we allow any EKU value. */
if (isCritical && !allowed) {
PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED);
}
if (!(certType & requiredCertType)) {
PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED);
}
cleanup:
PKIX_DECREF(basicConstraints);
+6
View File
@@ -1145,3 +1145,9 @@ HASH_GetHashOidTagByHashType;
;+ local:
;+ *;
;+};
;+NSS_3.44 { # NSS 3.44 release
;+ global:
CERT_GetCertificateDer;
;+ local:
;+ *;
;+};
+3 -3
View File
@@ -22,10 +22,10 @@
* The format of the version string should be
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
*/
#define NSS_VERSION "3.43" _NSS_CUSTOMIZED
#define NSS_VERSION "3.44.1" _NSS_CUSTOMIZED
#define NSS_VMAJOR 3
#define NSS_VMINOR 43
#define NSS_VPATCH 0
#define NSS_VMINOR 44
#define NSS_VPATCH 1
#define NSS_VBUILD 0
#define NSS_BETA PR_FALSE
+13 -8
View File
@@ -190,7 +190,6 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey,
attrs++;
PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
attrs++;
signedattr = attrs;
PK11_SETATTRS(attrs, CKA_EC_PARAMS,
pubKey->u.ec.DEREncodedParams.data,
pubKey->u.ec.DEREncodedParams.len);
@@ -222,12 +221,14 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey,
PORT_SetError(SEC_ERROR_BAD_KEY);
return CK_INVALID_HANDLE;
}
templateCount = attrs - theTemplate;
signedcount = attrs - signedattr;
PORT_Assert(templateCount <= (sizeof(theTemplate) / sizeof(CK_ATTRIBUTE)));
for (attrs = signedattr; signedcount; attrs++, signedcount--) {
pk11_SignedToUnsigned(attrs);
if (pubKey->keyType != ecKey) {
PORT_Assert(signedattr);
signedcount = attrs - signedattr;
for (attrs = signedattr; signedcount; attrs++, signedcount--) {
pk11_SignedToUnsigned(attrs);
}
}
rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, theTemplate,
templateCount, isToken, &objectID);
@@ -1074,9 +1075,13 @@ pk11_loadPrivKeyWithFlags(PK11SlotInfo *slot, SECKEYPrivateKey *privKey,
&cktrue, &ckfalse);
/* Not everyone can handle zero padded key values, give
* them the raw data as unsigned */
for (ap = attrs; extra_count; ap++, extra_count--) {
pk11_SignedToUnsigned(ap);
* them the raw data as unsigned. The exception is EC,
* where the values are encoded or zero-preserving
* per-RFC5915 */
if (privKey->keyType != ecKey) {
for (ap = attrs; extra_count; ap++, extra_count--) {
pk11_SignedToUnsigned(ap);
}
}
/* now Store the puppies */
+3 -1
View File
@@ -184,7 +184,9 @@ PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert,
SECKEY_DestroyPublicKey(pubKey);
return PR_FALSE;
}
pk11_SignedToUnsigned(&theTemplate);
if (pubKey->keyType != ecKey) {
pk11_SignedToUnsigned(&theTemplate);
}
if (pk11_FindObjectByTemplate(slot, &theTemplate, 1) != CK_INVALID_HANDLE) {
SECKEY_DestroyPublicKey(pubKey);
return PR_TRUE;
+4 -4
View File
@@ -353,7 +353,7 @@ SECMOD_SetRootCerts(PK11SlotInfo *slot, SECMODModule *mod)
}
}
#ifndef NSS_TEST_BUILD
#ifndef NSS_STATIC_SOFTOKEN
static const char *my_shlib_name =
SHLIB_PREFIX "nss" SHLIB_VERSION "." SHLIB_SUFFIX;
static const char *softoken_shlib_name =
@@ -403,7 +403,7 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
/* internal modules get loaded from their internal list */
if (mod->internal && (mod->dllName == NULL)) {
#ifdef NSS_TEST_BUILD
#ifdef NSS_STATIC_SOFTOKEN
entry = (CK_C_GetFunctionList)NSC_GetFunctionList;
#else
/*
@@ -430,7 +430,7 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
if (mod->isModuleDB) {
mod->moduleDBFunc = (CK_C_GetFunctionList)
#ifdef NSS_TEST_BUILD
#ifdef NSS_STATIC_SOFTOKEN
NSC_ModuleDBFunc;
#else
PR_FindSymbol(softokenLib, "NSC_ModuleDBFunc");
@@ -612,7 +612,7 @@ SECMOD_UnloadModule(SECMODModule *mod)
* if not, we should change this to SECFailure and move it above the
* mod->loaded = PR_FALSE; */
if (mod->internal && (mod->dllName == NULL)) {
#ifndef NSS_TEST_BUILD
#ifndef NSS_STATIC_SOFTOKEN
if (0 == PR_ATOMIC_DECREMENT(&softokenLoadCount)) {
if (softokenLib) {
disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
+11
View File
@@ -226,6 +226,7 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type, unsigned long len)
return CKK_CAMELLIA;
case CKM_NSS_CHACHA20_POLY1305:
case CKM_NSS_CHACHA20_KEY_GEN:
case CKM_NSS_CHACHA20_CTR:
return CKK_NSS_CHACHA20;
case CKM_AES_ECB:
case CKM_AES_CBC:
@@ -239,6 +240,8 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type, unsigned long len)
case CKM_AES_KEY_GEN:
case CKM_NETSCAPE_AES_KEY_WRAP:
case CKM_NETSCAPE_AES_KEY_WRAP_PAD:
case CKM_AES_XCBC_MAC:
case CKM_AES_XCBC_MAC_96:
return CKK_AES;
case CKM_DES_ECB:
case CKM_DES_CBC:
@@ -440,6 +443,7 @@ PK11_GetKeyGenWithSize(CK_MECHANISM_TYPE type, int size)
case CKM_CAMELLIA_KEY_GEN:
return CKM_CAMELLIA_KEY_GEN;
case CKM_NSS_CHACHA20_POLY1305:
case CKM_NSS_CHACHA20_CTR:
return CKM_NSS_CHACHA20_KEY_GEN;
case CKM_AES_ECB:
case CKM_AES_CBC:
@@ -730,6 +734,9 @@ PK11_GetBlockSize(CK_MECHANISM_TYPE type, SECItem *params)
case CKM_RSA_X_509:
/*actually it's the modulus length of the key!*/
return -1; /* failure */
case CKM_NSS_CHACHA20_POLY1305:
case CKM_NSS_CHACHA20_CTR:
return 64;
default:
return pk11_lookup(type)->blockSize;
}
@@ -784,12 +791,16 @@ PK11_GetIVLength(CK_MECHANISM_TYPE type)
case CKM_CAST3_CBC_PAD:
case CKM_CAST5_CBC_PAD:
return 8;
case CKM_AES_GCM:
case CKM_NSS_CHACHA20_POLY1305:
return 12;
case CKM_SEED_CBC:
case CKM_SEED_CBC_PAD:
case CKM_CAMELLIA_CBC:
case CKM_CAMELLIA_CBC_PAD:
case CKM_AES_CBC:
case CKM_AES_CBC_PAD:
case CKM_NSS_CHACHA20_CTR:
return 16;
case CKM_SKIPJACK_CBC64:
case CKM_SKIPJACK_ECB64:
+2
View File
@@ -238,6 +238,8 @@ static const oidValDef curveOptList[] = {
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
{ CIPHER_NAME("SECP521R1"), SEC_OID_SECG_EC_SECP521R1,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
{ CIPHER_NAME("CURVE25519"), SEC_OID_CURVE25519,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
/* ANSI X9.62 named elliptic curves (characteristic two field) */
{ CIPHER_NAME("C2PNB163V1"), SEC_OID_ANSIX962_EC_C2PNB163V1,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
+7 -6
View File
@@ -505,7 +505,7 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
}
PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
attrs++;
signedattr = attrs;
/* No signed attrs for EC */
/* curveOID always is a copy of AlgorithmID.parameters. */
PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data,
lpk->u.ec.curveOID.len);
@@ -523,11 +523,12 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
}
templateCount = attrs - theTemplate;
PORT_Assert(templateCount <= sizeof(theTemplate) / sizeof(CK_ATTRIBUTE));
PORT_Assert(signedattr != NULL);
signedcount = attrs - signedattr;
for (ap = signedattr; signedcount; ap++, signedcount--) {
pk11_SignedToUnsigned(ap);
if (lpk->keyType != ecKey) {
PORT_Assert(signedattr);
signedcount = attrs - signedattr;
for (ap = signedattr; signedcount; ap++, signedcount--) {
pk11_SignedToUnsigned(ap);
}
}
rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION,
+1
View File
@@ -111,6 +111,7 @@ CK_OBJECT_HANDLE PK11_FindObjectForCert(CERTCertificate *cert,
PK11SymKey *pk11_CopyToSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey);
unsigned int pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType);
CK_OBJECT_HANDLE PK11_DerivePubKeyFromPrivKey(SECKEYPrivateKey *privKey);
/**********************************************************************
* Certs
+30
View File
@@ -1598,6 +1598,7 @@ PK11_DeriveWithTemplate(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
PK11_FreeSymKey(newBaseKey);
if (crv != CKR_OK) {
PK11_FreeSymKey(symKey);
PORT_SetError(PK11_MapError(crv));
return NULL;
}
return symKey;
@@ -1839,6 +1840,35 @@ loser:
return NULL;
}
/*
* This regenerate a public key from a private key. This function is currently
* NSS private. If we want to make it public, we need to add and optional
* template or at least flags (a.la. PK11_DeriveWithFlags).
*/
CK_OBJECT_HANDLE
PK11_DerivePubKeyFromPrivKey(SECKEYPrivateKey *privKey)
{
PK11SlotInfo *slot = privKey->pkcs11Slot;
CK_MECHANISM mechanism;
CK_OBJECT_HANDLE objectID = CK_INVALID_HANDLE;
CK_RV crv;
mechanism.mechanism = CKM_NSS_PUB_FROM_PRIV;
mechanism.pParameter = NULL;
mechanism.ulParameterLen = 0;
PK11_EnterSlotMonitor(slot);
crv = PK11_GETTAB(slot)->C_DeriveKey(slot->session, &mechanism,
privKey->pkcs11ID, NULL, 0,
&objectID);
PK11_ExitSlotMonitor(slot);
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
return CK_INVALID_HANDLE;
}
return objectID;
}
/*
* This Generates a wrapping key based on a privateKey, publicKey, and two
* random numbers. For Mail usage RandomB should be NULL. In the Sender's
+1 -1
View File
@@ -10,7 +10,7 @@
'target_name': 'pk11wrap_static',
'type': 'static_library',
'defines': [
'NSS_TEST_BUILD',
'NSS_STATIC_SOFTOKEN',
],
'dependencies': [
'pk11wrap_base',
+10 -8
View File
@@ -492,14 +492,16 @@ typedef struct {
static SECStatus
collect_certs(void *arg, SECItem **certs, int numcerts)
{
SECStatus rv;
collect_args *collectArgs;
collectArgs = (collect_args *)arg;
rv = SECITEM_CopyItem(collectArgs->arena, &collectArgs->cert, *certs);
return (rv);
collect_args *collectArgs = (collect_args *)arg;
if (!collectArgs || !collectArgs->arena) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (numcerts < 1 || !certs || !*certs) {
PORT_SetError(SEC_ERROR_BAD_DER);
return SECFailure;
}
return SECITEM_CopyItem(collectArgs->arena, &collectArgs->cert, *certs);
}
/*
+5
View File
@@ -12,6 +12,7 @@
#include "lowkeyi.h"
#include "secoid.h"
#include "secerr.h"
#include "pkcs11i.h"
/*
* different platforms have different ways of calling and initial entry point
@@ -626,6 +627,10 @@ sftk_startup_tests(void)
* the token */
return;
}
rv = sftk_fips_IKE_PowerUpSelfTests();
if (rv != SECSuccess) {
return;
}
sftk_self_tests_success = PR_TRUE;
}
+3 -3
View File
@@ -950,9 +950,9 @@ lg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
case CKA_UNWRAP:
return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
case CKA_VALUE:
return lg_CopyPrivAttrSigned(attribute, type,
key->u.ec.privateValue.data,
key->u.ec.privateValue.len, sdbpw);
return lg_CopyPrivAttribute(attribute, type,
key->u.ec.privateValue.data,
key->u.ec.privateValue.len, sdbpw);
case CKA_EC_PARAMS:
return lg_CopyAttributeSigned(attribute, type,
key->u.ec.ecParams.DEREncoding.data,
+27
View File
@@ -261,6 +261,7 @@ NSSLOWKEYPublicKey *
nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
{
NSSLOWKEYPublicKey *pubk;
SECItem publicValue;
PLArenaPool *arena;
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
@@ -301,6 +302,19 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
pubk->arena = arena;
pubk->keyType = privk->keyType;
/* if the public key value doesn't exist, calculate it */
if (privk->u.dsa.publicValue.len == 0) {
rv = DH_Derive(&privk->u.dsa.params.base, &privk->u.dsa.params.prime,
&privk->u.dsa.privateValue, &publicValue, 0);
if (rv != SECSuccess) {
break;
}
rv = SECITEM_CopyItem(privk->arena, &privk->u.dsa.publicValue, &publicValue);
SECITEM_FreeItem(&publicValue, PR_FALSE);
if (rv != SECSuccess) {
break;
}
}
rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
&privk->u.dsa.publicValue);
if (rv != SECSuccess)
@@ -327,6 +341,19 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
pubk->arena = arena;
pubk->keyType = privk->keyType;
/* if the public key value doesn't exist, calculate it */
if (privk->u.dh.publicValue.len == 0) {
rv = DH_Derive(&privk->u.dh.base, &privk->u.dh.prime,
&privk->u.dh.privateValue, &publicValue, 0);
if (rv != SECSuccess) {
break;
}
rv = SECITEM_CopyItem(privk->arena, &privk->u.dh.publicValue, &publicValue);
SECITEM_FreeItem(&publicValue, PR_FALSE);
if (rv != SECSuccess) {
break;
}
}
rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
&privk->u.dh.publicValue);
if (rv != SECSuccess)
+1
View File
@@ -46,6 +46,7 @@ CSRCS = \
sdb.c \
sftkdb.c \
sftkhmac.c \
sftkike.c \
sftkpars.c \
sftkpwd.c \
softkver.c \
+122 -2
View File
@@ -328,6 +328,8 @@ static const struct mechanismList mechanisms[] = {
{ CKM_AES_CTS, { 16, 32, CKF_EN_DE }, PR_TRUE },
{ CKM_AES_CTR, { 16, 32, CKF_EN_DE }, PR_TRUE },
{ CKM_AES_GCM, { 16, 32, CKF_EN_DE }, PR_TRUE },
{ CKM_AES_XCBC_MAC_96, { 16, 16, CKF_SN_VR }, PR_TRUE },
{ CKM_AES_XCBC_MAC, { 16, 16, CKF_SN_VR }, PR_TRUE },
/* ------------------------- Camellia Operations --------------------- */
{ CKM_CAMELLIA_KEY_GEN, { 16, 32, CKF_GENERATE }, PR_TRUE },
{ CKM_CAMELLIA_ECB, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
@@ -346,6 +348,7 @@ static const struct mechanismList mechanisms[] = {
/* ------------------------- ChaCha20 Operations ---------------------- */
{ CKM_NSS_CHACHA20_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE },
{ CKM_NSS_CHACHA20_POLY1305, { 32, 32, CKF_EN_DE }, PR_TRUE },
{ CKM_NSS_CHACHA20_CTR, { 32, 32, CKF_EN_DE }, PR_TRUE },
#endif /* NSS_DISABLE_CHACHAPOLY */
/* ------------------------- Hashing Operations ----------------------- */
{ CKM_MD2, { 0, 0, CKF_DIGEST }, PR_FALSE },
@@ -509,7 +512,11 @@ static const struct mechanismList mechanisms[] = {
{ CKM_NSS_JPAKE_FINAL_SHA512, { 0, 0, CKF_DERIVE }, PR_TRUE },
/* -------------------- Constant Time TLS MACs ----------------------- */
{ CKM_NSS_HMAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE },
{ CKM_NSS_SSL3_MAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE }
{ CKM_NSS_SSL3_MAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE },
/* --------------------IPSEC ----------------------- */
{ CKM_NSS_IKE_PRF_PLUS_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE },
{ CKM_NSS_IKE_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE },
{ CKM_NSS_IKE1_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE }
};
static const CK_ULONG mechanismCount = sizeof(mechanisms) / sizeof(mechanisms[0]);
@@ -2199,6 +2206,119 @@ sftk_GetPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp)
return priv;
}
/* populate a public key object from a lowpublic keys structure */
CK_RV
sftk_PutPubKey(SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType, NSSLOWKEYPublicKey *pubKey)
{
CK_OBJECT_CLASS classType = CKO_PUBLIC_KEY;
CK_BBOOL cktrue = CK_TRUE;
CK_RV crv = CKR_OK;
sftk_DeleteAttributeType(publicKey, CKA_CLASS);
sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE);
sftk_DeleteAttributeType(publicKey, CKA_VALUE);
switch (keyType) {
case CKK_RSA:
sftk_DeleteAttributeType(publicKey, CKA_MODULUS);
sftk_DeleteAttributeType(publicKey, CKA_PUBLIC_EXPONENT);
/* format the keys */
/* fill in the RSA dependent paramenters in the public key */
crv = sftk_AddAttributeType(publicKey, CKA_MODULUS,
sftk_item_expand(&pubKey->u.rsa.modulus));
if (crv != CKR_OK) {
break;
}
crv = sftk_AddAttributeType(publicKey, CKA_PUBLIC_EXPONENT,
sftk_item_expand(&pubKey->u.rsa.publicExponent));
break;
case CKK_DSA:
sftk_DeleteAttributeType(publicKey, CKA_PRIME);
sftk_DeleteAttributeType(publicKey, CKA_SUBPRIME);
sftk_DeleteAttributeType(publicKey, CKA_BASE);
crv = sftk_AddAttributeType(publicKey, CKA_PRIME,
sftk_item_expand(&pubKey->u.dsa.params.prime));
if (crv != CKR_OK) {
break;
}
crv = sftk_AddAttributeType(publicKey, CKA_SUBPRIME,
sftk_item_expand(&pubKey->u.dsa.params.subPrime));
if (crv != CKR_OK) {
break;
}
crv = sftk_AddAttributeType(publicKey, CKA_BASE,
sftk_item_expand(&pubKey->u.dsa.params.base));
if (crv != CKR_OK) {
break;
}
crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
sftk_item_expand(&pubKey->u.dsa.publicValue));
break;
case CKK_DH:
sftk_DeleteAttributeType(publicKey, CKA_PRIME);
sftk_DeleteAttributeType(publicKey, CKA_BASE);
crv = sftk_AddAttributeType(publicKey, CKA_PRIME,
sftk_item_expand(&pubKey->u.dh.prime));
if (crv != CKR_OK) {
break;
}
crv = sftk_AddAttributeType(publicKey, CKA_BASE,
sftk_item_expand(&pubKey->u.dh.base));
if (crv != CKR_OK) {
break;
}
crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
sftk_item_expand(&pubKey->u.dh.publicValue));
break;
case CKK_EC:
sftk_DeleteAttributeType(publicKey, CKA_EC_PARAMS);
sftk_DeleteAttributeType(publicKey, CKA_EC_POINT);
crv = sftk_AddAttributeType(publicKey, CKA_EC_PARAMS,
sftk_item_expand(&pubKey->u.ec.ecParams.DEREncoding));
if (crv != CKR_OK) {
break;
}
crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
sftk_item_expand(&pubKey->u.ec.publicValue));
break;
default:
return CKR_KEY_TYPE_INCONSISTENT;
}
crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &classType,
sizeof(CK_OBJECT_CLASS));
if (crv != CKR_OK)
return crv;
crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &keyType,
sizeof(CK_KEY_TYPE));
if (crv != CKR_OK)
return crv;
/* now handle the operator attributes */
if (sftk_isTrue(privateKey, CKA_DECRYPT)) {
crv = sftk_forceAttribute(publicKey, CKA_ENCRYPT, &cktrue, sizeof(CK_BBOOL));
if (crv != CKR_OK) {
return crv;
}
}
if (sftk_isTrue(privateKey, CKA_SIGN)) {
crv = sftk_forceAttribute(publicKey, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
if (crv != CKR_OK) {
return crv;
}
}
if (sftk_isTrue(privateKey, CKA_SIGN_RECOVER)) {
crv = sftk_forceAttribute(publicKey, CKA_VERIFY_RECOVER, &cktrue, sizeof(CK_BBOOL));
if (crv != CKR_OK) {
return crv;
}
}
if (sftk_isTrue(privateKey, CKA_DERIVE)) {
crv = sftk_forceAttribute(publicKey, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
if (crv != CKR_OK) {
return crv;
}
}
return crv;
}
/*
**************************** Symetric Key utils ************************
*/
@@ -3156,7 +3276,7 @@ nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS)
* this call doesn't force freebl to be reloaded. */
BL_SetForkState(PR_FALSE);
#ifndef NSS_TEST_BUILD
#ifndef NSS_STATIC_SOFTOKEN
/* unload freeBL shared library from memory. This may only decrement the
* OS refcount if it's been loaded multiple times, eg. by libssl */
BL_Unload();
+226 -45
View File
@@ -96,42 +96,10 @@ sftk_Space(void *data, PRBool freeit)
/*
* map all the SEC_ERROR_xxx error codes that may be returned by freebl
* functions to CKR_xxx. return CKR_DEVICE_ERROR by default for backward
* compatibility.
* functions to CKR_xxx. Most of the mapping is done in
* sftk_mapCryptError (now in pkcs11u.c). The next two functions adjust
* that mapping based for different contexts (Decrypt or Verify).
*/
static CK_RV
sftk_MapCryptError(int error)
{
switch (error) {
case SEC_ERROR_INVALID_ARGS:
case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */
return CKR_ARGUMENTS_BAD;
case SEC_ERROR_INPUT_LEN:
return CKR_DATA_LEN_RANGE;
case SEC_ERROR_OUTPUT_LEN:
return CKR_BUFFER_TOO_SMALL;
case SEC_ERROR_LIBRARY_FAILURE:
return CKR_GENERAL_ERROR;
case SEC_ERROR_NO_MEMORY:
return CKR_HOST_MEMORY;
case SEC_ERROR_BAD_SIGNATURE:
return CKR_SIGNATURE_INVALID;
case SEC_ERROR_INVALID_KEY:
return CKR_KEY_SIZE_RANGE;
case SEC_ERROR_BAD_KEY: /* an EC public key that fails validation */
return CKR_KEY_SIZE_RANGE; /* the closest error code */
case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM:
return CKR_TEMPLATE_INCONSISTENT;
case SEC_ERROR_UNSUPPORTED_KEYALG:
return CKR_MECHANISM_INVALID;
case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE:
return CKR_DOMAIN_PARAMS_INVALID;
/* key pair generation failed after max number of attempts */
case SEC_ERROR_NEED_RANDOM:
return CKR_FUNCTION_FAILED;
}
return CKR_DEVICE_ERROR;
}
/* used by Decrypt and UnwrapKey (indirectly) */
static CK_RV
@@ -760,6 +728,32 @@ sftk_ChaCha20Poly1305_Decrypt(const SFTKChaCha20Poly1305Info *ctx,
sizeof(ctx->nonce), ad, ctx->adLen);
}
static SECStatus
sftk_ChaCha20Ctr(const SFTKChaCha20CtrInfo *ctx,
unsigned char *output, unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
if (maxOutputLen < inputLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
ChaCha20_Xor(output, input, inputLen, ctx->key,
ctx->nonce, ctx->counter);
*outputLen = inputLen;
return SECSuccess;
}
static void
sftk_ChaCha20Ctr_DestroyContext(SFTKChaCha20CtrInfo *ctx,
PRBool freeit)
{
memset(ctx, 0, sizeof(*ctx));
if (freeit) {
PORT_Free(ctx);
}
}
/** NSC_CryptInit initializes an encryption/Decryption operation.
*
* Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey.
@@ -1180,6 +1174,51 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
context->destroy = (SFTKDestroy)sftk_ChaCha20Poly1305_DestroyContext;
break;
case CKM_NSS_CHACHA20_CTR: {
SFTKChaCha20CtrInfo *ctx;
PRUint8 *param;
int i;
if (key_type != CKK_NSS_CHACHA20) {
crv = CKR_KEY_TYPE_INCONSISTENT;
break;
}
if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != 16) {
crv = CKR_MECHANISM_PARAM_INVALID;
break;
}
att = sftk_FindAttribute(key, CKA_VALUE);
if (att == NULL) {
crv = CKR_KEY_HANDLE_INVALID;
break;
}
ctx = PORT_ZNew(SFTKChaCha20CtrInfo);
if (!ctx) {
sftk_FreeAttribute(att);
crv = CKR_HOST_MEMORY;
break;
}
if (att->attrib.ulValueLen != sizeof(ctx->key)) {
sftk_FreeAttribute(att);
PORT_Free(ctx);
crv = CKR_KEY_HANDLE_INVALID;
break;
}
memcpy(ctx->key, att->attrib.pValue, att->attrib.ulValueLen);
sftk_FreeAttribute(att);
/* The counter is little endian. */
param = pMechanism->pParameter;
i = 0;
for (; i < 4; ++i) {
ctx->counter |= param[i] << (i * 8);
}
memcpy(ctx->nonce, param + 4, 12);
context->cipherInfo = ctx;
context->update = (SFTKCipher)sftk_ChaCha20Ctr;
context->destroy = (SFTKDestroy)sftk_ChaCha20Ctr_DestroyContext;
break;
}
case CKM_NSS_AES_KEY_WRAP_PAD:
context->doPad = PR_TRUE;
/* fall thru */
@@ -2080,9 +2119,12 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
#endif
unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE];
unsigned char k2[SFTK_MAX_BLOCK_SIZE];
unsigned char k3[SFTK_MAX_BLOCK_SIZE];
SFTKSessionContext *context;
CK_RV crv;
unsigned int blockSize;
PRBool isXCBC = PR_FALSE;
switch (pMechanism->mechanism) {
case CKM_RC2_MAC_GENERAL:
@@ -2186,6 +2228,26 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
cbc_mechanism.pParameter = &ivBlock;
cbc_mechanism.ulParameterLen = blockSize;
break;
case CKM_AES_XCBC_MAC_96:
case CKM_AES_XCBC_MAC:
/* The only difference between CKM_AES_XCBC_MAC
* and CKM_AES_XCBC_MAC_96 is the size of the returned mac. */
mac_bytes = pMechanism->mechanism == CKM_AES_XCBC_MAC_96 ? 12 : 16;
blockSize = 16;
PORT_Memset(ivBlock, 0, blockSize);
cbc_mechanism.mechanism = CKM_AES_CBC;
cbc_mechanism.pParameter = &ivBlock;
cbc_mechanism.ulParameterLen = blockSize;
/* is XCBC requires extra processing at the end of the operation */
isXCBC = PR_TRUE;
/* The input key is used to generate k1, k2, and k3. k2 and k3
* are used at the end in the pad step. k1 replaces the input
* key in the aes cbc mac */
crv = sftk_aes_xcbc_new_keys(hSession, hKey, &hKey, k2, k3);
if (crv != CKR_OK) {
return crv;
}
break;
default:
return CKR_FUNCTION_NOT_SUPPORTED;
}
@@ -2195,24 +2257,43 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
if (mac_bytes == SFTK_INVALID_MAC_SIZE)
mac_bytes = blockSize >> 1;
else {
if (mac_bytes > blockSize)
return CKR_MECHANISM_PARAM_INVALID;
if (mac_bytes > blockSize) {
crv = CKR_MECHANISM_PARAM_INVALID;
goto fail;
}
}
crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey,
CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */
keyUsage, contextType, PR_TRUE);
if (crv != CKR_OK)
return crv;
goto fail;
crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL);
/* this shouldn't happen! */
PORT_Assert(crv == CKR_OK);
if (crv != CKR_OK)
return crv;
goto fail;
context->blockSize = blockSize;
context->macSize = mac_bytes;
context->isXCBC = isXCBC;
if (isXCBC) {
/* save the xcbc specific parameters */
PORT_Memcpy(context->k2, k2, blockSize);
PORT_Memcpy(context->k3, k3, blockSize);
PORT_Memset(k2, 0, blockSize);
PORT_Memset(k3, 0, blockSize);
/* get rid of the temp key now that the context has been created */
NSC_DestroyObject(hSession, hKey);
}
return CKR_OK;
fail:
if (isXCBC) {
PORT_Memset(k2, 0, blockSize);
PORT_Memset(k3, 0, blockSize);
NSC_DestroyObject(hSession, hKey); /* get rid of our temp key */
}
return crv;
}
/*
@@ -2828,6 +2909,13 @@ sftk_MACFinal(SFTKSessionContext *ctx)
{
unsigned int padLen = ctx->padDataLength;
/* pad and proceed the residual */
if (ctx->isXCBC) {
CK_RV crv = sftk_xcbc_mac_pad(ctx->padBuf, padLen, ctx->blockSize,
ctx->k2, ctx->k3);
if (crv != CKR_OK)
return crv;
return sftk_MACBlock(ctx, ctx->padBuf);
}
if (padLen) {
/* shd clr ctx->padLen to make sftk_MACFinal idempotent */
PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen);
@@ -2866,7 +2954,7 @@ sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
blkSize - context->padDataLength;
/* not enough data even for one block */
if (ulPartLen < minInput) {
if (ulPartLen <= minInput) {
PORT_Memcpy(residual, pPart, ulPartLen);
context->padDataLength += ulPartLen;
goto cleanup;
@@ -2880,7 +2968,7 @@ sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
goto terminate;
}
/* MACing full blocks */
while (ulPartLen >= blkSize) {
while (ulPartLen > blkSize) {
if (CKR_OK != (crv = sftk_MACBlock(context, pPart)))
goto terminate;
ulPartLen -= blkSize;
@@ -4645,6 +4733,13 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
return crv;
}
/* detect trivial signing transforms */
if ((signature_length >= pairwise_digest_length) &&
(PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) {
PORT_Free(signature);
return CKR_DEVICE_ERROR;
}
/* Verify the known hash using the public key. */
crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
if (crv != CKR_OK) {
@@ -6478,6 +6573,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
extractValue = PR_FALSE;
classType = CKO_PRIVATE_KEY;
break;
case CKM_NSS_PUB_FROM_PRIV:
extractValue = PR_FALSE;
classType = CKO_PUBLIC_KEY;
break;
case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */
case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
@@ -6519,6 +6618,73 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
}
switch (mechanism) {
/* get a public key from a private key. nsslowkey_ConvertToPublickey()
* will generate the public portion if it doesn't already exist. */
case CKM_NSS_PUB_FROM_PRIV: {
NSSLOWKEYPrivateKey *privKey;
NSSLOWKEYPublicKey *pubKey;
int error;
crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType);
if (crv != CKR_OK) {
break;
}
/* privKey is stored in sourceKey and will be destroyed when
* the sourceKey is freed. */
privKey = sftk_GetPrivKey(sourceKey, keyType, &crv);
if (privKey == NULL) {
break;
}
pubKey = nsslowkey_ConvertToPublicKey(privKey);
if (pubKey == NULL) {
error = PORT_GetError();
crv = sftk_MapCryptError(error);
break;
}
crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey);
nsslowkey_DestroyPublicKey(pubKey);
break;
}
case CKM_NSS_IKE_PRF_DERIVE:
if (pMechanism->ulParameterLen !=
sizeof(CK_NSS_IKE_PRF_DERIVE_PARAMS)) {
crv = CKR_MECHANISM_PARAM_INVALID;
break;
}
crv = sftk_ike_prf(hSession, att,
(CK_NSS_IKE_PRF_DERIVE_PARAMS *)pMechanism->pParameter, key);
break;
case CKM_NSS_IKE1_PRF_DERIVE:
if (pMechanism->ulParameterLen !=
sizeof(CK_NSS_IKE1_PRF_DERIVE_PARAMS)) {
crv = CKR_MECHANISM_PARAM_INVALID;
break;
}
crv = sftk_ike1_prf(hSession, att,
(CK_NSS_IKE1_PRF_DERIVE_PARAMS *)pMechanism->pParameter,
key, keySize);
break;
case CKM_NSS_IKE1_APP_B_PRF_DERIVE:
if (pMechanism->ulParameterLen !=
sizeof(CK_MECHANISM_TYPE)) {
crv = CKR_MECHANISM_PARAM_INVALID;
break;
}
crv = sftk_ike1_appendix_b_prf(hSession, att,
(CK_MECHANISM_TYPE *)pMechanism->pParameter,
key, keySize);
break;
case CKM_NSS_IKE_PRF_PLUS_DERIVE:
if (pMechanism->ulParameterLen !=
sizeof(CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS)) {
crv = CKR_MECHANISM_PARAM_INVALID;
break;
}
crv = sftk_ike_prf_plus(hSession, att,
(CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *)pMechanism->pParameter,
key, keySize);
break;
/*
* generate the master secret
*/
@@ -7481,14 +7647,14 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
case CKM_DH_PKCS_DERIVE: {
SECItem derived, dhPublic;
SECItem dhPrime, dhValue;
SECItem dhPrime, dhSubPrime, dhValue;
/* sourceKey - values for the local existing low key */
/* get prime and value attributes */
crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
if (crv != SECSuccess)
if (crv != CKR_OK)
break;
crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
if (crv != SECSuccess) {
if (crv != CKR_OK) {
PORT_Free(dhPrime.data);
break;
}
@@ -7496,6 +7662,20 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
dhPublic.data = pMechanism->pParameter;
dhPublic.len = pMechanism->ulParameterLen;
/* If the caller bothered to provide Q, use Q to validate
* the public key. */
crv = sftk_Attribute2SecItem(NULL, &dhSubPrime, sourceKey, CKA_SUBPRIME);
if (crv == CKR_OK) {
rv = KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime);
PORT_Free(dhSubPrime.data);
if (rv != SECSuccess) {
crv = CKR_ARGUMENTS_BAD;
PORT_Free(dhPrime.data);
PORT_Free(dhValue.data);
break;
}
}
/* calculate private value - oct */
rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
@@ -7505,6 +7685,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
if (rv == SECSuccess) {
sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
PORT_ZFree(derived.data, derived.len);
crv = CKR_OK;
} else
crv = CKR_HOST_MEMORY;
@@ -7570,7 +7751,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
withCofactor, &tmp);
PORT_Free(ecScalar.data);
PORT_ZFree(ecScalar.data, ecScalar.len);
ecScalar.data = NULL;
if (privKey != sourceKey->objectInfo) {
nsslowkey_DestroyPrivateKey(privKey);
+39
View File
@@ -106,6 +106,7 @@ typedef struct SFTKOAEPEncryptInfoStr SFTKOAEPEncryptInfo;
typedef struct SFTKOAEPDecryptInfoStr SFTKOAEPDecryptInfo;
typedef struct SFTKSSLMACInfoStr SFTKSSLMACInfo;
typedef struct SFTKChaCha20Poly1305InfoStr SFTKChaCha20Poly1305Info;
typedef struct SFTKChaCha20CtrInfoStr SFTKChaCha20CtrInfo;
typedef struct SFTKItemTemplateStr SFTKItemTemplate;
/* define function pointer typdefs for pointer tables */
@@ -253,12 +254,15 @@ struct SFTKSessionContextStr {
PRBool multi; /* is multipart */
PRBool rsa; /* is rsa */
PRBool doPad; /* use PKCS padding for block ciphers */
PRBool isXCBC; /* xcbc, use special handling in final */
unsigned int blockSize; /* blocksize for padding */
unsigned int padDataLength; /* length of the valid data in padbuf */
/** latest incomplete block of data for block cipher */
unsigned char padBuf[SFTK_MAX_BLOCK_SIZE];
/** result of MAC'ing of latest full block of data with block cipher */
unsigned char macBuf[SFTK_MAX_BLOCK_SIZE];
unsigned char k2[SFTK_MAX_BLOCK_SIZE];
unsigned char k3[SFTK_MAX_BLOCK_SIZE];
CK_ULONG macSize; /* size of a general block cipher mac*/
void *cipherInfo;
void *hashInfo;
@@ -409,6 +413,14 @@ struct SFTKChaCha20Poly1305InfoStr {
unsigned int adLen;
};
/* SFTKChaCha20BlockInfoStr the key, nonce and counter for a
* ChaCha20 block operation. */
struct SFTKChaCha20CtrInfoStr {
PRUint8 key[32];
PRUint8 nonce[12];
PRUint32 counter;
};
/*
* Template based on SECItems, suitable for passing as arrays
*/
@@ -605,6 +617,7 @@ extern CK_RV SFTK_ShutdownSlot(SFTKSlot *slot);
extern CK_RV sftk_CloseAllSessions(SFTKSlot *slot, PRBool logout);
/* internal utility functions used by pkcs11.c */
extern CK_RV sftk_MapCryptError(int error);
extern SFTKAttribute *sftk_FindAttribute(SFTKObject *object,
CK_ATTRIBUTE_TYPE type);
extern void sftk_FreeAttribute(SFTKAttribute *attribute);
@@ -682,10 +695,36 @@ extern NSSLOWKEYPublicKey *sftk_GetPubKey(SFTKObject *object,
CK_KEY_TYPE key_type, CK_RV *crvp);
extern NSSLOWKEYPrivateKey *sftk_GetPrivKey(SFTKObject *object,
CK_KEY_TYPE key_type, CK_RV *crvp);
extern CK_RV sftk_PutPubKey(SFTKObject *publicKey, SFTKObject *privKey, CK_KEY_TYPE keyType,
NSSLOWKEYPublicKey *pubKey);
extern void sftk_FormatDESKey(unsigned char *key, int length);
extern PRBool sftk_CheckDESKey(unsigned char *key);
extern PRBool sftk_IsWeakKey(unsigned char *key, CK_KEY_TYPE key_type);
/* ike and xcbc helpers */
extern CK_RV sftk_ike_prf(CK_SESSION_HANDLE hSession,
const SFTKAttribute *inKey,
const CK_NSS_IKE_PRF_DERIVE_PARAMS *params, SFTKObject *outKey);
extern CK_RV sftk_ike1_prf(CK_SESSION_HANDLE hSession,
const SFTKAttribute *inKey,
const CK_NSS_IKE1_PRF_DERIVE_PARAMS *params, SFTKObject *outKey,
unsigned int keySize);
extern CK_RV sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession,
const SFTKAttribute *inKey,
const CK_MECHANISM_TYPE *params, SFTKObject *outKey,
unsigned int keySize);
extern CK_RV sftk_ike_prf_plus(CK_SESSION_HANDLE hSession,
const SFTKAttribute *inKey,
const CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *params, SFTKObject *outKey,
unsigned int keySize);
extern CK_RV sftk_aes_xcbc_new_keys(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE_PTR phKey,
unsigned char *k2, unsigned char *k3);
extern CK_RV sftk_xcbc_mac_pad(unsigned char *padBuf, unsigned int bufLen,
int blockSize, const unsigned char *k2,
const unsigned char *k3);
extern SECStatus sftk_fips_IKE_PowerUpSelfTests(void);
/* mechanism allows this operation */
extern CK_RV sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op);
+41
View File
@@ -14,6 +14,47 @@
#include "sftkdb.h"
#include "softoken.h"
/*
* ******************** Error mapping *******************************
*/
/*
* map all the SEC_ERROR_xxx error codes that may be returned by freebl
* functions to CKR_xxx. return CKR_DEVICE_ERROR by default for backward
* compatibility.
*/
CK_RV
sftk_MapCryptError(int error)
{
switch (error) {
case SEC_ERROR_INVALID_ARGS:
case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */
return CKR_ARGUMENTS_BAD;
case SEC_ERROR_INPUT_LEN:
return CKR_DATA_LEN_RANGE;
case SEC_ERROR_OUTPUT_LEN:
return CKR_BUFFER_TOO_SMALL;
case SEC_ERROR_LIBRARY_FAILURE:
return CKR_GENERAL_ERROR;
case SEC_ERROR_NO_MEMORY:
return CKR_HOST_MEMORY;
case SEC_ERROR_BAD_SIGNATURE:
return CKR_SIGNATURE_INVALID;
case SEC_ERROR_INVALID_KEY:
return CKR_KEY_SIZE_RANGE;
case SEC_ERROR_BAD_KEY: /* an EC public key that fails validation */
return CKR_KEY_SIZE_RANGE; /* the closest error code */
case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM:
return CKR_TEMPLATE_INCONSISTENT;
case SEC_ERROR_UNSUPPORTED_KEYALG:
return CKR_MECHANISM_INVALID;
case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE:
return CKR_DOMAIN_PARAMS_INVALID;
/* key pair generation failed after max number of attempts */
case SEC_ERROR_NEED_RANDOM:
return CKR_FUNCTION_FAILED;
}
return CKR_DEVICE_ERROR;
}
/*
* ******************** Attribute Utilities *******************************
*/
+64 -45
View File
@@ -859,7 +859,6 @@ sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind)
return sdb_mapSQLError(sdb_p->type, sqlerr);
}
static const char GET_ATTRIBUTE_CMD[] = "SELECT ALL %s FROM %s WHERE id=$ID;";
CK_RV
sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
CK_ATTRIBUTE *template, CK_ULONG count)
@@ -867,14 +866,19 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
SDBPrivate *sdb_p = sdb->private;
sqlite3 *sqlDB = NULL;
sqlite3_stmt *stmt = NULL;
char *getStr = NULL;
char *newStr = NULL;
const char *table = NULL;
int sqlerr = SQLITE_OK;
CK_RV error = CKR_OK;
int found = 0;
int retry = 0;
unsigned int i;
char *columns = NULL;
char *statement;
if (count == 0) {
error = CKR_OBJECT_HANDLE_INVALID;
goto loser;
}
/* open a new db if necessary */
error = sdb_openDBLocal(sdb_p, &sqlDB, &table);
@@ -883,52 +887,66 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
}
for (i = 0; i < count; i++) {
getStr = sqlite3_mprintf("a%x", template[i].type);
if (getStr == NULL) {
char *newColumns;
if (columns) {
newColumns = sqlite3_mprintf("%s, a%x", columns, template[i].type);
sqlite3_free(columns);
columns = NULL;
} else {
newColumns = sqlite3_mprintf("a%x", template[i].type);
}
if (!newColumns) {
error = CKR_HOST_MEMORY;
goto loser;
}
columns = newColumns;
}
newStr = sqlite3_mprintf(GET_ATTRIBUTE_CMD, getStr, table);
sqlite3_free(getStr);
getStr = NULL;
if (newStr == NULL) {
error = CKR_HOST_MEMORY;
goto loser;
PORT_Assert(columns);
statement = sqlite3_mprintf("SELECT DISTINCT %s FROM %s where id=$ID LIMIT 1;",
columns, table);
sqlite3_free(columns);
columns = NULL;
if (!statement) {
error = CKR_HOST_MEMORY;
goto loser;
}
sqlerr = sqlite3_prepare_v2(sqlDB, statement, -1, &stmt, NULL);
sqlite3_free(statement);
statement = NULL;
if (sqlerr != SQLITE_OK) {
goto loser;
}
// NB: indices in sqlite3_bind_int are 1-indexed
sqlerr = sqlite3_bind_int(stmt, 1, object_id);
if (sqlerr != SQLITE_OK) {
goto loser;
}
do {
sqlerr = sqlite3_step(stmt);
if (sqlerr == SQLITE_BUSY) {
PR_Sleep(SDB_BUSY_RETRY_TIME);
}
sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL);
sqlite3_free(newStr);
newStr = NULL;
if (sqlerr == SQLITE_ERROR) {
template[i].ulValueLen = -1;
error = CKR_ATTRIBUTE_TYPE_INVALID;
continue;
} else if (sqlerr != SQLITE_OK) {
goto loser;
}
sqlerr = sqlite3_bind_int(stmt, 1, object_id);
if (sqlerr != SQLITE_OK) {
goto loser;
}
do {
sqlerr = sqlite3_step(stmt);
if (sqlerr == SQLITE_BUSY) {
PR_Sleep(SDB_BUSY_RETRY_TIME);
}
if (sqlerr == SQLITE_ROW) {
if (sqlerr == SQLITE_ROW) {
PORT_Assert(!found);
for (i = 0; i < count; i++) {
unsigned int blobSize;
const char *blobData;
blobSize = sqlite3_column_bytes(stmt, 0);
blobData = sqlite3_column_blob(stmt, 0);
// NB: indices in sqlite_column_{bytes,blob} are 0-indexed
blobSize = sqlite3_column_bytes(stmt, i);
blobData = sqlite3_column_blob(stmt, i);
if (blobData == NULL) {
/* PKCS 11 requires that get attributes process all the
* attributes in the template, marking the attributes with
* issues with -1. Mark the error but continue */
template[i].ulValueLen = -1;
error = CKR_ATTRIBUTE_TYPE_INVALID;
break;
continue;
}
/* If the blob equals our explicit NULL value, then the
* attribute is a NULL. */
@@ -939,20 +957,21 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
}
if (template[i].pValue) {
if (template[i].ulValueLen < blobSize) {
/* like CKR_ATTRIBUTE_TYPE_INVALID, continue processing */
template[i].ulValueLen = -1;
error = CKR_BUFFER_TOO_SMALL;
break;
continue;
}
PORT_Memcpy(template[i].pValue, blobData, blobSize);
}
template[i].ulValueLen = blobSize;
found = 1;
}
} while (!sdb_done(sqlerr, &retry));
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
stmt = NULL;
}
found = 1;
}
} while (!sdb_done(sqlerr, &retry));
sqlite3_reset(stmt);
sqlite3_finalize(stmt);
stmt = NULL;
loser:
/* fix up the error if necessary */
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More