Bug 1934958 - land NSS NSS_3_108_BETA1 UPGRADE_NSS_RELEASE, r=nss-reviewers,jschanck

Differential Revision: https://phabricator.services.mozilla.com/D233104
This commit is contained in:
Dennis Jackson
2025-01-07 16:58:35 +00:00
parent ecfa655e10
commit a68667f89c
99 changed files with 1410 additions and 712 deletions

View File

@@ -13,7 +13,7 @@ system_lib_option(
imply_option("--with-system-nspr", True, when="--with-system-nss") imply_option("--with-system-nspr", True, when="--with-system-nss")
nss_pkg = pkg_check_modules( nss_pkg = pkg_check_modules(
"NSS", "nss >= 3.107", when="--with-system-nss", config=False "NSS", "nss >= 3.108", when="--with-system-nss", config=False
) )
set_config("MOZ_SYSTEM_NSS", True, when="--with-system-nss") set_config("MOZ_SYSTEM_NSS", True, when="--with-system-nss")

View File

@@ -1 +1 @@
NSS_3_107_RTM NSS_3_108_BETA1

View File

@@ -0,0 +1,3 @@
1 Added function:
'function SECMODModule* SECMOD_LoadUserModuleWithFunction(const char*, CK_C_GetFunctionList)' {SECMOD_LoadUserModuleWithFunction@@NSS_3.107}

View File

@@ -0,0 +1,5 @@
1 Added function:
'function void PORT_SafeZero(void*, size_t)' {PORT_SafeZero@@NSSUTIL_3.108}

View File

@@ -1 +1 @@
NSS_3_106_BRANCH NSS_3_107_BRANCH

View File

@@ -218,6 +218,7 @@ export default async function main() {
NSS_DISABLE_UNLOAD: "1", NSS_DISABLE_UNLOAD: "1",
CC: "clang", CC: "clang",
CCC: "clang++", CCC: "clang++",
CFLAGS: "-O2",
}, },
platform: "linux64", platform: "linux64",
collection: "asan", collection: "asan",

View File

@@ -8,7 +8,7 @@ source $(dirname "$0")/tools.sh
export CRYPTOFUZZ_VERSION="687d3064c5cef2b0fe1f30824065a2f2c9c0bbd8" export CRYPTOFUZZ_VERSION="687d3064c5cef2b0fe1f30824065a2f2c9c0bbd8"
export BOTAN_VERSION="3.6.1" export BOTAN_VERSION="3.6.1"
git clone -q https://github.com/guidovranken/cryptofuzz.git git clone -q https://github.com/MozillaSecurity/cryptofuzz.git
git -C cryptofuzz checkout "$CRYPTOFUZZ_VERSION" git -C cryptofuzz checkout "$CRYPTOFUZZ_VERSION"
git clone -q https://github.com/randombit/botan.git git clone -q https://github.com/randombit/botan.git

View File

@@ -27,7 +27,9 @@ popd
./cryptofuzz/generate_dict ./cryptofuzz/generate_dict
# Run Cryptofuzz. # Run Cryptofuzz.
./cryptofuzz/cryptofuzz -dict="cryptofuzz-dict.txt" "nss/fuzz/corpus/cryptofuzz" "$@" # Decrease the default ASAN quarantine size of 256 MB as we tend to run
# out of memory on 32-bit.
ASAN_OPTIONS="quarantine_size_mb=128" ./cryptofuzz/cryptofuzz -dict="cryptofuzz-dict.txt" --force-module=nss "nss/fuzz/corpus/cryptofuzz" "$@"
# Alert if version is older than half a year. # Alert if version is older than half a year.
cryptofuzz_timestamp=$(git -C cryptofuzz show -s --format=%ct $CRYPTOFUZZ_VERSION) cryptofuzz_timestamp=$(git -C cryptofuzz show -s --format=%ct $CRYPTOFUZZ_VERSION)

View File

@@ -111,6 +111,7 @@ while [ $# -gt 0 ]; do
--fuzz) fuzz=1 ;; --fuzz) fuzz=1 ;;
--fuzz=oss) fuzz=1; fuzz_oss=1 ;; --fuzz=oss) fuzz=1; fuzz_oss=1 ;;
--fuzz=tls) fuzz=1; fuzz_tls=1 ;; --fuzz=tls) fuzz=1; fuzz_tls=1 ;;
--gtests-corpus) gyp_params+=(-Dgtests_corpus=1) ;;
--sancov) enable_sancov; gyp_params+=(-Dcoverage=1) ;; --sancov) enable_sancov; gyp_params+=(-Dcoverage=1) ;;
--sancov=?*) enable_sancov "${1#*=}"; gyp_params+=(-Dcoverage=1) ;; --sancov=?*) enable_sancov "${1#*=}"; gyp_params+=(-Dcoverage=1) ;;
--emit-llvm) gyp_params+=(-Demit_llvm=1 -Dsign_libs=0) ;; --emit-llvm) gyp_params+=(-Demit_llvm=1 -Dsign_libs=0) ;;

View File

