nss: update to 3.44.1, with vc2013 fix and gyp fix

This commit is contained in:
Roy Tam 2019-06-24 21:44:17 +08:00
commit d4b834111b
553 changed files with 1515569 additions and 1130 deletions

View file

@ -21,10 +21,12 @@ tasks:
$if: 'repository.url[-1] == "/"' $if: 'repository.url[-1] == "/"'
then: {$eval: 'repository.url[:-1]'} then: {$eval: 'repository.url[:-1]'}
else: {$eval: 'repository.url'} else: {$eval: 'repository.url'}
# scheduler id
schedulerId: 'nss-level-${repository.level}'
in: in:
taskId: '${ownTaskId}' taskId: '${ownTaskId}'
taskGroupId: '${ownTaskId}' taskGroupId: '${ownTaskId}'
schedulerId: 'nss-level-${repository.level}' schedulerId: '${schedulerId}'
created: {$fromNow: ''} created: {$fromNow: ''}
deadline: {$fromNow: '1 day'} deadline: {$fromNow: '1 day'}
expires: {$fromNow: '14 days'} expires: {$fromNow: '14 days'}
@ -56,6 +58,7 @@ tasks:
TC_OWNER: "${push.owner}" TC_OWNER: "${push.owner}"
TC_SOURCE: "${repository.url}" TC_SOURCE: "${repository.url}"
TC_PROJECT: ${repository.project} TC_PROJECT: ${repository.project}
TC_SCHEDULER_ID: "${schedulerId}"
NSS_PUSHLOG_ID: '${push.pushlog_id}' NSS_PUSHLOG_ID: '${push.pushlog_id}'
NSS_HEAD_REPOSITORY: '${repository.url}' NSS_HEAD_REPOSITORY: '${repository.url}'
NSS_HEAD_REVISION: '${push.revision}' NSS_HEAD_REVISION: '${push.revision}'

View file

@ -87,10 +87,10 @@ ifdef NS_USE_GCC
NSPR_CONFIGURE_ENV = CC=gcc CXX=g++ NSPR_CONFIGURE_ENV = CC=gcc CXX=g++
endif endif
ifdef CC ifdef CC
NSPR_CONFIGURE_ENV = CC=$(CC) NSPR_CONFIGURE_ENV = CC="$(CC)"
endif endif
ifdef CCC ifdef CCC
NSPR_CONFIGURE_ENV += CXX=$(CCC) NSPR_CONFIGURE_ENV += CXX="$(CCC)"
endif endif
# Remove -arch definitions. NSPR can't handle that. # Remove -arch definitions. NSPR can't handle that.
NSPR_CONFIGURE_ENV := $(filter-out -arch x86_64,$(NSPR_CONFIGURE_ENV)) NSPR_CONFIGURE_ENV := $(filter-out -arch x86_64,$(NSPR_CONFIGURE_ENV))

View file

@ -1,5 +1,21 @@
1 Added function: 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1 +1 @@
NSS_3_42_BRANCH NSS_3_43_BRANCH

View file

@ -924,9 +924,13 @@ async function scheduleWindows(name, base, build_script) {
function scheduleTests(task_build, task_cert, test_base) { function scheduleTests(task_build, task_cert, test_base) {
test_base = merge(test_base, {kind: "test"}); 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 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, { queue.scheduleTask(merge(no_cert_base, {
name: "Gtests", symbol: "Gtest", tests: "ssl_gtests gtests", cycle: "standard" 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, { queue.scheduleTask(merge(no_cert_base, {
name: "tlsfuzzer tests", symbol: "tlsfuzzer", tests: "tlsfuzzer", cycle: "standard" 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" 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" 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", name: "Cipher tests", symbol: "NoAESNI", tests: "cipher",
env: {NSS_DISABLE_HW_AES: "1"}, group: "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", name: "Cipher tests", symbol: "NoPCLMUL", tests: "cipher",
env: {NSS_DISABLE_PCLMUL: "1"}, group: "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", name: "Cipher tests", symbol: "NoAVX", tests: "cipher",
env: {NSS_DISABLE_AVX: "1"}, group: "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", name: "Cipher tests", symbol: "NoSSSE3|NEON", tests: "cipher",
env: { env: {
NSS_DISABLE_ARM_NEON: "1", NSS_DISABLE_ARM_NEON: "1",
NSS_DISABLE_SSSE3: "1" NSS_DISABLE_SSSE3: "1"
}, group: "Cipher" }, group: "Cipher"
})); }));
queue.scheduleTask(merge(no_cert_base, { queue.scheduleTask(merge(cert_base, {
name: "EC tests", symbol: "EC", tests: "ec" 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" 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" 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" name: "Policy tests", symbol: "Policy", tests: "policy"
})); }));
// Schedule tests that need certificates. // Schedule tests that need certificates.
let cert_base = merge(test_base, {parent: task_cert});
queue.scheduleTask(merge(cert_base, { queue.scheduleTask(merge(cert_base, {
name: "CRMF tests", symbol: "CRMF", tests: "crmf" name: "CRMF tests", symbol: "CRMF", tests: "crmf"
})); }));

View file

@ -135,7 +135,8 @@ function convertTask(def) {
return { return {
provisionerId: def.provisioner || "aws-provisioner-v1", provisionerId: def.provisioner || "aws-provisioner-v1",
workerType: def.workerType || "hg-worker", workerType: def.workerType || "hg-worker",
schedulerId: "task-graph-scheduler", schedulerId: process.env.TC_SCHEDULER_ID,
taskGroupId: process.env.TASK_ID,
scopes, scopes,
created: fromNow(0), created: fromNow(0),

View file

@ -167,7 +167,7 @@ export async function initFilter() {
let comment = await getCommitComment(); let comment = await getCommitComment();
// Check for try syntax in changeset comment. // 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. // Add try syntax filter.
if (match) { if (match) {

View file

@ -103,6 +103,7 @@ abi_diff()
cat ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt \ cat ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt \
| grep -v "^Functions changes summary:" \ | grep -v "^Functions changes summary:" \
| grep -v "^Variables 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 > ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt
rm -f ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt rm -f ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt

View file

@ -50,6 +50,7 @@ fuzz=0
fuzz_tls=0 fuzz_tls=0
fuzz_oss=0 fuzz_oss=0
no_local_nspr=0 no_local_nspr=0
sslkeylogfile=1
gyp_params=(--depth="$cwd" --generator-output=".") gyp_params=(--depth="$cwd" --generator-output=".")
ninja_params=() ninja_params=()
@ -94,7 +95,8 @@ while [ $# -gt 0 ]; do
--sancov=?*) enable_sancov "${1#*=}" ;; --sancov=?*) enable_sancov "${1#*=}" ;;
--emit-llvm) gyp_params+=(-Demit_llvm=1 -Dsign_libs=0) ;; --emit-llvm) gyp_params+=(-Demit_llvm=1 -Dsign_libs=0) ;;
--no-zdefs) gyp_params+=(-Dno_zdefs=1) ;; --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) ;; --ct-verif) gyp_params+=(-Dct_verif=1) ;;
--nspr) nspr_clean; rebuild_nspr=1 ;; --nspr) nspr_clean; rebuild_nspr=1 ;;
--with-nspr=?*) set_nspr_path "${1#*=}"; no_local_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-fips) gyp_params+=(-Ddisable_fips=0) ;;
--enable-libpkix) gyp_params+=(-Ddisable_libpkix=0) ;; --enable-libpkix) gyp_params+=(-Ddisable_libpkix=0) ;;
--mozpkix-only) gyp_params+=(-Dmozpkix_only=1 -Ddisable_tests=1 -Dsign_libs=0) ;; --mozpkix-only) gyp_params+=(-Dmozpkix_only=1 -Ddisable_tests=1 -Dsign_libs=0) ;;
--disable-keylog) sslkeylogfile=0 ;;
-D*) gyp_params+=("$1") ;; -D*) gyp_params+=("$1") ;;
*) show_help; exit 2 ;; *) show_help; exit 2 ;;
esac esac
@ -117,6 +120,8 @@ else
target=Debug target=Debug
fi fi
#gyp_params+=(-Denable_sslkeylogfile="$sslkeylogfile")
# Do special setup. # Do special setup.
if [ "$fuzz" = 1 ]; then if [ "$fuzz" = 1 ]; then
source "$cwd"/coreconf/fuzz.sh source "$cwd"/coreconf/fuzz.sh

View file

@ -120,6 +120,7 @@ main(int argc, char **argv)
/* Parse command line arguments */ /* Parse command line arguments */
optstate = PL_CreateOptState(argc, argv, "i:o:w:"); optstate = PL_CreateOptState(argc, argv, "i:o:w:");
PORT_Assert(optstate);
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
switch (optstate->option) { switch (optstate->option) {
default: default:
@ -203,9 +204,7 @@ main(int argc, char **argv)
} }
exitCode = 0; exitCode = 0;
loser: loser:
if (optstate) { PL_DestroyOptState(optstate);
PL_DestroyOptState(optstate);
}
if (inFile && closeIn) { if (inFile && closeIn) {
fclose(inFile); fclose(inFile);
} }

View file

@ -497,6 +497,13 @@ static const char *const
"ocspResponder", "ocspResponder",
"stepUp", "stepUp",
"msTrustListSigning", "msTrustListSigning",
"x509Any",
"ipsecIKE",
"ipsecIKEEnd",
"ipsecIKEIntermediate",
"ipsecEnd",
"ipsecTunnel",
"ipsecUser",
NULL }; NULL };
static SECStatus static SECStatus
@ -517,6 +524,10 @@ AddExtKeyUsage(void *extHandle, const char *userSuppliedValue)
while (1) { while (1) {
if (!userSuppliedValue) { 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( if (PrintChoicesAndGetAnswer(
"\t\t0 - Server Auth\n" "\t\t0 - Server Auth\n"
"\t\t1 - Client Auth\n" "\t\t1 - Client Auth\n"
@ -572,6 +583,45 @@ AddExtKeyUsage(void *extHandle, const char *userSuppliedValue)
case 7: case 7:
rv = AddOidToSequence(os, SEC_OID_MS_EXT_KEY_USAGE_CTL_SIGNING); rv = AddOidToSequence(os, SEC_OID_MS_EXT_KEY_USAGE_CTL_SIGNING);
break; 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: default:
goto endloop; goto endloop;
} }

View file

@ -1362,8 +1362,11 @@ luC(enum usage_level ul, const char *command)
"%-20s Create extended key usage extension. Possible keywords:\n" "%-20s Create extended key usage extension. Possible keywords:\n"
"%-20s \"serverAuth\", \"clientAuth\",\"codeSigning\",\n" "%-20s \"serverAuth\", \"clientAuth\",\"codeSigning\",\n"
"%-20s \"emailProtection\", \"timeStamp\",\"ocspResponder\",\n" "%-20s \"emailProtection\", \"timeStamp\",\"ocspResponder\",\n"
"%-20s \"stepUp\", \"msTrustListSign\", \"critical\"\n", "%-20s \"stepUp\", \"msTrustListSign\", \"x509Any\",\n"
" -6 | --extKeyUsage keyword,keyword,...", "", "", "", ""); "%-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", FPS "%-20s Create an email subject alt name extension\n",
" -7 emailAddrs"); " -7 emailAddrs");
FPS "%-20s Create an dns subject alt name extension\n", 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, PR_fprintf(PR_STDERR,
"%s -%c: specify a nickname (-n) or\n" "%s -%c: specify a nickname (-n) or\n"
" a key ID (-k).\n", " a key ID (-k).\n",
commandToRun, progName); progName, commandToRun);
return 255; return 255;
} }

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

View file

