diff --git a/security/manager/boot/src/PreloadedHPKPins.json b/security/manager/boot/src/PreloadedHPKPins.json index 68c90c2b083b..d52d2f36fef7 100644 --- a/security/manager/boot/src/PreloadedHPKPins.json +++ b/security/manager/boot/src/PreloadedHPKPins.json @@ -11,7 +11,7 @@ // name: (string) the name of the pinset // static_spki_hashes: (list of strings) the set of allowed SPKIs hashes // -// For a given pinset, a certifiacte is accepted if at least one of the +// For a given pinset, a certificate is accepted if at least one of the // "static_spki_hashes" SPKIs is found in the chain. // SPKIs are specified as names, which must match up with the name given // in the Mozilla root store. @@ -81,8 +81,14 @@ "thawte Primary Root CA - G3", "Baltimore CyberTrust Root" ] - } - ], + }, + // For pinning tests on pinning.example.com, the issuer must be testCA. + { + "name": "mozilla_test", + "static_spki_hashes": [ + "End Entity Test Cert" + ] + } ], "entries": [ { "name": "addons.mozilla.org", "include_subdomains": true, "pins": "mozilla" }, @@ -90,6 +96,7 @@ { "name": "cdn.mozilla.net", "include_subdomains": true, "pins": "mozilla_cdn" }, { "name": "cdn.mozilla.org", "include_subdomains": true, "pins": "mozilla_cdn" }, { "name": "media.mozilla.com", "include_subdomains": true, "pins": "mozilla_cdn" }, - { "name": "getpersonas.org", "include_subdomains": true, "pins": "mozilla_cdn" } + { "name": "include-subdomain.pinning.example.com", "include_subdomains": true, "pins": "mozilla_test" }, + { "name": "exclude-subdomains.pinning.example.com", "include_subdomains": false, "pins": "mozilla_test" } ] } diff --git a/security/manager/boot/src/StaticHPKPins.h b/security/manager/boot/src/StaticHPKPins.h index a8229b758b38..a20f292921c1 100644 --- a/security/manager/boot/src/StaticHPKPins.h +++ b/security/manager/boot/src/StaticHPKPins.h @@ -23,6 +23,10 @@ static const char kDigiCert_Global_Root_CAFingerprint[]= static const char kDigiCert_High_Assurance_EV_Root_CAFingerprint[]= "WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; +/* End Entity Test Cert */ +static const char kEnd_Entity_Test_CertFingerprint[]= + "97H5CNFJ2u3u1NvH3ru67t5OiCO8KydOyNh9GCEyAeM="; + /* Equifax Secure CA */ static const char kEquifax_Secure_CAFingerprint[]= "/1aAzXOlcD2gSBegdf1GJQanNQbEuBoVg+9UlHjSZHY="; @@ -174,6 +178,11 @@ static const char* const kPinSet_mozilla_cdn_Data[] = { }; const StaticPinset kPinSet_mozilla_cdn = { 28, kPinSet_mozilla_cdn_Data}; +static const char* const kPinSet_mozilla_test_Data[] = { + kEnd_Entity_Test_CertFingerprint, +}; +const StaticPinset kPinSet_mozilla_test = { 1, kPinSet_mozilla_test_Data}; + /*Domainlist*/ typedef struct { const char *mHost; @@ -186,10 +195,11 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = { { "addons.mozilla.org", true, &kPinSet_mozilla }, { "cdn.mozilla.net", true, &kPinSet_mozilla_cdn }, { "cdn.mozilla.org", true, &kPinSet_mozilla_cdn }, - { "getpersonas.org", true, &kPinSet_mozilla_cdn }, + { "exclude-subdomains.pinning.example.com", false, &kPinSet_mozilla_test }, + { "include-subdomain.pinning.example.com", true, &kPinSet_mozilla_test }, { "media.mozilla.com", true, &kPinSet_mozilla_cdn }, }; -static const int kPublicKeyPinningPreloadListLength = 6; +static const int kPublicKeyPinningPreloadListLength = 7; -const PRTime kPreloadPKPinsExpirationTime = INT64_C(1409688371834000); +const PRTime kPreloadPKPinsExpirationTime = INT64_C(1409763023059000); diff --git a/security/manager/boot/src/default-ee.der b/security/manager/boot/src/default-ee.der new file mode 100644 index 000000000000..0f52bac754ea Binary files /dev/null and b/security/manager/boot/src/default-ee.der differ diff --git a/security/manager/boot/src/genHPKPStaticPins.js b/security/manager/boot/src/genHPKPStaticPins.js index 5781829f527d..ba5809affe17 100644 --- a/security/manager/boot/src/genHPKPStaticPins.js +++ b/security/manager/boot/src/genHPKPStaticPins.js @@ -7,13 +7,14 @@ // 2. [build/obtain firefox binaries] // 3. run `[path to]/run-mozilla.sh [path to]/xpcshell \ // [path to]/genHPKPStaticpins.js +// Files PreloadedHPKPins.json and default-ee.der must be in the current +// working directory. const { 'classes': Cc, 'interfaces': Ci, 'utils': Cu, 'results': Cr } = Components; let { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {}); let { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {}); let { Services } = Cu.import("resource://gre/modules/Services.jsm", {}); -let { XPCOMUtils } = Cu.import("resource:///modules/XPCOMUtils.jsm", {}); const certdb2 = Cc["@mozilla.org/security/x509certdb;1"] .getService(Ci.nsIX509CertDB2); @@ -48,8 +49,7 @@ function writeTo(string, fos) { fos.write(string, string.length); } -function readFile(filename) { - print("filename =" + filename) +function readFileToString(filename) { let path = filename; let lf = Components.classes["@mozilla.org/file/directory_service;1"] @@ -67,26 +67,23 @@ function readFile(filename) { } } } - let file = lf; - let fstream = Cc["@mozilla.org/network/file-input-stream;1"] - .createInstance(Ci.nsIFileInputStream); - fstream.init(file, -1, 0, 0); - var line = {}; + let stream = Cc["@mozilla.org/network/file-input-stream;1"] + .createInstance(Ci.nsIFileInputStream); + stream.init(lf, -1, 0, 0); + let buf = NetUtil.readInputStreamToString(stream, stream.available()); + return buf; +} + +function stripComments(buf) { + var lines = buf.split("\n"); let entryRegex = /^\s*\/\//; let data = ""; - while(fstream.readLine(line)) { - let match = entryRegex.exec(line.value); + for (let i = 0; i < lines.length; ++i) { + let match = entryRegex.exec(lines[i]); if (!match) { - data = data + line.value; + data = data + lines[i]; } } - // The last line of the read is a false, but content can be there - // so: repeat the logic - let match = entryRegex.exec(line.value); - if (!match) { - data = data + line.value; - } - fstream.close(); return data; } @@ -124,11 +121,25 @@ function loadNSSCertinfo() { certNameToSKD[name] = SDK; certSDKToName[SDK] = name; } + { + // A certificate for *.example.com. + let der = readFileToString("default-ee.der"); + // XPCOM is too dumb to automatically query the parent interface of + // nsIX509CertDB2 without a hint. + let certdb = certdb2.QueryInterface(Ci.nsIX509CertDB); + let testCert = certdb.constructX509(der, der.length); + // We can't include this cert in the previous loop, because it skips + // non-builtin certs and the nickname is not built-in to the cert. + let name = "End Entity Test Cert"; + let SDK = testCert.sha256SubjectPublicKeyInfoDigest; + certNameToSKD[name] = SDK; + certSDKToName[SDK] = name; + } return [certNameToSKD, certSDKToName]; } function parseMozFile() { - mozFile = readFile(MOZINPUT); + mozFile = stripComments(readFileToString(MOZINPUT)); mozJSON = JSON.parse(mozFile); return mozJSON; } @@ -221,8 +232,7 @@ function writeFile(certNameToSDK, certSDKToName, jsonPins) { FileUtils.closeSafeFileOutputStream(fos); - } - catch (e) { + } catch (e) { dump("ERROR: problem writing output to '" + OUTPUT + "': " + e + "\n"); } } diff --git a/security/manager/ssl/tests/unit/tlsserver/cert8.db b/security/manager/ssl/tests/unit/tlsserver/cert8.db index 13c101f2a27d..ce9c312fb8b5 100644 Binary files a/security/manager/ssl/tests/unit/tlsserver/cert8.db and b/security/manager/ssl/tests/unit/tlsserver/cert8.db differ diff --git a/security/manager/ssl/tests/unit/tlsserver/default-ee.der b/security/manager/ssl/tests/unit/tlsserver/default-ee.der index ac98037be14f..0f52bac754ea 100644 Binary files a/security/manager/ssl/tests/unit/tlsserver/default-ee.der and b/security/manager/ssl/tests/unit/tlsserver/default-ee.der differ diff --git a/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh b/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh index ef388bbdda77..7397485f2c15 100755 --- a/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh +++ b/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh @@ -12,7 +12,10 @@ # # NB: This will cause the following files to be overwritten if they are in # the output directory: -# cert8.db, key3.db, secmod.db, ocsp-ca.der, ocsp-other-ca.der +# cert8.db, key3.db, secmod.db, ocsp-ca.der, ocsp-other-ca.der, default-ee.der +# NB: You must run genHPKPStaticPins.js after running this file, since its +# output (StaticHPKPins.h) depends on default-ee.der + set -x set -e @@ -25,11 +28,13 @@ OBJDIR=${1} OUTPUT_DIR=${2} RUN_MOZILLA="$OBJDIR/dist/bin/run-mozilla.sh" CERTUTIL="$OBJDIR/dist/bin/certutil" +# On BSD, mktemp requires either a template or a prefix. +MKTEMP="mktemp temp.XXXX" -NOISE_FILE=`mktemp` +NOISE_FILE=`$MKTEMP` # Make a good effort at putting something unique in the noise file. date +%s%N > "$NOISE_FILE" -PASSWORD_FILE=`mktemp` +PASSWORD_FILE=`$MKTEMP` function cleanup { rm -f "$NOISE_FILE" "$PASSWORD_FILE" @@ -134,7 +139,8 @@ function make_delegated { make_CA testCA 'CN=Test CA' test-ca.der make_CA otherCA 'CN=Other test CA' other-test-ca.der -make_EE localhostAndExampleCom 'CN=Test End-entity' testCA "localhost,*.example.com" +make_EE localhostAndExampleCom 'CN=Test End-entity' testCA "localhost,*.example.com,*.pinning.example.com" + $RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -L -n localhostAndExampleCom -r > $OUTPUT_DIR/default-ee.der # A cert that is like localhostAndExampleCom, but with a different serial number for # testing the "OCSP response is from the right issuer, but it is for the wrong cert" diff --git a/security/manager/ssl/tests/unit/tlsserver/key3.db b/security/manager/ssl/tests/unit/tlsserver/key3.db index 283e8fbf695d..4236e1041cfd 100644 Binary files a/security/manager/ssl/tests/unit/tlsserver/key3.db and b/security/manager/ssl/tests/unit/tlsserver/key3.db differ diff --git a/security/manager/ssl/tests/unit/tlsserver/other-test-ca.der b/security/manager/ssl/tests/unit/tlsserver/other-test-ca.der index 794fb9cec9b1..fcc0c530a541 100644 Binary files a/security/manager/ssl/tests/unit/tlsserver/other-test-ca.der and b/security/manager/ssl/tests/unit/tlsserver/other-test-ca.der differ diff --git a/security/manager/ssl/tests/unit/tlsserver/test-ca.der b/security/manager/ssl/tests/unit/tlsserver/test-ca.der index f4c4863a5bba..2695862cd928 100644 Binary files a/security/manager/ssl/tests/unit/tlsserver/test-ca.der and b/security/manager/ssl/tests/unit/tlsserver/test-ca.der differ