@@ -32,12 +32,12 @@ static void
Usage() Usage()
{ {
#define FPS PR_fprintf(PR_STDERR, #define FPS PR_fprintf(PR_STDERR,
FPS "Usage: %s -i importfile [-d certdir] [-P dbprefix] [-h tokenname]\n", FPS "Usage: %s -i importfile [-I] [-d certdir] [-P dbprefix] [-h tokenname]\n",
progName); progName);
FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n"); FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n");
FPS "\t\t [-v]\n"); FPS "\t\t [-v]\n");
FPS "Usage: %s -l listfile [-d certdir] [-P dbprefix] [-h tokenname]\n", FPS "Usage: %s -l listfile [-I] [-d certdir] [-P dbprefix] [-h tokenname]\n",
progName); progName);
FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n"); FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n");
FPS "\t\t [-v]\n"); FPS "\t\t [-v]\n");
@@ -351,7 +351,8 @@ P12U_InitSlot(PK11SlotInfo *slot, secuPWData *slotPw)
*/ */
SEC_PKCS12DecoderContext * SEC_PKCS12DecoderContext *
p12U_ReadPKCS12File(SECItem *uniPwp, char *in_file, PK11SlotInfo *slot, p12U_ReadPKCS12File(SECItem *uniPwp, char *in_file, PK11SlotInfo *slot,
secuPWData *slotPw, secuPWData *p12FilePw) secuPWData *slotPw, secuPWData *p12FilePw,
PRBool ignoreIntegrity)
{ {
SEC_PKCS12DecoderContext *p12dcx = NULL; SEC_PKCS12DecoderContext *p12dcx = NULL;
p12uContext *p12cxt = NULL; p12uContext *p12cxt = NULL;
@@ -458,7 +459,10 @@ p12U_ReadPKCS12File(SECItem *uniPwp, char *in_file, PK11SlotInfo *slot,
/* rv has been set at this point */ /* rv has been set at this point */
done: done:
if (rv != SECSuccess) { /* if we are ignoring Integrity and we failed because we couldn't
* verify the integrity code, go ahead and succeed */
if (rv != SECSuccess && !(ignoreIntegrity &&
(pk12uErrno == PK12UERR_DECODEVERIFY))) {
if (p12dcx != NULL) { if (p12dcx != NULL) {
SEC_PKCS12DecoderFinish(p12dcx); SEC_PKCS12DecoderFinish(p12dcx);
p12dcx = NULL; p12dcx = NULL;
@@ -490,7 +494,8 @@ done:
*/ */
PRIntn PRIntn
P12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot, P12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot,
secuPWData *slotPw, secuPWData *p12FilePw) secuPWData *slotPw, secuPWData *p12FilePw,
PRBool ignoreIntegrity)
{ {
SEC_PKCS12DecoderContext *p12dcx = NULL; SEC_PKCS12DecoderContext *p12dcx = NULL;
SECItem uniPwitem = { 0 }; SECItem uniPwitem = { 0 };
@@ -509,7 +514,8 @@ P12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot,
do { do {
trypw = PR_FALSE; /* normally we do this once */ trypw = PR_FALSE; /* normally we do this once */
rv = SECFailure; rv = SECFailure;
p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw); p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw,
p12FilePw, ignoreIntegrity);
if (p12dcx == NULL) { if (p12dcx == NULL) {
goto loser; goto loser;
@@ -777,14 +783,16 @@ loser:
PRIntn PRIntn
P12U_ListPKCS12File(char *in_file, PK11SlotInfo *slot, P12U_ListPKCS12File(char *in_file, PK11SlotInfo *slot,
secuPWData *slotPw, secuPWData *p12FilePw) secuPWData *slotPw, secuPWData *p12FilePw,
PRBool ignoreIntegrity)
{ {
SEC_PKCS12DecoderContext *p12dcx = NULL; SEC_PKCS12DecoderContext *p12dcx = NULL;
SECItem uniPwitem = { 0 }; SECItem uniPwitem = { 0 };
SECStatus rv = SECFailure; SECStatus rv = SECFailure;
const SEC_PKCS12DecoderItem *dip; const SEC_PKCS12DecoderItem *dip;
p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw); p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw,
ignoreIntegrity);
/* did the blob authenticate properly? */ /* did the blob authenticate properly? */
if (p12dcx == NULL) { if (p12dcx == NULL) {
SECU_PrintError(progName, "PKCS12 decode not verified"); SECU_PrintError(progName, "PKCS12 decode not verified");
@@ -997,7 +1005,8 @@ enum {
opt_CertCipher, opt_CertCipher,
opt_KeyLength, opt_KeyLength,
opt_CertKeyLength, opt_CertKeyLength,
opt_Mac opt_Mac,
opt_IgnoreIntegrity
}; };
static secuCommandFlag pk12util_options[] = { static secuCommandFlag pk12util_options[] = {
@@ -1018,7 +1027,8 @@ static secuCommandFlag pk12util_options[] = {
{ /* opt_CertCipher */ 'C', PR_TRUE, 0, PR_FALSE }, { /* opt_CertCipher */ 'C', PR_TRUE, 0, PR_FALSE },
{ /* opt_KeyLength */ 'm', PR_TRUE, 0, PR_FALSE, "key_len" }, { /* opt_KeyLength */ 'm', PR_TRUE, 0, PR_FALSE, "key_len" },
{ /* opt_CertKeyLength */ 0, PR_TRUE, 0, PR_FALSE, "cert_key_len" }, { /* opt_CertKeyLength */ 0, PR_TRUE, 0, PR_FALSE, "cert_key_len" },
{ /* opt_Mac */ 'M', PR_TRUE, 0, PR_FALSE, PR_FALSE } { /* opt_Mac */ 'M', PR_TRUE, 0, PR_FALSE },
{ /* opt_IgnoreIntegrity */ 'I', PR_FALSE, 0, PR_FALSE }
}; };
int int
@@ -1039,6 +1049,7 @@ main(int argc, char **argv)
int certKeyLen = 0; int certKeyLen = 0;
secuCommand pk12util; secuCommand pk12util;
PRInt32 forceUnicode; PRInt32 forceUnicode;
PRBool ignoreIntegrity = PR_FALSE;
#ifdef _CRTDBG_MAP_ALLOC #ifdef _CRTDBG_MAP_ALLOC
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
@@ -1113,6 +1124,9 @@ main(int argc, char **argv)
if (pk12util.options[opt_Raw].activated) { if (pk12util.options[opt_Raw].activated) {
dumpRawFile = PR_TRUE; dumpRawFile = PR_TRUE;
} }
if (pk12util.options[opt_IgnoreIntegrity].activated) {
ignoreIntegrity = PR_TRUE;
}
if (pk12util.options[opt_KeyLength].activated) { if (pk12util.options[opt_KeyLength].activated) {
keyLen = atoi(pk12util.options[opt_KeyLength].arg); keyLen = atoi(pk12util.options[opt_KeyLength].arg);
} }
@@ -1183,7 +1197,8 @@ main(int argc, char **argv)
} }
if (pk12util.options[opt_Import].activated) { if (pk12util.options[opt_Import].activated) {
P12U_ImportPKCS12Object(import_file, slot, &slotPw, &p12FilePw); P12U_ImportPKCS12Object(import_file, slot, &slotPw, &p12FilePw,
ignoreIntegrity);
} else if (pk12util.options[opt_Export].activated) { } else if (pk12util.options[opt_Export].activated) {
P12U_ExportPKCS12Object(pk12util.options[opt_Nickname].arg, P12U_ExportPKCS12Object(pk12util.options[opt_Nickname].arg,
@@ -1191,7 +1206,8 @@ main(int argc, char **argv)
hash, &slotPw, &p12FilePw); hash, &slotPw, &p12FilePw);
} else if (pk12util.options[opt_List].activated) { } else if (pk12util.options[opt_List].activated) {
P12U_ListPKCS12File(import_file, slot, &slotPw, &p12FilePw); P12U_ListPKCS12File(import_file, slot, &slotPw, &p12FilePw,
ignoreIntegrity);
} else { } else {
Usage(); Usage();

View File

@@ -16,7 +16,6 @@
'dependencies': [ 'dependencies': [
'<(DEPTH)/exports.gyp:dbm_exports', '<(DEPTH)/exports.gyp:dbm_exports',
'<(DEPTH)/exports.gyp:nss_exports', '<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/lib/ssl/ssl.gyp:ssl',
'<(DEPTH)/lib/zlib/zlib.gyp:nss_zlib' '<(DEPTH)/lib/zlib/zlib.gyp:nss_zlib'
], ],
'include_dirs': [ 'include_dirs': [

View File

@@ -125,6 +125,7 @@
'fuzz%': 0, 'fuzz%': 0,
'fuzz_tls%': 0, 'fuzz_tls%': 0,
'fuzz_oss%': 0, 'fuzz_oss%': 0,
'gtests_corpus%': 0,
'sign_libs%': 1, 'sign_libs%': 1,
'use_pprof%': 0, 'use_pprof%': 0,
'ct_verif%': 0, 'ct_verif%': 0,

View File

@@ -10,4 +10,3 @@
*/ */
#error "Do not include this header file." #error "Do not include this header file."

View File

@@ -38,6 +38,7 @@
<arg>-P dbprefix</arg> <arg>-P dbprefix</arg>
<arg>-r</arg> <arg>-r</arg>
<arg>-v</arg> <arg>-v</arg>
<arg>-I</arg>
<arg>--cert-key-len certKeyLength</arg> <arg>--cert-key-len certKeyLength</arg>
<arg>-k slotPasswordFile|-K slotPassword</arg> <arg>-k slotPasswordFile|-K slotPassword</arg>
<arg>-w p12filePasswordFile|-W p12filePassword</arg> <arg>-w p12filePasswordFile|-W p12filePassword</arg>
@@ -146,6 +147,11 @@
<listitem><para>Enable debug logging when importing.</para></listitem> <listitem><para>Enable debug logging when importing.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>-I </term>
<listitem><para>Ignore integrity check results on importing and listing.</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term>-w p12filePasswordFile</term> <term>-w p12filePasswordFile</term>
<listitem><para>Specify the text file containing the pkcs #12 file password.</para></listitem> <listitem><para>Specify the text file containing the pkcs #12 file password.</para></listitem>
@@ -317,7 +323,7 @@ Certificate Friendly Name: Thawte Freemail Member's Thawte Consulting (Pty) L
<refsection id="encryption"> <refsection id="encryption">
<title>Password Encryption</title> <title>Password Encryption</title>
<para>PKCS #12 provides for not only the protection of the private keys but also the certificate and meta-data associated with the keys. Password-based encryption is used to protect private keys on export to a PKCS #12 file and, optionally, the associated certificates. If no algorithm is specified, the tool defaults to using PKCS #12 SHA-1 and 3-key triple DES for private key encryption. When not in FIPS mode, PKCS #12 SHA-1 and 40-bit RC4 is used for certificate encryption. When in FIPS mode, there is no certificate encryption. If certificate encryption is not wanted, specify <userinput>"NONE"</userinput> as the argument of the <option>-C</option> option.</para> <para>PKCS #12 provides for not only the protection of the private keys but also the certificate and meta-data associated with the keys. Password-based encryption is used to protect private keys on export to a PKCS #12 file and, optionally, the associated certificates. If no algorithm is specified, the tool defaults to using AES-256-CBC for private key encryption and AES-128-CBC for certificate encryption. If certificate encryption is not wanted, specify <userinput>"NONE"</userinput> as the argument of the <option>-C</option> option.</para>
<para>The private key is always protected with strong encryption by default.</para> <para>The private key is always protected with strong encryption by default.</para>
<para>Several types of ciphers are supported.</para> <para>Several types of ciphers are supported.</para>
<variablelist> <variablelist>
@@ -327,6 +333,7 @@ Certificate Friendly Name: Thawte Freemail Member's Thawte Consulting (Pty) L
<listitem> <listitem>
<itemizedlist> <itemizedlist>
<listitem><para>PBES2 with AES-CBC-Pad as underlying encryption scheme (<userinput>"AES-128-CBC"</userinput>, <userinput>"AES-192-CBC"</userinput>, and <userinput>"AES-256-CBC"</userinput>)</para></listitem> <listitem><para>PBES2 with AES-CBC-Pad as underlying encryption scheme (<userinput>"AES-128-CBC"</userinput>, <userinput>"AES-192-CBC"</userinput>, and <userinput>"AES-256-CBC"</userinput>)</para></listitem>
<listitem><para>PBES2 with CAMELLIA-CBC-Pad as underlying encryption scheme (<userinput>"CAMELLIA-128-CBC"</userinput>, <userinput>"CAMELLIA-192-CBC"</userinput>, and <userinput>"CAMELLIA-256-CBC"</userinput>)</para></listitem>
</itemizedlist> </itemizedlist>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@@ -1,228 +1,14 @@
# 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/.
{ {
'includes': [ 'includes': [
'../coreconf/config.gypi', '../coreconf/config.gypi',
], ],
'target_defaults': {
'variables': {
'debug_optimization_level': '3',
},
'cflags_cc': [
'-Wno-vla-extension',
],
'target_conditions': [
[ '_type=="executable"', {
'libraries!': [
'<@(nspr_libs)',
],
'libraries': [
'<(nss_dist_obj_dir)/lib/libplds4.a',
'<(nss_dist_obj_dir)/lib/libnspr4.a',
'<(nss_dist_obj_dir)/lib/libplc4.a',
],
}],
],
},
'targets': [ 'targets': [
{ {
'target_name': 'fuzz_base', 'target_name': 'fuzz',
'type': 'static_library',
'sources': [
'shared.cc',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/lib/certdb/certdb.gyp:certdb',
'<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
'<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
'<(DEPTH)/lib/ssl/ssl.gyp:ssl',
'<(DEPTH)/lib/base/base.gyp:nssb',
'<(DEPTH)/lib/dev/dev.gyp:nssdev',
'<(DEPTH)/lib/pki/pki.gyp:nsspki',
'<(DEPTH)/lib/util/util.gyp:nssutil',
'<(DEPTH)/lib/nss/nss.gyp:nss_static',
'<(DEPTH)/lib/pkcs7/pkcs7.gyp:pkcs7',
'<(DEPTH)/lib/pkcs12/pkcs12.gyp:pkcs12',
# This is a static build of pk11wrap, softoken, and freebl.
'<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
'<(DEPTH)/lib/libpkix/libpkix.gyp:libpkix',
],
'cflags_cc': [
'-Wno-error=shadow',
],
'conditions': [
['fuzz_oss==0', {
'all_dependent_settings': {
'libraries': [
'-fsanitize=fuzzer',
],
}
}, {
'all_dependent_settings': {
'libraries': ['-lFuzzingEngine'],
}
}]
],
},
{
'target_name': 'nssfuzz-pkcs7',
'type': 'executable',
'sources': [
'asn1_mutators.cc',
'pkcs7_target.cc',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'fuzz_base',
],
},
{
'target_name': 'nssfuzz-pkcs8',
'type': 'executable',
'sources': [
'asn1_mutators.cc',
'pkcs8_target.cc',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'fuzz_base',
],
},
{
'target_name': 'nssfuzz-pkcs12',
'type': 'executable',
'sources': [
'asn1_mutators.cc',
'pkcs12_target.cc',
],
'dependencies': [
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'<(DEPTH)/exports.gyp:nss_exports',
'fuzz_base',
],
},
{
'target_name': 'nssfuzz-quickder',
'type': 'executable',
'sources': [
'asn1_mutators.cc',
'quickder_target.cc',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'fuzz_base',
],
},
{
'target_name': 'nssfuzz-certDN',
'type': 'executable',
'sources': [
'certDN_target.cc',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'fuzz_base',
],
},
{
'target_name': 'nssfuzz-tls-base',
'type': 'static_library',
'sources': [
'tls_common.cc',
'tls_mutators.cc',
'tls_socket.cc',
],
'dependencies': [
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'<(DEPTH)/exports.gyp:nss_exports',
'fuzz_base',
],
'include_dirs': [
'<(DEPTH)/lib/ssl',
],
'direct_dependent_settings': {
'include_dirs': [
'<(DEPTH)/lib/freebl',
'<(DEPTH)/lib/ssl',
],
},
},
{
'target_name': 'nssfuzz-tls-client',
'type': 'executable',
'sources': [
'tls_client_config.cc',
'tls_client_target.cc',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'nssfuzz-tls-base',
],
},
{
'target_name': 'nssfuzz-tls-server',
'type': 'executable',
'sources': [
'tls_server_certs.cc',
'tls_server_config.cc',
'tls_server_target.cc',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'nssfuzz-tls-base',
],
},
{
'target_name': 'nssfuzz-dtls-client',
'type': 'executable',
'sources': [
'tls_client_config.cc',
'tls_client_target.cc',
],
'defines': [
'IS_DTLS_FUZZ'
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'nssfuzz-tls-base',
],
},
{
'target_name': 'nssfuzz-dtls-server',
'type': 'executable',
'sources': [
'tls_server_certs.cc',
'tls_server_config.cc',
'tls_server_target.cc',
],
'defines': [
'IS_DTLS_FUZZ'
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'nssfuzz-tls-base',
],
},
{
'target_name': 'nssfuzz',
'type': 'none', 'type': 'none',
'dependencies': [ 'dependencies': [
'nssfuzz-certDN', '<(DEPTH)/fuzz/targets/targets.gyp:nssfuzz',
'nssfuzz-dtls-client',
'nssfuzz-dtls-server',
'nssfuzz-pkcs7',
'nssfuzz-pkcs8',
'nssfuzz-pkcs12',
'nssfuzz-quickder',
'nssfuzz-tls-client',
'nssfuzz-tls-server',
], ],
} },
], ]
} }

View File

@@ -0,0 +1,17 @@
# 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/.
{
'includes': [
'../../../../coreconf/config.gypi',
],
'targets': [
{
'target_name': 'asn1',
'type': 'static_library',
'sources': [
'mutators.cc',
],
}
],
}

View File

@@ -2,57 +2,56 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mutators.h"
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <random> #include <random>
#include <tuple> #include <tuple>
#include "asn1_mutators.h" static std::tuple<uint8_t *, size_t> ParseItem(uint8_t *data,
size_t maxLength) {
using namespace std;
static tuple<uint8_t *, size_t> ParseItem(uint8_t *Data, size_t MaxLength) {
// Short form. Bit 8 has value "0" and bits 7-1 give the length. // Short form. Bit 8 has value "0" and bits 7-1 give the length.
if ((Data[1] & 0x80) == 0) { if ((data[1] & 0x80) == 0) {
size_t length = min(static_cast<size_t>(Data[1]), MaxLength - 2); size_t length = std::min(static_cast<size_t>(data[1]), maxLength - 2);
return make_tuple(&Data[2], length); return std::make_tuple(&data[2], length);
} }
// Constructed, indefinite length. Read until {0x00, 0x00}. // Constructed, indefinite length. Read until {0x00, 0x00}.
if (Data[1] == 0x80) { if (data[1] == 0x80) {
void *offset = memmem(&Data[2], MaxLength - 2, "\0", 2); void *offset = memmem(&data[2], maxLength - 2, "\0", 2);
size_t length = offset ? (static_cast<uint8_t *>(offset) - &Data[2]) + 2 size_t length = offset ? (static_cast<uint8_t *>(offset) - &data[2]) + 2
: MaxLength - 2; : maxLength - 2;
return make_tuple(&Data[2], length); return std::make_tuple(&data[2], length);
} }
// Long form. Two to 127 octets. Bit 8 of first octet has value "1" // Long form. Two to 127 octets. Bit 8 of first octet has value "1"
// and bits 7-1 give the number of additional length octets. // and bits 7-1 give the number of additional length octets.
size_t octets = min(static_cast<size_t>(Data[1] & 0x7f), MaxLength - 2); size_t octets = std::min(static_cast<size_t>(data[1] & 0x7f), maxLength - 2);
// Handle lengths bigger than 32 bits. // Handle lengths bigger than 32 bits.
if (octets > 4) { if (octets > 4) {
// Ignore any further children, assign remaining length. // Ignore any further children, assign remaining length.
return make_tuple(&Data[2] + octets, MaxLength - 2 - octets); return std::make_tuple(&data[2] + octets, maxLength - 2 - octets);
} }
// Parse the length. // Parse the length.
size_t length = 0; size_t length = 0;
for (size_t j = 0; j < octets; j++) { for (size_t j = 0; j < octets; j++) {
length = (length << 8) | Data[2 + j]; length = (length << 8) | data[2 + j];
} }
length = min(length, MaxLength - 2 - octets); length = std::min(length, maxLength - 2 - octets);
return make_tuple(&Data[2] + octets, length); return std::make_tuple(&data[2] + octets, length);
} }
static vector<uint8_t *> ParseItems(uint8_t *Data, size_t Size) { static std::vector<uint8_t *> ParseItems(uint8_t *data, size_t size) {
vector<uint8_t *> items; std::vector<uint8_t *> items;
vector<size_t> lengths; std::vector<size_t> lengths;
// The first item is always the whole corpus. // The first item is always the whole corpus.
items.push_back(Data); items.push_back(data);
lengths.push_back(Size); lengths.push_back(size);
// Can't use iterators here because the `items` vector is modified inside the // Can't use iterators here because the `items` vector is modified inside the
// loop. That's safe as long as we always check `items.size()` before every // loop. That's safe as long as we always check `items.size()` before every
@@ -71,7 +70,7 @@ static vector<uint8_t *> ParseItems(uint8_t *Data, size_t Size) {
uint8_t *content; uint8_t *content;
size_t length; size_t length;
tie(content, length) = ParseItem(item, remaining); std::tie(content, length) = ParseItem(item, remaining);
if (length > 0) { if (length > 0) {
// Record the item. // Record the item.
@@ -94,25 +93,25 @@ static vector<uint8_t *> ParseItems(uint8_t *Data, size_t Size) {
namespace ASN1Mutators { namespace ASN1Mutators {
size_t FlipConstructed(uint8_t *Data, size_t Size, size_t MaxSize, size_t FlipConstructed(uint8_t *data, size_t size, size_t maxSize,
unsigned int Seed) { unsigned int seed) {
auto items = ParseItems(Data, Size); auto items = ParseItems(data, size);
std::mt19937 rng(Seed); std::mt19937 rng(seed);
std::uniform_int_distribution<size_t> dist(0, items.size() - 1); std::uniform_int_distribution<size_t> dist(0, items.size() - 1);
uint8_t *item = items.at(dist(rng)); uint8_t *item = items.at(dist(rng));
// Flip "constructed" type bit. // Flip "constructed" type bit.
item[0] ^= 0x20; item[0] ^= 0x20;
return Size; return size;
} }
size_t ChangeType(uint8_t *Data, size_t Size, size_t MaxSize, size_t ChangeType(uint8_t *data, size_t size, size_t maxSize,
unsigned int Seed) { unsigned int seed) {
auto items = ParseItems(Data, Size); auto items = ParseItems(data, size);
std::mt19937 rng(Seed); std::mt19937 rng(seed);
std::uniform_int_distribution<size_t> dist(0, items.size() - 1); std::uniform_int_distribution<size_t> dist(0, items.size() - 1);
uint8_t *item = items.at(dist(rng)); uint8_t *item = items.at(dist(rng));
@@ -120,7 +119,7 @@ size_t ChangeType(uint8_t *Data, size_t Size, size_t MaxSize,
static std::uniform_int_distribution<size_t> tdist(0, 30); static std::uniform_int_distribution<size_t> tdist(0, 30);
item[0] = tdist(rng); item[0] = tdist(rng);
return Size; return size;
} }
} // namespace ASN1Mutators } // namespace ASN1Mutators

View File

@@ -0,0 +1,17 @@
# 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/.
{
'includes': [
'../../../../coreconf/config.gypi',
],
'targets': [
{
'target_name': 'base',
'type': 'static_library',
'sources': [
'mutate.cc',
],
}
],
}

View File

@@ -0,0 +1,19 @@
/* 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 BASE_DATABASE_H_
#define BASE_DATABASE_H_
#include <cassert>
#include "nss.h"
// TODO(mdauer): Add constructor for initializing with DB.
class NSSDatabase {
public:
NSSDatabase() { assert(NSS_NoDB_Init(nullptr) == SECSuccess); }
~NSSDatabase() { assert(NSS_Shutdown() == SECSuccess); }
};
#endif // BASE_DATABASE_H_

View File

@@ -2,21 +2,21 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "shared.h" #include "mutate.h"
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <random> #include <random>
size_t CustomMutate(Mutators mutators, uint8_t* data, size_t size, size_t CustomMutate(Mutators mutators, uint8_t* data, size_t size,
size_t max_size, unsigned int seed) { size_t maxSize, unsigned int seed) {
std::mt19937 rng(seed); std::mt19937 rng(seed);
static std::bernoulli_distribution bdist; static std::bernoulli_distribution bdist;
if (bdist(rng)) { if (bdist(rng)) {
std::uniform_int_distribution<size_t> idist(0, mutators.size() - 1); std::uniform_int_distribution<size_t> idist(0, mutators.size() - 1);
return mutators.at(idist(rng))(data, size, max_size, seed); return mutators.at(idist(rng))(data, size, maxSize, seed);
} }
return LLVMFuzzerMutate(data, size, max_size); return LLVMFuzzerMutate(data, size, maxSize);
} }

View File

@@ -1,32 +1,21 @@
/* -*- 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 /* 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, * 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/. */
#ifndef SHARED_H_ #ifndef BASE_MUTATE_H_
#define SHARED_H_ #define BASE_MUTATE_H_
#include <cassert>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include "nss.h"
extern "C" size_t LLVMFuzzerMutate(uint8_t* data, size_t size, size_t maxSize); extern "C" size_t LLVMFuzzerMutate(uint8_t* data, size_t size, size_t maxSize);
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size, extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
size_t maxSize, unsigned int seed); size_t maxSize, unsigned int seed);
class NSSDatabase {
public:
NSSDatabase() { assert(NSS_NoDB_Init(nullptr) == SECSuccess); }
~NSSDatabase() { assert(NSS_Shutdown() == SECSuccess); }
};
typedef std::vector<decltype(LLVMFuzzerCustomMutator)*> Mutators; typedef std::vector<decltype(LLVMFuzzerCustomMutator)*> Mutators;
size_t CustomMutate(Mutators mutators, uint8_t* data, size_t size, size_t CustomMutate(Mutators mutators, uint8_t* data, size_t size,
size_t maxSize, unsigned int seed); size_t maxSize, unsigned int seed);
#endif // SHARED_H_ #endif // BASE_MUTATE_H_

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "tls_client_config.h" #include "client_config.h"
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
@@ -16,23 +16,24 @@
#include "ssl.h" #include "ssl.h"
#include "sslexp.h" #include "sslexp.h"
#include "tls_common.h" #include "common.h"
const SSLCertificateCompressionAlgorithm kCompressionAlg = {
0x1337, "fuzz", TlsCommon::DummyCompressionEncode,
TlsCommon::DummyCompressionDecode};
const PRUint8 kPskIdentity[] = "fuzz-psk-identity";
#ifndef IS_DTLS_FUZZ #ifndef IS_DTLS_FUZZ
const char kEchConfigs[] = const char kEchConfigs[] =
"AEX+" "AEX+"
"DQBBcQAgACDh4IuiuhhInUcKZx5uYcehlG9PQ1ZlzhvVZyjJl7dscQAEAAEAAQASY2xvdWRmbG" "DQBBcQAgACDh4IuiuhhInUcKZx5uYcehlG9PQ1ZlzhvVZyjJl7dscQAEAAEAAQASY2xvdWRmbG"
"FyZS1lY2guY29tAAA="; "FyZS1lY2guY29tAAA=";
#endif // IS_DTLS_FUZZ #endif // IS_DTLS_FUZZ
const SSLCertificateCompressionAlgorithm kCompressionAlg = {
0x1337, "fuzz", DummyCompressionEncode, DummyCompressionDecode};
const PRUint8 kPskIdentity[] = "fuzz-psk-identity";
static SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checksig, static SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checksig,
PRBool isServer) { PRBool isServer) {
assert(!isServer); assert(!isServer);
auto config = reinterpret_cast<ClientConfig*>(arg); auto config = reinterpret_cast<TlsClient::Config*>(arg);
if (config->FailCertificateAuthentication()) return SECFailure; if (config->FailCertificateAuthentication()) return SECFailure;
return SECSuccess; return SECSuccess;
@@ -44,10 +45,12 @@ static SECStatus CanFalseStartCallback(PRFileDesc* fd, void* arg,
return SECSuccess; return SECSuccess;
} }
namespace TlsClient {
// XOR 64-bit chunks of data to build a bitmap of config options derived from // XOR 64-bit chunks of data to build a bitmap of config options derived from
// the fuzzing input. This seems the only way to fuzz various options while // the fuzzing input. This seems the only way to fuzz various options while
// still maintaining compatibility with BoringSSL or OpenSSL fuzzers. // still maintaining compatibility with BoringSSL or OpenSSL fuzzers.
ClientConfig::ClientConfig(const uint8_t* data, size_t len) { Config::Config(const uint8_t* data, size_t len) {
union { union {
uint64_t bitmap; uint64_t bitmap;
struct { struct {
@@ -78,7 +81,7 @@ ClientConfig::ClientConfig(const uint8_t* data, size_t len) {
}; };
} }
void ClientConfig::SetCallbacks(PRFileDesc* fd) { void Config::SetCallbacks(PRFileDesc* fd) {
SECStatus rv = SSL_AuthCertificateHook(fd, AuthCertificateHook, this); SECStatus rv = SSL_AuthCertificateHook(fd, AuthCertificateHook, this);
assert(rv == SECSuccess); assert(rv == SECSuccess);
@@ -86,7 +89,7 @@ void ClientConfig::SetCallbacks(PRFileDesc* fd) {
assert(rv == SECSuccess); assert(rv == SECSuccess);
} }
void ClientConfig::SetSocketOptions(PRFileDesc* fd) { void Config::SetSocketOptions(PRFileDesc* fd) {
SECStatus rv = SSL_OptionSet(fd, SSL_ENABLE_EXTENDED_MASTER_SECRET, SECStatus rv = SSL_OptionSet(fd, SSL_ENABLE_EXTENDED_MASTER_SECRET,
this->EnableExtendedMasterSecret()); this->EnableExtendedMasterSecret());
assert(rv == SECSuccess); assert(rv == SECSuccess);
@@ -168,6 +171,20 @@ void ClientConfig::SetSocketOptions(PRFileDesc* fd) {
rv = SSL_OptionSet(fd, SSL_NO_LOCKS, this->NoLocks()); rv = SSL_OptionSet(fd, SSL_NO_LOCKS, this->NoLocks());
assert(rv == SECSuccess); assert(rv == SECSuccess);
rv = SSL_EnableTls13GreaseEch(fd, this->EnableTls13GreaseEch());
assert(rv == SECSuccess);
rv = SSL_SetDtls13VersionWorkaround(fd, this->SetDtls13VersionWorkaround());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_ENABLE_DELEGATED_CREDENTIALS,
this->EnableDelegatedCredentials());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_ENABLE_DTLS_SHORT_HEADER,
this->EnableDtlsShortHeader());
assert(rv == SECSuccess);
#ifndef IS_DTLS_FUZZ #ifndef IS_DTLS_FUZZ
rv = rv =
SSL_OptionSet(fd, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_UNRESTRICTED); SSL_OptionSet(fd, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_UNRESTRICTED);
@@ -184,7 +201,7 @@ void ClientConfig::SetSocketOptions(PRFileDesc* fd) {
#endif // IS_DTLS_FUZZ #endif // IS_DTLS_FUZZ
} }
std::ostream& operator<<(std::ostream& out, ClientConfig& config) { std::ostream& operator<<(std::ostream& out, Config& config) {
out << "============= ClientConfig =============" out << "============= ClientConfig ============="
<< "\n"; << "\n";
out << "SSL_NO_CACHE: " << config.NoCache() << "\n"; out << "SSL_NO_CACHE: " << config.NoCache() << "\n";
@@ -231,9 +248,15 @@ std::ostream& operator<<(std::ostream& out, ClientConfig& config) {
out << "SSL_ENABLE_TLS13_COMPAT_MODE: " out << "SSL_ENABLE_TLS13_COMPAT_MODE: "
<< config.EnableTls13CompatMode() << "\n"; << config.EnableTls13CompatMode() << "\n";
out << "SSL_NO_LOCKS: " << config.NoLocks() << "\n"; out << "SSL_NO_LOCKS: " << config.NoLocks() << "\n";
out << "SSL_EnableTls13GreaseEch: "
<< config.EnableTls13GreaseEch() << "\n";
out << "SSL_SetDtls13VersionWorkaround: "
<< config.SetDtls13VersionWorkaround() << "\n";
out << "SSL_SetClientEchConfigs: " out << "SSL_SetClientEchConfigs: "
<< config.SetClientEchConfigs() << "\n"; << config.SetClientEchConfigs() << "\n";
out << "========================================"; out << "========================================";
return out; return out;
} }
} // namespace TlsClient

View File

@@ -19,9 +19,11 @@
#endif #endif
#define SSL_VERSION_RANGE_MAX_VALID 0x0304 #define SSL_VERSION_RANGE_MAX_VALID 0x0304
class ClientConfig { namespace TlsClient {
class Config {
public: public:
ClientConfig(const uint8_t* data, size_t len); Config(const uint8_t* data, size_t len);
void SetCallbacks(PRFileDesc* fd); void SetCallbacks(PRFileDesc* fd);
void SetSocketOptions(PRFileDesc* fd); void SetSocketOptions(PRFileDesc* fd);
@@ -33,6 +35,8 @@ class ClientConfig {
}; };
SSLVersionRange SslVersionRange() { return ssl_version_range_; }; SSLVersionRange SslVersionRange() { return ssl_version_range_; };
// NOTE: When adding more config options here, don't forget to print
// them in the "<<"-overloaded operator.
bool FailCertificateAuthentication() { return config_ & (1 << 0); }; bool FailCertificateAuthentication() { return config_ & (1 << 0); };
bool EnableExtendedMasterSecret() { return config_ & (1 << 1); }; bool EnableExtendedMasterSecret() { return config_ & (1 << 1); };
bool RequireDhNamedGroups() { return config_ & (1 << 2); }; bool RequireDhNamedGroups() { return config_ & (1 << 2); };
@@ -55,12 +59,18 @@ class ClientConfig {
bool EnableSessionTickets() { return config_ & (1 << 19); }; bool EnableSessionTickets() { return config_ & (1 << 19); };
bool EnableTls13CompatMode() { return config_ & (1 << 20); }; bool EnableTls13CompatMode() { return config_ & (1 << 20); };
bool NoLocks() { return config_ & (1 << 21); }; bool NoLocks() { return config_ & (1 << 21); };
bool EnableTls13GreaseEch() { return config_ & (1 << 22); };
bool SetDtls13VersionWorkaround() { return config_ & (1 << 23); };
bool EnableDelegatedCredentials() { return config_ & (1 << 24); };
bool EnableDtlsShortHeader() { return config_ & (1 << 25); };
private: private:
uint32_t config_; uint32_t config_;
SSLVersionRange ssl_version_range_; SSLVersionRange ssl_version_range_;
}; };
std::ostream& operator<<(std::ostream& out, ClientConfig& config); std::ostream& operator<<(std::ostream& out, Config& config);
} // namespace TlsClient
#endif // TLS_CLIENT_CONFIG_H_ #endif // TLS_CLIENT_CONFIG_H_

View File

@@ -2,18 +2,21 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "tls_common.h" #include "common.h"
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include "prio.h" #include "prio.h"
#include "secport.h"
#include "ssl.h" #include "ssl.h"
#include "sslexp.h" #include "sslexp.h"
static PRTime FixedTime(void*) { return 1234; } static PRTime FixedTime(void*) { return 1234; }
namespace TlsCommon {
// Fix the time input, to avoid any time-based variation. // Fix the time input, to avoid any time-based variation.
void FixTime(PRFileDesc* fd) { void FixTime(PRFileDesc* fd) {
SECStatus rv = SSL_SetTimeFunc(fd, FixedTime, nullptr); SECStatus rv = SSL_SetTimeFunc(fd, FixedTime, nullptr);
@@ -68,7 +71,7 @@ void DoHandshake(PRFileDesc* fd, bool isServer) {
SECStatus DummyCompressionEncode(const SECItem* input, SECItem* output) { SECStatus DummyCompressionEncode(const SECItem* input, SECItem* output) {
if (!input || !input->data || input->len == 0 || !output) { if (!input || !input->data || input->len == 0 || !output) {
PR_SetError(SEC_ERROR_INVALID_ARGS, 0); PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure; return SECFailure;
} }
@@ -80,12 +83,12 @@ SECStatus DummyCompressionEncode(const SECItem* input, SECItem* output) {
SECStatus DummyCompressionDecode(const SECItem* input, unsigned char* output, SECStatus DummyCompressionDecode(const SECItem* input, unsigned char* output,
size_t outputLen, size_t* usedLen) { size_t outputLen, size_t* usedLen) {
if (!input || !input->data || input->len == 0 || !output || outputLen == 0) { if (!input || !input->data || input->len == 0 || !output || outputLen == 0) {
PR_SetError(SEC_ERROR_INVALID_ARGS, 0); PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure; return SECFailure;
} }
if (input->len > outputLen) { if (input->len > outputLen) {
PR_SetError(SEC_ERROR_BAD_DATA, 0); PORT_SetError(SEC_ERROR_BAD_DATA);
return SECFailure; return SECFailure;
} }
@@ -94,3 +97,5 @@ SECStatus DummyCompressionDecode(const SECItem* input, unsigned char* output,
return SECSuccess; return SECSuccess;
} }
} // namespace TlsCommon

View File

@@ -10,6 +10,8 @@
#include "prio.h" #include "prio.h"
#include "seccomon.h" #include "seccomon.h"
namespace TlsCommon {
void FixTime(PRFileDesc* fd); void FixTime(PRFileDesc* fd);
void EnableAllProtocolVersions(); void EnableAllProtocolVersions();
void EnableAllCipherSuites(PRFileDesc* fd); void EnableAllCipherSuites(PRFileDesc* fd);
@@ -19,4 +21,6 @@ SECStatus DummyCompressionEncode(const SECItem* input, SECItem* output);
SECStatus DummyCompressionDecode(const SECItem* input, unsigned char* output, SECStatus DummyCompressionDecode(const SECItem* input, unsigned char* output,
size_t outputLen, size_t* usedLen); size_t outputLen, size_t* usedLen);
} // namespace TlsCommon
#endif // TLS_COMMON_H_ #endif // TLS_COMMON_H_

View File

@@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mutators.h"
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
@@ -11,12 +13,6 @@
#include "tls_parser.h" #include "tls_parser.h"
using namespace nss_test;
// Number of additional bytes in the TLS header.
// Used to properly skip DTLS seqnums.
static size_t gExtraHeaderBytes = 0;
// Helper class to simplify TLS record manipulation. // Helper class to simplify TLS record manipulation.
class Record { class Record {
public: public:
@@ -40,9 +36,9 @@ class Record {
} }
void truncate(size_t length) { void truncate(size_t length) {
assert(length >= 5 + gExtraHeaderBytes); assert(length >= 5 + EXTRA_HEADER_BYTES);
uint8_t *dest = const_cast<uint8_t *>(data_); uint8_t *dest = const_cast<uint8_t *>(data_);
size_t l = length - (5 + gExtraHeaderBytes); size_t l = length - (5 + EXTRA_HEADER_BYTES);
dest[3] = (l >> 8) & 0xff; dest[3] = (l >> 8) & 0xff;
dest[4] = l & 0xff; dest[4] = l & 0xff;
memmove(dest + length, data_ + size_, remaining_); memmove(dest + length, data_ + size_, remaining_);
@@ -70,23 +66,23 @@ class Record {
std::vector<std::unique_ptr<Record>> ParseRecords(const uint8_t *data, std::vector<std::unique_ptr<Record>> ParseRecords(const uint8_t *data,
size_t size) { size_t size) {
std::vector<std::unique_ptr<Record>> records; std::vector<std::unique_ptr<Record>> records;
TlsParser parser(data, size); nss_test::TlsParser parser(data, size);
while (parser.remaining()) { while (parser.remaining()) {
size_t offset = parser.consumed(); size_t offset = parser.consumed();
// Skip type, version, and DTLS seqnums. // Skip type, version, and DTLS seqnums.
if (!parser.Skip(3 + gExtraHeaderBytes)) { if (!parser.Skip(3 + EXTRA_HEADER_BYTES)) {
break; break;
} }
DataBuffer fragment; nss_test::DataBuffer fragment;
if (!parser.ReadVariable(&fragment, 2)) { if (!parser.ReadVariable(&fragment, 2)) {
break; break;
} }
records.push_back(Record::Create(data + offset, records.push_back(Record::Create(data + offset,
fragment.len() + 5 + gExtraHeaderBytes, fragment.len() + 5 + EXTRA_HEADER_BYTES,
parser.remaining())); parser.remaining()));
} }
@@ -95,11 +91,8 @@ std::vector<std::unique_ptr<Record>> ParseRecords(const uint8_t *data,
namespace TlsMutators { namespace TlsMutators {
// Handle seqnums in DTLS transcripts.
void SetIsDTLS() { gExtraHeaderBytes = 8; }
// Mutator that drops whole TLS records. // Mutator that drops whole TLS records.
size_t DropRecord(uint8_t *data, size_t size, size_t max_size, size_t DropRecord(uint8_t *data, size_t size, size_t maxSize,
unsigned int seed) { unsigned int seed) {
std::mt19937 rng(seed); std::mt19937 rng(seed);
@@ -121,7 +114,7 @@ size_t DropRecord(uint8_t *data, size_t size, size_t max_size,
} }
// Mutator that shuffles TLS records in a transcript. // Mutator that shuffles TLS records in a transcript.
size_t ShuffleRecords(uint8_t *data, size_t size, size_t max_size, size_t ShuffleRecords(uint8_t *data, size_t size, size_t maxSize,
unsigned int seed) { unsigned int seed) {
std::mt19937 rng(seed); std::mt19937 rng(seed);
@@ -152,7 +145,7 @@ size_t ShuffleRecords(uint8_t *data, size_t size, size_t max_size,
} }
// Mutator that duplicates a single TLS record and randomly inserts it. // Mutator that duplicates a single TLS record and randomly inserts it.
size_t DuplicateRecord(uint8_t *data, size_t size, size_t max_size, size_t DuplicateRecord(uint8_t *data, size_t size, size_t maxSize,
unsigned int seed) { unsigned int seed) {
std::mt19937 rng(seed); std::mt19937 rng(seed);
@@ -165,7 +158,7 @@ size_t DuplicateRecord(uint8_t *data, size_t size, size_t max_size,
// Pick a record to duplicate at random. // Pick a record to duplicate at random.
std::uniform_int_distribution<size_t> dist(0, records.size() - 1); std::uniform_int_distribution<size_t> dist(0, records.size() - 1);
auto &rec = records.at(dist(rng)); auto &rec = records.at(dist(rng));
if (size + rec->size() > max_size) { if (size + rec->size() > maxSize) {
return 0; return 0;
} }
@@ -177,7 +170,7 @@ size_t DuplicateRecord(uint8_t *data, size_t size, size_t max_size,
} }
// Mutator that truncates a TLS record. // Mutator that truncates a TLS record.
size_t TruncateRecord(uint8_t *data, size_t size, size_t max_size, size_t TruncateRecord(uint8_t *data, size_t size, size_t maxSize,
unsigned int seed) { unsigned int seed) {
std::mt19937 rng(seed); std::mt19937 rng(seed);
@@ -192,12 +185,12 @@ size_t TruncateRecord(uint8_t *data, size_t size, size_t max_size,
auto &rec = records.at(dist(rng)); auto &rec = records.at(dist(rng));
// Need a record with data. // Need a record with data.
if (rec->size() <= 5 + gExtraHeaderBytes) { if (rec->size() <= 5 + EXTRA_HEADER_BYTES) {
return 0; return 0;
} }
// Truncate. // Truncate.
std::uniform_int_distribution<size_t> dist2(5 + gExtraHeaderBytes, std::uniform_int_distribution<size_t> dist2(5 + EXTRA_HEADER_BYTES,
rec->size() - 1); rec->size() - 1);
size_t new_length = dist2(rng); size_t new_length = dist2(rng);
rec->truncate(new_length); rec->truncate(new_length);
@@ -207,16 +200,16 @@ size_t TruncateRecord(uint8_t *data, size_t size, size_t max_size,
} }
// Mutator that splits a TLS record in two. // Mutator that splits a TLS record in two.
size_t FragmentRecord(uint8_t *data, size_t size, size_t max_size, size_t FragmentRecord(uint8_t *data, size_t size, size_t maxSize,
unsigned int seed) { unsigned int seed) {
std::mt19937 rng(seed); std::mt19937 rng(seed);
// We can't deal with DTLS yet. // We can't deal with DTLS yet.
if (gExtraHeaderBytes > 0) { if (EXTRA_HEADER_BYTES > 0) {
return 0; return 0;
} }
if (size + 5 > max_size) { if (size + 5 > maxSize) {
return 0; return 0;
} }
@@ -259,7 +252,7 @@ size_t FragmentRecord(uint8_t *data, size_t size, size_t max_size,
// Cross-over function that merges and shuffles two transcripts. // Cross-over function that merges and shuffles two transcripts.
size_t CrossOver(const uint8_t *data1, size_t size1, const uint8_t *data2, size_t CrossOver(const uint8_t *data1, size_t size1, const uint8_t *data2,
size_t size2, uint8_t *out, size_t max_out_size, size_t size2, uint8_t *out, size_t maxOutSize,
unsigned int seed) { unsigned int seed) {
std::mt19937 rng(seed); std::mt19937 rng(seed);
@@ -283,7 +276,7 @@ size_t CrossOver(const uint8_t *data1, size_t size1, const uint8_t *data2,
size_t total = 0; size_t total = 0;
for (auto &rec : records1) { for (auto &rec : records1) {
size_t length = rec->size(); size_t length = rec->size();
if (total + length > max_out_size) { if (total + length > maxOutSize) {
break; break;
} }
@@ -295,4 +288,4 @@ size_t CrossOver(const uint8_t *data1, size_t size1, const uint8_t *data2,
return total; return total;
} }
} // namespace TlsMutators } // namespace TlsMutators

View File

@@ -8,23 +8,29 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
// Number of additional bytes in the TLS header.
// Used to properly skip DTLS seqnums.
#ifdef IS_DTLS_FUZZ
#define EXTRA_HEADER_BYTES 8
#else
#define EXTRA_HEADER_BYTES 0
#endif
namespace TlsMutators { namespace TlsMutators {
void SetIsDTLS(); size_t DropRecord(uint8_t *data, size_t size, size_t maxSize,
size_t DropRecord(uint8_t *data, size_t size, size_t max_size,
unsigned int seed); unsigned int seed);
size_t ShuffleRecords(uint8_t *data, size_t size, size_t max_size, size_t ShuffleRecords(uint8_t *data, size_t size, size_t maxSize,
unsigned int seed); unsigned int seed);
size_t DuplicateRecord(uint8_t *data, size_t size, size_t max_size, size_t DuplicateRecord(uint8_t *data, size_t size, size_t maxSize,
unsigned int seed); unsigned int seed);
size_t TruncateRecord(uint8_t *data, size_t size, size_t max_size, size_t TruncateRecord(uint8_t *data, size_t size, size_t maxSize,
unsigned int seed); unsigned int seed);
size_t FragmentRecord(uint8_t *data, size_t size, size_t max_size, size_t FragmentRecord(uint8_t *data, size_t size, size_t maxSize,
unsigned int seed); unsigned int seed);
size_t CrossOver(const uint8_t *data1, size_t size1, const uint8_t *data2, size_t CrossOver(const uint8_t *data1, size_t size1, const uint8_t *data2,
size_t size2, uint8_t *out, size_t max_out_size, size_t size2, uint8_t *out, size_t maxOutSize,
unsigned int seed); unsigned int seed);
} // namespace TlsMutators } // namespace TlsMutators

View File

@@ -2,14 +2,15 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <assert.h> #include "server_certs.h"
#include <stdint.h>
#include "ssl.h" #include <cassert>
#include <cstddef>
#include <cstdint>
#include "cpputil.h" #include "cpputil.h"
#include "nss_scoped_ptrs.h" #include "nss_scoped_ptrs.h"
#include "tls_server_certs.h" #include "ssl.h"
const uint8_t kP256ServerCert[] = { const uint8_t kP256ServerCert[] = {
0x30, 0x82, 0x01, 0xcf, 0x30, 0x82, 0x01, 0x76, 0xa0, 0x03, 0x02, 0x01, 0x30, 0x82, 0x01, 0xcf, 0x30, 0x82, 0x01, 0x76, 0xa0, 0x03, 0x02, 0x01,
@@ -252,16 +253,16 @@ const uint8_t kRsaServerKey[] = {
0xfe, 0xbf, 0xda, 0x0e, 0xce, 0x28, 0xb9, 0xdb, 0x9b, 0xcf, 0x6e, 0xa8, 0xfe, 0xbf, 0xda, 0x0e, 0xce, 0x28, 0xb9, 0xdb, 0x9b, 0xcf, 0x6e, 0xa8,
0xe4, 0x60, 0xca, 0x98}; 0xe4, 0x60, 0xca, 0x98};
void InstallServerCertificate(PRFileDesc* fd, const uint8_t* cert_data, static void InstallServerCertificate(PRFileDesc* fd, const uint8_t* certData,
size_t cert_len, const uint8_t* key_data, size_t certLen, const uint8_t* keyData,
size_t key_len) { size_t keyLen) {
ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
assert(slot); assert(slot);
SECItem certItem = {siBuffer, toUcharPtr(cert_data), SECItem certItem = {siBuffer, toUcharPtr(certData),
static_cast<unsigned int>(cert_len)}; static_cast<unsigned int>(certLen)};
SECItem pkcs8Item = {siBuffer, toUcharPtr(key_data), SECItem pkcs8Item = {siBuffer, toUcharPtr(keyData),
static_cast<unsigned int>(key_len)}; static_cast<unsigned int>(keyLen)};
// Import the certificate. // Import the certificate.
static CERTCertDBHandle* certDB = CERT_GetDefaultCertDB(); static CERTCertDBHandle* certDB = CERT_GetDefaultCertDB();
@@ -284,6 +285,8 @@ void InstallServerCertificate(PRFileDesc* fd, const uint8_t* cert_data,
assert(rv == SECSuccess); assert(rv == SECSuccess);
} }
namespace TlsServer {
void InstallServerCertificates(PRFileDesc* fd) { void InstallServerCertificates(PRFileDesc* fd) {
// ECDSA P-256 certificate. // ECDSA P-256 certificate.
InstallServerCertificate(fd, kP256ServerCert, sizeof(kP256ServerCert), InstallServerCertificate(fd, kP256ServerCert, sizeof(kP256ServerCert),
@@ -292,4 +295,8 @@ void InstallServerCertificates(PRFileDesc* fd) {
// RSA-2048 certificate. // RSA-2048 certificate.
InstallServerCertificate(fd, kRsaServerCert, sizeof(kRsaServerCert), InstallServerCertificate(fd, kRsaServerCert, sizeof(kRsaServerCert),
kRsaServerKey, sizeof(kRsaServerKey)); kRsaServerKey, sizeof(kRsaServerKey));
// TODO(mdauer): Install more different cerificate types.
} }
} // namespace TlsServer

View File

@@ -2,11 +2,15 @@
* 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/. */
#ifndef tls_server_certs_h__ #ifndef TLS_SERVER_CERT_H_
#define tls_server_certs_h__ #define TLS_SERVER_CERT_H_
#include "prio.h" #include "prio.h"
namespace TlsServer {
void InstallServerCertificates(PRFileDesc* fd); void InstallServerCertificates(PRFileDesc* fd);
#endif // tls_server_certs_h__ } // namespace TlsServer
#endif // TLS_SERVER_CERT_H_

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "tls_server_config.h" #include "server_config.h"
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
@@ -16,16 +16,17 @@
#include "sslexp.h" #include "sslexp.h"
#include "sslt.h" #include "sslt.h"
#include "tls_common.h" #include "common.h"
const SSLCertificateCompressionAlgorithm kCompressionAlg = { const SSLCertificateCompressionAlgorithm kCompressionAlg = {
0x1337, "fuzz", DummyCompressionEncode, DummyCompressionDecode}; 0x1337, "fuzz", TlsCommon::DummyCompressionEncode,
TlsCommon::DummyCompressionDecode};
const PRUint8 kPskIdentity[] = "fuzz-psk-identity"; const PRUint8 kPskIdentity[] = "fuzz-psk-identity";
static SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checksig, static SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checksig,
PRBool isServer) { PRBool isServer) {
assert(isServer); assert(isServer);
auto config = reinterpret_cast<ServerConfig*>(arg); auto config = reinterpret_cast<TlsServer::Config*>(arg);
if (config->FailCertificateAuthentication()) return SECFailure; if (config->FailCertificateAuthentication()) return SECFailure;
return SECSuccess; return SECSuccess;
@@ -37,10 +38,12 @@ static SECStatus CanFalseStartCallback(PRFileDesc* fd, void* arg,
return SECSuccess; return SECSuccess;
} }
namespace TlsServer {
// XOR 64-bit chunks of data to build a bitmap of config options derived from // XOR 64-bit chunks of data to build a bitmap of config options derived from
// the fuzzing input. This seems the only way to fuzz various options while // the fuzzing input. This seems the only way to fuzz various options while
// still maintaining compatibility with BoringSSL or OpenSSL fuzzers. // still maintaining compatibility with BoringSSL or OpenSSL fuzzers.
ServerConfig::ServerConfig(const uint8_t* data, size_t len) { Config::Config(const uint8_t* data, size_t len) {
union { union {
uint64_t bitmap; uint64_t bitmap;
struct { struct {
@@ -71,7 +74,7 @@ ServerConfig::ServerConfig(const uint8_t* data, size_t len) {
}; };
} }
void ServerConfig::SetCallbacks(PRFileDesc* fd) { void Config::SetCallbacks(PRFileDesc* fd) {
SECStatus rv = SSL_AuthCertificateHook(fd, AuthCertificateHook, this); SECStatus rv = SSL_AuthCertificateHook(fd, AuthCertificateHook, this);
assert(rv == SECSuccess); assert(rv == SECSuccess);
@@ -79,7 +82,7 @@ void ServerConfig::SetCallbacks(PRFileDesc* fd) {
assert(rv == SECSuccess); assert(rv == SECSuccess);
} }
void ServerConfig::SetSocketOptions(PRFileDesc* fd) { void Config::SetSocketOptions(PRFileDesc* fd) {
SECStatus rv = SSL_OptionSet(fd, SSL_ENABLE_EXTENDED_MASTER_SECRET, SECStatus rv = SSL_OptionSet(fd, SSL_ENABLE_EXTENDED_MASTER_SECRET,
this->EnableExtendedMasterSecret()); this->EnableExtendedMasterSecret());
assert(rv == SECSuccess); assert(rv == SECSuccess);
@@ -145,6 +148,17 @@ void ServerConfig::SetSocketOptions(PRFileDesc* fd) {
rv = SSL_OptionSet(fd, SSL_NO_LOCKS, this->NoLocks()); rv = SSL_OptionSet(fd, SSL_NO_LOCKS, this->NoLocks());
assert(rv == SECSuccess); assert(rv == SECSuccess);
rv = SSL_EnableTls13BackendEch(fd, this->EnableTls13BackendEch());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_ENABLE_DELEGATED_CREDENTIALS,
this->EnableDelegatedCredentials());
assert(rv == SECSuccess);
rv = SSL_OptionSet(fd, SSL_ENABLE_DTLS_SHORT_HEADER,
this->EnableDtlsShortHeader());
assert(rv == SECSuccess);
#ifndef IS_DTLS_FUZZ #ifndef IS_DTLS_FUZZ
rv = rv =
SSL_OptionSet(fd, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_UNRESTRICTED); SSL_OptionSet(fd, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_UNRESTRICTED);
@@ -152,7 +166,7 @@ void ServerConfig::SetSocketOptions(PRFileDesc* fd) {
#endif #endif
} }
std::ostream& operator<<(std::ostream& out, ServerConfig& config) { std::ostream& operator<<(std::ostream& out, Config& config) {
out << "============= ServerConfig =============" out << "============= ServerConfig ============="
<< "\n"; << "\n";
out << "SSL_NO_CACHE: " << config.NoCache() << "\n"; out << "SSL_NO_CACHE: " << config.NoCache() << "\n";
@@ -195,3 +209,5 @@ std::ostream& operator<<(std::ostream& out, ServerConfig& config) {
return out; return out;
} }
} // namespace TlsServer

View File

@@ -19,9 +19,11 @@
#endif #endif
#define SSL_VERSION_RANGE_MAX_VALID 0x0304 #define SSL_VERSION_RANGE_MAX_VALID 0x0304
class ServerConfig { namespace TlsServer {
class Config {
public: public:
ServerConfig(const uint8_t* data, size_t len); Config(const uint8_t* data, size_t len);
void SetCallbacks(PRFileDesc* fd); void SetCallbacks(PRFileDesc* fd);
void SetSocketOptions(PRFileDesc* fd); void SetSocketOptions(PRFileDesc* fd);
@@ -33,6 +35,8 @@ class ServerConfig {
}; };
SSLVersionRange SslVersionRange() { return ssl_version_range_; }; SSLVersionRange SslVersionRange() { return ssl_version_range_; };
// NOTE: When adding more config options here, don't forget to print
// them in the "<<"-overloaded operator.
bool EnableExtendedMasterSecret() { return config_ & (1 << 0); }; bool EnableExtendedMasterSecret() { return config_ & (1 << 0); };
bool RequestCertificate() { return config_ & (1 << 1); }; bool RequestCertificate() { return config_ & (1 << 1); };
bool RequireCertificate() { return config_ & (1 << 2); }; bool RequireCertificate() { return config_ & (1 << 2); };
@@ -50,12 +54,17 @@ class ServerConfig {
bool EnableSessionTickets() { return config_ & (1 << 14); }; bool EnableSessionTickets() { return config_ & (1 << 14); };
bool NoLocks() { return config_ & (1 << 15); }; bool NoLocks() { return config_ & (1 << 15); };
bool FailCertificateAuthentication() { return config_ & (1 << 16); } bool FailCertificateAuthentication() { return config_ & (1 << 16); }
bool EnableTls13BackendEch() { return config_ & (1 << 17); }
bool EnableDelegatedCredentials() { return config_ & (1 << 18); };
bool EnableDtlsShortHeader() { return config_ & (1 << 19); };
private: private:
uint32_t config_; uint32_t config_;
SSLVersionRange ssl_version_range_; SSLVersionRange ssl_version_range_;
}; };
std::ostream& operator<<(std::ostream& out, ServerConfig& config); std::ostream& operator<<(std::ostream& out, Config& config);
} // namespace TlsServer
#endif // TLS_SERVER_CONFIG_H_ #endif // TLS_SERVER_CONFIG_H_

View File

@@ -2,16 +2,19 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <assert.h> #include "socket.h"
#include <string.h>
#include <algorithm>
#include "prerror.h" #include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
#include "prinrval.h"
#include "prio.h" #include "prio.h"
#include "tls_socket.h" namespace TlsSocket {
int32_t DummyPrSocket::Read(PRFileDesc *f, void *data, int32_t len) { int32_t DummyPrSocket::Read(PRFileDesc *fd, void *data, int32_t len) {
assert(data && len > 0); assert(data && len > 0);
int32_t amount = std::min(len, static_cast<int32_t>(len_)); int32_t amount = std::min(len, static_cast<int32_t>(len_));
@@ -23,12 +26,14 @@ int32_t DummyPrSocket::Read(PRFileDesc *f, void *data, int32_t len) {
return amount; return amount;
} }
int32_t DummyPrSocket::Write(PRFileDesc *f, const void *buf, int32_t length) { int32_t DummyPrSocket::Write(PRFileDesc *fd, const void *buf, int32_t length) {
return length; return length;
} }
int32_t DummyPrSocket::Recv(PRFileDesc *f, void *buf, int32_t buflen, int32_t DummyPrSocket::Recv(PRFileDesc *fd, void *buf, int32_t buflen,
int32_t flags, PRIntervalTime to) { int32_t flags, PRIntervalTime to) {
assert(flags == 0); assert(flags == 0);
return Read(f, buf, buflen); return Read(fd, buf, buflen);
} }
} // namespace TlsSocket

View File

@@ -2,19 +2,24 @@
* 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/. */
#ifndef tls_socket_h__ #ifndef TLS_SOCKET_H_
#define tls_socket_h__ #define TLS_SOCKET_H_
#include <cstdint>
#include "dummy_io.h" #include "dummy_io.h"
#include "prinrval.h"
#include "prio.h"
namespace TlsSocket {
class DummyPrSocket : public DummyIOLayerMethods { class DummyPrSocket : public DummyIOLayerMethods {
public: public:
DummyPrSocket(const uint8_t *buf, size_t len) : buf_(buf), len_(len) {} DummyPrSocket(const uint8_t *buf, size_t len) : buf_(buf), len_(len) {}
virtual ~DummyPrSocket() {}
int32_t Read(PRFileDesc *f, void *data, int32_t len) override; int32_t Read(PRFileDesc *fd, void *data, int32_t len) override;
int32_t Write(PRFileDesc *f, const void *buf, int32_t length) override; int32_t Write(PRFileDesc *fd, const void *buf, int32_t length) override;
int32_t Recv(PRFileDesc *f, void *buf, int32_t buflen, int32_t flags, int32_t Recv(PRFileDesc *fd, void *buf, int32_t buflen, int32_t flags,
PRIntervalTime to) override; PRIntervalTime to) override;
private: private:
@@ -22,4 +27,6 @@ class DummyPrSocket : public DummyIOLayerMethods {
size_t len_; size_t len_;
}; };
#endif // tls_socket_h__ } // namespace TlsSocket
#endif // TLS_SOCKET_H_

View File

@@ -0,0 +1,43 @@
# 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/.
{
'includes': [
'../../../../coreconf/config.gypi',
],
'targets': [
{
'target_name': 'tls_client',
'type': 'none',
'direct_dependent_settings': {
'sources': [
'client_config.cc',
'common.cc',
'mutators.cc',
'socket.cc'
],
'include_dirs': [
'<(DEPTH)/lib/freebl',
'<(DEPTH)/lib/ssl',
],
},
},
{
'target_name': 'tls_server',
'type': 'none',
'direct_dependent_settings': {
'sources': [
'common.cc',
'mutators.cc',
'server_certs.cc',
'server_config.cc',
'socket.cc'
],
'include_dirs': [
'<(DEPTH)/lib/freebl',
'<(DEPTH)/lib/ssl',
],
},
},
],
}

View File

@@ -5,15 +5,15 @@
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <memory>
#include "nss_scoped_ptrs.h" #include "nss_scoped_ptrs.h"
#include "p12.h" #include "p12.h"
#include "pk11pub.h" #include "pk11pub.h"
#include "seccomon.h" #include "seccomon.h"
#include "asn1_mutators.h" #include "asn1/mutators.h"
#include "shared.h" #include "base/database.h"
#include "base/mutate.h"
static SECItem* nicknameCollision(SECItem* oldNick, PRBool* cancel, static SECItem* nicknameCollision(SECItem* oldNick, PRBool* cancel,
void* wincx) { void* wincx) {
@@ -22,7 +22,7 @@ static SECItem* nicknameCollision(SECItem* oldNick, PRBool* cancel,
} }
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
static std::unique_ptr<NSSDatabase> db(new NSSDatabase()); static NSSDatabase db = NSSDatabase();
ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
assert(slot); assert(slot);

View File

@@ -4,32 +4,18 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <memory>
#include "cert.h" #include "cert.h"
#include "seccomon.h"
#include "asn1_mutators.h" #include "asn1/mutators.h"
#include "shared.h" #include "base/database.h"
#include "base/mutate.h"
static SECStatus importFunc(void *arg, SECItem **certs, int numCerts) {
// This way we check that the callback gets called with the correct
// `numCerts`, as an invalid value potentially causes `certs` to go
// out-of-bounds. Testing `CERT_Hexify` is a nice bonus.
while (numCerts--) {
char *hex = CERT_Hexify(*certs, false);
free(hex);
certs++;
}
return SECSuccess;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
static std::unique_ptr<NSSDatabase> db(new NSSDatabase()); static NSSDatabase db = NSSDatabase();
CERT_DecodeCertPackage((char *)data, (int)size, importFunc, nullptr); CERTCertificate *cert = CERT_DecodeCertFromPackage((char *)data, (int)size);
CERT_DestroyCertificate(cert);
return 0; return 0;
} }

View File

@@ -2,32 +2,33 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <cassert>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <memory>
#include "keyhi.h" #include "keyhi.h"
#include "nss_scoped_ptrs.h"
#include "pk11pub.h" #include "pk11pub.h"
#include "asn1_mutators.h" #include "asn1/mutators.h"
#include "shared.h" #include "base/database.h"
#include "base/mutate.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
static std::unique_ptr<NSSDatabase> db(new NSSDatabase()); static NSSDatabase db = NSSDatabase();
PK11SlotInfo *slot = PK11_GetInternalSlot();
assert(slot);
SECItem derPki = {siBuffer, (unsigned char *)data, (unsigned int)size}; SECItem derPki = {siBuffer, (unsigned char *)data, (unsigned int)size};
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
assert(slot);
SECKEYPrivateKey *key = nullptr; SECKEYPrivateKey *key = nullptr;
if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, &derPki, nullptr, nullptr, if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot.get(), &derPki, nullptr,
false, false, KU_ALL, &key, nullptr, false, false, KU_ALL,
nullptr) == SECSuccess) { &key, nullptr) == SECSuccess) {
SECKEY_DestroyPrivateKey(key); SECKEY_DestroyPrivateKey(key);
} }
PK11_FreeSlot(slot);
return 0; return 0;
} }

View File

@@ -6,11 +6,13 @@
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include "asn1_mutators.h"
#include "certt.h" #include "certt.h"
#include "keythi.h" #include "keythi.h"
#include "secdert.h" #include "secdert.h"
#include "shared.h" #include "secport.h"
#include "asn1/mutators.h"
#include "base/mutate.h"
const std::vector<const SEC_ASN1Template *> templates = { const std::vector<const SEC_ASN1Template *> templates = {
CERT_AttributeTemplate, CERT_AttributeTemplate,
@@ -68,19 +70,19 @@ const std::vector<const SEC_ASN1Template *> templates = {
SECKEY_RSAPublicKeyTemplate, SECKEY_RSAPublicKeyTemplate,
SECOID_AlgorithmIDTemplate}; SECOID_AlgorithmIDTemplate};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
char *dest[2048]; static char *dest[2048];
PORTCheapArenaPool pool;
PORT_InitCheapArena(&pool, DER_DEFAULT_CHUNKSIZE);
for (auto tpl : templates) { for (auto tpl : templates) {
PORTCheapArenaPool pool; SECItem buf = {siBuffer, (unsigned char *)data, (unsigned int)size};
SECItem buf = {siBuffer, const_cast<unsigned char *>(Data),
static_cast<unsigned int>(Size)};
PORT_InitCheapArena(&pool, DER_DEFAULT_CHUNKSIZE);
(void)SEC_QuickDERDecodeItem(&pool.arena, dest, tpl, &buf); (void)SEC_QuickDERDecodeItem(&pool.arena, dest, tpl, &buf);
PORT_DestroyCheapArena(&pool);
} }
PORT_DestroyCheapArena(&pool);
return 0; return 0;
} }

View File

@@ -0,0 +1,202 @@
# 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/.
{
'includes': [
'../../coreconf/config.gypi',
],
'target_defaults': {
'variables': {
'debug_optimization_level': '3',
},
'target_conditions': [
[ '_type=="executable"', {
'libraries!': [
'<@(nspr_libs)',
],
'libraries': [
'<(nss_dist_obj_dir)/lib/libplds4.a',
'<(nss_dist_obj_dir)/lib/libnspr4.a',
'<(nss_dist_obj_dir)/lib/libplc4.a',
],
}],
],
},
'targets': [
{
'target_name': 'nssfuzz_base',
'type': 'none',
'dependencies': [
'<(DEPTH)/lib/certdb/certdb.gyp:certdb',
'<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
'<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
'<(DEPTH)/lib/ssl/ssl.gyp:ssl',
'<(DEPTH)/lib/base/base.gyp:nssb',
'<(DEPTH)/lib/dev/dev.gyp:nssdev',
'<(DEPTH)/lib/pki/pki.gyp:nsspki',
'<(DEPTH)/lib/util/util.gyp:nssutil',
'<(DEPTH)/lib/nss/nss.gyp:nss_static',
'<(DEPTH)/lib/pkcs7/pkcs7.gyp:pkcs7',
'<(DEPTH)/lib/pkcs12/pkcs12.gyp:pkcs12',
# This is a static build of pk11wrap, softoken, and freebl.
'<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
'<(DEPTH)/lib/libpkix/libpkix.gyp:libpkix',
],
'direct_dependent_settings': {
'include_dirs': [ '<(DEPTH)/fuzz/targets/lib' ],
},
'conditions': [
['fuzz_oss==0', {
'all_dependent_settings': {
'libraries': [
'-fsanitize=fuzzer',
],
}
}, {
'all_dependent_settings': {
'libraries': [ '-lFuzzingEngine' ],
}
}]
],
},
{
'target_name': 'nssfuzz-certDN',
'type': 'executable',
'sources': [
'certDN.cc',
],
'dependencies': [
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'<(DEPTH)/exports.gyp:nss_exports',
'nssfuzz_base',
],
},
{
'target_name': 'nssfuzz-dtls-client',
'type': 'executable',
'sources': [
'tls_client.cc',
],
'defines': [ 'IS_DTLS_FUZZ' ],
'dependencies': [
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/fuzz/targets/lib/base/base.gyp:base',
'<(DEPTH)/fuzz/targets/lib/tls/tls.gyp:tls_client',
'nssfuzz_base',
],
},
{
'target_name': 'nssfuzz-dtls-server',
'type': 'executable',
'sources': [
'tls_server.cc',
],
'defines': [ 'IS_DTLS_FUZZ' ],
'dependencies': [
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/fuzz/targets/lib/base/base.gyp:base',
'<(DEPTH)/fuzz/targets/lib/tls/tls.gyp:tls_server',
'nssfuzz_base',
],
},
{
'target_name': 'nssfuzz-pkcs7',
'type': 'executable',
'sources': [
'pkcs7.cc',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/fuzz/targets/lib/asn1/asn1.gyp:asn1',
'<(DEPTH)/fuzz/targets/lib/base/base.gyp:base',
'nssfuzz_base',
],
},
{
'target_name': 'nssfuzz-pkcs8',
'type': 'executable',
'sources': [
'pkcs8.cc',
],
'dependencies': [
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/fuzz/targets/lib/asn1/asn1.gyp:asn1',
'<(DEPTH)/fuzz/targets/lib/base/base.gyp:base',
'nssfuzz_base',
],
},
{
'target_name': 'nssfuzz-pkcs12',
'type': 'executable',
'sources': [
'pkcs12.cc',
],
'dependencies': [
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/fuzz/targets/lib/asn1/asn1.gyp:asn1',
'<(DEPTH)/fuzz/targets/lib/base/base.gyp:base',
'nssfuzz_base',
],
},
{
'target_name': 'nssfuzz-quickder',
'type': 'executable',
'sources': [
'quickder.cc',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/fuzz/targets/lib/asn1/asn1.gyp:asn1',
'<(DEPTH)/fuzz/targets/lib/base/base.gyp:base',
'nssfuzz_base',
],
},
{
'target_name': 'nssfuzz-tls-client',
'type': 'executable',
'sources': [
'tls_client.cc',
],
'dependencies': [
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/fuzz/targets/lib/base/base.gyp:base',
'<(DEPTH)/fuzz/targets/lib/tls/tls.gyp:tls_client',
'nssfuzz_base',
],
},
{
'target_name': 'nssfuzz-tls-server',
'type': 'executable',
'sources': [
'tls_server.cc',
],
'dependencies': [
'<(DEPTH)/cpputil/cpputil.gyp:cpputil',
'<(DEPTH)/exports.gyp:nss_exports',
'<(DEPTH)/fuzz/targets/lib/base/base.gyp:base',
'<(DEPTH)/fuzz/targets/lib/tls/tls.gyp:tls_server',
'nssfuzz_base',
],
},
{
'target_name': 'nssfuzz',
'type': 'none',
'dependencies': [
'nssfuzz-certDN',
'nssfuzz-dtls-client',
'nssfuzz-dtls-server',
'nssfuzz-pkcs7',
'nssfuzz-pkcs8',
'nssfuzz-pkcs12',
'nssfuzz-quickder',
'nssfuzz-tls-client',
'nssfuzz-tls-server',
],
},
],
}

View File

@@ -12,36 +12,31 @@
#include "ssl.h" #include "ssl.h"
#include "sslimpl.h" #include "sslimpl.h"
#include "shared.h" #include "base/database.h"
#include "tls_client_config.h" #include "base/mutate.h"
#include "tls_common.h" #include "tls/client_config.h"
#include "tls_mutators.h" #include "tls/common.h"
#include "tls_socket.h" #include "tls/mutators.h"
#include "tls/socket.h"
#ifdef IS_DTLS_FUZZ #ifdef IS_DTLS_FUZZ
__attribute__((constructor)) static void set_is_dtls() {
TlsMutators::SetIsDTLS();
}
#define ImportFD DTLS_ImportFD #define ImportFD DTLS_ImportFD
#else #else
#define ImportFD SSL_ImportFD #define ImportFD SSL_ImportFD
#endif // IS_DTLS_FUZZ #endif // IS_DTLS_FUZZ
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
static NSSDatabase db = NSSDatabase(); static NSSDatabase db = NSSDatabase();
static PRDescIdentity id = PR_GetUniqueIdentity("fuzz-client"); static PRDescIdentity id = PR_GetUniqueIdentity("fuzz-client");
EnableAllProtocolVersions();
// Create and import dummy socket. // Create and import dummy socket.
DummyPrSocket socket = DummyPrSocket(data, len); TlsSocket::DummyPrSocket socket = TlsSocket::DummyPrSocket(data, size);
ScopedPRFileDesc prFd(DummyIOLayerMethods::CreateFD(id, &socket)); ScopedPRFileDesc prFd(DummyIOLayerMethods::CreateFD(id, &socket));
PRFileDesc* sslFd = ImportFD(nullptr, prFd.get()); PRFileDesc* sslFd = ImportFD(nullptr, prFd.get());
assert(sslFd == prFd.get()); assert(sslFd == prFd.get());
// Derive client config from input data. // Derive client config from input data.
ClientConfig config = ClientConfig(data, len); TlsClient::Config config = TlsClient::Config(data, size);
if (ssl_trace >= 90) { if (ssl_trace >= 90) {
std::cerr << config << "\n"; std::cerr << config << "\n";
@@ -51,15 +46,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) {
assert(RNG_RandomUpdate(NULL, 0) == SECSuccess); assert(RNG_RandomUpdate(NULL, 0) == SECSuccess);
assert(SSL_SetURL(sslFd, "fuzz.client") == SECSuccess); assert(SSL_SetURL(sslFd, "fuzz.client") == SECSuccess);
FixTime(sslFd); TlsCommon::EnableAllProtocolVersions();
EnableAllCipherSuites(sslFd); TlsCommon::EnableAllCipherSuites(sslFd);
TlsCommon::FixTime(sslFd);
// Set socket callbacks & options from client config. // Set socket callbacks & options from client config.
config.SetCallbacks(sslFd); config.SetCallbacks(sslFd);
config.SetSocketOptions(sslFd); config.SetSocketOptions(sslFd);
// Perform the acutal handshake. // Perform the acutal handshake.
DoHandshake(sslFd, false); TlsCommon::DoHandshake(sslFd, false);
// Release all SIDs. // Release all SIDs.
SSL_ClearSessionCache(); SSL_ClearSessionCache();
@@ -68,18 +64,18 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) {
} }
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size, extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
size_t max_size, unsigned int seed) { size_t maxSize, unsigned int seed) {
Mutators mutators = {TlsMutators::DropRecord, TlsMutators::ShuffleRecords, Mutators mutators = {TlsMutators::DropRecord, TlsMutators::ShuffleRecords,
TlsMutators::DuplicateRecord, TlsMutators::DuplicateRecord,
TlsMutators::TruncateRecord, TlsMutators::TruncateRecord,
TlsMutators::FragmentRecord}; TlsMutators::FragmentRecord};
return CustomMutate(mutators, data, size, max_size, seed); return CustomMutate(mutators, data, size, maxSize, seed);
} }
extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t* data1, size_t size1, extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t* data1, size_t size1,
const uint8_t* data2, size_t size2, const uint8_t* data2, size_t size2,
uint8_t* out, size_t max_out_size, uint8_t* out, size_t maxOutSize,
unsigned int seed) { unsigned int seed) {
return TlsMutators::CrossOver(data1, size1, data2, size2, out, max_out_size, return TlsMutators::CrossOver(data1, size1, data2, size2, out, maxOutSize,
seed); seed);
} }

View File

@@ -11,22 +11,19 @@
#include "ssl.h" #include "ssl.h"
#include "sslimpl.h" #include "sslimpl.h"
#include "shared.h" #include "base/database.h"
#include "tls_common.h" #include "base/mutate.h"
#include "tls_mutators.h" #include "tls/common.h"
#include "tls_server_certs.h" #include "tls/mutators.h"
#include "tls_server_config.h" #include "tls/server_certs.h"
#include "tls_socket.h" #include "tls/server_config.h"
#include "tls/socket.h"
#ifdef IS_DTLS_FUZZ #ifdef IS_DTLS_FUZZ
__attribute__((constructor)) static void set_is_dtls() {
TlsMutators::SetIsDTLS();
}
#define ImportFD DTLS_ImportFD #define ImportFD DTLS_ImportFD
#else #else
#define ImportFD SSL_ImportFD #define ImportFD SSL_ImportFD
#endif #endif // IS_DTLS_FUZZ
class SSLServerSessionCache { class SSLServerSessionCache {
public: public:
@@ -42,13 +39,13 @@ class SSLServerSessionCache {
static PRStatus InitModelSocket(void* arg) { static PRStatus InitModelSocket(void* arg) {
PRFileDesc* fd = reinterpret_cast<PRFileDesc*>(arg); PRFileDesc* fd = reinterpret_cast<PRFileDesc*>(arg);
EnableAllCipherSuites(fd); TlsCommon::EnableAllCipherSuites(fd);
InstallServerCertificates(fd); TlsServer::InstallServerCertificates(fd);
return PR_SUCCESS; return PR_SUCCESS;
} }
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
static NSSDatabase db = NSSDatabase(); static NSSDatabase db = NSSDatabase();
static SSLServerSessionCache cache = SSLServerSessionCache(); static SSLServerSessionCache cache = SSLServerSessionCache();
static PRDescIdentity id = PR_GetUniqueIdentity("fuzz-server"); static PRDescIdentity id = PR_GetUniqueIdentity("fuzz-server");
@@ -61,16 +58,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) {
static PRCallOnceType initModelOnce; static PRCallOnceType initModelOnce;
PR_CallOnceWithArg(&initModelOnce, InitModelSocket, model.get()); PR_CallOnceWithArg(&initModelOnce, InitModelSocket, model.get());
EnableAllProtocolVersions();
// Create and import dummy socket. // Create and import dummy socket.
DummyPrSocket socket = DummyPrSocket(data, len); TlsSocket::DummyPrSocket socket = TlsSocket::DummyPrSocket(data, size);
ScopedPRFileDesc prFd(DummyIOLayerMethods::CreateFD(id, &socket)); ScopedPRFileDesc prFd(DummyIOLayerMethods::CreateFD(id, &socket));
PRFileDesc* sslFd = ImportFD(model.get(), prFd.get()); PRFileDesc* sslFd = ImportFD(model.get(), prFd.get());
assert(sslFd == prFd.get()); assert(sslFd == prFd.get());
// Derive server config from input data. // Derive server config from input data.
ServerConfig config = ServerConfig(data, len); TlsServer::Config config = TlsServer::Config(data, size);
if (ssl_trace >= 90) { if (ssl_trace >= 90) {
std::cerr << config << "\n"; std::cerr << config << "\n";
@@ -80,15 +75,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) {
assert(RNG_RandomUpdate(NULL, 0) == SECSuccess); assert(RNG_RandomUpdate(NULL, 0) == SECSuccess);
assert(SSL_SetURL(sslFd, "fuzz.server") == SECSuccess); assert(SSL_SetURL(sslFd, "fuzz.server") == SECSuccess);
FixTime(sslFd); TlsCommon::EnableAllProtocolVersions();
EnableAllCipherSuites(sslFd); TlsCommon::EnableAllCipherSuites(sslFd);
TlsCommon::FixTime(sslFd);
// Set socket options from server config. // Set socket options from server config.
config.SetCallbacks(sslFd); config.SetCallbacks(sslFd);
config.SetSocketOptions(sslFd); config.SetSocketOptions(sslFd);
// Perform the acutal handshake. // Perform the acutal handshake.
DoHandshake(sslFd, true); TlsCommon::DoHandshake(sslFd, true);
// Clear the cache. We never want to resume as we couldn't reproduce that. // Clear the cache. We never want to resume as we couldn't reproduce that.
SSL_ClearSessionCache(); SSL_ClearSessionCache();
@@ -97,18 +93,18 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) {
} }
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size, extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size,
size_t max_size, unsigned int seed) { size_t maxSize, unsigned int seed) {
return CustomMutate( return CustomMutate(
{TlsMutators::DropRecord, TlsMutators::ShuffleRecords, {TlsMutators::DropRecord, TlsMutators::ShuffleRecords,
TlsMutators::DuplicateRecord, TlsMutators::TruncateRecord, TlsMutators::DuplicateRecord, TlsMutators::TruncateRecord,
TlsMutators::FragmentRecord}, TlsMutators::FragmentRecord},
data, size, max_size, seed); data, size, maxSize, seed);
} }
extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t* data1, size_t size1, extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t* data1, size_t size1,
const uint8_t* data2, size_t size2, const uint8_t* data2, size_t size2,
uint8_t* out, size_t max_out_size, uint8_t* out, size_t maxOutSize,
unsigned int seed) { unsigned int seed) {
return TlsMutators::CrossOver(data1, size1, data2, size2, out, max_out_size, return TlsMutators::CrossOver(data1, size1, data2, size2, out, maxOutSize,
seed); seed);
} }

View File

@@ -39,6 +39,11 @@
'UNSAFE_FUZZER_MODE', 'UNSAFE_FUZZER_MODE',
], ],
}], }],
['gtests_corpus==1', {
'defines': [
'GTESTS_CORPUS',
]
}]
], ],
'msvs_settings': { 'msvs_settings': {
'VCCLCompilerTool': { 'VCCLCompilerTool': {

View File

@@ -105,6 +105,16 @@ static const PresentedMatchesReference DNSID_MATCH_PARAMS[] =
DNS_ID_MATCH("_example", "_example"), DNS_ID_MATCH("_example", "_example"),
DNS_ID_MATCH("*._._", "x._._"), DNS_ID_MATCH("*._._", "x._._"),
// We allow reference ID labels to start and end with hyphens for
// compatibility.
DNS_ID_MATCH("*.example.com", "-.example.com"),
DNS_ID_MATCH("*.example.com", "-hyphenstart.example.com"),
DNS_ID_MATCH("*.example.com", "hyphenend-.example.com"),
// Presented ID labels may not start or end with hyphens.
DNS_ID_BAD_DER("-.example.com", "-.example.com"),
DNS_ID_BAD_DER("-hyphenstart.example.com", "-hyphenstart.example.com"),
DNS_ID_BAD_DER("hyphenend-.example.com", "hyphenend-.example.com"),
// See bug 1139039 // See bug 1139039
// A DNS-ID must not end in an all-numeric label. We don't consider // A DNS-ID must not end in an all-numeric label. We don't consider
// underscores to be numeric. // underscores to be numeric.
@@ -371,13 +381,13 @@ static const InputValidity DNSNAMES_VALIDITY[] =
I("a...", false, false), I("a...", false, false),
// Punycode // Punycode
I("xn--", false, false), I("xn--", true, false),
I("xn--.", false, false), I("xn--.", true, false),
I("xn--.a", false, false), I("xn--.a", true, false),
I("a.xn--", false, false), I("a.xn--", true, false),
I("a.xn--.", false, false), I("a.xn--.", true, false),
I("a.xn--.b", false, false), I("a.xn--.b", true, false),
I("a.xn--.b", false, false), I("a.xn--.b", true, false),
I("a.xn--\0.b", false, false), I("a.xn--\0.b", false, false),
I("a.xn--a.b", true, true), I("a.xn--a.b", true, true),
I("xn--a", true, true), I("xn--a", true, true),
@@ -416,7 +426,7 @@ static const InputValidity DNSNAMES_VALIDITY[] =
I("a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z", true, true), I("a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z", true, true),
I("A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z", true, true), I("A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z", true, true),
I("0.1.2.3.4.5.6.7.8.9.a", true, true), // "a" needed to avoid numeric last label I("0.1.2.3.4.5.6.7.8.9.a", true, true), // "a" needed to avoid numeric last label
I("a-b", true, true), // hyphen (a label cannot start or end with a hyphen) I("a-b", true, true), // hyphen (presented ID labels cannot start or end with a hyphen)
// Underscores // Underscores
I("a_b", true, true), I("a_b", true, true),
@@ -469,17 +479,17 @@ static const InputValidity DNSNAMES_VALIDITY[] =
I("a.1-1", true, true), I("a.1-1", true, true),
I("a.1-a", true, true), I("a.1-a", true, true),
// labels cannot start with a hyphen // presented ID labels cannot start with a hyphen
I("-", false, false), I("-", true, false),
I("-1", false, false), I("-1", true, false),
// labels cannot end with a hyphen // presented ID labels cannot end with a hyphen
I("1-", false, false), I("1-", true, false),
I("1-.a", false, false), I("1-.a", true, false),
I("a-", false, false), I("a-", true, false),
I("a-.a", false, false), I("a-.a", true, false),
I("a.1-.a", false, false), I("a.1-.a", true, false),
I("a.a-.a", false, false), I("a.a-.a", true, false),
// labels can contain a hyphen in the middle // labels can contain a hyphen in the middle
I("a-b", true, true), I("a-b", true, true),

View File

@@ -155,4 +155,84 @@ TEST_F(Pkcs11NonAsciiTest, LoadUnload) {
} }
#endif // defined(_WIN32) #endif // defined(_WIN32)
class Pkcs11ModuleLoadFunctionTest : public ::testing::Test {
public:
Pkcs11ModuleLoadFunctionTest() { library = NULL; };
void TearDown() override {
if (library != NULL) {
PR_UnloadLibrary(library);
}
}
PRLibrary *library;
};
CK_RV NotSuppoted_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) {
return CKR_FUNCTION_NOT_SUPPORTED;
}
CK_RV SupportedButNull(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) {
ppFunctionList = NULL;
return CKR_OK;
}
TEST_F(Pkcs11ModuleLoadFunctionTest, LoadModuleWithNullFunc) {
ScopedSECMODModule userModule(
SECMOD_LoadUserModuleWithFunction("LoadFunctionModule", NULL));
EXPECT_NE(userModule, nullptr);
EXPECT_FALSE(userModule->loaded);
}
TEST_F(Pkcs11ModuleLoadFunctionTest, LoadModuleWithUnsupportedFunc) {
ScopedSECMODModule userModule(SECMOD_LoadUserModuleWithFunction(
"LoadFunctionModule", &NotSuppoted_GetFunctionList));
EXPECT_FALSE(userModule->loaded);
}
TEST_F(Pkcs11ModuleLoadFunctionTest, LoadModuleWithEmptyFunctionList) {
ScopedSECMODModule userModule(SECMOD_LoadUserModuleWithFunction(
"LoadFunctionModule", &SupportedButNull));
EXPECT_NE(userModule, nullptr);
EXPECT_FALSE(userModule->loaded);
}
TEST_F(Pkcs11ModuleLoadFunctionTest, SuccessLoadModuleWithFunction) {
library = PR_LoadLibrary(DLL_PREFIX "pkcs11testmodule." DLL_SUFFIX);
EXPECT_NE(nullptr, library);
CK_C_GetFunctionList fentry = NULL;
fentry = (CK_C_GetFunctionList)PR_FindSymbol(library, "C_GetFunctionList");
EXPECT_NE(nullptr, fentry);
ScopedSECMODModule userModule(
SECMOD_LoadUserModuleWithFunction("LoadFunctionModule", fentry));
EXPECT_NE(nullptr, userModule);
EXPECT_EQ(userModule->loaded, PR_TRUE);
/* We can find the module*/
ScopedSECMODModule module(SECMOD_FindModule("LoadFunctionModule"));
EXPECT_NE(nullptr, module);
CK_INFO info;
EXPECT_EQ(SECSuccess, PK11_GetModInfo(userModule.get(), &info));
/* See pkcs11testmodule.cpp */
CK_VERSION expectedCryptokiVersion = {2, 2};
CK_VERSION expectedLibraryVersion = {0, 0};
EXPECT_EQ(info.cryptokiVersion.minor, expectedCryptokiVersion.minor);
EXPECT_EQ(info.cryptokiVersion.major, expectedCryptokiVersion.major);
EXPECT_EQ(
0, PORT_Memcmp((char *)info.manufacturerID, "Test PKCS11 Manufacturer ID",
sizeof("Test PKCS11 Manufacturer ID") - 1));
EXPECT_EQ(info.flags, 0UL);
EXPECT_EQ(0,
PORT_Memcmp((char *)info.libraryDescription, "Test PKCS11 Library",
sizeof("Test PKCS11 Library") - 1));
EXPECT_EQ(info.libraryVersion.minor, expectedLibraryVersion.minor);
EXPECT_EQ(info.libraryVersion.major, expectedLibraryVersion.major);
EXPECT_EQ(SECSuccess, SECMOD_UnloadUserModule(userModule.get()));
}
} // namespace nss_test } // namespace nss_test

View File

@@ -25,48 +25,46 @@ namespace nss_test {
static std::unordered_set<PRInt32> gFuzzedSslOptions = { static std::unordered_set<PRInt32> gFuzzedSslOptions = {
SSL_SECURITY, // irrelevant SSL_SECURITY, // irrelevant
SSL_SOCKS, // irrelevant SSL_SOCKS, // irrelevant
SSL_REQUEST_CERTIFICATE, // tls_server_fuzz_target SSL_REQUEST_CERTIFICATE, // tls_server
SSL_HANDSHAKE_AS_CLIENT, // irrelevant SSL_HANDSHAKE_AS_CLIENT, // irrelevant
SSL_HANDSHAKE_AS_SERVER, // irrelevant SSL_HANDSHAKE_AS_SERVER, // irrelevant
SSL_ENABLE_SSL2, // obsolete SSL_ENABLE_SSL2, // obsolete
SSL_ENABLE_SSL3, // obsolete SSL_ENABLE_SSL3, // obsolete
SSL_NO_CACHE, // tls_client_fuzz_target, tls_server_fuzz_target SSL_NO_CACHE, // tls_client, tls_server
SSL_REQUIRE_CERTIFICATE, // tls_server_fuzz_target SSL_REQUIRE_CERTIFICATE, // tls_server
SSL_ENABLE_FDX, SSL_ENABLE_FDX,
SSL_V2_COMPATIBLE_HELLO, // obsolete SSL_V2_COMPATIBLE_HELLO, // obsolete
SSL_ENABLE_TLS, // obsolete SSL_ENABLE_TLS, // obsolete
SSL_ROLLBACK_DETECTION, SSL_ROLLBACK_DETECTION,
SSL_NO_STEP_DOWN, // unsupported SSL_NO_STEP_DOWN, // unsupported
SSL_BYPASS_PKCS11, // unsupported SSL_BYPASS_PKCS11, // unsupported
SSL_NO_LOCKS, // tls_client_fuzz_target. tls_server_fuzz_target SSL_NO_LOCKS, // tls_client, tls_server
SSL_ENABLE_SESSION_TICKETS, // tls_client_fuzz_target, SSL_ENABLE_SESSION_TICKETS, // tls_client, tls_server
// tls_server_fuzz_target SSL_ENABLE_DEFLATE, // tls_client, tls_server
SSL_ENABLE_DEFLATE, // tls_client_fuzz_target, tls_server_fuzz_target
SSL_ENABLE_RENEGOTIATION, SSL_ENABLE_RENEGOTIATION,
SSL_REQUIRE_SAFE_NEGOTIATION, // tls_client_fuzz_target, SSL_REQUIRE_SAFE_NEGOTIATION, // tls_client, tls_server
// tls_server_fuzz_target SSL_ENABLE_FALSE_START, // tls_client
SSL_ENABLE_FALSE_START, // tls_client_fuzz_target SSL_CBC_RANDOM_IV, // tls_client, tls_server
SSL_CBC_RANDOM_IV, // tls_client_fuzz_target, tls_server_fuzz_target SSL_ENABLE_OCSP_STAPLING, // tls_client
SSL_ENABLE_OCSP_STAPLING, // tls_client_fuzz_target SSL_ENABLE_NPN, // defunct
SSL_ENABLE_NPN, // defunct SSL_ENABLE_ALPN, // tls_client, tls_server
SSL_ENABLE_ALPN, // tls_client_fuzz_target, tls_server_fuzz_target
SSL_REUSE_SERVER_ECDHE_KEY, SSL_REUSE_SERVER_ECDHE_KEY,
SSL_ENABLE_FALLBACK_SCSV, // tls_client_fuzz_target, SSL_ENABLE_FALLBACK_SCSV, // tls_client, tls_server
// tls_server_fuzz_target
SSL_ENABLE_SERVER_DHE, SSL_ENABLE_SERVER_DHE,
SSL_ENABLE_EXTENDED_MASTER_SECRET, // tls_client_fuzz_target, SSL_ENABLE_EXTENDED_MASTER_SECRET, // tls_client, tls_server
// tls_server_fuzz_target
SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
SSL_REQUIRE_DH_NAMED_GROUPS, // tls_client_fuzz_target SSL_REQUIRE_DH_NAMED_GROUPS, // tls_client
SSL_ENABLE_0RTT_DATA, // tls_client_fuzz_target, tls_server_fuzz_target SSL_ENABLE_0RTT_DATA, // tls_client, tls_server
SSL_RECORD_SIZE_LIMIT, SSL_RECORD_SIZE_LIMIT,
SSL_ENABLE_TLS13_COMPAT_MODE, // tls_client_fuzz_target SSL_ENABLE_TLS13_COMPAT_MODE, // tls_client
SSL_ENABLE_DTLS_SHORT_HEADER, SSL_ENABLE_HELLO_DOWNGRADE_CHECK, SSL_ENABLE_DTLS_SHORT_HEADER, // tls_client, tls_server
SSL_ENABLE_HELLO_DOWNGRADE_CHECK,
SSL_ENABLE_V2_COMPATIBLE_HELLO, SSL_ENABLE_V2_COMPATIBLE_HELLO,
SSL_ENABLE_POST_HANDSHAKE_AUTH, // tls_client_fuzz_target SSL_ENABLE_POST_HANDSHAKE_AUTH, // tls_client
SSL_ENABLE_DELEGATED_CREDENTIALS, SSL_SUPPRESS_END_OF_EARLY_DATA, SSL_ENABLE_DELEGATED_CREDENTIALS, // tls_client, tls_server
SSL_ENABLE_GREASE, // tls_client_fuzz_target, tls_server_fuzz_target SSL_SUPPRESS_END_OF_EARLY_DATA,
SSL_ENABLE_CH_EXTENSION_PERMUTATION, // tls_client_fuzz_target SSL_ENABLE_GREASE, // tls_client, tls_server
SSL_ENABLE_CH_EXTENSION_PERMUTATION, // tls_client
}; };
const uint8_t kShortEmptyFinished[8] = {0}; const uint8_t kShortEmptyFinished[8] = {0};

View File

@@ -8,9 +8,14 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <fstream>
#include <iostream> #include <iostream>
#include <iterator>
#include <memory> #include <memory>
#include <sstream>
#include <sys/stat.h>
#include "blapi.h"
#include "prerror.h" #include "prerror.h"
#include "prlog.h" #include "prlog.h"
#include "prthread.h" #include "prthread.h"
@@ -25,6 +30,45 @@ namespace nss_test {
if (g_ssl_gtest_verbose) LOG(a); \ if (g_ssl_gtest_verbose) LOG(a); \
} while (false) } while (false)
DummyPrSocket::~DummyPrSocket() {
#ifdef GTESTS_CORPUS
if (name_ != "client" && name_ != "server") {
return;
}
assert(variant_ == ssl_variant_stream || variant_ == ssl_variant_datagram);
assert(name_ == "client" || name_ == "server");
// We don't care if they already exist, just make sure they do at all.
mkdir("dtls-client-corpus", 0775);
mkdir("dtls-server-corpus", 0775);
mkdir("tls-client-corpus", 0775);
mkdir("tls-server-corpus", 0775);
std::stringstream filepath;
filepath << (variant_ == ssl_variant_stream ? "tls" : "dtls") << "-" << name_
<< "-corpus/";
unsigned char digest[20];
SHA1_HashBuf(digest, receivedData_.data(), receivedData_.size());
for (unsigned long i = 0; i < sizeof(digest); ++i) {
filepath << std::hex << std::setfill('0') << std::setw(2) << (int)digest[i];
}
std::ofstream file;
file.open(filepath.str(), std::ios::out | std::ofstream::binary);
if (file.fail()) {
std::cerr << "Failed to open file: " << filepath.str() << "\n";
abort();
}
std::copy(receivedData_.begin(), receivedData_.end(),
std::ostreambuf_iterator<char>(file));
#endif // GTESTS_CORPUS
}
PRDescIdentity DummyPrSocket::LayerId() { PRDescIdentity DummyPrSocket::LayerId() {
static PRDescIdentity id = PR_GetUniqueIdentity("dummysocket"); static PRDescIdentity id = PR_GetUniqueIdentity("dummysocket");
return id; return id;
@@ -49,6 +93,11 @@ void DummyPrSocket::Reset() {
} }
void DummyPrSocket::PacketReceived(const DataBuffer &packet) { void DummyPrSocket::PacketReceived(const DataBuffer &packet) {
#ifdef GTESTS_CORPUS
receivedData_.reserve(receivedData_.size() + packet.len());
std::copy(packet.data(), packet.data() + packet.len(),
std::back_inserter(receivedData_));
#endif // GTESTS_CORPUS
input_.push(Packet(packet)); input_.push(Packet(packet));
} }

View File

@@ -67,8 +67,9 @@ class DummyPrSocket : public DummyIOLayerMethods {
peer_(), peer_(),
input_(), input_(),
filter_(nullptr), filter_(nullptr),
write_error_(0) {} write_error_(0),
virtual ~DummyPrSocket() {} receivedData_() {}
virtual ~DummyPrSocket();
static PRDescIdentity LayerId(); static PRDescIdentity LayerId();
@@ -117,6 +118,8 @@ class DummyPrSocket : public DummyIOLayerMethods {
std::queue<Packet> input_; std::queue<Packet> input_;
std::shared_ptr<PacketFilter> filter_; std::shared_ptr<PacketFilter> filter_;
PRErrorCode write_error_; PRErrorCode write_error_;
std::vector<uint8_t> receivedData_;
}; };
// Marker interface. // Marker interface.

View File

@@ -577,9 +577,11 @@ get_token_objects_for_cache(
} else { } else {
PRUint32 j; PRUint32 j;
for (j = 0; j < i; j++) { for (j = 0; j < i; j++) {
/* Any token references that were removed in successful loop iterations /* Objects that were successfully added to the cache do not own a
* need to be restored before we call nssCryptokiObjectArray_Destroy */ * token reference (they share a reference with the cache itself).
nssToken_AddRef(cache->objects[objectType][j]->object->token); * Nulling out the pointer here prevents the token's refcount
* from being decremented in nssCryptokiObject_Destroy */
cache->objects[objectType][j]->object->token = NULL;
nssArena_Destroy(cache->objects[objectType][j]->arena); nssArena_Destroy(cache->objects[objectType][j]->arena);
} }
nss_ZFreeIf(cache->objects[objectType]); nss_ZFreeIf(cache->objects[objectType]);

View File

@@ -512,7 +512,7 @@ AESKeyWrap_EncryptKWP(AESKeyWrapContext *cx, unsigned char *output,
PORT_Memcpy(iv + AES_KEY_WRAP_BLOCK_SIZE, input, inputLen); PORT_Memcpy(iv + AES_KEY_WRAP_BLOCK_SIZE, input, inputLen);
rv = AES_Encrypt(&cx->aescx, output, pOutputLen, maxOutputLen, iv, rv = AES_Encrypt(&cx->aescx, output, pOutputLen, maxOutputLen, iv,
outLen); outLen);
PORT_Memset(iv, 0, sizeof(iv)); PORT_SafeZero(iv, sizeof(iv));
return rv; return rv;
} }
@@ -528,7 +528,7 @@ AESKeyWrap_EncryptKWP(AESKeyWrapContext *cx, unsigned char *output,
PORT_ZFree(newBuf, paddedInputLen); PORT_ZFree(newBuf, paddedInputLen);
/* a little overkill, we only need to clear out the length, but this /* a little overkill, we only need to clear out the length, but this
* is easier to verify we got it all */ * is easier to verify we got it all */
PORT_Memset(iv, 0, sizeof(iv)); PORT_SafeZero(iv, sizeof(iv));
return rv; return rv;
} }
@@ -631,12 +631,12 @@ AESKeyWrap_DecryptKWP(AESKeyWrapContext *cx, unsigned char *output,
loser: loser:
/* if we failed, make sure we don't return any data to the user */ /* if we failed, make sure we don't return any data to the user */
if ((rv != SECSuccess) && (output == newBuf)) { if ((rv != SECSuccess) && (output == newBuf)) {
PORT_Memset(newBuf, 0, paddedLen); PORT_SafeZero(newBuf, paddedLen);
} }
/* clear out CSP sensitive data from the heap and stack */ /* clear out CSP sensitive data from the heap and stack */
if (allocBuf) { if (allocBuf) {
PORT_ZFree(allocBuf, paddedLen); PORT_ZFree(allocBuf, paddedLen);
} }
PORT_Memset(iv, 0, sizeof(iv)); PORT_SafeZero(iv, sizeof(iv));
return rv; return rv;
} }

View File

@@ -113,10 +113,10 @@ PRBool ppc_crypto_support();
#ifdef NSS_FIPS_DISABLED #ifdef NSS_FIPS_DISABLED
#define BLAPI_CLEAR_STACK(stack_size) #define BLAPI_CLEAR_STACK(stack_size)
#else #else
#define BLAPI_CLEAR_STACK(stack_size) \ #define BLAPI_CLEAR_STACK(stack_size) \
{ \ { \
volatile char _stkclr[stack_size]; \ volatile char _stkclr[stack_size]; \
PORT_Memset((void *)&_stkclr[0], 0, stack_size); \ PORT_SafeZero((void *)&_stkclr[0], stack_size); \
} }
#endif #endif

View File

@@ -90,4 +90,8 @@ ifeq ($(OS_ARCH), Darwin)
EXTRA_SHARED_LIBS += -dylib_file @executable_path/libplc4.dylib:$(DIST)/lib/libplc4.dylib -dylib_file @executable_path/libplds4.dylib:$(DIST)/lib/libplds4.dylib EXTRA_SHARED_LIBS += -dylib_file @executable_path/libplc4.dylib:$(DIST)/lib/libplc4.dylib -dylib_file @executable_path/libplds4.dylib:$(DIST)/lib/libplds4.dylib
endif endif
ifdef NSS_FIPS_140_3
DEFINES += -DNSS_FIPS_140_3
endif
endif endif

View File

@@ -135,7 +135,7 @@ prng_Hash_df(PRUint8 *requested_bytes, unsigned int no_of_bytes_to_return,
unsigned int hash_return_len; unsigned int hash_return_len;
SHA256_Begin(&ctx); SHA256_Begin(&ctx);
SHA256_Update(&ctx, &counter, 1); SHA256_Update(&ctx, &counter, 1);
SHA256_Update(&ctx, (unsigned char *)&tmp, sizeof tmp); SHA256_Update(&ctx, (unsigned char *)&tmp, sizeof(tmp));
SHA256_Update(&ctx, input_string_1, input_string_1_len); SHA256_Update(&ctx, input_string_1, input_string_1_len);
if (input_string_2) { if (input_string_2) {
SHA256_Update(&ctx, input_string_2, input_string_2_len); SHA256_Update(&ctx, input_string_2, input_string_2_len);
@@ -168,7 +168,8 @@ prng_instantiate(RNGContext *rng, const PRUint8 *bytes, unsigned int len)
} }
prng_Hash_df(V(rng), VSize(rng), bytes, len, NULL, 0); prng_Hash_df(V(rng), VSize(rng), bytes, len, NULL, 0);
rng->V_type = prngCGenerateType; rng->V_type = prngCGenerateType;
prng_Hash_df(rng->C, sizeof rng->C, rng->V_Data, sizeof rng->V_Data, NULL, 0); prng_Hash_df(rng->C, sizeof(rng->C), rng->V_Data, sizeof(rng->V_Data),
NULL, 0);
PRNG_RESET_RESEED_COUNT(rng) PRNG_RESET_RESEED_COUNT(rng)
return SECSuccess; return SECSuccess;
} }
@@ -197,7 +198,7 @@ prng_initEntropy(void)
SHA256_Update(&ctx, block, sizeof(block)); SHA256_Update(&ctx, block, sizeof(block));
SHA256_End(&ctx, globalrng->previousEntropyHash, NULL, SHA256_End(&ctx, globalrng->previousEntropyHash, NULL,
sizeof(globalrng->previousEntropyHash)); sizeof(globalrng->previousEntropyHash));
PORT_Memset(block, 0, sizeof(block)); PORT_SafeZero(block, sizeof(block));
SHA256_DestroyContext(&ctx, PR_FALSE); SHA256_DestroyContext(&ctx, PR_FALSE);
return PR_SUCCESS; return PR_SUCCESS;
} }
@@ -246,8 +247,8 @@ prng_getEntropy(PRUint8 *buffer, size_t requestLength)
} }
out: out:
PORT_Memset(hash, 0, sizeof hash); PORT_SafeZero(hash, sizeof(hash));
PORT_Memset(block, 0, sizeof block); PORT_SafeZero(block, sizeof(block));
return rv; return rv;
} }
@@ -262,14 +263,14 @@ static SECStatus
prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len, prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len,
const PRUint8 *additional_input, unsigned int additional_input_len) const PRUint8 *additional_input, unsigned int additional_input_len)
{ {
PRUint8 noiseData[(sizeof rng->V_Data) + PRNG_SEEDLEN]; PRUint8 noiseData[(sizeof(rng->V_Data)) + PRNG_SEEDLEN];
PRUint8 *noise = &noiseData[0]; PRUint8 *noise = &noiseData[0];
SECStatus rv; SECStatus rv;
/* if entropy wasn't supplied, fetch it. (normal operation case) */ /* if entropy wasn't supplied, fetch it. (normal operation case) */
if (entropy == NULL) { if (entropy == NULL) {
entropy_len = PRNG_SEEDLEN; entropy_len = PRNG_SEEDLEN;
rv = prng_getEntropy(&noiseData[sizeof rng->V_Data], entropy_len); rv = prng_getEntropy(&noiseData[sizeof(rng->V_Data)], entropy_len);
if (rv != SECSuccess) { if (rv != SECSuccess) {
return SECFailure; /* error is already set */ return SECFailure; /* error is already set */
} }
@@ -277,12 +278,12 @@ prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len,
/* NOTE: this code is only available for testing, not to applications */ /* NOTE: this code is only available for testing, not to applications */
/* if entropy was too big for the stack variable, get it from malloc */ /* if entropy was too big for the stack variable, get it from malloc */
if (entropy_len > PRNG_SEEDLEN) { if (entropy_len > PRNG_SEEDLEN) {
noise = PORT_Alloc(entropy_len + (sizeof rng->V_Data)); noise = PORT_Alloc(entropy_len + (sizeof(rng->V_Data)));
if (noise == NULL) { if (noise == NULL) {
return SECFailure; return SECFailure;
} }
} }
PORT_Memcpy(&noise[sizeof rng->V_Data], entropy, entropy_len); PORT_Memcpy(&noise[sizeof(rng->V_Data)], entropy, entropy_len);
} }
if (entropy_len < 256 / PR_BITS_PER_BYTE) { if (entropy_len < 256 / PR_BITS_PER_BYTE) {
@@ -292,13 +293,14 @@ prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len,
} }
rng->V_type = prngReseedType; rng->V_type = prngReseedType;
PORT_Memcpy(noise, rng->V_Data, sizeof rng->V_Data); PORT_Memcpy(noise, rng->V_Data, sizeof(rng->V_Data));
prng_Hash_df(V(rng), VSize(rng), noise, (sizeof rng->V_Data) + entropy_len, prng_Hash_df(V(rng), VSize(rng), noise, (sizeof(rng->V_Data)) + entropy_len,
additional_input, additional_input_len); additional_input, additional_input_len);
/* clear potential CSP */ /* clear potential CSP */
PORT_Memset(noise, 0, (sizeof rng->V_Data) + entropy_len); PORT_Memset(noise, 0, (sizeof(rng->V_Data)) + entropy_len);
rng->V_type = prngCGenerateType; rng->V_type = prngCGenerateType;
prng_Hash_df(rng->C, sizeof rng->C, rng->V_Data, sizeof rng->V_Data, NULL, 0); prng_Hash_df(rng->C, sizeof(rng->C), rng->V_Data, sizeof(rng->V_Data),
NULL, 0);
PRNG_RESET_RESEED_COUNT(rng) PRNG_RESET_RESEED_COUNT(rng)
if (noise != &noiseData[0]) { if (noise != &noiseData[0]) {
@@ -379,7 +381,7 @@ prng_Hashgen(RNGContext *rng, PRUint8 *returned_bytes,
unsigned int carry; unsigned int carry;
SHA256_Begin(&ctx); SHA256_Begin(&ctx);
SHA256_Update(&ctx, data, sizeof data); SHA256_Update(&ctx, data, sizeof(data));
SHA256_End(&ctx, thisHash, &len, SHA256_LENGTH); SHA256_End(&ctx, thisHash, &len, SHA256_LENGTH);
if (no_of_returned_bytes < SHA256_LENGTH) { if (no_of_returned_bytes < SHA256_LENGTH) {
len = no_of_returned_bytes; len = no_of_returned_bytes;
@@ -390,11 +392,11 @@ prng_Hashgen(RNGContext *rng, PRUint8 *returned_bytes,
/* The carry parameter is a bool (increment or not). /* The carry parameter is a bool (increment or not).
* This increments data if no_of_returned_bytes is not zero */ * This increments data if no_of_returned_bytes is not zero */
carry = no_of_returned_bytes; carry = no_of_returned_bytes;
PRNG_ADD_CARRY_ONLY(data, (sizeof data) - 1, carry); PRNG_ADD_CARRY_ONLY(data, (sizeof(data)) - 1, carry);
SHA256_DestroyContext(&ctx, PR_FALSE); SHA256_DestroyContext(&ctx, PR_FALSE);
} }
PORT_Memset(data, 0, sizeof data); PORT_SafeZero(data, sizeof(data));
PORT_Memset(thisHash, 0, sizeof thisHash); PORT_SafeZero(thisHash, sizeof(thisHash));
} }
/* /*
@@ -429,11 +431,11 @@ prng_generateNewBytes(RNGContext *rng,
#define w H #define w H
rng->V_type = prngAdditionalDataType; rng->V_type = prngAdditionalDataType;
SHA256_Begin(&ctx); SHA256_Begin(&ctx);
SHA256_Update(&ctx, rng->V_Data, sizeof rng->V_Data); SHA256_Update(&ctx, rng->V_Data, sizeof(rng->V_Data));
SHA256_Update(&ctx, additional_input, additional_input_len); SHA256_Update(&ctx, additional_input, additional_input_len);
SHA256_End(&ctx, w, NULL, sizeof w); SHA256_End(&ctx, w, NULL, sizeof(w));
PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), w, sizeof w, carry) PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), w, sizeof(w), carry)
PORT_Memset(w, 0, sizeof w); PORT_Memset(w, 0, sizeof(w));
SHA256_DestroyContext(&ctx, PR_FALSE); SHA256_DestroyContext(&ctx, PR_FALSE);
#undef w #undef w
} }
@@ -446,16 +448,16 @@ prng_generateNewBytes(RNGContext *rng,
} }
/* advance our internal state... */ /* advance our internal state... */
rng->V_type = prngGenerateByteType; rng->V_type = prngGenerateByteType;
SHA256_HashBuf(H, rng->V_Data, sizeof rng->V_Data); SHA256_HashBuf(H, rng->V_Data, sizeof(rng->V_Data));
PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), H, sizeof H, carry) PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), H, sizeof(H), carry)
PRNG_ADD_BITS(V(rng), VSize(rng), rng->C, sizeof rng->C, carry); PRNG_ADD_BITS(V(rng), VSize(rng), rng->C, sizeof(rng->C), carry);
PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), rng->reseed_counter, PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), rng->reseed_counter,
sizeof rng->reseed_counter, carry) sizeof(rng->reseed_counter), carry)
carry = 1; carry = 1;
PRNG_ADD_CARRY_ONLY(rng->reseed_counter, (sizeof rng->reseed_counter) - 1, carry); PRNG_ADD_CARRY_ONLY(rng->reseed_counter, (sizeof(rng->reseed_counter)) - 1, carry);
/* if the prng failed, don't return any output, signal softoken */ /* if the prng failed, don't return any output, signal softoken */
PORT_Memset(H, 0, sizeof H); PORT_SafeZero(H, sizeof(H));
if (!rng->isValid) { if (!rng->isValid) {
PORT_Memset(returned_bytes, 0, no_of_returned_bytes); PORT_Memset(returned_bytes, 0, no_of_returned_bytes);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
@@ -491,17 +493,17 @@ rng_init(void)
} }
/* Try to get some seed data for the RNG */ /* Try to get some seed data for the RNG */
rv = prng_getEntropy(bytes, sizeof bytes); rv = prng_getEntropy(bytes, sizeof(bytes));
if (rv == SECSuccess) { if (rv == SECSuccess) {
/* if this is our first call, instantiate, otherwise reseed /* if this is our first call, instantiate, otherwise reseed
* prng_instantiate gets a new clean state, we want to mix * prng_instantiate gets a new clean state, we want to mix
* any previous entropy we may have collected */ * any previous entropy we may have collected */
if (V(globalrng)[0] == 0) { if (V(globalrng)[0] == 0) {
rv = prng_instantiate(globalrng, bytes, sizeof bytes); rv = prng_instantiate(globalrng, bytes, sizeof(bytes));
} else { } else {
rv = prng_reseed_test(globalrng, bytes, sizeof bytes, NULL, 0); rv = prng_reseed_test(globalrng, bytes, sizeof(bytes), NULL, 0);
} }
memset(bytes, 0, sizeof bytes); memset(bytes, 0, sizeof(bytes));
} else { } else {
PZ_DestroyLock(globalrng->lock); PZ_DestroyLock(globalrng->lock);
globalrng->lock = NULL; globalrng->lock = NULL;
@@ -532,20 +534,20 @@ rng_init(void)
static void static void
prng_freeRNGContext(RNGContext *rng) prng_freeRNGContext(RNGContext *rng)
{ {
PRUint8 inputhash[VSize(rng) + (sizeof rng->C)]; PRUint8 inputhash[VSize(rng) + (sizeof(rng->C))];
/* destroy context lock */ /* destroy context lock */
SKIP_AFTER_FORK(PZ_DestroyLock(globalrng->lock)); SKIP_AFTER_FORK(PZ_DestroyLock(globalrng->lock));
/* zero global RNG context except for C & V to preserve entropy */ /* zero global RNG context except for C & V to preserve entropy */
prng_Hash_df(inputhash, sizeof rng->C, rng->C, sizeof rng->C, NULL, 0); prng_Hash_df(inputhash, sizeof(rng->C), rng->C, sizeof(rng->C), NULL, 0);
prng_Hash_df(&inputhash[sizeof rng->C], VSize(rng), V(rng), VSize(rng), prng_Hash_df(&inputhash[sizeof(rng->C)], VSize(rng), V(rng), VSize(rng),
NULL, 0); NULL, 0);
memset(rng, 0, sizeof *rng); memset(rng, 0, sizeof(*rng));
memcpy(rng->C, inputhash, sizeof rng->C); memcpy(rng->C, inputhash, sizeof(rng->C));
memcpy(V(rng), &inputhash[sizeof rng->C], VSize(rng)); memcpy(V(rng), &inputhash[sizeof(rng->C)], VSize(rng));
memset(inputhash, 0, sizeof inputhash); memset(inputhash, 0, sizeof(inputhash));
} }
/* /*
@@ -621,7 +623,7 @@ RNG_RandomUpdate(const void *data, size_t bytes)
if (bytes > sizeof(globalrng->additionalDataCache)) { if (bytes > sizeof(globalrng->additionalDataCache)) {
rv = prng_reseed_test(globalrng, NULL, 0, data, (unsigned int)bytes); rv = prng_reseed_test(globalrng, NULL, 0, data, (unsigned int)bytes);
/* if we aren't going to fill or overflow the buffer, just cache it */ /* if we aren't going to fill or overflow the buffer, just cache it */
} else if (bytes < ((sizeof globalrng->additionalDataCache) - globalrng->additionalAvail)) { } else if (bytes < ((sizeof(globalrng->additionalDataCache)) - globalrng->additionalAvail)) {
PORT_Memcpy(globalrng->additionalDataCache + globalrng->additionalAvail, PORT_Memcpy(globalrng->additionalDataCache + globalrng->additionalAvail,
data, bytes); data, bytes);
globalrng->additionalAvail += (PRUint32)bytes; globalrng->additionalAvail += (PRUint32)bytes;
@@ -632,7 +634,7 @@ RNG_RandomUpdate(const void *data, size_t bytes)
* remainder. We know the remainder will fit in the buffer because * remainder. We know the remainder will fit in the buffer because
* we already handled the case where bytes > the size of the buffer. * we already handled the case where bytes > the size of the buffer.
*/ */
size_t bufRemain = (sizeof globalrng->additionalDataCache) - globalrng->additionalAvail; size_t bufRemain = (sizeof(globalrng->additionalDataCache)) - globalrng->additionalAvail;
/* fill the rest of the buffer */ /* fill the rest of the buffer */
if (bufRemain) { if (bufRemain) {
PORT_Memcpy(globalrng->additionalDataCache + globalrng->additionalAvail, PORT_Memcpy(globalrng->additionalDataCache + globalrng->additionalAvail,
@@ -643,7 +645,7 @@ RNG_RandomUpdate(const void *data, size_t bytes)
/* reseed from buffer */ /* reseed from buffer */
rv = prng_reseed_test(globalrng, NULL, 0, rv = prng_reseed_test(globalrng, NULL, 0,
globalrng->additionalDataCache, globalrng->additionalDataCache,
sizeof globalrng->additionalDataCache); sizeof(globalrng->additionalDataCache));
/* copy the rest into the cache */ /* copy the rest into the cache */
PORT_Memcpy(globalrng->additionalDataCache, data, bytes); PORT_Memcpy(globalrng->additionalDataCache, data, bytes);
@@ -693,21 +695,21 @@ prng_GenerateGlobalRandomBytes(RNGContext *rng,
* see if we have enough bytes to fulfill the request. * see if we have enough bytes to fulfill the request.
*/ */
if (len <= rng->dataAvail) { if (len <= rng->dataAvail) {
memcpy(output, rng->data + ((sizeof rng->data) - rng->dataAvail), len); memcpy(output, rng->data + ((sizeof(rng->data)) - rng->dataAvail), len);
memset(rng->data + ((sizeof rng->data) - rng->dataAvail), 0, len); memset(rng->data + ((sizeof(rng->data)) - rng->dataAvail), 0, len);
rng->dataAvail -= len; rng->dataAvail -= len;
rv = SECSuccess; rv = SECSuccess;
/* if we are asking for a small number of bytes, cache the rest of /* if we are asking for a small number of bytes, cache the rest of
* the bytes */ * the bytes */
} else if (len < sizeof rng->data) { } else if (len < sizeof(rng->data)) {
rv = prng_generateNewBytes(rng, rng->data, sizeof rng->data, rv = prng_generateNewBytes(rng, rng->data, sizeof(rng->data),
rng->additionalAvail ? rng->additionalDataCache : NULL, rng->additionalAvail ? rng->additionalDataCache : NULL,
rng->additionalAvail); rng->additionalAvail);
rng->additionalAvail = 0; rng->additionalAvail = 0;
if (rv == SECSuccess) { if (rv == SECSuccess) {
memcpy(output, rng->data, len); memcpy(output, rng->data, len);
memset(rng->data, 0, len); memset(rng->data, 0, len);
rng->dataAvail = (sizeof rng->data) - len; rng->dataAvail = (sizeof(rng->data)) - len;
} }
/* we are asking for lots of bytes, just ask the generator to pass them */ /* we are asking for lots of bytes, just ask the generator to pass them */
} else { } else {
@@ -858,7 +860,7 @@ PRNGTEST_Uninstantiate()
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure; return SECFailure;
} }
PORT_Memset(&testContext, 0, sizeof testContext); PORT_Memset(&testContext, 0, sizeof(testContext));
return SECSuccess; return SECSuccess;
} }
@@ -943,31 +945,31 @@ PRNGTEST_RunHealthTests()
/********************************************/ /********************************************/
/* Generate random bytes with a known seed. */ /* Generate random bytes with a known seed. */
/********************************************/ /********************************************/
rng_status = PRNGTEST_Instantiate(entropy, sizeof entropy, rng_status = PRNGTEST_Instantiate(entropy, sizeof(entropy),
NULL, 0, NULL, 0); NULL, 0, NULL, 0);
if (rng_status != SECSuccess) { if (rng_status != SECSuccess) {
/* Error set by PRNGTEST_Instantiate */ /* Error set by PRNGTEST_Instantiate */
return SECFailure; return SECFailure;
} }
rng_status = PRNGTEST_Generate(result, sizeof rng_known_result, NULL, 0); rng_status = PRNGTEST_Generate(result, sizeof(rng_known_result), NULL, 0);
if ((rng_status != SECSuccess) || if ((rng_status != SECSuccess) ||
(PORT_Memcmp(result, rng_known_result, (PORT_Memcmp(result, rng_known_result,
sizeof rng_known_result) != 0)) { sizeof(rng_known_result)) != 0)) {
PRNGTEST_Uninstantiate(); PRNGTEST_Uninstantiate();
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure; return SECFailure;
} }
rng_status = PRNGTEST_Reseed(reseed_entropy, sizeof reseed_entropy, rng_status = PRNGTEST_Reseed(reseed_entropy, sizeof(reseed_entropy),
additional_input, sizeof additional_input); additional_input, sizeof(additional_input));
if (rng_status != SECSuccess) { if (rng_status != SECSuccess) {
/* Error set by PRNG_Reseed */ /* Error set by PRNG_Reseed */
PRNGTEST_Uninstantiate(); PRNGTEST_Uninstantiate();
return SECFailure; return SECFailure;
} }
rng_status = PRNGTEST_Generate(result, sizeof rng_reseed_result, NULL, 0); rng_status = PRNGTEST_Generate(result, sizeof(rng_reseed_result), NULL, 0);
if ((rng_status != SECSuccess) || if ((rng_status != SECSuccess) ||
(PORT_Memcmp(result, rng_reseed_result, (PORT_Memcmp(result, rng_reseed_result,
sizeof rng_reseed_result) != 0)) { sizeof(rng_reseed_result)) != 0)) {
PRNGTEST_Uninstantiate(); PRNGTEST_Uninstantiate();
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure; return SECFailure;
@@ -981,13 +983,13 @@ PRNGTEST_RunHealthTests()
return SECFailure; return SECFailure;
} }
/* This generate should now reseed */ /* This generate should now reseed */
rng_status = PRNGTEST_Generate(result, sizeof rng_reseed_result, NULL, 0); rng_status = PRNGTEST_Generate(result, sizeof(rng_reseed_result), NULL, 0);
if ((rng_status != SECSuccess) || if ((rng_status != SECSuccess) ||
/* NOTE we fail if the result is equal to the no_reseed_result. /* NOTE we fail if the result is equal to the no_reseed_result.
* no_reseed_result is the value we would have gotten if we didn't * no_reseed_result is the value we would have gotten if we didn't
* do an automatic reseed in PRNGTEST_Generate */ * do an automatic reseed in PRNGTEST_Generate */
(PORT_Memcmp(result, rng_no_reseed_result, (PORT_Memcmp(result, rng_no_reseed_result,
sizeof rng_no_reseed_result) == 0)) { sizeof(rng_no_reseed_result)) == 0)) {
PRNGTEST_Uninstantiate(); PRNGTEST_Uninstantiate();
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure; return SECFailure;

View File

@@ -471,7 +471,7 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
err = MP_OKAY; err = MP_OKAY;
signature->len = dsa_signature_len; signature->len = dsa_signature_len;
cleanup: cleanup:
PORT_Memset(localDigestData, 0, DSA_MAX_SUBPRIME_LEN); PORT_SafeZero(localDigestData, DSA_MAX_SUBPRIME_LEN);
mp_clear(&p); mp_clear(&p);
mp_clear(&q); mp_clear(&q);
mp_clear(&g); mp_clear(&g);
@@ -532,7 +532,7 @@ DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest)
rv = dsa_SignDigest(key, signature, digest, kSeed); rv = dsa_SignDigest(key, signature, digest, kSeed);
} while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM && } while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM &&
--retries > 0); --retries > 0);
PORT_Memset(kSeed, 0, sizeof kSeed); PORT_SafeZero(kSeed, sizeof kSeed);
return rv; return rv;
} }
@@ -673,7 +673,7 @@ DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
verified = SECSuccess; /* Signature verified. */ verified = SECSuccess; /* Signature verified. */
} }
cleanup: cleanup:
PORT_Memset(localDigestData, 0, sizeof localDigestData); PORT_SafeZero(localDigestData, sizeof localDigestData);
mp_clear(&p); mp_clear(&p);
mp_clear(&q); mp_clear(&q);
mp_clear(&g); mp_clear(&g);

View File

@@ -480,7 +480,7 @@ gcmHash_Final(gcmHashContext *ghash, unsigned char *outbuf,
rv = SECSuccess; rv = SECSuccess;
cleanup: cleanup:
PORT_Memset(T, 0, sizeof(T)); PORT_SafeZero(T, sizeof(T));
return rv; return rv;
} }
@@ -596,15 +596,15 @@ GCM_CreateContext(void *context, freeblCipherFunc cipher,
if (rv != SECSuccess) { if (rv != SECSuccess) {
goto loser; goto loser;
} }
PORT_Memset(H, 0, AES_BLOCK_SIZE); PORT_SafeZero(H, AES_BLOCK_SIZE);
gcm->ctr_context_init = PR_TRUE; gcm->ctr_context_init = PR_TRUE;
return gcm; return gcm;
loser: loser:
PORT_Memset(H, 0, AES_BLOCK_SIZE); PORT_SafeZero(H, AES_BLOCK_SIZE);
if (ghash && ghash->mem) { if (ghash && ghash->mem) {
void *mem = ghash->mem; void *mem = ghash->mem;
PORT_Memset(ghash, 0, sizeof(gcmHashContext)); PORT_SafeZero(ghash, sizeof(gcmHashContext));
PORT_Free(mem); PORT_Free(mem);
} }
if (gcm) { if (gcm) {
@@ -682,11 +682,11 @@ gcm_InitCounter(GCMContext *gcm, const unsigned char *iv, unsigned int ivLen,
goto loser; goto loser;
} }
PORT_Memset(&ctrParams, 0, sizeof ctrParams); PORT_SafeZero(&ctrParams, sizeof ctrParams);
return SECSuccess; return SECSuccess;
loser: loser:
PORT_Memset(&ctrParams, 0, sizeof ctrParams); PORT_SafeZero(&ctrParams, sizeof ctrParams);
if (freeCtr) { if (freeCtr) {
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE); CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
} }
@@ -866,10 +866,10 @@ GCM_DecryptUpdate(GCMContext *gcm, unsigned char *outbuf,
if (NSS_SecureMemcmp(tag, intag, tagBytes) != 0) { if (NSS_SecureMemcmp(tag, intag, tagBytes) != 0) {
/* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */ /* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
PORT_SetError(SEC_ERROR_BAD_DATA); PORT_SetError(SEC_ERROR_BAD_DATA);
PORT_Memset(tag, 0, sizeof(tag)); PORT_SafeZero(tag, sizeof(tag));
return SECFailure; return SECFailure;
} }
PORT_Memset(tag, 0, sizeof(tag)); PORT_SafeZero(tag, sizeof(tag));
/* finish the decryption */ /* finish the decryption */
return CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout, return CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
inbuf, inlen, AES_BLOCK_SIZE); inbuf, inlen, AES_BLOCK_SIZE);
@@ -1159,10 +1159,10 @@ GCM_DecryptAEAD(GCMContext *gcm, unsigned char *outbuf,
/* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */ /* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE); CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
PORT_SetError(SEC_ERROR_BAD_DATA); PORT_SetError(SEC_ERROR_BAD_DATA);
PORT_Memset(tag, 0, sizeof(tag)); PORT_SafeZero(tag, sizeof(tag));
return SECFailure; return SECFailure;
} }
PORT_Memset(tag, 0, sizeof(tag)); PORT_SafeZero(tag, sizeof(tag));
/* finish the decryption */ /* finish the decryption */
rv = CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout, rv = CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
inbuf, inlen, AES_BLOCK_SIZE); inbuf, inlen, AES_BLOCK_SIZE);

View File

@@ -274,10 +274,10 @@ MAC(unsigned char *mdOut,
hashObj->end(mdState, mdOut, mdOutLen, mdOutMax); hashObj->end(mdState, mdOut, mdOutLen, mdOutMax);
hashObj->destroy(mdState, PR_TRUE); hashObj->destroy(mdState, PR_TRUE);
PORT_Memset(lengthBytes, 0, sizeof lengthBytes); PORT_SafeZero(lengthBytes, sizeof lengthBytes);
PORT_Memset(hmacPad, 0, sizeof hmacPad); PORT_SafeZero(hmacPad, sizeof hmacPad);
PORT_Memset(firstBlock, 0, sizeof firstBlock); PORT_SafeZero(firstBlock, sizeof firstBlock);
PORT_Memset(macOut, 0, sizeof macOut); PORT_SafeZero(macOut, sizeof macOut);
return SECSuccess; return SECSuccess;
} }

View File

@@ -195,7 +195,7 @@ intel_aes_gcmInitCounter(intel_AES_GCMContext *gcm,
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)); PORT_SafeZero(gcm, sizeof(intel_AES_GCMContext));
if (freeit) { if (freeit) {
PORT_Free(gcm); PORT_Free(gcm);
} }

View File

@@ -169,7 +169,7 @@ ppc_aes_gcmInitCounter(ppc_AES_GCMContext *gcm,
void void
ppc_AES_GCM_DestroyContext(ppc_AES_GCMContext *gcm, PRBool freeit) ppc_AES_GCM_DestroyContext(ppc_AES_GCMContext *gcm, PRBool freeit)
{ {
PORT_Memset(gcm, 0, sizeof(ppc_AES_GCMContext)); PORT_SafeZero(gcm, sizeof(ppc_AES_GCMContext));
if (freeit) { if (freeit) {
PORT_Free(gcm); PORT_Free(gcm);
} }

View File

@@ -703,7 +703,7 @@ cleanup:
mp_clear(&a); mp_clear(&a);
mp_clear(&z); mp_clear(&z);
mp_clear(&two_length_minus_1); mp_clear(&two_length_minus_1);
PORT_Memset(x, 0, sizeof(x)); PORT_SafeZero(x, sizeof(x));
if (err) { if (err) {
MP_TO_SEC_ERROR(err); MP_TO_SEC_ERROR(err);
rv = SECFailure; rv = SECFailure;
@@ -859,7 +859,7 @@ cleanup:
mp_clear(&c); mp_clear(&c);
mp_clear(&c0); mp_clear(&c0);
mp_clear(&one); mp_clear(&one);
PORT_Memset(x, 0, sizeof(x)); PORT_SafeZero(x, sizeof(x));
if (err) { if (err) {
MP_TO_SEC_ERROR(err); MP_TO_SEC_ERROR(err);
rv = SECFailure; rv = SECFailure;
@@ -1072,7 +1072,7 @@ makePfromQandSeed(
CHECK_MPI_OK(mp_sub_d(&c, 1, &c)); /* c -= 1 */ CHECK_MPI_OK(mp_sub_d(&c, 1, &c)); /* c -= 1 */
CHECK_MPI_OK(mp_sub(&X, &c, P)); /* P = X - c */ CHECK_MPI_OK(mp_sub(&X, &c, P)); /* P = X - c */
cleanup: cleanup:
PORT_Memset(V_j, 0, sizeof V_j); PORT_SafeZero(V_j, sizeof V_j);
mp_clear(&W); mp_clear(&W);
mp_clear(&X); mp_clear(&X);
mp_clear(&c); mp_clear(&c);
@@ -1221,7 +1221,7 @@ makeGfromIndex(HASH_HashType hashtype,
/* step 11. /* step 11.
* return valid G */ * return valid G */
cleanup: cleanup:
PORT_Memset(data, 0, sizeof(data)); PORT_SafeZero(data, sizeof(data));
if (hashcx) { if (hashcx) {
hashobj->destroy(hashcx, PR_TRUE); hashobj->destroy(hashcx, PR_TRUE);
} }

View File

@@ -1251,7 +1251,7 @@ AES_DestroyContext(AESContext *cx, PRBool freeit)
cx->worker_cx = NULL; cx->worker_cx = NULL;
cx->destroy = NULL; cx->destroy = NULL;
} }
PORT_Memset(cx, 0, sizeof(AESContext)); PORT_SafeZero(cx, sizeof(AESContext));
if (freeit) { if (freeit) {
PORT_Free(mem); PORT_Free(mem);
} else { } else {

View File

@@ -978,14 +978,14 @@ rsa_GetHMACContext(const SECHashObject *hash, RSAPrivateKey *key,
/* now create the hmac key */ /* now create the hmac key */
hmac = HMAC_Create(hash, keyHash, keyLen, PR_TRUE); hmac = HMAC_Create(hash, keyHash, keyLen, PR_TRUE);
if (hmac == NULL) { if (hmac == NULL) {
PORT_Memset(keyHash, 0, sizeof(keyHash)); PORT_SafeZero(keyHash, sizeof(keyHash));
return NULL; return NULL;
} }
HMAC_Begin(hmac); HMAC_Begin(hmac);
HMAC_Update(hmac, input, inputLen); HMAC_Update(hmac, input, inputLen);
rv = HMAC_Finish(hmac, keyHash, &keyLen, sizeof(keyHash)); rv = HMAC_Finish(hmac, keyHash, &keyLen, sizeof(keyHash));
if (rv != SECSuccess) { if (rv != SECSuccess) {
PORT_Memset(keyHash, 0, sizeof(keyHash)); PORT_SafeZero(keyHash, sizeof(keyHash));
HMAC_Destroy(hmac, PR_TRUE); HMAC_Destroy(hmac, PR_TRUE);
return NULL; return NULL;
} }
@@ -993,7 +993,7 @@ rsa_GetHMACContext(const SECHashObject *hash, RSAPrivateKey *key,
* reuse the original context allocated above so we don't * reuse the original context allocated above so we don't
* need to allocate and free another one */ * need to allocate and free another one */
rv = HMAC_ReInit(hmac, hash, keyHash, keyLen, PR_TRUE); rv = HMAC_ReInit(hmac, hash, keyHash, keyLen, PR_TRUE);
PORT_Memset(keyHash, 0, sizeof(keyHash)); PORT_SafeZero(keyHash, sizeof(keyHash));
if (rv != SECSuccess) { if (rv != SECSuccess) {
HMAC_Destroy(hmac, PR_TRUE); HMAC_Destroy(hmac, PR_TRUE);
return NULL; return NULL;
@@ -1043,7 +1043,7 @@ rsa_HMACPrf(HMACContext *hmac, const char *label, int labelLen,
return rv; return rv;
} }
PORT_Memcpy(output, hmacLast, left); PORT_Memcpy(output, hmacLast, left);
PORT_Memset(hmacLast, 0, sizeof(hmacLast)); PORT_SafeZero(hmacLast, sizeof(hmacLast));
} }
return rv; return rv;
} }
@@ -1088,7 +1088,7 @@ rsa_GetErrorLength(HMACContext *hmac, int hashLen, int maxLegalLen)
outLength = PORT_CT_SEL(PORT_CT_LT(candidate, maxLegalLen), outLength = PORT_CT_SEL(PORT_CT_LT(candidate, maxLegalLen),
candidate, outLength); candidate, outLength);
} }
PORT_Memset(out, 0, sizeof(out)); PORT_SafeZero(out, sizeof(out));
return outLength; return outLength;
} }

View File

@@ -365,7 +365,7 @@ blapi_SHVerifyDSACheck(PRFileDesc *shFD, const SECHashObject *hashObj,
/* verify the hash against the check file */ /* verify the hash against the check file */
rv = DSA_VerifyDigest(key, signature, &hash); rv = DSA_VerifyDigest(key, signature, &hash);
PORT_Memset(hashBuf, 0, sizeof hashBuf); PORT_SafeZero(hashBuf, sizeof hashBuf);
return (rv == SECSuccess) ? PR_TRUE : PR_FALSE; return (rv == SECSuccess) ? PR_TRUE : PR_FALSE;
} }
#endif #endif
@@ -427,7 +427,7 @@ blapi_SHVerifyHMACCheck(PRFileDesc *shFD, const SECHashObject *hashObj,
if (rv == SECSuccess) { if (rv == SECSuccess) {
result = SECITEM_ItemsAreEqual(signature, &hash); result = SECITEM_ItemsAreEqual(signature, &hash);
} }
PORT_Memset(hashBuf, 0, sizeof hashBuf); PORT_SafeZero(hashBuf, sizeof hashBuf);
return result; return result;
} }
@@ -451,7 +451,7 @@ blapi_SHVerifyFile(const char *shName, PRBool self, PRBool rerun)
#ifndef NSS_STRICT_INTEGRITY #ifndef NSS_STRICT_INTEGRITY
DSAPublicKey key; DSAPublicKey key;
PORT_Memset(&key, 0, sizeof(key)); PORT_SafeZero(&key, sizeof(key));
#endif #endif
/* If our integrity check was never ran or failed, fail any other /* If our integrity check was never ran or failed, fail any other
@@ -597,7 +597,7 @@ blapi_SHVerifyFile(const char *shName, PRBool self, PRBool rerun)
shFD = NULL; shFD = NULL;
loser: loser:
PORT_Memset(&header, 0, sizeof header); PORT_SafeZero(&header, sizeof header);
if (checkName != NULL) { if (checkName != NULL) {
PORT_Free(checkName); PORT_Free(checkName);
} }

View File

@@ -144,6 +144,7 @@ STUB_DECLARE(void, PORT_Free_Util, (void *ptr));
STUB_DECLARE(void, PORT_FreeArena_Util, (PLArenaPool * arena, PRBool zero)); STUB_DECLARE(void, PORT_FreeArena_Util, (PLArenaPool * arena, PRBool zero));
STUB_DECLARE(int, PORT_GetError_Util, (void)); STUB_DECLARE(int, PORT_GetError_Util, (void));
STUB_DECLARE(PLArenaPool *, PORT_NewArena_Util, (unsigned long chunksize)); STUB_DECLARE(PLArenaPool *, PORT_NewArena_Util, (unsigned long chunksize));
STUB_DECLARE(void, PORT_SafeZero, (void *p, size_t n));
STUB_DECLARE(void, PORT_SetError_Util, (int value)); STUB_DECLARE(void, PORT_SetError_Util, (int value));
STUB_DECLARE(void *, PORT_ZAlloc_Util, (size_t len)); STUB_DECLARE(void *, PORT_ZAlloc_Util, (size_t len));
STUB_DECLARE(void *, PORT_ZAllocAligned_Util, (size_t bytes, size_t alignment, void **mem)); STUB_DECLARE(void *, PORT_ZAllocAligned_Util, (size_t bytes, size_t alignment, void **mem));
@@ -488,6 +489,20 @@ PORT_GetError_stub(void)
return errno; return errno;
} }
extern void
PORT_SafeZero(void *p, size_t n)
{
STUB_SAFE_CALL2(PORT_SafeZero, p, n);
/* just use a generic call in the case where we are running
* standalone freebl */
if (p != NULL) {
volatile unsigned char *__vl = (unsigned char *)p;
size_t __nl = n;
while (__nl--)
*__vl++ = 0;
}
}
extern void extern void
PORT_SetError_stub(int value) PORT_SetError_stub(int value)
{ {

View File

@@ -27,6 +27,7 @@
#define PORT_FreeArena PORT_FreeArena_stub #define PORT_FreeArena PORT_FreeArena_stub
#define PORT_GetError PORT_GetError_stub #define PORT_GetError PORT_GetError_stub
#define PORT_NewArena PORT_NewArena_stub #define PORT_NewArena PORT_NewArena_stub
#define PORT_SaveZero PORT_SaveZero_stub
#define PORT_SetError PORT_SetError_stub #define PORT_SetError PORT_SetError_stub
#define PORT_ZAlloc PORT_ZAlloc_stub #define PORT_ZAlloc PORT_ZAlloc_stub
#define PORT_ZFree PORT_ZFree_stub #define PORT_ZFree PORT_ZFree_stub

View File

@@ -8,7 +8,9 @@
#include "seccomon.h" #include "seccomon.h"
#if defined(XP_UNIX) && defined(SEED_ONLY_DEV_URANDOM) #if defined(XP_UNIX) && defined(NSS_FIPS_140_3)
#include "unix_fips140_3.c"
#elif defined(XP_UNIX) && defined(SEED_ONLY_DEV_URANDOM)
#include "unix_urandom.c" #include "unix_urandom.c"
#elif defined(XP_UNIX) #elif defined(XP_UNIX)
#include "unix_rand.c" #include "unix_rand.c"

View File

@@ -82,8 +82,8 @@ loser:
/* clear out state so it's not left on the stack */ /* clear out state so it's not left on the stack */
if (cx) if (cx)
HMAC_Destroy(cx, PR_TRUE); HMAC_Destroy(cx, PR_TRUE);
PORT_Memset(state, 0, sizeof(state)); PORT_SafeZero(state, sizeof(state));
PORT_Memset(outbuf, 0, sizeof(outbuf)); PORT_SafeZero(outbuf, sizeof(outbuf));
return rv; return rv;
} }

View File

@@ -0,0 +1,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 <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "secerr.h"
#include "secrng.h"
#include "prprf.h"
#include <sys/random.h>
#include "prinit.h"
#ifndef GRND_RANDOM
/* if you don't have get random, you'll need to add your platform specific
* support for FIPS 104-3 compliant random seed source here */
PR_STATIC_ASSERT("You'll need to add our platform specific solution for FIPS 140-3 RNG" == NULL);
#endif
/* syscall getentropy() is limited to retrieving 256 bytes */
#define GETENTROPY_MAX_BYTES 256
void
RNG_SystemInfoForRNG(void)
{
PRUint8 bytes[SYSTEM_RNG_SEED_COUNT];
size_t numBytes = RNG_SystemRNG(bytes, SYSTEM_RNG_SEED_COUNT);
if (!numBytes) {
/* error is set */
return;
}
RNG_RandomUpdate(bytes, numBytes);
PORT_SaveZero(bytes, sizeof(bytes));
}
static unsigned int rng_grndFlags = 0;
static PRCallOnceType rng_KernelFips;
static PRStatus
rng_getKernelFips()
{
if (NSS_GetSystemFIPSEnabled()) {
rng_grndFlags = GRND_RANDOM;
}
return PR_SUCCESS;
}
size_t
RNG_SystemRNG(void *dest, size_t maxLen)
{
size_t fileBytes = 0;
unsigned char *buffer = dest;
ssize_t result;
PR_CallOnce(&rng_KernelFips, rng_getKernelFips);
while (fileBytes < maxLen) {
size_t getBytes = maxLen - fileBytes;
if (getBytes > GETENTROPY_MAX_BYTES) {
getBytes = GETENTROPY_MAX_BYTES;
}
/* FIP 140-3 requires full kernel reseeding for chained entropy sources
* so we need to use getrandom with GRND_RANDOM.
* getrandom returns -1 on failure, otherwise returns
* the number of bytes, which can be less than getBytes */
result = getrandom(buffer, getBytes, rng_grndFlags);
if (result < 0) {
break;
}
fileBytes += result;
buffer += result;
}
if (fileBytes == maxLen) { /* success */
return maxLen;
}
/* in FIPS 104-3 we don't fallback, just fail */
PORT_SetError(SEC_ERROR_NEED_RANDOM);
return 0;
}

View File

@@ -22,7 +22,7 @@ RNG_SystemInfoForRNG(void)
return; return;
} }
RNG_RandomUpdate(bytes, numBytes); RNG_RandomUpdate(bytes, numBytes);
PORT_Memset(bytes, 0, sizeof bytes); PORT_SafeZero(bytes, sizeof bytes);
} }
size_t size_t
@@ -41,6 +41,9 @@ RNG_SystemRNG(void *dest, size_t maxLen)
if (getBytes > GETENTROPY_MAX_BYTES) { if (getBytes > GETENTROPY_MAX_BYTES) {
getBytes = GETENTROPY_MAX_BYTES; getBytes = GETENTROPY_MAX_BYTES;
} }
/* get entropy returns 0 on success and always return
* getBytes on success */
result = getentropy(buffer, getBytes); result = getentropy(buffer, getBytes);
if (result == 0) { /* success */ if (result == 0) { /* success */
fileBytes += getBytes; fileBytes += getBytes;
@@ -61,7 +64,7 @@ RNG_SystemRNG(void *dest, size_t maxLen)
/* ENOSYS means the kernel doesn't support getentropy()/getrandom(). /* ENOSYS means the kernel doesn't support getentropy()/getrandom().
* Reset the number of bytes to get and fall back to /dev/urandom. */ * Reset the number of bytes to get and fall back to /dev/urandom. */
fileBytes = 0; fileBytes = 0;
#endif #endif /* platorm has getentropy */
fd = open("/dev/urandom", O_RDONLY); fd = open("/dev/urandom", O_RDONLY);
if (fd < 0) { if (fd < 0) {
PORT_SetError(SEC_ERROR_NEED_RANDOM); PORT_SetError(SEC_ERROR_NEED_RANDOM);

View File

@@ -1967,8 +1967,9 @@ IsValidDNSID(Input hostname, IDRole idRole, AllowWildcards allowWildcards)
} }
switch (b) { switch (b) {
case '-': case '-':
if (labelLength == 0) { // Only reference ID labels can start with a hyphen.
return false; // Labels must not start with a hyphen. if (labelLength == 0 && idRole != IDRole::ReferenceID) {
return false;
} }
labelIsAllNumeric = false; labelIsAllNumeric = false;
labelEndsWithHyphen = true; labelEndsWithHyphen = true;
@@ -2028,8 +2029,9 @@ IsValidDNSID(Input hostname, IDRole idRole, AllowWildcards allowWildcards)
(idRole != IDRole::NameConstraint || !isFirstByte)) { (idRole != IDRole::NameConstraint || !isFirstByte)) {
return false; return false;
} }
if (labelEndsWithHyphen) { // Only reference ID labels can end with a hyphen.
return false; // Labels must not end with a hyphen. if (labelEndsWithHyphen && idRole != IDRole::ReferenceID) {
return false;
} }
labelLength = 0; labelLength = 0;
break; break;
@@ -2046,8 +2048,9 @@ IsValidDNSID(Input hostname, IDRole idRole, AllowWildcards allowWildcards)
return false; return false;
} }
if (labelEndsWithHyphen) { // Only reference ID labels can end with a hyphen.
return false; // Labels must not end with a hyphen. if (labelEndsWithHyphen && idRole != IDRole::ReferenceID) {
return false;
} }
if (labelIsAllNumeric) { if (labelIsAllNumeric) {

View File

@@ -1270,3 +1270,9 @@ SECKEY_PrivateKeyStrengthInBits;
;+ local: ;+ local:
;+ *; ;+ *;
;+}; ;+};
;+NSS_3.107 { # NSS 3.107 release
;+ global:
SECMOD_LoadUserModuleWithFunction;
;+ local:
;+ *;
;+};

View File

@@ -22,12 +22,12 @@
* 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.107" _NSS_CUSTOMIZED #define NSS_VERSION "3.108" _NSS_CUSTOMIZED " Beta"
#define NSS_VMAJOR 3 #define NSS_VMAJOR 3
#define NSS_VMINOR 107 #define NSS_VMINOR 108
#define NSS_VPATCH 0 #define NSS_VPATCH 0
#define NSS_VBUILD 0 #define NSS_VBUILD 0
#define NSS_BETA PR_FALSE #define NSS_BETA PR_TRUE
#ifndef RC_INVOKED #ifndef RC_INVOKED

View File

@@ -387,19 +387,12 @@ CK_RV NSC_GetInterface(CK_UTF8CHAR_PTR pInterfaceName,
char **NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args); char **NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args);
#endif #endif
/*
* load a new module into our address space and initialize it.
*/
SECStatus SECStatus
secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule) secmod_DetermineModuleFunctionList(SECMODModule *mod)
{ {
PRLibrary *library = NULL; PRLibrary *library = NULL;
CK_C_GetInterface ientry = NULL; CK_C_GetInterface ientry = NULL;
CK_C_GetFunctionList fentry = NULL; CK_C_GetFunctionList fentry = NULL;
CK_INFO info;
CK_ULONG slotCount = 0;
SECStatus rv;
PRBool alreadyLoaded = PR_FALSE;
char *disableUnload = NULL; char *disableUnload = NULL;
#ifndef NSS_STATIC_SOFTOKEN #ifndef NSS_STATIC_SOFTOKEN
const char *nss_interface; const char *nss_interface;
@@ -407,11 +400,6 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
#endif #endif
CK_INTERFACE_PTR interface; CK_INTERFACE_PTR interface;
if (mod->loaded)
return SECSuccess;
mod->fipsIndicator = NULL;
/* 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_STATIC_SOFTOKEN #ifdef NSS_STATIC_SOFTOKEN
@@ -553,6 +541,25 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
} }
#endif #endif
return SECSuccess;
fail:
mod->functionList = NULL;
disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
if (library && !disableUnload) {
PR_UnloadLibrary(library);
}
return SECFailure;
}
SECStatus
secmod_InitializeModuleAndGetSlotInfo(SECMODModule *mod, SECMODModule **oldModule)
{
CK_INFO info;
CK_ULONG slotCount = 0;
SECStatus rv;
PRBool alreadyLoaded = PR_FALSE;
/* This test operation makes sure our locking system is /* This test operation makes sure our locking system is
* consistent even if we are using non-thread safe tokens by * consistent even if we are using non-thread safe tokens by
* simulating unsafe tokens with safe ones. */ * simulating unsafe tokens with safe ones. */
@@ -643,13 +650,80 @@ fail2:
} }
fail: fail:
mod->functionList = NULL; mod->functionList = NULL;
disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
if (library && !disableUnload) {
PR_UnloadLibrary(library);
}
return SECFailure; return SECFailure;
} }
/*
* load a new module into our address space and initialize it.
*/
SECStatus
secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
{
SECStatus rv = SECFailure;
if (mod->loaded) {
return SECSuccess;
}
mod->fipsIndicator = NULL;
rv = secmod_DetermineModuleFunctionList(mod);
if (rv != SECSuccess) { // The error code is set up by secmod_DetermineModuleFunctionList.
return rv;
}
if (mod->loaded == PR_TRUE) {
return SECSuccess;
}
rv = secmod_InitializeModuleAndGetSlotInfo(mod, oldModule);
if (rv != SECSuccess) { // The error code is set up by secmod_InitializeModuleAndGetSlotInfo
return rv;
}
return SECSuccess;
}
/*
* load a new module using provided fentry function
*/
SECStatus
secmod_LoadPKCS11ModuleFromFunction(SECMODModule *mod, SECMODModule **oldModule,
CK_C_GetFunctionList fentry)
{
SECStatus rv = SECFailure;
CK_RV crv;
if (mod->loaded) {
return SECSuccess;
}
mod->fipsIndicator = NULL;
if (!fentry) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
crv = fentry((CK_FUNCTION_LIST_PTR *)&mod->functionList);
if (crv != CKR_OK) {
mod->functionList = NULL;
PORT_SetError(PK11_MapError(crv));
return SECFailure;
}
if (mod->functionList == NULL) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
mod->flags = 0;
rv = secmod_InitializeModuleAndGetSlotInfo(mod, oldModule);
if (rv != SECSuccess) {
return rv;
}
return SECSuccess;
}
SECStatus SECStatus
SECMOD_UnloadModule(SECMODModule *mod) SECMOD_UnloadModule(SECMODModule *mod)
{ {
@@ -692,9 +766,9 @@ SECMOD_UnloadModule(SECMODModule *mod)
} }
library = (PRLibrary *)mod->library; library = (PRLibrary *)mod->library;
/* paranoia */ /* if no library, then we should not unload it */
if (library == NULL) { if (library == NULL) {
return SECFailure; return SECSuccess;
} }
disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD"); disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");

View File

@@ -1719,10 +1719,19 @@ PK11_ParamToAlgid(SECOidTag algTag, SECItem *param,
case CKM_JUNIPER_CBC128: case CKM_JUNIPER_CBC128:
case CKM_JUNIPER_COUNTER: case CKM_JUNIPER_COUNTER:
case CKM_JUNIPER_SHUFFLE: case CKM_JUNIPER_SHUFFLE:
newParams = SEC_ASN1EncodeItem(NULL, NULL, param, if (param && param->len > 0) {
SEC_ASN1_GET(SEC_OctetStringTemplate)); newParams = SEC_ASN1EncodeItem(NULL, NULL, param,
if (newParams == NULL) SEC_ASN1_GET(SEC_OctetStringTemplate));
break; if (newParams == NULL)
break;
} else {
/* if no parameters have been supplied, then use NULL params
* The SECOID_SetAlgorithmID encoder will encode that as no
* params (since params are optional) or with an explicit NULL
* (for some historical cases where explicit NULL is expected).
*/
newParams = NULL;
}
rv = SECSuccess; rv = SECSuccess;
break; break;
} }

View File

@@ -2240,6 +2240,72 @@ loser:
return module; return module;
} }
SECMODModule *
SECMOD_LoadModuleWithFunction(const char *moduleName, CK_C_GetFunctionList fentry)
{
SECMODModule *module = NULL;
SECMODModule *oldModule = NULL;
SECStatus rv;
/* initialize the underlying module structures */
SECMOD_Init();
module = secmod_NewModule();
if (module == NULL) {
goto loser;
}
module->commonName = PORT_ArenaStrdup(module->arena, moduleName ? moduleName : "");
module->internal = PR_FALSE;
module->isFIPS = PR_FALSE;
/* if the system FIPS mode is enabled, force FIPS to be on */
if (SECMOD_GetSystemFIPSEnabled()) {
module->isFIPS = PR_TRUE;
}
module->isCritical = PR_FALSE;
/* new field */
module->trustOrder = NSSUTIL_DEFAULT_TRUST_ORDER;
/* new field */
module->cipherOrder = NSSUTIL_DEFAULT_CIPHER_ORDER;
/* new field */
module->isModuleDB = PR_FALSE;
module->moduleDBOnly = PR_FALSE;
module->ssl[0] = 0;
module->ssl[1] = 0;
secmod_PrivateModuleCount++;
/* load it */
rv = secmod_LoadPKCS11ModuleFromFunction(module, &oldModule, fentry);
if (rv != SECSuccess) {
goto loser;
}
/* if we just reload an old module, no need to add it to any lists.
* we simple release all our references */
if (oldModule) {
/* This module already exists, don't link it anywhere. This
* will probably destroy this module */
SECMOD_DestroyModule(module);
return oldModule;
}
SECMOD_AddModuleToList(module);
/* handle any additional work here */
return module;
loser:
if (module) {
if (module->loaded) {
SECMOD_UnloadModule(module);
}
SECMOD_AddModuleToUnloadList(module);
}
return module;
}
/* /*
* load a PKCS#11 module and add it to the default NSS trust domain * load a PKCS#11 module and add it to the default NSS trust domain
*/ */
@@ -2262,6 +2328,25 @@ SECMOD_LoadUserModule(char *modulespec, SECMODModule *parent, PRBool recurse)
return newmod; return newmod;
} }
SECMODModule *
SECMOD_LoadUserModuleWithFunction(const char *moduleName, CK_C_GetFunctionList fentry)
{
SECStatus rv = SECSuccess;
SECMODModule *newmod = SECMOD_LoadModuleWithFunction(moduleName, fentry);
SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
if (newmod) {
SECMOD_GetReadLock(moduleLock);
rv = STAN_AddModuleToDefaultTrustDomain(newmod);
SECMOD_ReleaseReadLock(moduleLock);
if (SECSuccess != rv) {
SECMOD_DestroyModule(newmod);
return NULL;
}
}
return newmod;
}
/* /*
* remove the PKCS#11 module from the default NSS trust domain, call * remove the PKCS#11 module from the default NSS trust domain, call
* C_Finalize, and destroy the module structure * C_Finalize, and destroy the module structure

View File

@@ -770,9 +770,10 @@ sec_pkcs5CreateAlgorithmID(SECOidTag algorithm,
algorithm = sec_pkcs5v2_get_pbe(cipherAlgorithm); algorithm = sec_pkcs5v2_get_pbe(cipherAlgorithm);
} }
SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm);
/* set the PKCS5v2 specific parameters */ /* set the PKCS5v2 specific parameters */
if (keyLength == 0) { if (keyLength == 0) {
SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm);
if (hashAlg != SEC_OID_UNKNOWN) { if (hashAlg != SEC_OID_UNKNOWN) {
keyLength = HASH_ResultLenByOidTag(hashAlg); keyLength = HASH_ResultLenByOidTag(hashAlg);
} else { } else {
@@ -787,18 +788,25 @@ sec_pkcs5CreateAlgorithmID(SECOidTag algorithm,
prfAlg = SEC_OID_HMAC_SHA1; prfAlg = SEC_OID_HMAC_SHA1;
} }
/* build the PKCS5v2 cipher algorithm id */ /* build the PKCS5v2 cipher algorithm id, if cipher
cipherParams = pk11_GenerateNewParamWithKeyLen( * is an HMAC, the cipherParams should be NULL */
PK11_AlgtagToMechanism(cipherAlgorithm), keyLength); if (hashAlg == SEC_OID_UNKNOWN) {
if (!cipherParams) { cipherParams = pk11_GenerateNewParamWithKeyLen(
goto loser; PK11_AlgtagToMechanism(cipherAlgorithm), keyLength);
if (!cipherParams) {
goto loser;
}
} else {
cipherParams = NULL;
} }
PORT_Memset(&pbeV2_param, 0, sizeof(pbeV2_param)); PORT_Memset(&pbeV2_param, 0, sizeof(pbeV2_param));
rv = PK11_ParamToAlgid(cipherAlgorithm, cipherParams, rv = PK11_ParamToAlgid(cipherAlgorithm, cipherParams,
poolp, &pbeV2_param.cipherAlgId); poolp, &pbeV2_param.cipherAlgId);
SECITEM_FreeItem(cipherParams, PR_TRUE); if (cipherParams) {
SECITEM_FreeItem(cipherParams, PR_TRUE);
}
if (rv != SECSuccess) { if (rv != SECSuccess) {
goto loser; goto loser;
} }

View File

@@ -6,6 +6,7 @@
#include "seccomon.h" #include "seccomon.h"
#include "secmodt.h" #include "secmodt.h"
#include "prinrval.h" #include "prinrval.h"
#include "pkcs11.h"
/* These mechanisms flags are visible to all other libraries. */ /* These mechanisms flags are visible to all other libraries. */
/* They must be converted to internal SECMOD_*_FLAG */ /* They must be converted to internal SECMOD_*_FLAG */
@@ -60,6 +61,9 @@ extern SECMODModule *SECMOD_LoadModule(char *moduleSpec, SECMODModule *parent,
extern SECMODModule *SECMOD_LoadUserModule(char *moduleSpec, SECMODModule *parent, extern SECMODModule *SECMOD_LoadUserModule(char *moduleSpec, SECMODModule *parent,
PRBool recurse); PRBool recurse);
extern SECMODModule *SECMOD_LoadUserModuleWithFunction(const char *moduleName,
CK_C_GetFunctionList fentry);
SECStatus SECMOD_UnloadUserModule(SECMODModule *mod); SECStatus SECMOD_UnloadUserModule(SECMODModule *mod);
SECMODModule *SECMOD_CreateModule(const char *lib, const char *name, SECMODModule *SECMOD_CreateModule(const char *lib, const char *name,

View File

@@ -57,6 +57,8 @@ extern unsigned long SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags
/* Library functions */ /* Library functions */
SECStatus secmod_LoadPKCS11Module(SECMODModule *, SECMODModule **oldModule); SECStatus secmod_LoadPKCS11Module(SECMODModule *, SECMODModule **oldModule);
SECStatus secmod_LoadPKCS11ModuleFromFunction(SECMODModule *, SECMODModule **oldModule, CK_C_GetFunctionList f);
SECStatus SECMOD_UnloadModule(SECMODModule *); SECStatus SECMOD_UnloadModule(SECMODModule *);
void SECMOD_SetInternalModule(SECMODModule *); void SECMOD_SetInternalModule(SECMODModule *);
PRBool secmod_IsInternalKeySlot(SECMODModule *); PRBool secmod_IsInternalKeySlot(SECMODModule *);

View File

@@ -1918,7 +1918,7 @@ sec_pkcs12_set_nickname_for_cert(sec_PKCS12SafeBag *cert,
static SECItem * static SECItem *
sec_pkcs12_get_der_cert(sec_PKCS12SafeBag *cert) sec_pkcs12_get_der_cert(sec_PKCS12SafeBag *cert)
{ {
if (!cert) { if (!cert || !cert->safeBagContent.certBag) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL; return NULL;
} }
@@ -3179,6 +3179,12 @@ SEC_PKCS12DecoderIterateNext(SEC_PKCS12DecoderContext *p12dcx,
p12dcx->decitem.der = sec_pkcs12_get_der_cert(bag); p12dcx->decitem.der = sec_pkcs12_get_der_cert(bag);
p12dcx->decitem.friendlyName = sec_pkcs12_get_friendlyName(bag); p12dcx->decitem.friendlyName = sec_pkcs12_get_friendlyName(bag);
p12dcx->decitem.hasKey = sec_pkcs12_bagHasKey(p12dcx, bag); p12dcx->decitem.hasKey = sec_pkcs12_bagHasKey(p12dcx, bag);
/* if we don't understand the cert, or it's not parsable, skip it */
/* as per the comment above, friendlyName may be null legitimately */
if (!p12dcx->decitem.der) {
p12dcx->decitem.type = 0; /* clear out the type we are ignoring */
continue;
}
break; break;
case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
p12dcx->decitem.shroudAlg = PORT_ZNew(SECAlgorithmID); p12dcx->decitem.shroudAlg = PORT_ZNew(SECAlgorithmID);
@@ -3195,6 +3201,7 @@ SEC_PKCS12DecoderIterateNext(SEC_PKCS12DecoderContext *p12dcx,
break; break;
case SEC_OID_UNKNOWN: case SEC_OID_UNKNOWN:
/* ignore these */ /* ignore these */
p12dcx->decitem.type = 0; /* clear out the type we are ignoring */
continue; continue;
} }
*ipp = &p12dcx->decitem; *ipp = &p12dcx->decitem;

View File

@@ -102,7 +102,7 @@ sec_pkcs12_integrity_key(PK11SlotInfo *slot, sec_PKCS12MacData *macData,
*hmacMech = PK11_AlgtagToMechanism(hmacAlg); *hmacMech = PK11_AlgtagToMechanism(hmacAlg);
/* pkcs12v2 hmac uses UTF8 rather than unicode */ /* pkcs12v2 hmac uses UTF8 rather than unicode */
if (!sec_pkcs12_convert_item_to_unicode(NULL, &utf8Pw, pwitem, if (!sec_pkcs12_convert_item_to_unicode(NULL, &utf8Pw, pwitem,
PR_TRUE, PR_FALSE, PR_FALSE)) { PR_FALSE, PR_FALSE, PR_FALSE)) {
return NULL; return NULL;
} }
symKey = PK11_PBEKeyGen(slot, prfAlgid, &utf8Pw, PR_FALSE, pwarg); symKey = PK11_PBEKeyGen(slot, prfAlgid, &utf8Pw, PR_FALSE, pwarg);

View File

@@ -520,6 +520,8 @@ CERT_DecodeCertFromPackage(char *certbuf, int certlen)
CERTCertificate *cert = NULL; CERTCertificate *cert = NULL;
collectArgs.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); collectArgs.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
collectArgs.cert.data = NULL;
collectArgs.cert.len = 0;
rv = CERT_DecodeCertPackage(certbuf, certlen, collect_certs, rv = CERT_DecodeCertPackage(certbuf, certlen, collect_certs,
(void *)&collectArgs); (void *)&collectArgs);

View File

@@ -1765,16 +1765,20 @@ sftk_fips_pbkdf_PowerUpSelfTests(void)
unsigned char iteration_count = 5; unsigned char iteration_count = 5;
unsigned char keyLen = 64; unsigned char keyLen = 64;
char *inKeyData = TEST_KEY; char *inKeyData = TEST_KEY;
static const unsigned char saltData[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; static const unsigned char saltData[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
};
static const unsigned char pbkdf_known_answer[] = { static const unsigned char pbkdf_known_answer[] = {
0x31, 0xf0, 0xe5, 0x39, 0x9f, 0x39, 0xb9, 0x29, 0x73, 0x8c, 0xfa, 0x02, 0xe8, 0xdb, 0x43, 0xe4,
0x68, 0xac, 0xf2, 0xe9, 0x53, 0x9b, 0xb4, 0x9c, 0x99, 0xc5, 0xfd, 0xd9, 0x4d, 0x8e, 0x3e, 0x7b,
0x28, 0x59, 0x8b, 0x5c, 0xd8, 0xd4, 0x02, 0x37, 0xc4, 0xda, 0x22, 0x1b, 0xe1, 0xae, 0x23, 0x7a,
0x18, 0x22, 0xc1, 0x92, 0xd0, 0xfa, 0x72, 0x90, 0x21, 0x27, 0xbd, 0xcc, 0x78, 0xc4, 0xe6, 0xc5,
0x2c, 0x8d, 0x19, 0xd4, 0x56, 0xfb, 0x16, 0xfa, 0x33, 0x38, 0x35, 0xe0, 0x68, 0x1a, 0x1e, 0x06,
0x8d, 0x5c, 0x06, 0x33, 0xd1, 0x5f, 0x17, 0xb1, 0xad, 0xaf, 0x7f, 0xd7, 0x3f, 0x0e, 0xc0, 0x90,
0x22, 0xd9, 0x9c, 0xaf, 0x5e, 0x3f, 0xf3, 0x66, 0x17, 0x97, 0x73, 0x75, 0x7b, 0x88, 0x49, 0xd8,
0xc6, 0x14, 0xfe, 0x83, 0xfa, 0x1a, 0x2a, 0xc5 0x6f, 0x78, 0x5a, 0xde, 0x50, 0x20, 0x55, 0x33
}; };
sftk_PBELockInit(); sftk_PBELockInit();

View File

@@ -3211,14 +3211,15 @@ SFTK_DestroySlotData(SFTKSlot *slot)
char ** char **
NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args) NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args)
{ {
#ifndef NSS_DISABLE_DBM #ifdef NSS_DISABLE_DBM
return NSSUTIL_DoModuleDBFunction(function, parameters, args);
#else
char *secmod = NULL; char *secmod = NULL;
char *appName = NULL; char *appName = NULL;
char *filename = NULL; char *filename = NULL;
NSSDBType dbType = NSS_DB_TYPE_NONE; NSSDBType dbType = NSS_DB_TYPE_NONE;
PRBool rw; PRBool rw;
static char *success = "Success"; static char *success = "Success";
#endif /* NSS_DISABLE_DBM */
char **rvstr = NULL; char **rvstr = NULL;
rvstr = NSSUTIL_DoModuleDBFunction(function, parameters, args); rvstr = NSSUTIL_DoModuleDBFunction(function, parameters, args);
@@ -3230,7 +3231,6 @@ NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args)
return NULL; return NULL;
} }
#ifndef NSS_DISABLE_DBM
/* The legacy database uses the old dbm, which is only linked with the /* The legacy database uses the old dbm, which is only linked with the
* legacy DB handler, which is only callable from softoken */ * legacy DB handler, which is only callable from softoken */
@@ -3322,8 +3322,8 @@ loser:
PORT_Free(appName); PORT_Free(appName);
if (filename) if (filename)
PORT_Free(filename); PORT_Free(filename);
#endif /* NSS_DISABLE_DBM */
return rvstr; return rvstr;
#endif /* NSS_DISABLE_DBM */
} }
static void static void

View File

@@ -17,11 +17,11 @@
* 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 SOFTOKEN_VERSION "3.107" SOFTOKEN_ECC_STRING #define SOFTOKEN_VERSION "3.108" SOFTOKEN_ECC_STRING " Beta"
#define SOFTOKEN_VMAJOR 3 #define SOFTOKEN_VMAJOR 3
#define SOFTOKEN_VMINOR 107 #define SOFTOKEN_VMINOR 108
#define SOFTOKEN_VPATCH 0 #define SOFTOKEN_VPATCH 0
#define SOFTOKEN_VBUILD 0 #define SOFTOKEN_VBUILD 0
#define SOFTOKEN_BETA PR_FALSE #define SOFTOKEN_BETA PR_TRUE
#endif /* _SOFTKVER_H_ */ #endif /* _SOFTKVER_H_ */

View File

@@ -107,6 +107,9 @@ HASH_GetHashOidTagByHMACOidTag(SECOidTag hmacOid)
switch (hmacOid) { switch (hmacOid) {
/* no oid exists for HMAC_MD2 */ /* no oid exists for HMAC_MD2 */
/* NSS does not define a oid for HMAC_MD4 */ /* NSS does not define a oid for HMAC_MD4 */
case SEC_OID_HMAC_MD5:
hashOid = SEC_OID_MD5;
break;
case SEC_OID_HMAC_SHA1: case SEC_OID_HMAC_SHA1:
hashOid = SEC_OID_SHA1; hashOid = SEC_OID_SHA1;
break; break;
@@ -150,6 +153,9 @@ HASH_GetHMACOidTagByHashOidTag(SECOidTag hashOid)
switch (hashOid) { switch (hashOid) {
/* no oid exists for HMAC_MD2 */ /* no oid exists for HMAC_MD2 */
/* NSS does not define a oid for HMAC_MD4 */ /* NSS does not define a oid for HMAC_MD4 */
case SEC_OID_MD5:
hmacOid = SEC_OID_HMAC_MD5;
break;
case SEC_OID_SHA1: case SEC_OID_SHA1:
hmacOid = SEC_OID_HMAC_SHA1; hmacOid = SEC_OID_HMAC_SHA1;
break; break;

View File

@@ -372,3 +372,9 @@ NSS_SetAlgorithmPolicyAll;
;+ local: ;+ local:
;+ *; ;+ *;
;+}; ;+};
;+NSSUTIL_3.108 { # NSS Utilities 3.108 release
;+ global:
PORT_SafeZero;
;+ local:
;+ *;
;+};

View File

@@ -19,12 +19,12 @@
* The format of the version string should be * The format of the version string should be
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]" * "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
*/ */
#define NSSUTIL_VERSION "3.107" #define NSSUTIL_VERSION "3.108 Beta"
#define NSSUTIL_VMAJOR 3 #define NSSUTIL_VMAJOR 3
#define NSSUTIL_VMINOR 107 #define NSSUTIL_VMINOR 108
#define NSSUTIL_VPATCH 0 #define NSSUTIL_VPATCH 0
#define NSSUTIL_VBUILD 0 #define NSSUTIL_VBUILD 0
#define NSSUTIL_BETA PR_FALSE #define NSSUTIL_BETA PR_TRUE
SEC_BEGIN_PROTOS SEC_BEGIN_PROTOS

View File

@@ -2274,6 +2274,11 @@ SECOID_FindOID(const SECItem *oid)
return NULL; return NULL;
} }
if ((oid == NULL) || (oid->data == NULL)) {
PORT_SetError(SEC_ERROR_UNRECOGNIZED_OID);
return NULL;
}
ret = PL_HashTableLookupConst(oidhash, oid); ret = PL_HashTableLookupConst(oidhash, oid);
if (ret == NULL) { if (ret == NULL) {
ret = secoid_FindDynamic(oid); ret = secoid_FindDynamic(oid);

View File

@@ -209,6 +209,44 @@ PORT_GetError(void)
return (PR_GetError()); return (PR_GetError());
} }
void
PORT_SafeZero(void *p, size_t n)
{
/* there are cases where the compiler optimizes away our attempt to clear
* out our stack variables. There are multiple solutions for this problem,
* but they aren't universally accepted on all platforms. This attempts
* to select the best solution available given our os, compilier, and
* libc */
#ifdef __STDC_LIB_EXT1__
/* if the os implements C11 annex K, use memset_s */
memset_s(p, n, 0, n);
#else
/* _DEFAULT_SORUCE == BSD source in GCC based environments
* if other environmens support explicit_bzero, their defines
* should be added here */
#if (defined(_DEFAULT_SOURCE) || defined(_BSD_SOURCE)) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))
explicit_bzero(p, n);
#else
#ifdef XP_WIN
/* windows has a secure zero funtion */
SecureZeroMemory(p, n);
#else
/* if the os doesn't support one of the above, but does support
* memset_explicit, you can add the definition for memset with the
* appropriate define check here */
/* define an explicitly implementated Safe zero if the OS
* doesn't provide one */
if (p != NULL) {
volatile unsigned char *__vl = (unsigned char *)p;
size_t __nl = n;
while (__nl--)
*__vl++ = 0;
}
#endif /* no windows SecureZeroMemory */
#endif /* no explicit_bzero */
#endif /* no memset_s */
}
/********************* Arena code follows ***************************** /********************* Arena code follows *****************************
* ArenaPools are like heaps. The memory in them consists of large blocks, * ArenaPools are like heaps. The memory in them consists of large blocks,
* called arenas, which are allocated from the/a system heap. Inside an * called arenas, which are allocated from the/a system heap. Inside an

View File

@@ -36,6 +36,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <ctype.h> #include <ctype.h>
/* ask for Annex K for memset_s. will set the appropriate #define
* if Annex K is supported */
#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h> #include <string.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
@@ -255,6 +258,7 @@ sec_port_iso88591_utf8_conversion_function(
extern int NSS_PutEnv(const char *envVarName, const char *envValue); extern int NSS_PutEnv(const char *envVarName, const char *envValue);
extern void PORT_SafeZero(void *p, size_t n);
extern int NSS_SecureMemcmp(const void *a, const void *b, size_t n); extern int NSS_SecureMemcmp(const void *a, const void *b, size_t n);
extern unsigned int NSS_SecureMemcmpZero(const void *mem, size_t n); extern unsigned int NSS_SecureMemcmpZero(const void *mem, size_t n);
extern void NSS_SecureSelect(void *dest, const void *src0, const void *src1, size_t n, unsigned char b); extern void NSS_SecureSelect(void *dest, const void *src0, const void *src1, size_t n, unsigned char b);

View File

@@ -308,6 +308,7 @@ nssutil_growList(char ***pModuleList, int *useCount, int last)
return SECSuccess; return SECSuccess;
} }
#ifndef NSS_DISABLE_DBM
static char * static char *
_NSSUTIL_GetOldSecmodName(const char *dbname, const char *filename) _NSSUTIL_GetOldSecmodName(const char *dbname, const char *filename)
{ {
@@ -332,6 +333,7 @@ _NSSUTIL_GetOldSecmodName(const char *dbname, const char *filename)
PORT_Free(dirPath); PORT_Free(dirPath);
return file; return file;
} }
#endif // NSS_DISABLE_DBM
static SECStatus nssutil_AddSecmodDBEntry(const char *appName, static SECStatus nssutil_AddSecmodDBEntry(const char *appName,
const char *filename, const char *filename,
@@ -567,6 +569,7 @@ nssutil_ReadSecmodDB(const char *appName,
moduleString = NULL; moduleString = NULL;
} }
done: done:
#ifndef NSS_DISABLE_DBM
/* if we couldn't open a pkcs11 database, look for the old one */ /* if we couldn't open a pkcs11 database, look for the old one */
if (fd == NULL) { if (fd == NULL) {
char *olddbname = _NSSUTIL_GetOldSecmodName(dbname, filename); char *olddbname = _NSSUTIL_GetOldSecmodName(dbname, filename);
@@ -591,6 +594,7 @@ done:
PR_smprintf_free(olddbname); PR_smprintf_free(olddbname);
} }
} }
#endif // NSS_DISABLE_DBM
return_default: return_default:

View File

@@ -213,7 +213,7 @@ class covAction(argparse.Action):
# Don't exit immediately on error # Don't exit immediately on error
symbol_retcode = subprocess.call([ symbol_retcode = subprocess.call([
"sancov", "sancov",
"-blacklist=" + os.path.join(cwd, ".sancov-blacklist"), "-ignorelist=" + os.path.join(cwd, ".sancov-blacklist"),
"-symbolize", sancov_file, "-symbolize", sancov_file,
os.path.join(cwd, "../dist/Debug/bin/ssl_gtest") os.path.join(cwd, "../dist/Debug/bin/ssl_gtest")
], stdout=out) ], stdout=out)

View File

@@ -315,7 +315,7 @@
'target_name': 'fuzz', 'target_name': 'fuzz',
'type': 'none', 'type': 'none',
'dependencies': [ 'dependencies': [
'fuzz/fuzz.gyp:nssfuzz', 'fuzz/fuzz.gyp:fuzz',
], ],
}, },
], ],

View File

@@ -109,7 +109,7 @@ dbtest_main()
Echo "test opening the database readonly in an empty directory" Echo "test opening the database readonly in an empty directory"
mkdir $EMPTY_DIR mkdir $EMPTY_DIR
${BINDIR}/tstclnt -h ${HOST} -d $EMPTY_DIR ${BINDIR}/tstclnt -h ${HOST} -d $EMPTY_DIR
ret=$? ret=$?
if [ $ret -ne 1 ]; then if [ $ret -ne 1 ]; then
html_failed "Tstclnt succeded in an empty directory $ret" html_failed "Tstclnt succeded in an empty directory $ret"

View File

@@ -21,7 +21,7 @@ name=`basename $request .req`
echo ">>>>> $name" echo ">>>>> $name"
sed -e 's; sed -e 's;
;;g' -e 's; ; ;g' -e '/^#/d' $extraneous_response ${TESTDIR}/resp/${name}.rsp > /tmp/y1 ;;g' -e 's; ; ;g' -e '/^#/d' $extraneous_response ${TESTDIR}/resp/${name}.rsp > /tmp/y1
# if we didn't generate any output, flag that as an error # if we didn't generate any output, flag that as an error
size=`sum /tmp/y1 | awk '{ print $1 }'` size=`sum /tmp/y1 | awk '{ print $1 }'`
if [ $size -eq 0 ]; then if [ $size -eq 0 ]; then
echo "${TESTDIR}/resp/${name}.rsp: empty" echo "${TESTDIR}/resp/${name}.rsp: empty"

View File

@@ -65,11 +65,6 @@ gtest_start()
pushd "$DIR" pushd "$DIR"
GTESTREPORT="$DIR/report.xml" GTESTREPORT="$DIR/report.xml"
PARSED_REPORT="$DIR/report.parsed" PARSED_REPORT="$DIR/report.parsed"
# The mozilla::pkix gtests cause an ODR violation that we ignore.
# See bug 1588567.
if [ "$i" = "mozpkix_gtest" ]; then
EXTRA_ASAN_OPTIONS="detect_odr_violation=0"
fi
# NSS CI sets a lower max for PBE iterations, otherwise cert.sh # NSS CI sets a lower max for PBE iterations, otherwise cert.sh
# is very slow. Unset this maxiumum for softoken_gtest, as it # is very slow. Unset this maxiumum for softoken_gtest, as it
# needs to check the default value. # needs to check the default value.
@@ -78,10 +73,9 @@ gtest_start()
unset NSS_MAX_MP_PBE_ITERATION_COUNT unset NSS_MAX_MP_PBE_ITERATION_COUNT
fi fi
echo "executing $i" echo "executing $i"
ASAN_OPTIONS="$ASAN_OPTIONS:$EXTRA_ASAN_OPTIONS" "${BINDIR}/$i" \ "${BINDIR}/$i" -s "${SOURCE_DIR}/gtests/$i" -d "$DIR" -w \
-s "${SOURCE_DIR}/gtests/$i" \ --gtest_output=xml:"${GTESTREPORT}" \
-d "$DIR" -w --gtest_output=xml:"${GTESTREPORT}" \ --gtest_filter="${GTESTFILTER:-*}"
--gtest_filter="${GTESTFILTER:-*}"
html_msg $? 0 "$i run successfully" html_msg $? 0 "$i run successfully"
if [ "$i" = "softoken_gtest" ]; then if [ "$i" = "softoken_gtest" ]; then
export NSS_MAX_MP_PBE_ITERATION_COUNT=$OLD_MAX_PBE_ITERATIONS export NSS_MAX_MP_PBE_ITERATION_COUNT=$OLD_MAX_PBE_ITERATIONS

View File

@@ -56,7 +56,7 @@ tlsfuzzer_init()
# Install tlslite-ng dependencies # Install tlslite-ng dependencies
${QADIR}/../fuzz/config/git-copy.sh https://github.com/warner/python-ecdsa master python-ecdsa ${QADIR}/../fuzz/config/git-copy.sh https://github.com/warner/python-ecdsa master python-ecdsa
${QADIR}/../fuzz/config/git-copy.sh https://github.com/benjaminp/six master six ${QADIR}/../fuzz/config/git-copy.sh https://github.com/benjaminp/six main six
pushd "$TLSFUZZER" pushd "$TLSFUZZER"
ln -s ../python-ecdsa/src/ecdsa ecdsa ln -s ../python-ecdsa/src/ecdsa ecdsa

View File

@@ -127,6 +127,7 @@ tools_init()
cp ${QADIR}/tools/pbmac1-invalid-bad-iter.p12 ${TOOLSDIR}/data cp ${QADIR}/tools/pbmac1-invalid-bad-iter.p12 ${TOOLSDIR}/data
cp ${QADIR}/tools/pbmac1-invalid-bad-salt.p12 ${TOOLSDIR}/data cp ${QADIR}/tools/pbmac1-invalid-bad-salt.p12 ${TOOLSDIR}/data
cp ${QADIR}/tools/pbmac1-invalid-no-length.p12 ${TOOLSDIR}/data cp ${QADIR}/tools/pbmac1-invalid-no-length.p12 ${TOOLSDIR}/data
cp ${QADIR}/tools/corrupted_cert_bag.p12 ${TOOLSDIR}/data
cd ${TOOLSDIR} cd ${TOOLSDIR}
} }
@@ -501,6 +502,12 @@ tools_p12_import_old_files()
html_msg $ret 0 "Importing PKCS#12 file with and implicit KDF value" html_msg $ret 0 "Importing PKCS#12 file with and implicit KDF value"
check_tmpfile check_tmpfile
echo "pk12util -I -l corrupted_cert_bag.p12 -W start"
${BINDIR}/pk12util -I -l ${TOOLSDIR}/data/corrupted_cert_bag.p12 -W start 2>&1
ret=$?
html_msg $ret 17 "Listing a PKCS#12 file with corrupted certificate bag"
check_tmpfile
} }
tools_p12_import_rsa_pss_private_key() tools_p12_import_rsa_pss_private_key()
@@ -541,24 +548,24 @@ tools_p12_import_pbmac1_samples()
html_msg $ret 0 "Importing private key pbmac1 hmac-sha-512 from PKCS#12 file" html_msg $ret 0 "Importing private key pbmac1 hmac-sha-512 from PKCS#12 file"
check_tmpfile check_tmpfile
echo "${BINDIR}/pk12util -l ${TOOLSDIR}/data/pbmac1-invalid-bad-iter.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -W '1234'" echo "${BINDIR}/pk12util -l ${TOOLSDIR}/data/pbmac1-invalid-bad-iter.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -W '1234' -I"
${BINDIR}/pk12util -l ${TOOLSDIR}/data/pbmac1-invalid-bad-iter.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -W '1234' 2>&1 ${BINDIR}/pk12util -l ${TOOLSDIR}/data/pbmac1-invalid-bad-iter.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -W '1234' -I 2>&1
ret=$? ret=$?
html_msg $ret 17 "Fail to list private key with bad iterator" html_msg $ret 19 "Fail to list private key with bad iterator"
check_tmpfile check_tmpfile
echo "${BINDIR}/pk12util -l ${TOOLSDIR}/data/pbmac1-invalid-bad-salt.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -W '1234'" echo "${BINDIR}/pk12util -l ${TOOLSDIR}/data/pbmac1-invalid-bad-salt.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -W '1234' -I"
${BINDIR}/pk12util -l ${TOOLSDIR}/data/pbmac1-invalid-bad-salt.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -W '1234' 2>&1 ${BINDIR}/pk12util -l ${TOOLSDIR}/data/pbmac1-invalid-bad-salt.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -W '1234' -I 2>&1
ret=$? ret=$?
echo "Fail to list private key with bad salt val=$ret" echo "Fail to list private key with bad salt val=$ret"
html_msg $ret 17 "Fail to import private key with bad salt" html_msg $ret 19 "Fail to import private key with bad salt"
check_tmpfile check_tmpfile
echo "${BINDIR}/pk12util -l ${TOOLSDIR}/data/pbmac1-invalid-no-length.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -W '1234'" echo "${BINDIR}/pk12util -l ${TOOLSDIR}/data/pbmac1-invalid-no-length.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -W '1234' -I "
${BINDIR}/pk12util -l ${TOOLSDIR}/data/pbmac1-invalid-no-length.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -W '1234' 2>&1 ${BINDIR}/pk12util -l ${TOOLSDIR}/data/pbmac1-invalid-no-length.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -W '1234' -I 2>&1
ret=$? ret=$?
echo "Fail to import private key with no length val=$ret" echo "Fail to import private key with no length val=$ret"
html_msg $ret 17 "Fail to import private key with no length" html_msg $ret 19 "Fail to import private key with no length"
check_tmpfile check_tmpfile
} }