@ -185,7 +185,7 @@ cleanup:
} }
static const char *const usageInfo[] = { static const char *const usageInfo[] = {
"pk11import - test PK11_PrivateKeyImport()" "pk11import - test PK11_PrivateKeyImport()",
"Options:", "Options:",
" -d certdir directory containing cert database", " -d certdir directory containing cert database",
" -k keysize size of the rsa, dh, and dsa key to test (default 1024)", " -k keysize size of the rsa, dh, and dsa key to test (default 1024)",

View file

@ -233,7 +233,9 @@ PrintParameterUsage()
" ecdsa_secp521r1_sha512,\n" " ecdsa_secp521r1_sha512,\n"
" rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_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" " 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); stderr);
} }
@ -804,6 +806,7 @@ PRBool failedToNegotiateName = PR_FALSE;
PRBool enableExtendedMasterSecret = PR_FALSE; PRBool enableExtendedMasterSecret = PR_FALSE;
PRBool zeroRTT = PR_FALSE; PRBool zeroRTT = PR_FALSE;
PRBool enableALPN = PR_FALSE; PRBool enableALPN = PR_FALSE;
PRBool enablePostHandshakeAuth = PR_FALSE;
SSLNamedGroup *enabledGroups = NULL; SSLNamedGroup *enabledGroups = NULL;
unsigned int enabledGroupsCount = 0; unsigned int enabledGroupsCount = 0;
const SSLSignatureScheme *enabledSigSchemes = NULL; const SSLSignatureScheme *enabledSigSchemes = NULL;
@ -1431,15 +1434,28 @@ handle_connection(PRFileDesc *tcp_sock, PRFileDesc *model_sock)
errWarn("second SSL_OptionSet SSL_REQUIRE_CERTIFICATE"); errWarn("second SSL_OptionSet SSL_REQUIRE_CERTIFICATE");
break; break;
} }
rv = SSL_ReHandshake(ssl_sock, PR_TRUE); if (enablePostHandshakeAuth) {
if (rv != 0) { rv = SSL_SendCertificateRequest(ssl_sock);
errWarn("SSL_ReHandshake"); if (rv != SECSuccess) {
break; errWarn("SSL_SendCertificateRequest");
} break;
rv = SSL_ForceHandshake(ssl_sock); }
if (rv < 0) { rv = SSL_ForceHandshake(ssl_sock);
errWarn("SSL_ForceHandshake"); if (rv != SECSuccess) {
break; 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) { if (enableALPN) {
PRUint8 alpnVal[] = { 0x08, PRUint8 alpnVal[] = { 0x08,
0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 }; 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. ** in 3.28, please leave some time before resuing those.
** 'z' was removed in 3.39. */ ** 'z' was removed in 3.39. */
optstate = PL_CreateOptState(argc, argv, 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) { while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
++optionsFound; ++optionsFound;
switch (optstate->option) { switch (optstate->option) {
@ -2243,6 +2269,11 @@ main(int argc, char **argv)
case 'D': case 'D':
noDelay = PR_TRUE; noDelay = PR_TRUE;
break; break;
case 'E':
enablePostHandshakeAuth = PR_TRUE;
break;
case 'H': case 'H':
configureDHE = (PORT_Atoi(optstate->value) != 0); configureDHE = (PORT_Atoi(optstate->value) != 0);
break; break;

View file

@ -221,7 +221,7 @@ PrintUsageHeader()
fprintf(stderr, fprintf(stderr,
"Usage: %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n" "Usage: %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n"
" [-D | -d certdir] [-C] [-b | -R root-module] \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" " [-V [min-version]:[max-version]] [-K] [-T] [-U]\n"
" [-r N] [-w passwd] [-W pwfile] [-q [-t seconds]]\n" " [-r N] [-w passwd] [-W pwfile] [-q [-t seconds]]\n"
" [-I groups] [-J signatureschemes]\n" " [-I groups] [-J signatureschemes]\n"
@ -311,6 +311,9 @@ PrintParameterUsage()
fprintf(stderr, "%-20s Use DTLS\n", "-P {client, server}"); fprintf(stderr, "%-20s Use DTLS\n", "-P {client, server}");
fprintf(stderr, "%-20s Exit after handshake\n", "-Q"); fprintf(stderr, "%-20s Exit after handshake\n", "-Q");
fprintf(stderr, "%-20s Encrypted SNI Keys\n", "-N"); 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 static void
@ -989,6 +992,7 @@ PRBool requestToExit = PR_FALSE;
char *versionString = NULL; char *versionString = NULL;
PRBool handshakeComplete = PR_FALSE; PRBool handshakeComplete = PR_FALSE;
char *encryptedSNIKeys = NULL; char *encryptedSNIKeys = NULL;
PRBool enablePostHandshakeAuth = PR_FALSE;
static int static int
writeBytesToServer(PRFileDesc *s, const PRUint8 *buf, int nb) writeBytesToServer(PRFileDesc *s, const PRUint8 *buf, int nb)
@ -1410,6 +1414,15 @@ run()
goto done; 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) { if (enabledGroups) {
rv = SSL_NamedGroupConfig(s, enabledGroups, enabledGroupsCount); rv = SSL_NamedGroupConfig(s, enabledGroups, enabledGroupsCount);
if (rv < 0) { if (rv < 0) {
@ -1707,7 +1720,7 @@ main(int argc, char **argv)
* Please leave some time before reusing these. * Please leave some time before reusing these.
*/ */
optstate = PL_CreateOptState(argc, argv, 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) { while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
switch (optstate->option) { switch (optstate->option) {
case '?': case '?':
@ -1738,6 +1751,10 @@ main(int argc, char **argv)
openDB = PR_FALSE; openDB = PR_FALSE;
break; break;
case 'E':
enablePostHandshakeAuth = PR_TRUE;
break;
case 'F': case 'F':
if (serverCertAuth.testFreshStatusFromSideChannel) { if (serverCertAuth.testFreshStatusFromSideChannel) {
/* parameter given twice or more */ /* parameter given twice or more */
@ -1988,6 +2005,11 @@ main(int argc, char **argv)
exit(1); 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); PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
PK11_SetPasswordFunc(SECU_GetModulePassword); PK11_SetPasswordFunc(SECU_GetModulePassword);

View file

@ -135,6 +135,10 @@ ifeq ($(KERNEL),Linux)
endif endif
OS_LIBS = $(OS_PTHREAD) -ldl -lc OS_LIBS = $(OS_PTHREAD) -ldl -lc
ifeq ($(OS_TARGET),Android)
OS_LIBS += -llog
endif
ifdef USE_PTHREADS ifdef USE_PTHREADS
DEFINES += -D_REENTRANT DEFINES += -D_REENTRANT
endif endif

View file

@ -5,17 +5,18 @@ import subprocess
import sys import sys
def main(): def main():
if sys.platform == 'win32': if sys.platform == 'win32' or len(sys.argv) < 2:
print(0) print(0)
else: else:
cc = os.environ.get('CC', 'cc') cc = os.environ.get('CC', 'cc')
try: try:
cc_is_clang = 'clang' in subprocess.check_output( cc_is_arg = sys.argv[1] in subprocess.check_output(
[cc, '--version'], universal_newlines=True) [cc, '--version'], universal_newlines=True)
except OSError: except OSError:
# We probably just don't have CC/cc. # We probably just don't have CC/cc.
cc_is_clang = False cc_is_arg = False
print(int(cc_is_clang)) print(int(cc_is_arg))
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View file

@ -19,6 +19,8 @@
'conditions': [ 'conditions': [
['OS=="android"', { ['OS=="android"', {
'target_arch%': 'arm', 'target_arch%': 'arm',
}, 'OS=="ios"', {
'target_arch%': 'arm64',
}, { }, {
# Default architecture we're building for is the architecture we're # Default architecture we're building for is the architecture we're
# building on. # building on.
@ -35,7 +37,7 @@
},{ },{
'use_system_sqlite%': 0, '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%': 0,
}, { }, {
'cc_use_gnu_ld%': 1, 'cc_use_gnu_ld%': 1,
@ -54,7 +56,7 @@
'zlib_libs%': ['-lz'], 'zlib_libs%': ['-lz'],
'dll_prefix': 'lib', 'dll_prefix': 'lib',
'conditions': [ 'conditions': [
['OS=="mac"', { ['OS=="mac" or OS=="ios"', {
'moz_debug_flags%': '-gdwarf-2 -gfull', 'moz_debug_flags%': '-gdwarf-2 -gfull',
'dll_suffix': 'dylib', 'dll_suffix': 'dylib',
}, { }, {
@ -64,10 +66,15 @@
], ],
}], }],
['"<(GENERATOR)"=="ninja"', { ['"<(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', '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. # Copy conditionally-set variables out one scope.
@ -86,6 +93,7 @@
'dll_suffix': '<(dll_suffix)', 'dll_suffix': '<(dll_suffix)',
'freebl_name': '<(freebl_name)', 'freebl_name': '<(freebl_name)',
'cc_is_clang%': '<(cc_is_clang)', 'cc_is_clang%': '<(cc_is_clang)',
'cc_is_gcc%': '<(cc_is_gcc)',
'cc_use_gnu_ld%': '<(cc_use_gnu_ld)', 'cc_use_gnu_ld%': '<(cc_use_gnu_ld)',
# Some defaults # Some defaults
'disable_tests%': 0, 'disable_tests%': 0,
@ -99,6 +107,7 @@
'moz_folded_library_name%': '', 'moz_folded_library_name%': '',
'sanitizer_flags%': 0, 'sanitizer_flags%': 0,
'test_build%': 0, 'test_build%': 0,
'static_libs%': 0,
'no_zdefs%': 0, 'no_zdefs%': 0,
'fuzz%': 0, 'fuzz%': 0,
'fuzz_tls%': 0, 'fuzz_tls%': 0,
@ -122,6 +131,7 @@
'variables': { 'variables': {
'mapfile%': '', 'mapfile%': '',
'test_build%': 0, 'test_build%': 0,
'static_libs%': 0,
'debug_optimization_level%': '0', 'debug_optimization_level%': '0',
'release_optimization_level%': '2', 'release_optimization_level%': '2',
}, },
@ -142,7 +152,12 @@
'NSS_NO_INIT_SUPPORT', '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': [ 'libraries': [
'-lpthread', '-lpthread',
], ],
@ -153,6 +168,11 @@
'-lc', '-lc',
], ],
}], }],
[ 'OS=="android"', {
'libraries': [
'-llog',
],
}],
[ 'fuzz==1', { [ 'fuzz==1', {
'variables': { 'variables': {
'debug_optimization_level%': '1', '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 # When linking a shared lib against a static one, XCode doesn't
# export the latter's symbols by default. -all_load fixes that. # export the latter's symbols by default. -all_load fixes that.
'xcode_settings': { 'xcode_settings': {
@ -355,7 +375,7 @@
'OPENBSD', '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': [ 'defines': [
'HAVE_BSD_FLOCK', 'HAVE_BSD_FLOCK',
], ],
@ -367,7 +387,7 @@
'_REENTRANT', '_REENTRANT',
], ],
}], }],
[ 'OS!="mac" and OS!="win"', { [ 'OS!="mac" and OS!="ios" and OS!="win"', {
'cflags': [ 'cflags': [
'-fPIC', '-fPIC',
'-pipe', '-pipe',
@ -393,7 +413,7 @@
}], }],
[ 'use_pprof==1 and OS!="android" and OS!="win"', { [ 'use_pprof==1 and OS!="android" and OS!="win"', {
'conditions': [ 'conditions': [
[ 'OS=="mac"', { [ 'OS=="mac" or OS=="ios"', {
'xcode_settings': { 'xcode_settings': {
'OTHER_LDFLAGS': [ '-lprofiler' ], 'OTHER_LDFLAGS': [ '-lprofiler' ],
}, },
@ -453,7 +473,7 @@
'ANDROID', 'ANDROID',
], ],
}], }],
[ 'OS=="mac"', { [ 'OS=="mac" or OS=="ios"', {
'defines': [ 'defines': [
'DARWIN', 'DARWIN',
], ],
@ -468,8 +488,18 @@
'ARCHS': ['x86_64'], 'ARCHS': ['x86_64'],
}, },
}], }],
[ 'target_arch=="arm64"', {
'xcode_settings': {
'ARCHS': ['arm64'],
},
}],
], ],
}], }],
[ 'OS=="ios"', {
'xcode_settings': {
'IPHONEOS_DEPLOYMENT_TARGET': '<(iphone_deployment_target)',
},
}],
[ 'OS=="win"', { [ 'OS=="win"', {
'defines': [ 'defines': [
'_WINDOWS', '_WINDOWS',
@ -537,7 +567,7 @@
'Debug': { 'Debug': {
'inherit_from': ['Common'], 'inherit_from': ['Common'],
'conditions': [ 'conditions': [
[ 'OS!="mac" and OS!="win"', { [ 'OS!="mac" and OS!="ios" and OS!="win"', {
'cflags': [ 'cflags': [
'-g', '-g',
'<(moz_debug_flags)', '<(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)'], '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': { '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)'], 'process_map_file': ['/bin/sh', '-c', '/usr/bin/grep -v ";+" >(mapfile) | grep -v ";-" | sed -e "s; DATA ;;" -e "s,;;,," -e "s,;.*,," -e "s,^,_," > >@(_outputs)'],
}, },

View file

@ -14,7 +14,7 @@ if [ -z "$CC" ]; then
export CXX=clang++ export CXX=clang++
fi 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. # Add debug symbols even for opt builds.
nspr_params+=(--enable-debug-symbols) nspr_params+=(--enable-debug-symbols)

View file

@ -52,6 +52,7 @@ const uint8_t kTlsAlertInappropriateFallback = 86;
const uint8_t kTlsAlertMissingExtension = 109; const uint8_t kTlsAlertMissingExtension = 109;
const uint8_t kTlsAlertUnsupportedExtension = 110; const uint8_t kTlsAlertUnsupportedExtension = 110;
const uint8_t kTlsAlertUnrecognizedName = 112; const uint8_t kTlsAlertUnrecognizedName = 112;
const uint8_t kTlsAlertCertificateRequired = 116;
const uint8_t kTlsAlertNoApplicationProtocol = 120; const uint8_t kTlsAlertNoApplicationProtocol = 120;
const uint8_t kTlsFakeChangeCipherSpec[] = { const uint8_t kTlsFakeChangeCipherSpec[] = {

View file

@ -427,6 +427,9 @@ of the attribute codes:
</listitem> </listitem>
<listitem> <listitem>
<para><command>J</command> (as an object signer)</para> <para><command>J</command> (as an object signer)</para>
</listitem>
<listitem>
<para><command>I</command> (as an IPSEC user)</para>
</listitem> </listitem>
</itemizedlist></listitem> </itemizedlist></listitem>
</varlistentry> </varlistentry>
@ -662,6 +665,41 @@ of the attribute codes:
critical critical
</para> </para>
</listitem> </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> </itemizedlist>
<para>X.509 certificate extensions are described in RFC 5280.</para></listitem> <para>X.509 certificate extensions are described in RFC 5280.</para></listitem>
</varlistentry> </varlistentry>

View file

@ -12,6 +12,8 @@
'type': 'executable', 'type': 'executable',
'sources': [ 'sources': [
'alg1485_unittest.cc', 'alg1485_unittest.cc',
'cert_unittest.cc',
'decode_certs_unittest.cc',
'<(DEPTH)/gtests/common/gtests.cc' '<(DEPTH)/gtests/common/gtests.cc'
], ],
'dependencies': [ 'dependencies': [
@ -20,6 +22,7 @@
'<(DEPTH)/lib/util/util.gyp:nssutil3', '<(DEPTH)/lib/util/util.gyp:nssutil3',
'<(DEPTH)/lib/ssl/ssl.gyp:ssl3', '<(DEPTH)/lib/ssl/ssl.gyp:ssl3',
'<(DEPTH)/lib/nss/nss.gyp:nss3', '<(DEPTH)/lib/nss/nss.gyp:nss3',
'<(DEPTH)/lib/smime/smime.gyp:smime3',
] ]
} }
], ],

View file

@ -8,6 +8,8 @@ MODULE = nss
CPPSRCS = \ CPPSRCS = \
alg1485_unittest.cc \ alg1485_unittest.cc \
cert_unittest.cc \
decode_certs_unittest.cc \
$(NULL) $(NULL)
INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \ INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \

View file

@ -1,172 +0,0 @@
/* 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/. */
#ifndef gcm_vectors_h__
#define gcm_vectors_h__
#include <string>
typedef struct gcm_kat_str {
std::string key;
std::string plaintext;
std::string additional_data;
std::string iv;
std::string hash_key;
std::string ghash;
std::string result;
} gcm_kat_value;
/*
* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
*/
const gcm_kat_value kGcmKatValues[] = {
{"00000000000000000000000000000000", "", "", "000000000000000000000000",
"66e94bd4ef8a2c3b884cfa59ca342b2e", "00000000000000000000000000000000",
"58e2fccefa7e3061367f1d57a4e7455a"},
{"00000000000000000000000000000000", "00000000000000000000000000000000", "",
"000000000000000000000000", "66e94bd4ef8a2c3b884cfa59ca342b2e",
"f38cbb1ad69223dcc3457ae5b6b0f885",
"0388dace60b6a392f328c2b971b2fe78ab6e47d42cec13bdf53a67b21257bddf"},
{"feffe9928665731c6d6a8f9467308308",
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c959"
"56809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
"", "cafebabefacedbaddecaf888", "b83b533708bf535d0aa6e52980d53b78",
"7f1b32b81b820d02614f8895ac1d4eac",
"42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25"
"466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f59854d5c2af327cd64a62c"
"f35abd2ba6fab4"},
{"feffe9928665731c6d6a8f9467308308",
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c959"
"56809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
"feedfacedeadbeeffeedfacedeadbeefabaddad2", "cafebabefacedbaddecaf888",
"b83b533708bf535d0aa6e52980d53b78", "698e57f70e6ecc7fd9463b7260a9ae5f",
"42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25"
"466931c7d8f6a5aac84aa051ba30b396a0aac973d58e0915bc94fbc3221a5db94fae95ae7"
"121a47"},
{"feffe9928665731c6d6a8f9467308308",
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c959"
"56809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
"feedfacedeadbeeffeedfacedeadbeefabaddad2", "cafebabefacedbad",
"b83b533708bf535d0aa6e52980d53b78", "df586bb4c249b92cb6922877e444d37b",
"61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e"
"49f24b22b097544d4896b424989b5e1ebac0f07c23f45983612d2e79e3b0785561be14aac"
"a2fccb"},
{"feffe9928665731c6d6a8f9467308308",
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c959"
"56809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
"feedfacedeadbeeffeedfacedeadbeefabaddad2",
"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c9515"
"6809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
"b83b533708bf535d0aa6e52980d53b78", "1c5afe9760d3932f3c9a878aac3dc3de",
"8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4f"
"ba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5619cc5aefffe0bfa462af43c16"
"99d050"},
{"000000000000000000000000000000000000000000000000", "", "",
"000000000000000000000000", "aae06992acbf52a3e8f4a96ec9300bd7",
"00000000000000000000000000000000", "cd33b28ac773f74ba00ed1f312572435"},
{"000000000000000000000000000000000000000000000000",
"00000000000000000000000000000000", "", "000000000000000000000000",
"aae06992acbf52a3e8f4a96ec9300bd7", "e2c63f0ac44ad0e02efa05ab6743d4ce",
"98e7247c07f0fe411c267e4384b0f6002ff58d80033927ab8ef4d4587514f0fb"},
{"feffe9928665731c6d6a8f9467308308feffe9928665731c",
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c959"
"56809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
"", "cafebabefacedbaddecaf888", "466923ec9ae682214f2c082badb39249",
"51110d40f6c8fff0eb1ae33445a889f0",
"3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c"
"144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade2569924a7c8587336bfb1"
"18024db8674a14"},
{"feffe9928665731c6d6a8f9467308308feffe9928665731c",
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c959"
"56809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
"feedfacedeadbeeffeedfacedeadbeefabaddad2", "cafebabefacedbaddecaf888",
"466923ec9ae682214f2c082badb39249", "ed2ce3062e4a8ec06db8b4c490e8a268",
"3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c"
"144c525ac619d18c84a3f4718e2448b2fe324d9ccda27102519498e80f1478f37ba55bd6d"
"27618c"},
{"feffe9928665731c6d6a8f9467308308feffe9928665731c",
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c959"
"56809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
"feedfacedeadbeeffeedfacedeadbeefabaddad2", "cafebabefacedbad",
"466923ec9ae682214f2c082badb39249", "1e6a133806607858ee80eaf237064089",
"0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9"
"a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f765dcc57fcf623a24094fcca40d"
"3533f8"},
{"feffe9928665731c6d6a8f9467308308feffe9928665731c",
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c959"
"56809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
"feedfacedeadbeeffeedfacedeadbeefabaddad2",
"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c9515"
"6809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
"466923ec9ae682214f2c082badb39249", "82567fb0b4cc371801eadec005968e94",
"d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012a"
"f34ddd9e2f037589b292db3e67c036745fa22e7e9b7373bdcf566ff291c25bbb8568fc3d3"
"76a6d9"},
{"0000000000000000000000000000000000000000000000000000000000000000", "", "",
"000000000000000000000000", "dc95c078a2408989ad48a21492842087",
"00000000000000000000000000000000", "530f8afbc74536b9a963b4f1c4cb738b"},
{"0000000000000000000000000000000000000000000000000000000000000000",
"00000000000000000000000000000000", "", "000000000000000000000000",
"dc95c078a2408989ad48a21492842087", "83de425c5edc5d498f382c441041ca92",
"cea7403d4d606b6e074ec5d3baf39d18d0d1c8a799996bf0265b98b5d48ab919"},
{"feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c959"
"56809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
"", "cafebabefacedbaddecaf888", "acbef20579b4b8ebce889bac8732dad7",
"4db870d37cb75fcb46097c36230d1612",
"522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e485"
"90dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015adb094dac5d93471bdec"
"1a502270e3cc6c"},
{"feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c959"
"56809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
"feedfacedeadbeeffeedfacedeadbeefabaddad2", "cafebabefacedbaddecaf888",
"acbef20579b4b8ebce889bac8732dad7", "8bd0c4d8aacd391e67cca447e8c38f65",
"522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e485"
"90dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f66276fc6ece0f4e1768cddf8853bb"
"2d551b"},
{"feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c959"
"56809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
"feedfacedeadbeeffeedfacedeadbeefabaddad2", "cafebabefacedbad",
"acbef20579b4b8ebce889bac8732dad7", "75a34288b8c68f811c52b2e9a2f97f63",
"c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33"
"934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f3a337dbf46a792c45e454913fe"
"2ea8f2"},
{"feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c959"
"56809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
"feedfacedeadbeeffeedfacedeadbeefabaddad2",
"9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c9515"
"6809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
"acbef20579b4b8ebce889bac8732dad7", "d5ffcf6fc5ac4d69722187421a7f170b",
"5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b78"
"0f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3fa44a8266ee1c8eb0c8b5d4cf5a"
"e9f19a"},
/* Extra, non-NIST, test case to test 64-bit binary multiplication carry
* correctness. This is a GHASH-only test. */
{"", "", "", "", "0000000000000000fcefef64ffc4766c",
"3561e34e52d8b598f9937982512fff27",
"0000000000000000ffcef9ebbffdbd8b00000000000000000000000000000000"}};
#endif // gcm_vectors_h__

View file

@ -40,6 +40,13 @@
'freebl_gtest_deps', 'freebl_gtest_deps',
'<(DEPTH)/exports.gyp:nss_exports', '<(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', 'target_name': 'prng_gtest',

View file

@ -6,6 +6,7 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <memory>
#ifdef __MACH__ #ifdef __MACH__
#include <mach/clock.h> #include <mach/clock.h>
@ -27,7 +28,7 @@ void gettime(struct timespec* tp) {
tp->tv_sec = mts.tv_sec; tp->tv_sec = mts.tv_sec;
tp->tv_nsec = mts.tv_nsec; tp->tv_nsec = mts.tv_nsec;
#else #else
clock_gettime(CLOCK_MONOTONIC, tp); ASSERT_NE(0, timespec_get(tp, TIME_UTC));
#endif #endif
} }
@ -84,8 +85,9 @@ class MPITest : public ::testing::Test {
mp_int a; mp_int a;
ASSERT_EQ(MP_OKAY, mp_init(&a)); ASSERT_EQ(MP_OKAY, mp_init(&a));
ASSERT_EQ(MP_OKAY, mp_read_unsigned_octets(&a, ref.data(), ref.size())); ASSERT_EQ(MP_OKAY, mp_read_unsigned_octets(&a, ref.data(), ref.size()));
uint8_t buf[len]; std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
ASSERT_EQ(MP_OKAY, mp_to_fixlen_octets(&a, buf, len)); ASSERT_NE(buf, nullptr);
ASSERT_EQ(MP_OKAY, mp_to_fixlen_octets(&a, buf.get(), len));
size_t compare; size_t compare;
if (len > ref.size()) { if (len > ref.size()) {
for (size_t i = 0; i < len - ref.size(); ++i) { for (size_t i = 0; i < len - ref.size(); ++i) {
@ -96,9 +98,9 @@ class MPITest : public ::testing::Test {
compare = len; compare = len;
} }
dump("value", ref.data(), ref.size()); dump("value", ref.data(), ref.size());
dump("output", buf, len); dump("output", buf.get(), len);
ASSERT_EQ(0, memcmp(buf + len - compare, ref.data() + ref.size() - compare, ASSERT_EQ(0, memcmp(buf.get() + len - compare,
compare)) ref.data() + ref.size() - compare, compare))
<< "comparing " << compare << " octets"; << "comparing " << compare << " octets";
mp_clear(&a); mp_clear(&a);
} }

View file

@ -5,6 +5,7 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include <stdint.h> #include <stdint.h>
#include <memory>
#include "blapi.h" #include "blapi.h"
#include "secitem.h" #include "secitem.h"

View file

@ -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 // but this should catch the problem on at least some compilers, if not all of
// them. // them.
const uint8_t* der = nullptr; const uint8_t* der = nullptr;
// coverity[FORWARD_NULL]
--der; --der;
Input buf; Input buf;
ASSERT_EQ(Success, buf.Init(der, 0)); ASSERT_EQ(Success, buf.Init(der, 0));

View file

@ -8,6 +8,7 @@ MODULE = nss
CPPSRCS = \ CPPSRCS = \
pk11_aeskeywrap_unittest.cc \ pk11_aeskeywrap_unittest.cc \
pk11_aes_gcm_unittest.cc \
pk11_chacha20poly1305_unittest.cc \ pk11_chacha20poly1305_unittest.cc \
pk11_curve25519_unittest.cc \ pk11_curve25519_unittest.cc \
pk11_ecdsa_unittest.cc \ pk11_ecdsa_unittest.cc \

View file

@ -8,6 +8,7 @@
#include "nss.h" #include "nss.h"
#include "pk11pub.h" #include "pk11pub.h"
#include "sechash.h" #include "sechash.h"
#include "secerr.h"
#include "cpputil.h" #include "cpputil.h"
#include "nss_scoped_ptrs.h" #include "nss_scoped_ptrs.h"
@ -17,10 +18,17 @@
namespace nss_test { 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 class Pkcs11ChaCha20Poly1305Test
: public ::testing::TestWithParam<chacha_testvector> { : public ::testing::TestWithParam<chacha_testvector> {
public: 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, const bool invalid_tag, const uint8_t* data,
size_t data_len, const uint8_t* aad, size_t aad_len, size_t data_len, const uint8_t* aad, size_t aad_len,
const uint8_t* iv, size_t iv_len, const uint8_t* iv, size_t iv_len,
@ -39,7 +47,7 @@ class Pkcs11ChaCha20Poly1305Test
// Encrypt. // Encrypt.
unsigned int outputLen = 0; unsigned int outputLen = 0;
std::vector<uint8_t> output(data_len + aead_params.ulTagLen); 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); &outputLen, output.size(), data, data_len);
// Return if encryption failure was expected due to invalid IV. // Return if encryption failure was expected due to invalid IV.
@ -60,8 +68,9 @@ class Pkcs11ChaCha20Poly1305Test
// Decrypt. // Decrypt.
unsigned int decryptedLen = 0; unsigned int decryptedLen = 0;
std::vector<uint8_t> decrypted(data_len); std::vector<uint8_t> decrypted(data_len);
rv = PK11_Decrypt(symKey, mech, &params, decrypted.data(), &decryptedLen, rv =
decrypted.size(), output.data(), outputLen); PK11_Decrypt(key.get(), kMech, &params, decrypted.data(), &decryptedLen,
decrypted.size(), output.data(), outputLen);
EXPECT_EQ(rv, SECSuccess); EXPECT_EQ(rv, SECSuccess);
// Check the plaintext. // Check the plaintext.
@ -73,8 +82,9 @@ class Pkcs11ChaCha20Poly1305Test
if (outputLen != 0) { if (outputLen != 0) {
std::vector<uint8_t> bogusCiphertext(output); std::vector<uint8_t> bogusCiphertext(output);
bogusCiphertext[0] ^= 0xff; bogusCiphertext[0] ^= 0xff;
rv = PK11_Decrypt(symKey, mech, &params, decrypted.data(), &decryptedLen, rv = PK11_Decrypt(key.get(), kMech, &params, decrypted.data(),
decrypted.size(), bogusCiphertext.data(), outputLen); &decryptedLen, decrypted.size(), bogusCiphertext.data(),
outputLen);
EXPECT_NE(rv, SECSuccess); EXPECT_NE(rv, SECSuccess);
} }
@ -83,8 +93,9 @@ class Pkcs11ChaCha20Poly1305Test
if (outputLen != 0) { if (outputLen != 0) {
std::vector<uint8_t> bogusTag(output); std::vector<uint8_t> bogusTag(output);
bogusTag[outputLen - 1] ^= 0xff; bogusTag[outputLen - 1] ^= 0xff;
rv = PK11_Decrypt(symKey, mech, &params, decrypted.data(), &decryptedLen, rv = PK11_Decrypt(key.get(), kMech, &params, decrypted.data(),
decrypted.size(), bogusTag.data(), outputLen); &decryptedLen, decrypted.size(), bogusTag.data(),
outputLen);
EXPECT_NE(rv, SECSuccess); EXPECT_NE(rv, SECSuccess);
} }
@ -100,7 +111,7 @@ class Pkcs11ChaCha20Poly1305Test
bogusAeadParams.pNonce = toUcharPtr(bogusIV.data()); bogusAeadParams.pNonce = toUcharPtr(bogusIV.data());
bogusIV[0] ^= 0xff; 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); &decryptedLen, data_len, output.data(), outputLen);
EXPECT_NE(rv, SECSuccess); EXPECT_NE(rv, SECSuccess);
} }
@ -117,7 +128,7 @@ class Pkcs11ChaCha20Poly1305Test
bogusAeadParams.pAAD = toUcharPtr(bogusAAD.data()); bogusAeadParams.pAAD = toUcharPtr(bogusAAD.data());
bogusAAD[0] ^= 0xff; 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); &decryptedLen, data_len, output.data(), outputLen);
EXPECT_NE(rv, SECSuccess); EXPECT_NE(rv, SECSuccess);
} }
@ -125,16 +136,16 @@ class Pkcs11ChaCha20Poly1305Test
void EncryptDecrypt(const chacha_testvector testvector) { void EncryptDecrypt(const chacha_testvector testvector) {
ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
SECItem keyItem = {siBuffer, toUcharPtr(testvector.Key.data()), SECItem key_item = {siBuffer, toUcharPtr(testvector.Key.data()),
static_cast<unsigned int>(testvector.Key.size())}; static_cast<unsigned int>(testvector.Key.size())};
// Import key. // Import key.
ScopedPK11SymKey symKey(PK11_ImportSymKey( ScopedPK11SymKey key(PK11_ImportSymKey(slot.get(), kMech, PK11_OriginUnwrap,
slot.get(), mech, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, nullptr)); CKA_ENCRYPT, &key_item, nullptr));
EXPECT_TRUE(!!symKey); EXPECT_TRUE(!!key);
// Check. // 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.Data.data(), testvector.Data.size(),
testvector.AAD.data(), testvector.AAD.size(), testvector.AAD.data(), testvector.AAD.size(),
testvector.IV.data(), testvector.IV.size(), testvector.IV.data(), testvector.IV.size(),
@ -142,14 +153,13 @@ class Pkcs11ChaCha20Poly1305Test
} }
protected: protected:
CK_MECHANISM_TYPE mech = CKM_NSS_CHACHA20_POLY1305;
}; };
TEST_F(Pkcs11ChaCha20Poly1305Test, GenerateEncryptDecrypt) { TEST_F(Pkcs11ChaCha20Poly1305Test, GenerateEncryptDecrypt) {
// Generate a random key. // Generate a random key.
ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ScopedPK11SymKey symKey(PK11_KeyGen(slot.get(), mech, nullptr, 32, nullptr)); ScopedPK11SymKey key(PK11_KeyGen(slot.get(), kMech, nullptr, 32, nullptr));
EXPECT_TRUE(!!symKey); EXPECT_TRUE(!!key);
// Generate random data. // Generate random data.
std::vector<uint8_t> data(512); std::vector<uint8_t> data(512);
@ -168,8 +178,85 @@ TEST_F(Pkcs11ChaCha20Poly1305Test, GenerateEncryptDecrypt) {
EXPECT_EQ(rv, SECSuccess); EXPECT_EQ(rv, SECSuccess);
// Check. // Check.
EncryptDecrypt(symKey.get(), false, false, data.data(), data.size(), EncryptDecrypt(key, false, false, data.data(), data.size(), aad.data(),
aad.data(), aad.size(), iv.data(), iv.size()); 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()); } TEST_P(Pkcs11ChaCha20Poly1305Test, TestVectors) { EncryptDecrypt(GetParam()); }

View file

@ -40,6 +40,9 @@ class Pkcs11Curve25519Test
ScopedCERTSubjectPublicKeyInfo certSpki( ScopedCERTSubjectPublicKeyInfo certSpki(
SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiItem)); SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiItem));
if (!expect_success && !certSpki) {
return;
}
ASSERT_TRUE(certSpki); ASSERT_TRUE(certSpki);
ScopedSECKEYPublicKey pubKey(SECKEY_ExtractPublicKey(certSpki.get())); ScopedSECKEYPublicKey pubKey(SECKEY_ExtractPublicKey(certSpki.get()));

View file

@ -29,20 +29,20 @@
], ],
'dependencies': [ 'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports', '<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/lib/util/util.gyp:nssutil3',
'<(DEPTH)/cpputil/cpputil.gyp:cpputil', '<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'<(DEPTH)/gtests/google_test/google_test.gyp:gtest', '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
'<(DEPTH)/lib/util/util.gyp:nssutil3',
], ],
'conditions': [ 'conditions': [
[ 'test_build==1', { [ 'static_libs==1', {
'dependencies': [ '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/nss/nss.gyp:nss_static',
'<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_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/pki/pki.gyp:nsspki',
'<(DEPTH)/lib/ssl/ssl.gyp:ssl', '<(DEPTH)/lib/ssl/ssl.gyp:ssl',
], ],

View file

@ -48,8 +48,15 @@ class Pk11KeyImportTestBase : public ::testing::Test {
ScopedSECKEYEncryptedPrivateKeyInfo key_info; ScopedSECKEYEncryptedPrivateKeyInfo key_info;
ScopedSECItem public_value; ScopedSECItem public_value;
GenerateAndExport(&key_type, &key_info, &public_value); GenerateAndExport(&key_type, &key_info, &public_value);
ASSERT_NE(nullptr, key_info);
ASSERT_NE(nullptr, public_value); 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. // Now import the encrypted key.
static const uint8_t nick[] = "nick"; static const uint8_t nick[] = "nick";
@ -78,17 +85,41 @@ class Pk11KeyImportTestBase : public ::testing::Test {
CK_MECHANISM_TYPE mech_; CK_MECHANISM_TYPE mech_;
private: 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, void CheckForPublicKey(const ScopedSECKEYPrivateKey& priv_key,
const SECItem* expected_public) { const SECItem* expected_public) {
// Verify the public key exists. // Verify the public key exists.
StackSECItem priv_id; StackSECItem priv_id;
KeyType type = SECKEY_GetPrivateKeyType(priv_key.get());
SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, priv_key.get(), SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, priv_key.get(),
CKA_ID, &priv_id); CKA_ID, &priv_id);
ASSERT_EQ(SECSuccess, rv) << "Couldn't read CKA_ID from private key: " ASSERT_EQ(SECSuccess, rv) << "Couldn't read CKA_ID from private key: "
<< PORT_ErrorToName(PORT_GetError()); << PORT_ErrorToName(PORT_GetError());
CK_ATTRIBUTE_TYPE value_type = CKA_VALUE; CK_ATTRIBUTE_TYPE value_type = CKA_VALUE;
switch (SECKEY_GetPrivateKeyType(priv_key.get())) { switch (type) {
case rsaKey: case rsaKey:
value_type = CKA_MODULUS; value_type = CKA_MODULUS;
break; break;
@ -106,6 +137,8 @@ class Pk11KeyImportTestBase : public ::testing::Test {
FAIL() << "unknown key type"; 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( std::unique_ptr<PK11GenericObject, PK11GenericObjectsDeleter> objs(
PK11_FindGenericObjects(slot_.get(), CKO_PUBLIC_KEY)); PK11_FindGenericObjects(slot_.get(), CKO_PUBLIC_KEY));
ASSERT_NE(nullptr, objs); ASSERT_NE(nullptr, objs);
@ -128,20 +161,44 @@ class Pk11KeyImportTestBase : public ::testing::Test {
ASSERT_EQ(1U, token.len); ASSERT_EQ(1U, token.len);
ASSERT_NE(0, token.data[0]); ASSERT_NE(0, token.data[0]);
StackSECItem value; StackSECItem raw_value;
rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, value_type, &value); SECItem decoded_value;
rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, value_type, &raw_value);
ASSERT_EQ(SECSuccess, rv); 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. // 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) { 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)) ASSERT_TRUE(SECITEM_ItemsAreEqual(expected_public, &value))
<< "expected: " << "expected: "
<< DataBuffer(expected_public->data, expected_public->len) << DataBuffer(expected_public->data, expected_public->len)
<< std::endl << std::endl
<< "actual: " << DataBuffer(value.data, value.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); ScopedSECKEYPublicKey pub_key(pub_tmp);
ASSERT_NE(nullptr, pub_key); 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 */ // Save the public value, which we will need on import */
SECItem* pub_val; SECItem* pub_val;
KeyType t = SECKEY_GetPublicKeyType(pub_key.get()); KeyType t = SECKEY_GetPublicKeyType(pub_key.get());
@ -190,8 +240,22 @@ class Pk11KeyImportTestBase : public ::testing::Test {
CheckForPublicKey(priv_key, pub_val); CheckForPublicKey(priv_key, pub_val);
*key_type = t; *key_type = t;
key_info->swap(epki);
public_value->reset(SECITEM_DupItem(pub_val)); 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_; ScopedPK11SlotInfo slot_;
@ -281,9 +345,8 @@ TEST_P(Pk11KeyImportTest, GenerateExportImport) { Test(); }
INSTANTIATE_TEST_CASE_P(Pk11KeyImportTest, Pk11KeyImportTest, INSTANTIATE_TEST_CASE_P(Pk11KeyImportTest, Pk11KeyImportTest,
::testing::Values(CKM_RSA_PKCS_KEY_PAIR_GEN, ::testing::Values(CKM_RSA_PKCS_KEY_PAIR_GEN,
CKM_DSA_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_DH_PKCS_KEY_PAIR_GEN.
class Pk11KeyImportTestEC : public Pk11KeyImportTestBase, class Pk11KeyImportTestEC : public Pk11KeyImportTestBase,
public ::testing::WithParamInterface<SECOidTag> { public ::testing::WithParamInterface<SECOidTag> {

View file

@ -19,7 +19,7 @@
'<(DEPTH)/gtests/google_test/google_test.gyp:gtest', '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
], ],
'conditions': [ 'conditions': [
[ 'test_build==1', { [ 'static_libs==1', {
'dependencies': [ 'dependencies': [
'<(DEPTH)/lib/nss/nss.gyp:nss_static', '<(DEPTH)/lib/nss/nss.gyp:nss_static',
'<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static', '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',

View file

@ -36,6 +36,12 @@ CPPSRCS := $(filter-out $(shell grep -l '^TEST_F' $(CPPSRCS)), $(CPPSRCS))
CFLAGS += -DNSS_DISABLE_TLS_1_3 CFLAGS += -DNSS_DISABLE_TLS_1_3
endif endif
ifdef NSS_ALLOW_SSLKEYLOGFILE
SSLKEYLOGFILE_FILES = ssl_keylog_unittest.cc
else
SSLKEYLOGFILE_FILES = $(NULL)
endif
####################################################################### #######################################################################
# (5) Execute "global" rules. (OPTIONAL) # # (5) Execute "global" rules. (OPTIONAL) #
####################################################################### #######################################################################

View file

@ -31,7 +31,6 @@ CPPSRCS = \
ssl_gather_unittest.cc \ ssl_gather_unittest.cc \
ssl_gtest.cc \ ssl_gtest.cc \
ssl_hrr_unittest.cc \ ssl_hrr_unittest.cc \
ssl_keylog_unittest.cc \
ssl_keyupdate_unittest.cc \ ssl_keyupdate_unittest.cc \
ssl_loopback_unittest.cc \ ssl_loopback_unittest.cc \
ssl_misc_unittest.cc \ ssl_misc_unittest.cc \
@ -55,6 +54,7 @@ CPPSRCS = \
tls_filter.cc \ tls_filter.cc \
tls_protect.cc \ tls_protect.cc \
tls_esni_unittest.cc \ tls_esni_unittest.cc \
$(SSLKEYLOGFILE_FILES) \
$(NULL) $(NULL)
INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \ INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \

View file

@ -649,6 +649,227 @@ TEST_P(TlsConnectTls13, ZeroRttOrdering) {
EXPECT_EQ(2U, step); 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 #ifndef NSS_DISABLE_TLS_1_3
INSTANTIATE_TEST_CASE_P(Tls13ZeroRttReplayTest, TlsZeroRttReplayTest, INSTANTIATE_TEST_CASE_P(Tls13ZeroRttReplayTest, TlsZeroRttReplayTest,
TlsConnectTestBase::kTlsVariantsAll); TlsConnectTestBase::kTlsVariantsAll);

View file

@ -320,6 +320,46 @@ TEST_F(TlsConnectStreamTls13, PostHandshakeAuthConcurrent) {
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); 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) { TEST_F(TlsConnectStreamTls13, PostHandshakeAuthMissingExtension) {
client_->SetupClientAuth(); client_->SetupClientAuth();
Connect(); Connect();
@ -454,6 +494,9 @@ TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDecline) {
client_->SetupClientAuth(); client_->SetupClientAuth();
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); 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. // Client to decline the certificate request.
EXPECT_EQ(SECSuccess, EXPECT_EQ(SECSuccess,
SSL_GetClientAuthDataHook( SSL_GetClientAuthDataHook(
@ -472,10 +515,13 @@ TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDecline) {
// Send CertificateRequest. // Send CertificateRequest.
EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
<< "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); << "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
server_->SendData(50); server_->SendData(50); // send Certificate Request
client_->ReadBytes(50); client_->ReadBytes(50); // read Certificate Request
client_->SendData(50); client_->SendData(50); // send empty Certificate+Finished
server_->ReadBytes(50); 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 // AuthCertificateCallback is not called, because the client sends
// an empty certificate_list. // an empty certificate_list.
EXPECT_EQ(0U, called); EXPECT_EQ(0U, called);
@ -655,6 +701,44 @@ TEST_P(TlsConnectTls12, ClientAuthInconsistentPssSignatureScheme) {
ConnectExpectAlert(server_, kTlsAlertIllegalParameter); 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 { class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter {
public: public:
TlsZeroCertificateRequestSigAlgsFilter(const std::shared_ptr<TlsAgent>& a) TlsZeroCertificateRequestSigAlgsFilter(const std::shared_ptr<TlsAgent>& a)
@ -887,7 +971,7 @@ TEST_P(TlsConnectTls13, InconsistentSignatureSchemeAlert) {
client_->CheckErrorCode(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM); client_->CheckErrorCode(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
} }
TEST_P(TlsConnectTls12Plus, RequestClientAuthWithSha384) { TEST_P(TlsConnectTls12, RequestClientAuthWithSha384) {
server_->SetSignatureSchemes(kSignatureSchemeRsaSha384, server_->SetSignatureSchemes(kSignatureSchemeRsaSha384,
PR_ARRAY_SIZE(kSignatureSchemeRsaSha384)); PR_ARRAY_SIZE(kSignatureSchemeRsaSha384));
server_->RequestClientAuth(false); server_->RequestClientAuth(false);
@ -1349,12 +1433,21 @@ TEST_P(TlsSignatureSchemeConfiguration, SignatureSchemeConfigBoth) {
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
SignatureSchemeRsa, TlsSignatureSchemeConfiguration, SignatureSchemeRsa, TlsSignatureSchemeConfiguration,
::testing::Combine( ::testing::Combine(
TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV12Plus, TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV12,
::testing::Values(TlsAgent::kServerRsaSign), ::testing::Values(TlsAgent::kServerRsaSign),
::testing::Values(ssl_auth_rsa_sign), ::testing::Values(ssl_auth_rsa_sign),
::testing::Values(ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pkcs1_sha384, ::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_pkcs1_sha512, ssl_sig_rsa_pss_rsae_sha256,
ssl_sig_rsa_pss_rsae_sha384))); 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. // PSS with SHA-512 needs a bigger key to work.
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
SignatureSchemeBigRsa, TlsSignatureSchemeConfiguration, SignatureSchemeBigRsa, TlsSignatureSchemeConfiguration,

View file

@ -68,12 +68,6 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase {
virtual void SetupCertificate() { virtual void SetupCertificate() {
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
switch (sig_scheme_) { 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_sha256:
case ssl_sig_rsa_pss_rsae_sha384: case ssl_sig_rsa_pss_rsae_sha384:
Reset(TlsAgent::kServerRsaSign); 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_sha256, ssl_sig_rsa_pss_pss_sha384,
ssl_sig_rsa_pss_pss_sha512}; 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, INSTANTIATE_CIPHER_TEST_P(RC4, Stream, V10ToV12, kDummyNamedGroupParams,
kDummySignatureSchemesParams, kDummySignatureSchemesParams,
TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_RC4_128_SHA,
@ -394,7 +394,7 @@ INSTANTIATE_CIPHER_TEST_P(
#ifndef NSS_DISABLE_TLS_1_3 #ifndef NSS_DISABLE_TLS_1_3
INSTANTIATE_CIPHER_TEST_P(TLS13, All, V13, INSTANTIATE_CIPHER_TEST_P(TLS13, All, V13,
::testing::ValuesIn(kFasterDHEGroups), ::testing::ValuesIn(kFasterDHEGroups),
::testing::ValuesIn(kSignatureSchemesParamsArr), ::testing::ValuesIn(kSignatureSchemesParamsArrTls13),
TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256,
TLS_AES_256_GCM_SHA384); TLS_AES_256_GCM_SHA384);
INSTANTIATE_CIPHER_TEST_P(TLS13AllGroups, All, V13, INSTANTIATE_CIPHER_TEST_P(TLS13AllGroups, All, V13,

View file

@ -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

View file

@ -436,14 +436,14 @@ TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsOddLength) {
} }
TEST_F(TlsExtensionTest13Stream, SignatureAlgorithmsPrecedingGarbage) { 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[] = { const uint8_t val[] = {
0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 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, 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)); DataBuffer extension(val, sizeof(val));
MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_signature_algorithms_xtn, MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_signature_algorithms_xtn,
extension); extension);
@ -482,6 +482,73 @@ TEST_P(TlsExtensionTestGeneric, SupportedCurvesTrailingData) {
client_, ssl_elliptic_curves_xtn, extension)); 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) { TEST_P(TlsExtensionTestPre13, SupportedPointsEmpty) {
const uint8_t val[] = {0x00}; const uint8_t val[] = {0x00};
DataBuffer extension(val, sizeof(val)); DataBuffer extension(val, sizeof(val));

View file

@ -32,7 +32,6 @@
'ssl_gather_unittest.cc', 'ssl_gather_unittest.cc',
'ssl_gtest.cc', 'ssl_gtest.cc',
'ssl_hrr_unittest.cc', 'ssl_hrr_unittest.cc',
'ssl_keylog_unittest.cc',
'ssl_keyupdate_unittest.cc', 'ssl_keyupdate_unittest.cc',
'ssl_loopback_unittest.cc', 'ssl_loopback_unittest.cc',
'ssl_misc_unittest.cc', 'ssl_misc_unittest.cc',
@ -76,7 +75,7 @@
'<(DEPTH)/lib/libpkix/libpkix.gyp:libpkix', '<(DEPTH)/lib/libpkix/libpkix.gyp:libpkix',
], ],
'conditions': [ 'conditions': [
[ 'test_build==1', { [ 'static_libs==1', {
'dependencies': [ 'dependencies': [
'<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static', '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
], ],
@ -93,6 +92,14 @@
'<(DEPTH)/lib/dbm/src/src.gyp:dbm', '<(DEPTH)/lib/dbm/src/src.gyp:dbm',
], ],
}], }],
[ 'enable_sslkeylogfile==1 and sanitizer_flags==0', {
'sources': [
'ssl_keylog_unittest.cc',
],
'defines': [
'NSS_ALLOW_SSLKEYLOGFILE',
],
}],
], ],
} }
], ],

View file

@ -4,8 +4,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file, * 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/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef NSS_ALLOW_SSLKEYLOGFILE
#include <cstdlib> #include <cstdlib>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
@ -114,5 +112,3 @@ INSTANTIATE_TEST_CASE_P(
#endif #endif
} // namespace nss_test } // namespace nss_test
#endif // NSS_ALLOW_SSLKEYLOGFILE

View file

@ -52,6 +52,7 @@ class AeadTest : public ::testing::Test {
static const size_t kMaxSize = 32; static const size_t kMaxSize = 32;
ASSERT_GE(kMaxSize, ciphertext_len); ASSERT_GE(kMaxSize, ciphertext_len);
ASSERT_LT(0U, ciphertext_len);
uint8_t output[kMaxSize]; uint8_t output[kMaxSize];
unsigned int output_len = 0; unsigned int output_len = 0;
@ -191,7 +192,7 @@ TEST_F(AeadTest, AeadAes128Gcm) {
} }
TEST_F(AeadTest, AeadAes256Gcm) { TEST_F(AeadTest, AeadAes256Gcm) {
SSLAeadContext *ctxInit; SSLAeadContext *ctxInit = nullptr;
ASSERT_EQ(SECSuccess, ASSERT_EQ(SECSuccess,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_256_GCM_SHA384, SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_256_GCM_SHA384,
secret_.get(), kLabel, strlen(kLabel), &ctxInit)); secret_.get(), kLabel, strlen(kLabel), &ctxInit));

View file

@ -176,6 +176,7 @@ class BadPrSocket : public DummyIOLayerMethods {
// NSPR method vtable with the ones from this object. // NSPR method vtable with the ones from this object.
dummy_layer_ = dummy_layer_ =
PR_GetIdentitiesLayer(agent->ssl_fd(), DummyPrSocket::LayerId()); PR_GetIdentitiesLayer(agent->ssl_fd(), DummyPrSocket::LayerId());
EXPECT_TRUE(dummy_layer_);
original_methods_ = dummy_layer_->methods; original_methods_ = dummy_layer_->methods;
original_secret_ = dummy_layer_->secret; original_secret_ = dummy_layer_->secret;
dummy_layer_->methods = fd_->methods; dummy_layer_->methods = fd_->methods;
@ -442,6 +443,48 @@ TEST_P(TlsConnectStream, ReplaceRecordLayerAsyncLateAuth) {
SendForwardReceive(client_, client_stage, server_); 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 // This test ensures that data is correctly forwarded when the handshake is
// resumed after asynchronous server certificate authentication, when // resumed after asynchronous server certificate authentication, when
// SSL_AuthCertificateComplete() is called. The logic for resuming the // SSL_AuthCertificateComplete() is called. The logic for resuming the

View file

@ -33,9 +33,11 @@ class PacketFilter {
CHANGE, // change the packet to a different value CHANGE, // change the packet to a different value
DROP // drop the packet DROP // drop the packet
}; };
PacketFilter(bool enabled = true) : enabled_(enabled) {} explicit PacketFilter(bool on = true) : enabled_(on) {}
virtual ~PacketFilter() {} virtual ~PacketFilter() {}
bool enabled() const { return enabled_; }
virtual Action Process(const DataBuffer& input, DataBuffer* output) { virtual Action Process(const DataBuffer& input, DataBuffer* output) {
if (!enabled_) { if (!enabled_) {
return KEEP; return KEEP;

View file

@ -250,6 +250,7 @@ void TlsConnectTestBase::Reset(const std::string& server_name,
server_->SkipVersionChecks(); server_->SkipVersionChecks();
} }
std::cerr << "Reset" << std::endl;
Init(); Init();
} }

View file

@ -156,7 +156,8 @@ class TlsConnectTestBase : public ::testing::Test {
// around test cases. In particular, DSA is checked in // around test cases. In particular, DSA is checked in
// ssl_extension_unittest.cc. // ssl_extension_unittest.cc.
const std::vector<SECOidTag> algorithms_ = {SEC_OID_APPLY_SSL_POLICY, 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_; std::vector<std::tuple<SECOidTag, uint32_t>> saved_policies_;
private: private:

View file

@ -70,7 +70,7 @@ static void GenerateEsniKey(time_t windowStart, SSLNamedGroup group,
ASSERT_NE(nullptr, priv); ASSERT_NE(nullptr, priv);
SECITEM_FreeItem(&ecParams, PR_FALSE); SECITEM_FreeItem(&ecParams, PR_FALSE);
PRUint8 encoded[1024]; PRUint8 encoded[1024];
unsigned int encoded_len; unsigned int encoded_len = 0;
SECStatus rv = SSL_EncodeESNIKeys( SECStatus rv = SSL_EncodeESNIKeys(
&cipher_suites[0], cipher_suites.size(), group, pub, 100, windowStart, &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, GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record,
&pub, &priv); &pub, &priv);
PRUint8 encoded[1024]; PRUint8 encoded[1024];
unsigned int encoded_len; unsigned int encoded_len = 0;
SECStatus rv = SSL_EncodeESNIKeys( SECStatus rv = SSL_EncodeESNIKeys(
&kChaChaSuite[0], kChaChaSuite.size(), ssl_grp_ec_curve25519, pub.get(), &kChaChaSuite[0], kChaChaSuite.size(), ssl_grp_ec_curve25519, pub.get(),
100, time(0), time(0) + 10, encoded, &encoded_len, sizeof(encoded)); 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); rv = SSL_SetESNIKeyPair(server_->ssl_fd(), priv.get(), encoded, encoded_len);
ASSERT_EQ(SECSuccess, rv); ASSERT_EQ(SECSuccess, rv);
rv = SSL_EnableESNI(client_->ssl_fd(), record.data(), record.len(), ""); rv = SSL_EnableESNI(client_->ssl_fd(), record.data(), record.len(), "");

View file

@ -549,9 +549,9 @@ class SelectiveDropFilter : public PacketFilter {
class SelectiveRecordDropFilter : public TlsRecordFilter { class SelectiveRecordDropFilter : public TlsRecordFilter {
public: public:
SelectiveRecordDropFilter(const std::shared_ptr<TlsAgent>& a, 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) { : TlsRecordFilter(a), pattern_(pattern), counter_(0) {
if (!enabled) { if (!on) {
Disable(); Disable();
} }
} }

View file

@ -40,6 +40,7 @@ NSS build tool options:
(requires the gold linker, use clang-3.8 for SAW) (requires the gold linker, use clang-3.8 for SAW)
--no-zdefs don't set -Wl,-z,defs --no-zdefs don't set -Wl,-z,defs
--test ignore map files and export everything we have --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 --ct-verif build with valgrind for ct-verif
--nspr force a rebuild of NSPR --nspr force a rebuild of NSPR
--with-nspr use the NSPR build at the given locations --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 --enable-libpkix make libpkix part of the build
--mozpkix-only build only static mozpkix and mozpkix-test libraries --mozpkix-only build only static mozpkix and mozpkix-test libraries
support for this build option is limited 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 -D<gyp-option> pass an option directly to gyp

View file

@ -215,6 +215,12 @@ extern void CERT_DestroyCertificate(CERTCertificate *cert);
*/ */
extern CERTCertificate *CERT_DupCertificate(CERTCertificate *c); 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 ** Create a new certificate request. This result must be wrapped with an
** CERTSignedData to create a signed certificate request. ** CERTSignedData to create a signed certificate request.

View file

@ -447,71 +447,39 @@ cert_GetCertType(CERTCertificate *cert)
} }
PRBool PRBool
cert_EKUAllowsIPsecIKE(CERTCertificate *cert, PRBool *isCritical) cert_IsIPsecOID(CERTOidSequence *extKeyUsage)
{ {
SECStatus rv; if (findOIDinOIDSeqByTagNum(
SECItem encodedExtKeyUsage; extKeyUsage, SEC_OID_EXT_KEY_USAGE_IPSEC_IKE) == SECSuccess) {
CERTOidSequence *extKeyUsage = NULL; return PR_TRUE;
PRBool result = PR_FALSE;
rv = CERT_GetExtenCriticality(cert->extensions,
SEC_OID_X509_EXT_KEY_USAGE,
isCritical);
if (rv != SECSuccess) {
*isCritical = PR_FALSE;
} }
if (findOIDinOIDSeqByTagNum(
encodedExtKeyUsage.data = NULL; extKeyUsage, SEC_OID_IPSEC_IKE_END) == SECSuccess) {
rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, return PR_TRUE;
&encodedExtKeyUsage);
if (rv != SECSuccess) {
/* EKU not present, allowed. */
result = PR_TRUE;
goto done;
} }
if (findOIDinOIDSeqByTagNum(
extKeyUsage = CERT_DecodeOidSequence(&encodedExtKeyUsage); extKeyUsage, SEC_OID_IPSEC_IKE_INTERMEDIATE) == SECSuccess) {
if (!extKeyUsage) { return PR_TRUE;
/* failure */
goto done;
} }
/* these are now deprecated, but may show up. Treat them the same as IKE */
if (findOIDinOIDSeqByTagNum(extKeyUsage, if (findOIDinOIDSeqByTagNum(
SEC_OID_X509_ANY_EXT_KEY_USAGE) == extKeyUsage, SEC_OID_EXT_KEY_USAGE_IPSEC_END) == SECSuccess) {
SECSuccess) { return PR_TRUE;
result = PR_TRUE;
goto done;
} }
if (findOIDinOIDSeqByTagNum(
if (findOIDinOIDSeqByTagNum(extKeyUsage, extKeyUsage, SEC_OID_EXT_KEY_USAGE_IPSEC_TUNNEL) == SECSuccess) {
SEC_OID_EXT_KEY_USAGE_IPSEC_IKE) == return PR_TRUE;
SECSuccess) {
result = PR_TRUE;
goto done;
} }
if (findOIDinOIDSeqByTagNum(
if (findOIDinOIDSeqByTagNum(extKeyUsage, extKeyUsage, SEC_OID_EXT_KEY_USAGE_IPSEC_USER) == SECSuccess) {
SEC_OID_IPSEC_IKE_END) == return PR_TRUE;
SECSuccess) {
result = PR_TRUE;
goto done;
} }
/* this one should probably be in cert_ComputeCertType and set all usages? */
if (findOIDinOIDSeqByTagNum(extKeyUsage, if (findOIDinOIDSeqByTagNum(
SEC_OID_IPSEC_IKE_INTERMEDIATE) == extKeyUsage, SEC_OID_X509_ANY_EXT_KEY_USAGE) == SECSuccess) {
SECSuccess) { return PR_TRUE;
result = PR_TRUE;
goto done;
} }
return PR_FALSE;
done:
if (encodedExtKeyUsage.data != NULL) {
PORT_Free(encodedExtKeyUsage.data);
}
if (extKeyUsage != NULL) {
CERT_DestroyOidSequence(extKeyUsage);
}
return result;
} }
PRUint32 PRUint32
@ -521,9 +489,9 @@ cert_ComputeCertType(CERTCertificate *cert)
SECItem tmpitem; SECItem tmpitem;
SECItem encodedExtKeyUsage; SECItem encodedExtKeyUsage;
CERTOidSequence *extKeyUsage = NULL; CERTOidSequence *extKeyUsage = NULL;
PRBool basicConstraintPresent = PR_FALSE;
CERTBasicConstraints basicConstraint; CERTBasicConstraints basicConstraint;
PRUint32 nsCertType = 0; PRUint32 nsCertType = 0;
PRBool isCA = PR_FALSE;
tmpitem.data = NULL; tmpitem.data = NULL;
CERT_FindNSCertTypeExtension(cert, &tmpitem); CERT_FindNSCertTypeExtension(cert, &tmpitem);
@ -535,7 +503,7 @@ cert_ComputeCertType(CERTCertificate *cert)
} }
rv = CERT_FindBasicConstraintExten(cert, &basicConstraint); rv = CERT_FindBasicConstraintExten(cert, &basicConstraint);
if (rv == SECSuccess) { if (rv == SECSuccess) {
basicConstraintPresent = PR_TRUE; isCA = basicConstraint.isCA;
} }
if (tmpitem.data != NULL || extKeyUsage != NULL) { if (tmpitem.data != NULL || extKeyUsage != NULL) {
if (tmpitem.data == NULL) { if (tmpitem.data == NULL) {
@ -571,19 +539,11 @@ cert_ComputeCertType(CERTCertificate *cert)
if (findOIDinOIDSeqByTagNum(extKeyUsage, if (findOIDinOIDSeqByTagNum(extKeyUsage,
SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT) == SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT) ==
SECSuccess) { SECSuccess) {
if (basicConstraintPresent == PR_TRUE && (basicConstraint.isCA)) { nsCertType |= isCA ? NS_CERT_TYPE_EMAIL_CA : NS_CERT_TYPE_EMAIL;
nsCertType |= NS_CERT_TYPE_EMAIL_CA;
} else {
nsCertType |= NS_CERT_TYPE_EMAIL;
}
} }
if (findOIDinOIDSeqByTagNum( if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH) == SECSuccess) { extKeyUsage, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH) == SECSuccess) {
if (basicConstraintPresent == PR_TRUE && (basicConstraint.isCA)) { nsCertType |= isCA ? NS_CERT_TYPE_SSL_CA : NS_CERT_TYPE_SSL_SERVER;
nsCertType |= NS_CERT_TYPE_SSL_CA;
} else {
nsCertType |= NS_CERT_TYPE_SSL_SERVER;
}
} }
/* /*
* Treat certs with step-up OID as also having SSL server type. * Treat certs with step-up OID as also having SSL server type.
@ -592,27 +552,18 @@ cert_ComputeCertType(CERTCertificate *cert)
if (findOIDinOIDSeqByTagNum(extKeyUsage, if (findOIDinOIDSeqByTagNum(extKeyUsage,
SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) == SEC_OID_NS_KEY_USAGE_GOVT_APPROVED) ==
SECSuccess) { SECSuccess) {
if (basicConstraintPresent == PR_TRUE && (basicConstraint.isCA)) { nsCertType |= isCA ? NS_CERT_TYPE_SSL_CA : NS_CERT_TYPE_SSL_SERVER;
nsCertType |= NS_CERT_TYPE_SSL_CA;
} else {
nsCertType |= NS_CERT_TYPE_SSL_SERVER;
}
} }
if (findOIDinOIDSeqByTagNum( if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH) == SECSuccess) { extKeyUsage, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH) == SECSuccess) {
if (basicConstraintPresent == PR_TRUE && (basicConstraint.isCA)) { nsCertType |= isCA ? NS_CERT_TYPE_SSL_CA : NS_CERT_TYPE_SSL_CLIENT;
nsCertType |= NS_CERT_TYPE_SSL_CA; }
} else { if (cert_IsIPsecOID(extKeyUsage)) {
nsCertType |= NS_CERT_TYPE_SSL_CLIENT; nsCertType |= isCA ? NS_CERT_TYPE_IPSEC_CA : NS_CERT_TYPE_IPSEC;
}
} }
if (findOIDinOIDSeqByTagNum( if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_EXT_KEY_USAGE_CODE_SIGN) == SECSuccess) { extKeyUsage, SEC_OID_EXT_KEY_USAGE_CODE_SIGN) == SECSuccess) {
if (basicConstraintPresent == PR_TRUE && (basicConstraint.isCA)) { nsCertType |= isCA ? NS_CERT_TYPE_OBJECT_SIGNING_CA : NS_CERT_TYPE_OBJECT_SIGNING;
nsCertType |= NS_CERT_TYPE_OBJECT_SIGNING_CA;
} else {
nsCertType |= NS_CERT_TYPE_OBJECT_SIGNING;
}
} }
if (findOIDinOIDSeqByTagNum( if (findOIDinOIDSeqByTagNum(
extKeyUsage, SEC_OID_EXT_KEY_USAGE_TIME_STAMP) == SECSuccess) { extKeyUsage, SEC_OID_EXT_KEY_USAGE_TIME_STAMP) == SECSuccess) {
@ -629,7 +580,7 @@ cert_ComputeCertType(CERTCertificate *cert)
nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER; nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER;
/* if the basic constraint extension says the cert is a CA, then /* if the basic constraint extension says the cert is a CA, then
allow SSL CA and EMAIL CA and Status Responder */ 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 | nsCertType |= (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA |
EXT_KEY_USAGE_STATUS_RESPONDER); EXT_KEY_USAGE_STATUS_RESPONDER);
} }
@ -638,6 +589,14 @@ cert_ComputeCertType(CERTCertificate *cert)
NS_CERT_TYPE_EMAIL; 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) { if (encodedExtKeyUsage.data != NULL) {
PORT_Free(encodedExtKeyUsage.data); PORT_Free(encodedExtKeyUsage.data);
} }
@ -1153,7 +1112,7 @@ CERT_KeyUsageAndTypeForCertUsage(SECCertUsage usage, PRBool ca,
break; break;
case certUsageIPsec: case certUsageIPsec:
requiredKeyUsage = KU_KEY_CERT_SIGN; requiredKeyUsage = KU_KEY_CERT_SIGN;
requiredCertType = NS_CERT_TYPE_SSL_CA; requiredCertType = NS_CERT_TYPE_IPSEC_CA;
break; break;
case certUsageSSLCA: case certUsageSSLCA:
requiredKeyUsage = KU_KEY_CERT_SIGN; requiredKeyUsage = KU_KEY_CERT_SIGN;
@ -1200,7 +1159,7 @@ CERT_KeyUsageAndTypeForCertUsage(SECCertUsage usage, PRBool ca,
case certUsageIPsec: case certUsageIPsec:
/* RFC 4945 Section 5.1.3.2 */ /* RFC 4945 Section 5.1.3.2 */
requiredKeyUsage = KU_DIGITAL_SIGNATURE_OR_NON_REPUDIATION; requiredKeyUsage = KU_DIGITAL_SIGNATURE_OR_NON_REPUDIATION;
requiredCertType = 0; requiredCertType = NS_CERT_TYPE_IPSEC;
break; break;
case certUsageSSLServerWithStepUp: case certUsageSSLServerWithStepUp:
requiredKeyUsage = requiredKeyUsage =
@ -1314,6 +1273,17 @@ CERT_DupCertificate(CERTCertificate *c)
return 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 * Allow use of default cert database, so that apps(such as mozilla) don't
* have to pass the handle all over the place. * have to pass the handle all over the place.

View file

@ -416,6 +416,19 @@ struct CERTDistNamesStr {
void *head; /* private */ 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_CLIENT (0x80) /* bit 0 */
#define NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ #define NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */
#define NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ #define NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */
@ -430,11 +443,12 @@ struct CERTDistNamesStr {
#define NS_CERT_TYPE_APP \ #define NS_CERT_TYPE_APP \
(NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_SSL_SERVER | NS_CERT_TYPE_EMAIL | \ (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 \ #define NS_CERT_TYPE_CA \
(NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_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_OBJECT_SIGNING_CA | EXT_KEY_USAGE_STATUS_RESPONDER | \
NS_CERT_TYPE_IPSEC_CA)
typedef enum SECCertUsageEnum { typedef enum SECCertUsageEnum {
certUsageSSLClient = 0, certUsageSSLClient = 0,
certUsageSSLServer = 1, certUsageSSLServer = 1,

View file

@ -1401,7 +1401,6 @@ CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
for (i = 1; i <= certificateUsageHighest && for (i = 1; i <= certificateUsageHighest &&
(SECSuccess == valid || returnedUsages || log);) { (SECSuccess == valid || returnedUsages || log);) {
PRBool typeAndEKUAllowed = PR_TRUE;
PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE; PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE;
if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) { if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) {
NEXT_USAGE(); NEXT_USAGE();
@ -1451,19 +1450,7 @@ CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
LOG_ERROR(log, cert, 0, requiredKeyUsage); LOG_ERROR(log, cert, 0, requiredKeyUsage);
INVALID_USAGE(); INVALID_USAGE();
} }
if (certUsage != certUsageIPsec) { if (!(certType & requiredCertType)) {
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 (PR_TRUE == requiredUsage) { if (PR_TRUE == requiredUsage) {
PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE); PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
} }

View file

@ -639,6 +639,11 @@ seckey_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki)
return pubk; return pubk;
break; break;
case SEC_OID_ANSIX962_EC_PUBLIC_KEY: 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->keyType = ecKey;
pubk->u.ec.size = 0; pubk->u.ec.size = 0;
@ -1206,6 +1211,37 @@ SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk)
return NULL; 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 * SECKEYPublicKey *
SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk) SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
{ {
@ -1213,6 +1249,8 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
PLArenaPool *arena; PLArenaPool *arena;
CERTCertificate *cert; CERTCertificate *cert;
SECStatus rv; SECStatus rv;
CK_OBJECT_HANDLE pubKeyHandle;
SECItem decodedPoint;
/* /*
* First try to look up the cert. * First try to look up the cert.
@ -1243,11 +1281,47 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
switch (privk->keyType) { switch (privk->keyType) {
case nullKey: case nullKey:
case dhKey:
case dsaKey:
/* Nothing to query, if the cert isn't there, we're done -- no way /* Nothing to query, if the cert isn't there, we're done -- no way
* to get the public key */ * to get the public key */
break; 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: case rsaKey:
rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID, rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
CKA_MODULUS, arena, &pubk->u.rsa.modulus); CKA_MODULUS, arena, &pubk->u.rsa.modulus);
@ -1258,7 +1332,6 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
if (rv != SECSuccess) if (rv != SECSuccess)
break; break;
return pubk; return pubk;
break;
case ecKey: case ecKey:
rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID, rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
CKA_EC_PARAMS, arena, &pubk->u.ec.DEREncodedParams); CKA_EC_PARAMS, arena, &pubk->u.ec.DEREncodedParams);
@ -1268,7 +1341,23 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID, rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
CKA_EC_POINT, arena, &pubk->u.ec.publicValue); CKA_EC_POINT, arena, &pubk->u.ec.publicValue);
if (rv != SECSuccess || pubk->u.ec.publicValue.len == 0) { 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; pubk->u.ec.encoding = ECPoint_Undefined;
return pubk; return pubk;
@ -1276,7 +1365,9 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
break; 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; return NULL;
} }

View file

@ -1013,6 +1013,10 @@ extern SECStatus ChaCha20Poly1305_Open(
const unsigned char *nonce, unsigned int nonceLen, const unsigned char *nonce, unsigned int nonceLen,
const unsigned char *ad, unsigned int adLen); 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 ** MD5 secure hash function

View file

@ -92,23 +92,32 @@ CheckX86CPUSupport()
#endif /* NSS_X86_OR_X64 */ #endif /* NSS_X86_OR_X64 */
/* clang-format off */ /* clang-format off */
#if (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__) #if defined(__aarch64__) || defined(__arm__)
#ifndef __has_include #ifndef __has_include
#define __has_include(x) 0 #define __has_include(x) 0
#endif #endif
#if (__has_include(<sys/auxv.h>) || defined(__linux__)) && \ #if (__has_include(<sys/auxv.h>) || defined(__linux__)) && \
defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__) defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)
/* This might be conflict with host compiler */
#if !defined(__ANDROID__)
#include <sys/auxv.h> #include <sys/auxv.h>
#endif
extern unsigned long getauxval(unsigned long type) __attribute__((weak)); extern unsigned long getauxval(unsigned long type) __attribute__((weak));
#else #else
static unsigned long (*getauxval)(unsigned long) = NULL; static unsigned long (*getauxval)(unsigned long) = NULL;
#define AT_HWCAP2 0
#define AT_HWCAP 0
#endif /* defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)*/ #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 */ /* clang-format on */
#if defined(__aarch64__) && !defined(__ANDROID__) #if defined(__aarch64__)
// Defines from hwcap.h in Linux kernel - ARM64 // Defines from hwcap.h in Linux kernel - ARM64
#ifndef HWCAP_AES #ifndef HWCAP_AES
#define HWCAP_AES (1 << 3) #define HWCAP_AES (1 << 3)
@ -138,9 +147,9 @@ CheckARMSupport()
/* aarch64 must support NEON. */ /* aarch64 must support NEON. */
arm_neon_support_ = disable_arm_neon == NULL; 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 // Defines from hwcap.h in Linux kernel - ARM
/* /*
* HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
@ -165,23 +174,58 @@ CheckARMSupport()
#define HWCAP2_SHA2 (1 << 3) #define HWCAP2_SHA2 (1 << 3)
#endif #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 void
CheckARMSupport() CheckARMSupport()
{ {
char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON");
char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES"); char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES");
if (getauxval) { 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); long hwcaps = getauxval(AT_HWCAP2);
arm_aes_support_ = hwcaps & HWCAP2_AES && disable_hw_aes == NULL; arm_aes_support_ = hwcaps & HWCAP2_AES && disable_hw_aes == NULL;
arm_pmull_support_ = hwcaps & HWCAP2_PMULL; arm_pmull_support_ = hwcaps & HWCAP2_PMULL;
arm_sha1_support_ = hwcaps & HWCAP2_SHA1; arm_sha1_support_ = hwcaps & HWCAP2_SHA1;
arm_sha2_support_ = hwcaps & HWCAP2_SHA2; 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__)) // #if defined(__ANDROID__) && (defined(__arm__) || defined(__aarch64__))
// #include <cpu-features.h> // #include <cpu-features.h>
// void // void
@ -262,7 +306,7 @@ FreeblInit(void)
{ {
#ifdef NSS_X86_OR_X64 #ifdef NSS_X86_OR_X64
CheckX86CPUSupport(); CheckX86CPUSupport();
#elif (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__) #elif (defined(__aarch64__) || defined(__arm__))
CheckARMSupport(); CheckARMSupport();
#endif #endif
return PR_SUCCESS; return PR_SUCCESS;

View file

@ -157,6 +157,7 @@ ChaCha20Poly1305_DestroyContext(ChaCha20Poly1305Context *ctx, PRBool freeit)
#endif #endif
} }
#ifndef NSS_DISABLE_CHACHAPOLY
void void
ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k, ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k,
uint8_t *nonce, uint32_t ctr) 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); 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 SECStatus
ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output, 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); PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure; 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; *outputLen = inputLen + ctx->tagLen;
if (maxOutputLen < *outputLen) { if (maxOutputLen < *outputLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN); PORT_SetError(SEC_ERROR_OUTPUT_LEN);

View file

@ -22,7 +22,7 @@ swap8b(PRUint64 value)
return (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 PRUint64
swap8b(PRUint64 x) swap8b(PRUint64 x)

View file

@ -11,6 +11,11 @@
#include <stdlib.h> #include <stdlib.h>
#include "prtypes.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. */ /* Unfortunately this isn't always set when it should be. */
#if defined(HAVE_LONG_LONG) #if defined(HAVE_LONG_LONG)
@ -29,11 +34,17 @@
/* /*
* FREEBL_HTONLL(x): swap bytes in a 64-bit integer. * FREEBL_HTONLL(x): swap bytes in a 64-bit integer.
*/ */
#if defined(IS_LITTLE_ENDIAN)
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma intrinsic(_byteswap_uint64) #pragma intrinsic(_byteswap_uint64)
#define FREEBL_HTONLL(x) _byteswap_uint64(x) #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)) #elif defined(__GNUC__) && (defined(__x86_64__) || defined(__x86_64))
PRUint64 swap8b(PRUint64 value); PRUint64 swap8b(PRUint64 value);
@ -48,4 +59,8 @@ PRUint64 swap8b(PRUint64 x);
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#else /* IS_LITTLE_ENDIAN */
#define FREEBL_HTONLL(x) (x)
#endif
#endif /* HAVE_LONG_LONG */ #endif /* HAVE_LONG_LONG */

View file

@ -210,7 +210,8 @@ DH_Derive(SECItem *publicValue,
unsigned int len = 0; unsigned int len = 0;
unsigned int nb; unsigned int nb;
unsigned char *secret = NULL; 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); PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure; return SECFailure;
} }

View file

@ -202,8 +202,8 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
#endif #endif
MP_DIGITS(&k) = 0; MP_DIGITS(&k) = 0;
if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0) || if (!ecParams || ecParams->name == ECCurve_noName ||
!ecParams->name) { !privKey || !privKeyBytes || privKeyLen <= 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure; return SECFailure;
} }
@ -391,7 +391,7 @@ EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey)
int len; int len;
unsigned char *privKeyBytes = NULL; unsigned char *privKeyBytes = NULL;
if (!ecParams) { if (!ecParams || ecParams->name == ECCurve_noName || !privKey) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure; return SECFailure;
} }
@ -430,7 +430,8 @@ EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue)
mp_err err = MP_OKAY; mp_err err = MP_OKAY;
int len; int len;
if (!ecParams || !publicValue || !ecParams->name) { if (!ecParams || ecParams->name == ECCurve_noName ||
!publicValue || !publicValue->len) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure; return SECFailure;
} }
@ -536,8 +537,9 @@ ECDH_Derive(SECItem *publicValue,
int i; int i;
#endif #endif
if (!publicValue || !ecParams || !privateValue || !derivedSecret || if (!publicValue || !publicValue->len ||
!ecParams->name) { !ecParams || ecParams->name == ECCurve_noName ||
!privateValue || !privateValue->len || !derivedSecret) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure; return SECFailure;
} }

View file

@ -114,6 +114,9 @@ ec_Curve25519_pt_mul(SECItem *X, SECItem *k, SECItem *P)
} }
px = P->data; px = P->data;
} }
if (k->len != 32) {
return SECFailure;
}
SECStatus rv = ec_Curve25519_mul(X->data, k->data, px); SECStatus rv = ec_Curve25519_mul(X->data, k->data, px);
if (NSS_SecureMemcmpZero(X->data, X->len) == 0) { if (NSS_SecureMemcmpZero(X->data, X->len) == 0) {

View file

@ -15,8 +15,10 @@
#include "seccomon.h" /* Required for RSA and DSA. */ #include "seccomon.h" /* Required for RSA and DSA. */
#include "secerr.h" #include "secerr.h"
#include "prtypes.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 * 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) */ /* AES Known Plaintext (128-bits). (blocksize is 128-bits) */
static const PRUint8 aes_known_plaintext[] = { "NetscapeepacsteN" }; static const PRUint8 aes_known_plaintext[] = { "NetscapeepacsteN" };
static const PRUint8 aes_gcm_known_aad[] = { "MozillaallizoM" };
/* AES Known Ciphertext (128-bit key). */ /* AES Known Ciphertext (128-bit key). */
static const PRUint8 aes_ecb128_known_ciphertext[] = { static const PRUint8 aes_ecb128_known_ciphertext[] = {
0x3c, 0xa5, 0x96, 0xf3, 0x34, 0x6a, 0x96, 0xc1, 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 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). */ /* AES Known Ciphertext (192-bit key). */
static const PRUint8 aes_ecb192_known_ciphertext[] = { static const PRUint8 aes_ecb192_known_ciphertext[] = {
0xa0, 0x18, 0x62, 0xed, 0x88, 0x19, 0xcb, 0x62, 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 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). */ /* AES Known Ciphertext (256-bit key). */
static const PRUint8 aes_ecb256_known_ciphertext[] = { static const PRUint8 aes_ecb256_known_ciphertext[] = {
0xdb, 0xa6, 0x52, 0x01, 0x8a, 0x70, 0xae, 0x66, 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 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 = 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; (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 = 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; (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. */ /* AES variables. */
PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH]; PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH * 2];
PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH]; PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH * 2];
AESContext *aes_context; AESContext *aes_context;
unsigned int aes_bytes_encrypted; unsigned int aes_bytes_encrypted;
unsigned int aes_bytes_decrypted; unsigned int aes_bytes_decrypted;
CK_GCM_PARAMS gcmParams;
SECStatus aes_status; SECStatus aes_status;
/*check if aes_key_size is 128, 192, or 256 bits */ /*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); 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); return (SECSuccess);
} }
@ -1094,7 +1186,7 @@ freebl_fips_ECDSA_Test(ECParams *ecparams,
"Firefox and ThunderBird are awesome!" "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]; unsigned char sig[2 * MAX_ECKEY_LEN];
SECItem signature, digest; SECItem signature, digest;
ECPrivateKey *ecdsa_private_key = NULL; ECPrivateKey *ecdsa_private_key = NULL;
@ -1136,13 +1228,13 @@ freebl_fips_ECDSA_Test(ECParams *ecparams,
/* ECDSA Single-Round Known Answer Signature Test. */ /* ECDSA Single-Round Known Answer Signature Test. */
/***************************************************/ /***************************************************/
ecdsaStatus = SHA1_HashBuf(sha1, msg, sizeof msg); ecdsaStatus = SHA256_HashBuf(sha256, msg, sizeof msg);
if (ecdsaStatus != SECSuccess) { if (ecdsaStatus != SECSuccess) {
goto loser; goto loser;
} }
digest.type = siBuffer; digest.type = siBuffer;
digest.data = sha1; digest.data = sha256;
digest.len = SHA1_LENGTH; digest.len = SHA256_LENGTH;
memset(sig, 0, sizeof sig); memset(sig, 0, sizeof sig);
signature.type = siBuffer; signature.type = siBuffer;
@ -1181,10 +1273,83 @@ loser:
} }
static SECStatus 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[] = { static const unsigned char p256_prime[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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[] = { static const unsigned char p256_encoding[] = {
0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 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 */ NULL, ec_params_named, /* arena, type */
/* fieldID */ /* fieldID */
{ 256, ec_field_GFp, /* size and type */ { 256, ec_field_GFp, /* size and type */
@ -1250,10 +1415,10 @@ freebl_fips_ECDSA_PowerUpSelfTest()
0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff, 0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff,
0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f, 0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f,
0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5, 0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5,
0x59, 0x6a, 0x62, 0x49, 0x3d, 0x50, 0xc9, 0xe1, 0xa7, 0xd2, 0x20, 0xdd, 0x45, 0xf9, 0x2b, 0xdd,
0x27, 0x3b, 0xff, 0x9b, 0x13, 0x66, 0x67, 0xdd, 0xda, 0x98, 0x99, 0x5b, 0x1c, 0x02, 0x3a, 0x27,
0x7d, 0xd1, 0x0d, 0x2d, 0x7c, 0x44, 0x04, 0x1b, 0x8b, 0x7d, 0xb6, 0xed, 0x0e, 0xe0, 0xa7, 0xac,
0x16, 0x21, 0x12, 0xc5, 0xcb, 0xbd, 0x9e, 0x75 0xaa, 0x36, 0x2c, 0xfa, 0x1a, 0xdf, 0x0d, 0xe1,
}; };
ECParams ecparams; ECParams ecparams;
@ -1261,13 +1426,18 @@ freebl_fips_ECDSA_PowerUpSelfTest()
SECStatus rv; SECStatus rv;
/* ECDSA GF(p) prime field curve test */ /* ECDSA GF(p) prime field curve test */
ecparams = ecdsa_known_P256_Params; ecparams = ec_known_P256_Params;
rv = freebl_fips_ECDSA_Test(&ecparams, rv = freebl_fips_ECDSA_Test(&ecparams,
ecdsa_known_P256_signature, ecdsa_known_P256_signature,
sizeof ecdsa_known_P256_signature); sizeof ecdsa_known_P256_signature);
if (rv != SECSuccess) { if (rv != SECSuccess) {
return (SECFailure); return (SECFailure);
} }
/* ECDH GF(p) prime field curve test */
rv = freebl_fips_ECDH_Test(&ecparams);
if (rv != SECSuccess) {
return (SECFailure);
}
return (SECSuccess); return (SECSuccess);
} }
@ -1417,6 +1587,138 @@ freebl_fips_DSA_PowerUpSelfTest(void)
return (SECSuccess); 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 static SECStatus
freebl_fips_RNG_PowerUpSelfTest(void) freebl_fips_RNG_PowerUpSelfTest(void)
{ {
@ -1541,7 +1843,7 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
return rv; return rv;
/* NOTE: RSA can only be tested in full freebl. It requires access to /* NOTE: RSA can only be tested in full freebl. It requires access to
* the locking primitives */ * the locking primitives */
/* RSA Power-Up SelfTest(s). */ /* RSA Power-Up SelfTest(s). */
rv = freebl_fips_RSA_PowerUpSelfTest(); rv = freebl_fips_RSA_PowerUpSelfTest();
@ -1554,8 +1856,14 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
if (rv != SECSuccess) if (rv != SECSuccess)
return rv; return rv;
/* ECDSA Power-Up SelfTest(s). */ /* DH Power-Up SelfTest(s). */
rv = freebl_fips_ECDSA_PowerUpSelfTest(); rv = freebl_fips_DH_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;
/* EC Power-Up SelfTest(s). */
rv = freebl_fips_EC_PowerUpSelfTest();
if (rv != SECSuccess) if (rv != SECSuccess)
return rv; return rv;

View file

@ -76,11 +76,11 @@
'__SSSE3__', '__SSSE3__',
], ],
}], }],
[ 'OS=="android"', { [ 'target_arch=="arm"', {
# On Android we can't use any of the hardware acceleration :( # Gecko doesn't support non-NEON platform on Android, but tier-3
'defines!': [ # platform such as Linux/arm will need it
'__ARM_NEON__', 'cflags_mozilla': [
'__ARM_NEON', '-mfpu=neon'
], ],
}], }],
], ],
@ -107,7 +107,7 @@
], ],
}], }],
# macOS build doesn't use cflags. # macOS build doesn't use cflags.
[ 'OS=="mac"', { [ 'OS=="mac" or OS=="ios"', {
'xcode_settings': { 'xcode_settings': {
'OTHER_CFLAGS': [ 'OTHER_CFLAGS': [
'-mpclmul', '-maes' '-mpclmul', '-maes'

View file

@ -143,6 +143,7 @@ loser:
void void
intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit) intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit)
{ {
PORT_Memset(gcm, 0, sizeof(intel_AES_GCMContext));
if (freeit) { if (freeit) {
PORT_Free(gcm); PORT_Free(gcm);
} }

View file

@ -313,10 +313,14 @@ static const struct FREEBLVectorStr vector =
BLAKE2B_End, BLAKE2B_End,
BLAKE2B_FlattenSize, BLAKE2B_FlattenSize,
BLAKE2B_Flatten, BLAKE2B_Flatten,
BLAKE2B_Resurrect BLAKE2B_Resurrect,
/* End of Version 3.020 */ /* End of Version 3.020 */
ChaCha20_Xor
/* End of version 3.021 */
}; };
const FREEBLVector* const FREEBLVector*

View file

@ -2060,6 +2060,16 @@ EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
return (vector->p_EC_CopyParams)(arena, dstParams, srcParams); 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 SECStatus
ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx, ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx,
const unsigned char *key, unsigned int keyLen, const unsigned char *key, unsigned int keyLen,

View file

@ -10,7 +10,7 @@
#include "blapi.h" #include "blapi.h"
#define FREEBL_VERSION 0x0314 #define FREEBL_VERSION 0x0315
struct FREEBLVectorStr { struct FREEBLVectorStr {
@ -759,6 +759,12 @@ struct FREEBLVectorStr {
/* Version 3.020 came to here */ /* 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 /* Add new function pointers at the end of this struct and bump
* FREEBL_VERSION at the beginning of this file. */ * FREEBL_VERSION at the beginning of this file. */
}; };

View file

@ -2063,7 +2063,10 @@ s_mp_almost_inverse(const mp_int *a, const mp_int *p, mp_int *c)
} }
} }
if (res >= 0) { 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)); MP_CHECKOK(mp_add(c, p, c));
} }
res = k; res = k;

View file

@ -491,11 +491,11 @@ cleanup:
** This implments steps 4 thorough 22 of FIPS 186-3 A.1.2.1 and ** 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 ** steps 16 through 34 of FIPS 186-2 C.6
*/ */
#define MAX_ST_SEED_BITS (HASH_LENGTH_MAX * PR_BITS_PER_BYTE)
static SECStatus static SECStatus
makePrimefromPrimesShaweTaylor( makePrimefromPrimesShaweTaylor(
HASH_HashType hashtype, /* selected Hashing algorithm */ HASH_HashType hashtype, /* selected Hashing algorithm */
unsigned int length, /* input. Length of prime in bits. */ unsigned int length, /* input. Length of prime in bits. */
unsigned int seedlen, /* input seed length in bits */
mp_int *c0, /* seed prime */ mp_int *c0, /* seed prime */
mp_int *q, /* sub prime, can be 1 */ mp_int *q, /* sub prime, can be 1 */
mp_int *prime, /* output. */ mp_int *prime, /* output. */
@ -557,7 +557,7 @@ makePrimefromPrimesShaweTaylor(
old_counter = *prime_gen_counter; old_counter = *prime_gen_counter;
/* /*
** Comment: Generate a pseudorandom integer x in the interval ** Comment: Generate a pseudorandom integer x in the interval
** [2**(lenght-1), 2**length]. ** [2**(length-1), 2**length].
** **
** Step 6/18 x = 0 ** Step 6/18 x = 0
*/ */
@ -569,11 +569,10 @@ makePrimefromPrimesShaweTaylor(
for (i = 0; i < iterations; i++) { for (i = 0; i < iterations; i++) {
/* is bigger than prime_seed should get to */ /* is bigger than prime_seed should get to */
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i, 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 */ /* Step 8/20 prime_seed = prime_seed + iterations + 1 */
CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS, CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
prime_seed));
/* /*
** Step 9/21 x = 2 ** (length-1) + x mod 2 ** (length-1) ** Step 9/21 x = 2 ** (length-1) + x mod 2 ** (length-1)
** **
@ -595,7 +594,7 @@ makePrimefromPrimesShaweTaylor(
x[offset] = (mask & x[offset]) | bit; x[offset] = (mask & x[offset]) | bit;
/* /*
** Comment: Generate a candidate prime c in the interval ** 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 10 t = ceiling(x/(2q(p0)))
** Step 22 t = ceiling(x/(2(c0))) ** Step 22 t = ceiling(x/(2(c0)))
@ -624,7 +623,7 @@ step_23:
/* t = 2**(length-1) + 2qc0 -1 */ /* t = 2**(length-1) + 2qc0 -1 */
CHECK_MPI_OK(mp_add(&two_length_minus_1, &t, &t)); CHECK_MPI_OK(mp_add(&two_length_minus_1, &t, &t));
/* t = floor((2**(length-1)+2qc0 -1)/2qco) /* 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_div(&t, &c0_2, &t, NULL));
CHECK_MPI_OK(mp_mul(&t, &c0_2, &c)); CHECK_MPI_OK(mp_mul(&t, &c0_2, &c));
CHECK_MPI_OK(mp_add_d(&c, (mp_digit)1, &c)); /* c= 2tqc0 + 1*/ 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. ** NOTE: we reuse the x array for 'a' initially.
*/ */
for (i = 0; i < iterations; i++) { 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, 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 */ /* Step 16/28 prime_seed = prime_seed + iterations + 1 */
CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS, CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
prime_seed));
/* Step 17/29 a = 2 + (a mod (c-3)). */ /* Step 17/29 a = 2 + (a mod (c-3)). */
CHECK_MPI_OK(mp_read_unsigned_octets(&a, x, iterations * hashlen)); 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 */ 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 hashlen = HASH_ResultLen(hashtype);
int outlen = hashlen * PR_BITS_PER_BYTE; int outlen = hashlen * PR_BITS_PER_BYTE;
int offset; int offset;
int seedlen = input_seed->len * 8; /*seedlen is in bits */
unsigned char bit, mask; unsigned char bit, mask;
unsigned char x[HASH_LENGTH_MAX * 2]; unsigned char x[HASH_LENGTH_MAX * 2];
mp_digit dummy; mp_digit dummy;
@ -775,7 +773,7 @@ makePrimefromSeedShaweTaylor(
goto cleanup; goto cleanup;
} }
/* Steps 16-34 */ /* Steps 16-34 */
rv = makePrimefromPrimesShaweTaylor(hashtype, length, &c0, &one, rv = makePrimefromPrimesShaweTaylor(hashtype, length, seedlen, &c0, &one,
prime, prime_seed, prime_gen_counter); prime, prime_seed, prime_gen_counter);
goto cleanup; /* we're done, one way or the other */ goto cleanup; /* we're done, one way or the other */
} }
@ -787,8 +785,7 @@ makePrimefromSeedShaweTaylor(
step_5: step_5:
/* Step 5 c = Hash(prime_seed) xor Hash(prime_seed+1). */ /* 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(HASH_HashBuf(hashtype, x, prime_seed->data, prime_seed->len));
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1, CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1, seedlen, &x[hashlen]));
MAX_ST_SEED_BITS, &x[hashlen]));
for (i = 0; i < hashlen; i++) { for (i = 0; i < hashlen; i++) {
x[i] = x[i] ^ x[i + hashlen]; x[i] = x[i] ^ x[i + hashlen];
} }
@ -817,7 +814,7 @@ step_5:
/* Step 8 prime_gen_counter = prime_gen_counter + 1 */ /* Step 8 prime_gen_counter = prime_gen_counter + 1 */
(*prime_gen_counter)++; (*prime_gen_counter)++;
/* Step 9 prime_seed = prime_seed + 2 */ /* 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 /* Step 10 Perform deterministic primality test on c. For example, since
** c is small, it's primality can be tested by trial division, See ** c is small, it's primality can be tested by trial division, See
** See Appendic C.7. ** See Appendic C.7.
@ -890,7 +887,8 @@ findQfromSeed(
mp_int *Q_, /* output. */ mp_int *Q_, /* output. */
unsigned int *qseed_len, /* output */ unsigned int *qseed_len, /* output */
HASH_HashType *hashtypePtr, /* output. Hash uses */ 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; HASH_HashType hashtype;
SECItem firstseed = { 0, 0, 0 }; SECItem firstseed = { 0, 0, 0 };
@ -964,6 +962,7 @@ findQfromSeed(
*qseed_len = qseed.len; *qseed_len = qseed.len;
*hashtypePtr = hashtype; *hashtypePtr = hashtype;
*typePtr = FIPS186_3_ST_TYPE; *typePtr = FIPS186_3_ST_TYPE;
*qgen_counter = count;
SECITEM_FreeItem(&qseed, PR_FALSE); SECITEM_FreeItem(&qseed, PR_FALSE);
return SECSuccess; return SECSuccess;
} }
@ -1388,19 +1387,26 @@ step_5:
CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1, 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 */ /* 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)); &p0, &Q, &P, &pseed, &pgen_counter));
/* combine all the seeds */ /* 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); seed->data = PORT_ArenaZAlloc(verify->arena, seed->len);
if (seed->data == NULL) { if (seed->data == NULL) {
goto cleanup; goto cleanup;
} }
PORT_Memcpy(seed->data, firstseed.data, firstseed.len); PORT_Memcpy(seed->data, firstseed.data, firstseed.len);
PORT_Memcpy(seed->data + firstseed.len, pseed.data, pseed.len); PORT_Memcpy(seed->data + 2 * firstseed.len - pseed.len, pseed.data, pseed.len);
PORT_Memcpy(seed->data + firstseed.len + pseed.len, qseed.data, qseed.len); PORT_Memcpy(seed->data + 3 * firstseed.len - qseed.len, qseed.data, qseed.len);
counter = 0; /* (qgen_counter << 16) | pgen_counter; */ counter = (qgen_counter << 16) | pgen_counter;
/* we've generated both P and Q now, skip to generating G */ /* we've generated both P and Q now, skip to generating G */
goto generate_G; goto generate_G;
@ -1620,6 +1626,7 @@ PQG_VerifyParams(const PQGParams *params,
int j; int j;
unsigned int counter_max = 0; /* handle legacy L < 1024 */ unsigned int counter_max = 0; /* handle legacy L < 1024 */
unsigned int qseed_len; unsigned int qseed_len;
unsigned int qgen_counter_ = 0;
SECItem pseed_ = { 0, 0, 0 }; SECItem pseed_ = { 0, 0, 0 };
HASH_HashType hashtype; HASH_HashType hashtype;
pqgGenType type; pqgGenType type;
@ -1699,48 +1706,55 @@ PQG_VerifyParams(const PQGParams *params,
/* Steps 7-12 are done only if the optional PQGVerify is supplied. */ /* Steps 7-12 are done only if the optional PQGVerify is supplied. */
/* continue processing P */ /* continue processing P */
/* 7. counter < 4*L */ /* 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) */ /* 8. g >= N and g < 2*L (g is length of seed in bits) */
g = vfy->seed.len * 8; /* step 7 and 8 are delayed until we determine which type of generation
CHECKPARAM(g >= N && g < counter_max / 2); * was used */
/* 9. Q generated from SEED matches Q in PQGParams. */ /* 9. Q generated from SEED matches Q in PQGParams. */
/* This function checks all possible hash and generation types to /* This function checks all possible hash and generation types to
* find a Q_ which matches Q. */ * find a Q_ which matches Q. */
g = vfy->seed.len * 8;
CHECKPARAM(findQfromSeed(L, N, g, &vfy->seed, &Q, &Q_, &qseed_len, 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); 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) { if (type == FIPS186_3_ST_TYPE) {
SECItem qseed = { 0, 0, 0 }; SECItem qseed = { 0, 0, 0 };
SECItem pseed = { 0, 0, 0 }; SECItem pseed = { 0, 0, 0 };
unsigned int first_seed_len; 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 /* extract pseed and qseed from domain_parameter_seed, which is
* first_seed || pseed || qseed. qseed is first_seed + small_integer * 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 * 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 * pseed.len will be smaller because mpi clamps them. pqgGen
* depend on the fact that * automatically adds the zero pad back though, so we can depend
* first_seed.len = floor(domain_parameter_seed.len/3). * domain_parameter_seed.len to be a multiple of three. We only have
* findQfromSeed returned qseed.len, so we can calculate pseed.len as * to deal with the fact that the returned seeds from our functions
* pseed.len = domain_parameter_seed.len - first_seed.len - qseed.len * could be shorter.
* this is probably over kill, since 99.999% of the time they will all * first_seed.len = domain_parameter_seed.len/3
* be equal. * We can now find the offsets;
*
* With the lengths, we can now find the offsets;
* first_seed.data = domain_parameter_seed.data + 0 * first_seed.data = domain_parameter_seed.data + 0
* pseed.data = domain_parameter_seed.data + first_seed.len * pseed.data = domain_parameter_seed.data + first_seed.len
* qseed.data = domain_parameter_seed.data * qseed.data = domain_parameter_seed.data
* + domain_paramter_seed.len - qseed.len * + 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; first_seed_len = vfy->seed.len / 3;
CHECKPARAM(qseed_len < vfy->seed.len); CHECKPARAM(qseed_len < vfy->seed.len);
CHECKPARAM(first_seed_len * 8 > N - 1); 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.len = qseed_len;
qseed.data = vfy->seed.data + vfy->seed.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; 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) ** (ST_Random_Prime((ceil(length/2)+1, input_seed)
*/ */
CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1, 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 */ /* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, first_seed_len * 8,
&p0, &Q_, &P_, &pseed_, &pgen_counter)); &p0, &Q_, &P_, &pseed_, &pgen_counter_));
CHECKPARAM(mp_cmp(&P, &P_) == 0); CHECKPARAM(mp_cmp(&P, &P_) == 0);
/* make sure pseed wasn't tampered with (since it is part of /* make sure pseed wasn't tampered with (since it is part of
* calculating G) */ * 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); 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) { } else if (vfy->counter == -1) {
/* If counter is set to -1, we are really only verifying G, skip /* If counter is set to -1, we are really only verifying G, skip
* the remainder of the checks for P */ * the remainder of the checks for P */

View file

@ -1032,13 +1032,19 @@ AES_CreateContext(const unsigned char *key, const unsigned char *iv,
void void
AES_DestroyContext(AESContext *cx, PRBool freeit) AES_DestroyContext(AESContext *cx, PRBool freeit)
{ {
void *mem = cx->mem;
if (cx->worker_cx && cx->destroy) { if (cx->worker_cx && cx->destroy) {
(*cx->destroy)(cx->worker_cx, PR_TRUE); (*cx->destroy)(cx->worker_cx, PR_TRUE);
cx->worker_cx = NULL; cx->worker_cx = NULL;
cx->destroy = NULL; cx->destroy = NULL;
} }
PORT_Memset(cx, 0, sizeof(AESContext));
if (freeit) { 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;
} }
} }

View file

@ -3002,17 +3002,8 @@ PKIX_PL_Cert_VerifyCertAndKeyType(
if (CERT_CheckKeyUsage(cert->nssCert, requiredKeyUsage) != SECSuccess) { if (CERT_CheckKeyUsage(cert->nssCert, requiredKeyUsage) != SECSuccess) {
PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED); PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED);
} }
if (certUsage != certUsageIPsec) { if (!(certType & requiredCertType)) {
if (!(certType & requiredCertType)) { PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED);
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);
}
} }
cleanup: cleanup:
PKIX_DECREF(basicConstraints); PKIX_DECREF(basicConstraints);

View file

@ -1145,3 +1145,9 @@ HASH_GetHashOidTagByHashType;
;+ local: ;+ local:
;+ *; ;+ *;
;+}; ;+};
;+NSS_3.44 { # NSS 3.44 release
;+ global:
CERT_GetCertificateDer;
;+ local:
;+ *;
;+};

View file

@ -22,10 +22,10 @@
* The format of the version string should be * The format of the version string should be
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]" * "<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_VMAJOR 3
#define NSS_VMINOR 43 #define NSS_VMINOR 44
#define NSS_VPATCH 0 #define NSS_VPATCH 1
#define NSS_VBUILD 0 #define NSS_VBUILD 0
#define NSS_BETA PR_FALSE #define NSS_BETA PR_FALSE

View file

@ -190,7 +190,6 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey,
attrs++; attrs++;
PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
attrs++; attrs++;
signedattr = attrs;
PK11_SETATTRS(attrs, CKA_EC_PARAMS, PK11_SETATTRS(attrs, CKA_EC_PARAMS,
pubKey->u.ec.DEREncodedParams.data, pubKey->u.ec.DEREncodedParams.data,
pubKey->u.ec.DEREncodedParams.len); pubKey->u.ec.DEREncodedParams.len);
@ -222,12 +221,14 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey,
PORT_SetError(SEC_ERROR_BAD_KEY); PORT_SetError(SEC_ERROR_BAD_KEY);
return CK_INVALID_HANDLE; return CK_INVALID_HANDLE;
} }
templateCount = attrs - theTemplate; templateCount = attrs - theTemplate;
signedcount = attrs - signedattr;
PORT_Assert(templateCount <= (sizeof(theTemplate) / sizeof(CK_ATTRIBUTE))); PORT_Assert(templateCount <= (sizeof(theTemplate) / sizeof(CK_ATTRIBUTE)));
for (attrs = signedattr; signedcount; attrs++, signedcount--) { if (pubKey->keyType != ecKey) {
pk11_SignedToUnsigned(attrs); PORT_Assert(signedattr);
signedcount = attrs - signedattr;
for (attrs = signedattr; signedcount; attrs++, signedcount--) {
pk11_SignedToUnsigned(attrs);
}
} }
rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, theTemplate, rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, theTemplate,
templateCount, isToken, &objectID); templateCount, isToken, &objectID);
@ -1074,9 +1075,13 @@ pk11_loadPrivKeyWithFlags(PK11SlotInfo *slot, SECKEYPrivateKey *privKey,
&cktrue, &ckfalse); &cktrue, &ckfalse);
/* Not everyone can handle zero padded key values, give /* Not everyone can handle zero padded key values, give
* them the raw data as unsigned */ * them the raw data as unsigned. The exception is EC,
for (ap = attrs; extra_count; ap++, extra_count--) { * where the values are encoded or zero-preserving
pk11_SignedToUnsigned(ap); * per-RFC5915 */
if (privKey->keyType != ecKey) {
for (ap = attrs; extra_count; ap++, extra_count--) {
pk11_SignedToUnsigned(ap);
}
} }
/* now Store the puppies */ /* now Store the puppies */

View file

@ -184,7 +184,9 @@ PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert,
SECKEY_DestroyPublicKey(pubKey); SECKEY_DestroyPublicKey(pubKey);
return PR_FALSE; return PR_FALSE;
} }
pk11_SignedToUnsigned(&theTemplate); if (pubKey->keyType != ecKey) {
pk11_SignedToUnsigned(&theTemplate);
}
if (pk11_FindObjectByTemplate(slot, &theTemplate, 1) != CK_INVALID_HANDLE) { if (pk11_FindObjectByTemplate(slot, &theTemplate, 1) != CK_INVALID_HANDLE) {
SECKEY_DestroyPublicKey(pubKey); SECKEY_DestroyPublicKey(pubKey);
return PR_TRUE; return PR_TRUE;

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 = static const char *my_shlib_name =
SHLIB_PREFIX "nss" SHLIB_VERSION "." SHLIB_SUFFIX; SHLIB_PREFIX "nss" SHLIB_VERSION "." SHLIB_SUFFIX;
static const char *softoken_shlib_name = static const char *softoken_shlib_name =
@ -403,7 +403,7 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
/* internal modules get loaded from their internal list */ /* internal modules get loaded from their internal list */
if (mod->internal && (mod->dllName == NULL)) { if (mod->internal && (mod->dllName == NULL)) {
#ifdef NSS_TEST_BUILD #ifdef NSS_STATIC_SOFTOKEN
entry = (CK_C_GetFunctionList)NSC_GetFunctionList; entry = (CK_C_GetFunctionList)NSC_GetFunctionList;
#else #else
/* /*
@ -430,7 +430,7 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
if (mod->isModuleDB) { if (mod->isModuleDB) {
mod->moduleDBFunc = (CK_C_GetFunctionList) mod->moduleDBFunc = (CK_C_GetFunctionList)
#ifdef NSS_TEST_BUILD #ifdef NSS_STATIC_SOFTOKEN
NSC_ModuleDBFunc; NSC_ModuleDBFunc;
#else #else
PR_FindSymbol(softokenLib, "NSC_ModuleDBFunc"); 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 * if not, we should change this to SECFailure and move it above the
* mod->loaded = PR_FALSE; */ * mod->loaded = PR_FALSE; */
if (mod->internal && (mod->dllName == NULL)) { if (mod->internal && (mod->dllName == NULL)) {
#ifndef NSS_TEST_BUILD #ifndef NSS_STATIC_SOFTOKEN
if (0 == PR_ATOMIC_DECREMENT(&softokenLoadCount)) { if (0 == PR_ATOMIC_DECREMENT(&softokenLoadCount)) {
if (softokenLib) { if (softokenLib) {
disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD"); disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");

View file

@ -226,6 +226,7 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type, unsigned long len)
return CKK_CAMELLIA; return CKK_CAMELLIA;
case CKM_NSS_CHACHA20_POLY1305: case CKM_NSS_CHACHA20_POLY1305:
case CKM_NSS_CHACHA20_KEY_GEN: case CKM_NSS_CHACHA20_KEY_GEN:
case CKM_NSS_CHACHA20_CTR:
return CKK_NSS_CHACHA20; return CKK_NSS_CHACHA20;
case CKM_AES_ECB: case CKM_AES_ECB:
case CKM_AES_CBC: case CKM_AES_CBC:
@ -239,6 +240,8 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type, unsigned long len)
case CKM_AES_KEY_GEN: case CKM_AES_KEY_GEN:
case CKM_NETSCAPE_AES_KEY_WRAP: case CKM_NETSCAPE_AES_KEY_WRAP:
case CKM_NETSCAPE_AES_KEY_WRAP_PAD: case CKM_NETSCAPE_AES_KEY_WRAP_PAD:
case CKM_AES_XCBC_MAC:
case CKM_AES_XCBC_MAC_96:
return CKK_AES; return CKK_AES;
case CKM_DES_ECB: case CKM_DES_ECB:
case CKM_DES_CBC: case CKM_DES_CBC:
@ -440,6 +443,7 @@ PK11_GetKeyGenWithSize(CK_MECHANISM_TYPE type, int size)
case CKM_CAMELLIA_KEY_GEN: case CKM_CAMELLIA_KEY_GEN:
return CKM_CAMELLIA_KEY_GEN; return CKM_CAMELLIA_KEY_GEN;
case CKM_NSS_CHACHA20_POLY1305: case CKM_NSS_CHACHA20_POLY1305:
case CKM_NSS_CHACHA20_CTR:
return CKM_NSS_CHACHA20_KEY_GEN; return CKM_NSS_CHACHA20_KEY_GEN;
case CKM_AES_ECB: case CKM_AES_ECB:
case CKM_AES_CBC: case CKM_AES_CBC:
@ -730,6 +734,9 @@ PK11_GetBlockSize(CK_MECHANISM_TYPE type, SECItem *params)
case CKM_RSA_X_509: case CKM_RSA_X_509:
/*actually it's the modulus length of the key!*/ /*actually it's the modulus length of the key!*/
return -1; /* failure */ return -1; /* failure */
case CKM_NSS_CHACHA20_POLY1305:
case CKM_NSS_CHACHA20_CTR:
return 64;
default: default:
return pk11_lookup(type)->blockSize; return pk11_lookup(type)->blockSize;
} }
@ -784,12 +791,16 @@ PK11_GetIVLength(CK_MECHANISM_TYPE type)
case CKM_CAST3_CBC_PAD: case CKM_CAST3_CBC_PAD:
case CKM_CAST5_CBC_PAD: case CKM_CAST5_CBC_PAD:
return 8; return 8;
case CKM_AES_GCM:
case CKM_NSS_CHACHA20_POLY1305:
return 12;
case CKM_SEED_CBC: case CKM_SEED_CBC:
case CKM_SEED_CBC_PAD: case CKM_SEED_CBC_PAD:
case CKM_CAMELLIA_CBC: case CKM_CAMELLIA_CBC:
case CKM_CAMELLIA_CBC_PAD: case CKM_CAMELLIA_CBC_PAD:
case CKM_AES_CBC: case CKM_AES_CBC:
case CKM_AES_CBC_PAD: case CKM_AES_CBC_PAD:
case CKM_NSS_CHACHA20_CTR:
return 16; return 16;
case CKM_SKIPJACK_CBC64: case CKM_SKIPJACK_CBC64:
case CKM_SKIPJACK_ECB64: case CKM_SKIPJACK_ECB64:

View file

@ -238,6 +238,8 @@ static const oidValDef curveOptList[] = {
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
{ CIPHER_NAME("SECP521R1"), SEC_OID_SECG_EC_SECP521R1, { CIPHER_NAME("SECP521R1"), SEC_OID_SECG_EC_SECP521R1,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, 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) */ /* ANSI X9.62 named elliptic curves (characteristic two field) */
{ CIPHER_NAME("C2PNB163V1"), SEC_OID_ANSIX962_EC_C2PNB163V1, { CIPHER_NAME("C2PNB163V1"), SEC_OID_ANSIX962_EC_C2PNB163V1,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },

View file

@ -505,7 +505,7 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
} }
PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len); PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
attrs++; attrs++;
signedattr = attrs; /* No signed attrs for EC */
/* curveOID always is a copy of AlgorithmID.parameters. */ /* curveOID always is a copy of AlgorithmID.parameters. */
PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data, PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data,
lpk->u.ec.curveOID.len); lpk->u.ec.curveOID.len);
@ -523,11 +523,12 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
} }
templateCount = attrs - theTemplate; templateCount = attrs - theTemplate;
PORT_Assert(templateCount <= sizeof(theTemplate) / sizeof(CK_ATTRIBUTE)); PORT_Assert(templateCount <= sizeof(theTemplate) / sizeof(CK_ATTRIBUTE));
PORT_Assert(signedattr != NULL); if (lpk->keyType != ecKey) {
signedcount = attrs - signedattr; PORT_Assert(signedattr);
signedcount = attrs - signedattr;
for (ap = signedattr; signedcount; ap++, signedcount--) { for (ap = signedattr; signedcount; ap++, signedcount--) {
pk11_SignedToUnsigned(ap); pk11_SignedToUnsigned(ap);
}
} }
rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION,

View file

@ -111,6 +111,7 @@ CK_OBJECT_HANDLE PK11_FindObjectForCert(CERTCertificate *cert,
PK11SymKey *pk11_CopyToSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PK11SymKey *pk11_CopyToSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey); CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey);
unsigned int pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType); unsigned int pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType);
CK_OBJECT_HANDLE PK11_DerivePubKeyFromPrivKey(SECKEYPrivateKey *privKey);
/********************************************************************** /**********************************************************************
* Certs * Certs

View file

@ -1598,6 +1598,7 @@ PK11_DeriveWithTemplate(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
PK11_FreeSymKey(newBaseKey); PK11_FreeSymKey(newBaseKey);
if (crv != CKR_OK) { if (crv != CKR_OK) {
PK11_FreeSymKey(symKey); PK11_FreeSymKey(symKey);
PORT_SetError(PK11_MapError(crv));
return NULL; return NULL;
} }
return symKey; return symKey;
@ -1839,6 +1840,35 @@ loser:
return NULL; 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 * 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 * random numbers. For Mail usage RandomB should be NULL. In the Sender's

View file

@ -10,7 +10,7 @@
'target_name': 'pk11wrap_static', 'target_name': 'pk11wrap_static',
'type': 'static_library', 'type': 'static_library',
'defines': [ 'defines': [
'NSS_TEST_BUILD', 'NSS_STATIC_SOFTOKEN',
], ],
'dependencies': [ 'dependencies': [
'pk11wrap_base', 'pk11wrap_base',

View file

@ -492,14 +492,16 @@ typedef struct {
static SECStatus static SECStatus
collect_certs(void *arg, SECItem **certs, int numcerts) collect_certs(void *arg, SECItem **certs, int numcerts)
{ {
SECStatus rv; collect_args *collectArgs = (collect_args *)arg;
collect_args *collectArgs; if (!collectArgs || !collectArgs->arena) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
collectArgs = (collect_args *)arg; return SECFailure;
}
rv = SECITEM_CopyItem(collectArgs->arena, &collectArgs->cert, *certs); if (numcerts < 1 || !certs || !*certs) {
PORT_SetError(SEC_ERROR_BAD_DER);
return (rv); return SECFailure;
}
return SECITEM_CopyItem(collectArgs->arena, &collectArgs->cert, *certs);
} }
/* /*

View file

@ -12,6 +12,7 @@
#include "lowkeyi.h" #include "lowkeyi.h"
#include "secoid.h" #include "secoid.h"
#include "secerr.h" #include "secerr.h"
#include "pkcs11i.h"
/* /*
* different platforms have different ways of calling and initial entry point * different platforms have different ways of calling and initial entry point
@ -626,6 +627,10 @@ sftk_startup_tests(void)
* the token */ * the token */
return; return;
} }
rv = sftk_fips_IKE_PowerUpSelfTests();
if (rv != SECSuccess) {
return;
}
sftk_self_tests_success = PR_TRUE; sftk_self_tests_success = PR_TRUE;
} }

View file

@ -950,9 +950,9 @@ lg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
case CKA_UNWRAP: case CKA_UNWRAP:
return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
case CKA_VALUE: case CKA_VALUE:
return lg_CopyPrivAttrSigned(attribute, type, return lg_CopyPrivAttribute(attribute, type,
key->u.ec.privateValue.data, key->u.ec.privateValue.data,
key->u.ec.privateValue.len, sdbpw); key->u.ec.privateValue.len, sdbpw);
case CKA_EC_PARAMS: case CKA_EC_PARAMS:
return lg_CopyAttributeSigned(attribute, type, return lg_CopyAttributeSigned(attribute, type,
key->u.ec.ecParams.DEREncoding.data, key->u.ec.ecParams.DEREncoding.data,

View file

@ -261,6 +261,7 @@ NSSLOWKEYPublicKey *
nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk) nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
{ {
NSSLOWKEYPublicKey *pubk; NSSLOWKEYPublicKey *pubk;
SECItem publicValue;
PLArenaPool *arena; PLArenaPool *arena;
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
@ -301,6 +302,19 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
pubk->arena = arena; pubk->arena = arena;
pubk->keyType = privk->keyType; 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, rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
&privk->u.dsa.publicValue); &privk->u.dsa.publicValue);
if (rv != SECSuccess) if (rv != SECSuccess)
@ -327,6 +341,19 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
pubk->arena = arena; pubk->arena = arena;
pubk->keyType = privk->keyType; 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, rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
&privk->u.dh.publicValue); &privk->u.dh.publicValue);
if (rv != SECSuccess) if (rv != SECSuccess)

View file

@ -46,6 +46,7 @@ CSRCS = \
sdb.c \ sdb.c \
sftkdb.c \ sftkdb.c \
sftkhmac.c \ sftkhmac.c \
sftkike.c \
sftkpars.c \ sftkpars.c \
sftkpwd.c \ sftkpwd.c \
softkver.c \ softkver.c \

View file

@ -328,6 +328,8 @@ static const struct mechanismList mechanisms[] = {
{ CKM_AES_CTS, { 16, 32, CKF_EN_DE }, PR_TRUE }, { CKM_AES_CTS, { 16, 32, CKF_EN_DE }, PR_TRUE },
{ CKM_AES_CTR, { 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_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 --------------------- */ /* ------------------------- Camellia Operations --------------------- */
{ CKM_CAMELLIA_KEY_GEN, { 16, 32, CKF_GENERATE }, PR_TRUE }, { CKM_CAMELLIA_KEY_GEN, { 16, 32, CKF_GENERATE }, PR_TRUE },
{ CKM_CAMELLIA_ECB, { 16, 32, CKF_EN_DE_WR_UN }, 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 ---------------------- */ /* ------------------------- ChaCha20 Operations ---------------------- */
{ CKM_NSS_CHACHA20_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE }, { 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_POLY1305, { 32, 32, CKF_EN_DE }, PR_TRUE },
{ CKM_NSS_CHACHA20_CTR, { 32, 32, CKF_EN_DE }, PR_TRUE },
#endif /* NSS_DISABLE_CHACHAPOLY */ #endif /* NSS_DISABLE_CHACHAPOLY */
/* ------------------------- Hashing Operations ----------------------- */ /* ------------------------- Hashing Operations ----------------------- */
{ CKM_MD2, { 0, 0, CKF_DIGEST }, PR_FALSE }, { 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 }, { CKM_NSS_JPAKE_FINAL_SHA512, { 0, 0, CKF_DERIVE }, PR_TRUE },
/* -------------------- Constant Time TLS MACs ----------------------- */ /* -------------------- Constant Time TLS MACs ----------------------- */
{ CKM_NSS_HMAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE }, { 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]); 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; 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 ************************ **************************** Symetric Key utils ************************
*/ */
@ -3156,7 +3276,7 @@ nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS)
* this call doesn't force freebl to be reloaded. */ * this call doesn't force freebl to be reloaded. */
BL_SetForkState(PR_FALSE); BL_SetForkState(PR_FALSE);
#ifndef NSS_TEST_BUILD #ifndef NSS_STATIC_SOFTOKEN
/* unload freeBL shared library from memory. This may only decrement the /* unload freeBL shared library from memory. This may only decrement the
* OS refcount if it's been loaded multiple times, eg. by libssl */ * OS refcount if it's been loaded multiple times, eg. by libssl */
BL_Unload(); BL_Unload();

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 * 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 * functions to CKR_xxx. Most of the mapping is done in
* compatibility. * 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) */ /* used by Decrypt and UnwrapKey (indirectly) */
static CK_RV static CK_RV
@ -760,6 +728,32 @@ sftk_ChaCha20Poly1305_Decrypt(const SFTKChaCha20Poly1305Info *ctx,
sizeof(ctx->nonce), ad, ctx->adLen); 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. /** NSC_CryptInit initializes an encryption/Decryption operation.
* *
* Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey. * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey.
@ -1180,6 +1174,48 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
context->destroy = (SFTKDestroy)sftk_ChaCha20Poly1305_DestroyContext; context->destroy = (SFTKDestroy)sftk_ChaCha20Poly1305_DestroyContext;
break; break;
case CKM_NSS_CHACHA20_CTR:
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;
}
SFTKChaCha20CtrInfo *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. */
PRUint8 *param = pMechanism->pParameter;
int 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: case CKM_NSS_AES_KEY_WRAP_PAD:
context->doPad = PR_TRUE; context->doPad = PR_TRUE;
/* fall thru */ /* fall thru */
@ -2080,9 +2116,12 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_RC5_MAC_GENERAL_PARAMS *rc5_mac; CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
#endif #endif
unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE]; unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE];
unsigned char k2[SFTK_MAX_BLOCK_SIZE];
unsigned char k3[SFTK_MAX_BLOCK_SIZE];
SFTKSessionContext *context; SFTKSessionContext *context;
CK_RV crv; CK_RV crv;
unsigned int blockSize; unsigned int blockSize;
PRBool isXCBC = PR_FALSE;
switch (pMechanism->mechanism) { switch (pMechanism->mechanism) {
case CKM_RC2_MAC_GENERAL: case CKM_RC2_MAC_GENERAL:
@ -2186,6 +2225,26 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
cbc_mechanism.pParameter = &ivBlock; cbc_mechanism.pParameter = &ivBlock;
cbc_mechanism.ulParameterLen = blockSize; cbc_mechanism.ulParameterLen = blockSize;
break; 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: default:
return CKR_FUNCTION_NOT_SUPPORTED; return CKR_FUNCTION_NOT_SUPPORTED;
} }
@ -2195,24 +2254,43 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
if (mac_bytes == SFTK_INVALID_MAC_SIZE) if (mac_bytes == SFTK_INVALID_MAC_SIZE)
mac_bytes = blockSize >> 1; mac_bytes = blockSize >> 1;
else { else {
if (mac_bytes > blockSize) if (mac_bytes > blockSize) {
return CKR_MECHANISM_PARAM_INVALID; crv = CKR_MECHANISM_PARAM_INVALID;
goto fail;
}
} }
crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey, crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey,
CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */ CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */
keyUsage, contextType, PR_TRUE); keyUsage, contextType, PR_TRUE);
if (crv != CKR_OK) if (crv != CKR_OK)
return crv; goto fail;
crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL); crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL);
/* this shouldn't happen! */ /* this shouldn't happen! */
PORT_Assert(crv == CKR_OK); PORT_Assert(crv == CKR_OK);
if (crv != CKR_OK) if (crv != CKR_OK)
return crv; goto fail;
context->blockSize = blockSize; context->blockSize = blockSize;
context->macSize = mac_bytes; 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; 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 +2906,13 @@ sftk_MACFinal(SFTKSessionContext *ctx)
{ {
unsigned int padLen = ctx->padDataLength; unsigned int padLen = ctx->padDataLength;
/* pad and proceed the residual */ /* 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) { if (padLen) {
/* shd clr ctx->padLen to make sftk_MACFinal idempotent */ /* shd clr ctx->padLen to make sftk_MACFinal idempotent */
PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen); PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen);
@ -2866,7 +2951,7 @@ sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
blkSize - context->padDataLength; blkSize - context->padDataLength;
/* not enough data even for one block */ /* not enough data even for one block */
if (ulPartLen < minInput) { if (ulPartLen <= minInput) {
PORT_Memcpy(residual, pPart, ulPartLen); PORT_Memcpy(residual, pPart, ulPartLen);
context->padDataLength += ulPartLen; context->padDataLength += ulPartLen;
goto cleanup; goto cleanup;
@ -2880,7 +2965,7 @@ sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
goto terminate; goto terminate;
} }
/* MACing full blocks */ /* MACing full blocks */
while (ulPartLen >= blkSize) { while (ulPartLen > blkSize) {
if (CKR_OK != (crv = sftk_MACBlock(context, pPart))) if (CKR_OK != (crv = sftk_MACBlock(context, pPart)))
goto terminate; goto terminate;
ulPartLen -= blkSize; ulPartLen -= blkSize;
@ -4645,6 +4730,13 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
return crv; 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. */ /* Verify the known hash using the public key. */
crv = NSC_VerifyInit(hSession, &mech, publicKey->handle); crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
if (crv != CKR_OK) { if (crv != CKR_OK) {
@ -6477,6 +6569,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
extractValue = PR_FALSE; extractValue = PR_FALSE;
classType = CKO_PRIVATE_KEY; classType = CKO_PRIVATE_KEY;
break; 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_SHA1: /* fall through */
case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */ case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */ case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
@ -6518,6 +6614,73 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
} }
switch (mechanism) { 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 * generate the master secret
*/ */
@ -7480,14 +7643,14 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
case CKM_DH_PKCS_DERIVE: { case CKM_DH_PKCS_DERIVE: {
SECItem derived, dhPublic; SECItem derived, dhPublic;
SECItem dhPrime, dhValue; SECItem dhPrime, dhSubPrime, dhValue;
/* sourceKey - values for the local existing low key */ /* sourceKey - values for the local existing low key */
/* get prime and value attributes */ /* get prime and value attributes */
crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME); crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
if (crv != SECSuccess) if (crv != CKR_OK)
break; break;
crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE); crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
if (crv != SECSuccess) { if (crv != CKR_OK) {
PORT_Free(dhPrime.data); PORT_Free(dhPrime.data);
break; break;
} }
@ -7495,6 +7658,20 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
dhPublic.data = pMechanism->pParameter; dhPublic.data = pMechanism->pParameter;
dhPublic.len = pMechanism->ulParameterLen; 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 */ /* calculate private value - oct */
rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize); rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
@ -7504,6 +7681,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
if (rv == SECSuccess) { if (rv == SECSuccess) {
sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len); sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
PORT_ZFree(derived.data, derived.len); PORT_ZFree(derived.data, derived.len);
crv = CKR_OK;
} else } else
crv = CKR_HOST_MEMORY; crv = CKR_HOST_MEMORY;
@ -7569,7 +7747,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar, rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
withCofactor, &tmp); withCofactor, &tmp);
PORT_Free(ecScalar.data); PORT_ZFree(ecScalar.data, ecScalar.len);
ecScalar.data = NULL; ecScalar.data = NULL;
if (privKey != sourceKey->objectInfo) { if (privKey != sourceKey->objectInfo) {
nsslowkey_DestroyPrivateKey(privKey); nsslowkey_DestroyPrivateKey(privKey);

View file

@ -106,6 +106,7 @@ typedef struct SFTKOAEPEncryptInfoStr SFTKOAEPEncryptInfo;
typedef struct SFTKOAEPDecryptInfoStr SFTKOAEPDecryptInfo; typedef struct SFTKOAEPDecryptInfoStr SFTKOAEPDecryptInfo;
typedef struct SFTKSSLMACInfoStr SFTKSSLMACInfo; typedef struct SFTKSSLMACInfoStr SFTKSSLMACInfo;
typedef struct SFTKChaCha20Poly1305InfoStr SFTKChaCha20Poly1305Info; typedef struct SFTKChaCha20Poly1305InfoStr SFTKChaCha20Poly1305Info;
typedef struct SFTKChaCha20CtrInfoStr SFTKChaCha20CtrInfo;
typedef struct SFTKItemTemplateStr SFTKItemTemplate; typedef struct SFTKItemTemplateStr SFTKItemTemplate;
/* define function pointer typdefs for pointer tables */ /* define function pointer typdefs for pointer tables */
@ -253,12 +254,15 @@ struct SFTKSessionContextStr {
PRBool multi; /* is multipart */ PRBool multi; /* is multipart */
PRBool rsa; /* is rsa */ PRBool rsa; /* is rsa */
PRBool doPad; /* use PKCS padding for block ciphers */ PRBool doPad; /* use PKCS padding for block ciphers */
PRBool isXCBC; /* xcbc, use special handling in final */
unsigned int blockSize; /* blocksize for padding */ unsigned int blockSize; /* blocksize for padding */
unsigned int padDataLength; /* length of the valid data in padbuf */ unsigned int padDataLength; /* length of the valid data in padbuf */
/** latest incomplete block of data for block cipher */ /** latest incomplete block of data for block cipher */
unsigned char padBuf[SFTK_MAX_BLOCK_SIZE]; unsigned char padBuf[SFTK_MAX_BLOCK_SIZE];
/** result of MAC'ing of latest full block of data with block cipher */ /** result of MAC'ing of latest full block of data with block cipher */
unsigned char macBuf[SFTK_MAX_BLOCK_SIZE]; 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*/ CK_ULONG macSize; /* size of a general block cipher mac*/
void *cipherInfo; void *cipherInfo;
void *hashInfo; void *hashInfo;
@ -409,6 +413,14 @@ struct SFTKChaCha20Poly1305InfoStr {
unsigned int adLen; 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 * 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); extern CK_RV sftk_CloseAllSessions(SFTKSlot *slot, PRBool logout);
/* internal utility functions used by pkcs11.c */ /* internal utility functions used by pkcs11.c */
extern CK_RV sftk_MapCryptError(int error);
extern SFTKAttribute *sftk_FindAttribute(SFTKObject *object, extern SFTKAttribute *sftk_FindAttribute(SFTKObject *object,
CK_ATTRIBUTE_TYPE type); CK_ATTRIBUTE_TYPE type);
extern void sftk_FreeAttribute(SFTKAttribute *attribute); extern void sftk_FreeAttribute(SFTKAttribute *attribute);
@ -682,10 +695,36 @@ extern NSSLOWKEYPublicKey *sftk_GetPubKey(SFTKObject *object,
CK_KEY_TYPE key_type, CK_RV *crvp); CK_KEY_TYPE key_type, CK_RV *crvp);
extern NSSLOWKEYPrivateKey *sftk_GetPrivKey(SFTKObject *object, extern NSSLOWKEYPrivateKey *sftk_GetPrivKey(SFTKObject *object,
CK_KEY_TYPE key_type, CK_RV *crvp); 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 void sftk_FormatDESKey(unsigned char *key, int length);
extern PRBool sftk_CheckDESKey(unsigned char *key); extern PRBool sftk_CheckDESKey(unsigned char *key);
extern PRBool sftk_IsWeakKey(unsigned char *key, CK_KEY_TYPE key_type); 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 */ /* mechanism allows this operation */
extern CK_RV sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op); extern CK_RV sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op);

View file

@ -14,6 +14,47 @@
#include "sftkdb.h" #include "sftkdb.h"
#include "softoken.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 ******************************* * ******************** Attribute Utilities *******************************
*/ */

View file

@ -858,7 +858,6 @@ sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind)
return sdb_mapSQLError(sdb_p->type, sqlerr); return sdb_mapSQLError(sdb_p->type, sqlerr);
} }
static const char GET_ATTRIBUTE_CMD[] = "SELECT ALL %s FROM %s WHERE id=$ID;";
CK_RV CK_RV
sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id, sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
CK_ATTRIBUTE *template, CK_ULONG count) CK_ATTRIBUTE *template, CK_ULONG count)
@ -866,8 +865,6 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
SDBPrivate *sdb_p = sdb->private; SDBPrivate *sdb_p = sdb->private;
sqlite3 *sqlDB = NULL; sqlite3 *sqlDB = NULL;
sqlite3_stmt *stmt = NULL; sqlite3_stmt *stmt = NULL;
char *getStr = NULL;
char *newStr = NULL;
const char *table = NULL; const char *table = NULL;
int sqlerr = SQLITE_OK; int sqlerr = SQLITE_OK;
CK_RV error = CKR_OK; CK_RV error = CKR_OK;
@ -875,59 +872,79 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
int retry = 0; int retry = 0;
unsigned int i; unsigned int i;
if (count == 0) {
error = CKR_OBJECT_HANDLE_INVALID;
goto loser;
}
/* open a new db if necessary */ /* open a new db if necessary */
error = sdb_openDBLocal(sdb_p, &sqlDB, &table); error = sdb_openDBLocal(sdb_p, &sqlDB, &table);
if (error != CKR_OK) { if (error != CKR_OK) {
goto loser; goto loser;
} }
char *columns = NULL;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
getStr = sqlite3_mprintf("a%x", template[i].type); char *newColumns;
if (columns) {
if (getStr == NULL) { 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; error = CKR_HOST_MEMORY;
goto loser; goto loser;
} }
columns = newColumns;
}
newStr = sqlite3_mprintf(GET_ATTRIBUTE_CMD, getStr, table); PORT_Assert(columns);
sqlite3_free(getStr);
getStr = NULL; char *statement = sqlite3_mprintf("SELECT DISTINCT %s FROM %s where id=$ID LIMIT 1;",
if (newStr == NULL) { columns, table);
error = CKR_HOST_MEMORY; sqlite3_free(columns);
goto loser; 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);
} }
if (sqlerr == SQLITE_ROW) {
sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL); PORT_Assert(!found);
sqlite3_free(newStr); for (i = 0; i < count; i++) {
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) {
unsigned int blobSize; unsigned int blobSize;
const char *blobData; const char *blobData;
blobSize = sqlite3_column_bytes(stmt, 0); // NB: indices in sqlite_column_{bytes,blob} are 0-indexed
blobData = sqlite3_column_blob(stmt, 0); blobSize = sqlite3_column_bytes(stmt, i);
blobData = sqlite3_column_blob(stmt, i);
if (blobData == NULL) { 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; template[i].ulValueLen = -1;
error = CKR_ATTRIBUTE_TYPE_INVALID; error = CKR_ATTRIBUTE_TYPE_INVALID;
break; continue;
} }
/* If the blob equals our explicit NULL value, then the /* If the blob equals our explicit NULL value, then the
* attribute is a NULL. */ * attribute is a NULL. */
@ -938,20 +955,21 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
} }
if (template[i].pValue) { if (template[i].pValue) {
if (template[i].ulValueLen < blobSize) { if (template[i].ulValueLen < blobSize) {
/* like CKR_ATTRIBUTE_TYPE_INVALID, continue processing */
template[i].ulValueLen = -1; template[i].ulValueLen = -1;
error = CKR_BUFFER_TOO_SMALL; error = CKR_BUFFER_TOO_SMALL;
break; continue;
} }
PORT_Memcpy(template[i].pValue, blobData, blobSize); PORT_Memcpy(template[i].pValue, blobData, blobSize);
} }
template[i].ulValueLen = blobSize; template[i].ulValueLen = blobSize;
found = 1;
} }
} while (!sdb_done(sqlerr, &retry)); found = 1;
sqlite3_reset(stmt); }
sqlite3_finalize(stmt); } while (!sdb_done(sqlerr, &retry));
stmt = NULL; sqlite3_reset(stmt);
} sqlite3_finalize(stmt);
stmt = NULL;
loser: loser:
/* fix up the error if necessary */ /* fix up the error if necessary */

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