summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@wolfbeast.com>2020-03-28 01:06:56 +0100
committerwolfbeast <mcwerewolf@wolfbeast.com>2020-04-14 13:19:41 +0200
commit99bad1726e897a82239e543a7a8e8fea36b797c0 (patch)
treeaf15c93fca2c7052c029e2422e852cd98b82eb8e
parentd86349716a9740226d9175b1cf4b60765cb707fc (diff)
downloadUXP-99bad1726e897a82239e543a7a8e8fea36b797c0.tar
UXP-99bad1726e897a82239e543a7a8e8fea36b797c0.tar.gz
UXP-99bad1726e897a82239e543a7a8e8fea36b797c0.tar.lz
UXP-99bad1726e897a82239e543a7a8e8fea36b797c0.tar.xz
UXP-99bad1726e897a82239e543a7a8e8fea36b797c0.zip
Issue #1280 - Part 1: Remove HPKP components.
This also removes leftover plumbing for storing preload information in SiteSecurityService since no service still uses it.
-rw-r--r--netwerk/base/security-prefs.js21
-rw-r--r--security/certverifier/NSSCertDBTrustDomain.cpp19
-rw-r--r--security/manager/ssl/PublicKeyPinningService.cpp333
-rw-r--r--security/manager/ssl/PublicKeyPinningService.h64
-rw-r--r--security/manager/ssl/StaticHPKPins.h712
-rw-r--r--security/manager/ssl/moz.build1
-rw-r--r--security/manager/ssl/nsISiteSecurityService.idl46
-rw-r--r--security/manager/ssl/nsSiteSecurityService.cpp595
-rw-r--r--security/manager/ssl/nsSiteSecurityService.h46
-rw-r--r--security/manager/tools/PreloadedHPKPins.json222
-rw-r--r--security/manager/tools/genHPKPStaticPins.js630
11 files changed, 32 insertions, 2657 deletions
diff --git a/netwerk/base/security-prefs.js b/netwerk/base/security-prefs.js
index 702315d43..973c73123 100644
--- a/netwerk/base/security-prefs.js
+++ b/netwerk/base/security-prefs.js
@@ -120,27 +120,6 @@ pref("security.webauth.u2f_enable_usbtoken", false);
// OCSP must-staple
pref("security.ssl.enable_ocsp_must_staple", true);
-// HPKP settings
-
-// Enable pinning checks by default.
-pref("security.cert_pinning.enforcement_level", 2);
-// Do not process hpkp headers rooted by not built in roots by default.
-// This is to prevent accidental pinning from MITM devices and is used
-// for tests.
-pref("security.cert_pinning.process_headers_from_non_builtin_roots", false);
-// Impose a maximum age on HPKP headers, to avoid sites getting permanently
-// blacking themselves out by setting a bad pin. (60 days by default)
-// https://tools.ietf.org/html/rfc7469#section-4.1
-pref("security.cert_pinning.max_max_age_seconds", 5184000);
-// Controls whether or not HPKP (the HTTP Public Key Pinning header) is enabled.
-// If true, the header is processed and collected HPKP information is consulted
-// when looking for pinning information.
-// If false, the header is not processed and collected HPKP information is not
-// consulted when looking for pinning information. Preloaded pins are not
-// affected by this preference.
-// Default: false
-pref("security.cert_pinning.hpkp.enabled", false);
-
// If a request is mixed-content, send an HSTS priming request to attempt to
// see if it is available over HTTPS.
pref("security.mixed_content.send_hsts_priming", true);
diff --git a/security/certverifier/NSSCertDBTrustDomain.cpp b/security/certverifier/NSSCertDBTrustDomain.cpp
index cf48f6392..fff75ee88 100644
--- a/security/certverifier/NSSCertDBTrustDomain.cpp
+++ b/security/certverifier/NSSCertDBTrustDomain.cpp
@@ -12,7 +12,6 @@
#include "NSSErrorsService.h"
#include "OCSPRequestor.h"
#include "OCSPVerificationTrustDomain.h"
-#include "PublicKeyPinningService.h"
#include "cert.h"
#include "certdb.h"
#include "mozilla/Assertions.h"
@@ -862,24 +861,6 @@ NSSCertDBTrustDomain::IsChainValid(const DERArray& certArray, Time time)
if (rv != Success) {
return rv;
}
- bool skipPinningChecksBecauseOfMITMMode =
- (!isBuiltInRoot && mPinningMode == CertVerifier::pinningAllowUserCAMITM);
- // If mHostname isn't set, we're not verifying in the context of a TLS
- // handshake, so don't verify HPKP in those cases.
- if (mHostname && (mPinningMode != CertVerifier::pinningDisabled) &&
- !skipPinningChecksBecauseOfMITMMode) {
- bool enforceTestMode =
- (mPinningMode == CertVerifier::pinningEnforceTestMode);
- bool chainHasValidPins;
- nsresult nsrv = PublicKeyPinningService::ChainHasValidPins(
- certList, mHostname, time, enforceTestMode, chainHasValidPins);
- if (NS_FAILED(nsrv)) {
- return Result::FATAL_ERROR_LIBRARY_FAILURE;
- }
- if (!chainHasValidPins) {
- return Result::ERROR_KEY_PINNING_FAILURE;
- }
- }
mBuiltChain = Move(certList);
diff --git a/security/manager/ssl/PublicKeyPinningService.cpp b/security/manager/ssl/PublicKeyPinningService.cpp
deleted file mode 100644
index ffee8ba48..000000000
--- a/security/manager/ssl/PublicKeyPinningService.cpp
+++ /dev/null
@@ -1,333 +0,0 @@
-/* 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 "PublicKeyPinningService.h"
-
-#include "mozilla/Base64.h"
-#include "mozilla/Casting.h"
-#include "mozilla/Logging.h"
-#include "nsISiteSecurityService.h"
-#include "nsServiceManagerUtils.h"
-#include "nsSiteSecurityService.h"
-#include "nssb64.h"
-#include "pkix/pkixtypes.h"
-#include "seccomon.h"
-#include "sechash.h"
-
-#include "StaticHPKPins.h" // autogenerated by genHPKPStaticpins.js
-
-using namespace mozilla;
-using namespace mozilla::pkix;
-using namespace mozilla::psm;
-
-LazyLogModule gPublicKeyPinningLog("PublicKeyPinningService");
-
-/**
- Computes in the location specified by base64Out the SHA256 digest
- of the DER Encoded subject Public Key Info for the given cert
-*/
-static nsresult
-GetBase64HashSPKI(const CERTCertificate* cert, nsACString& hashSPKIDigest)
-{
- hashSPKIDigest.Truncate();
- Digest digest;
- nsresult rv = digest.DigestBuf(SEC_OID_SHA256, cert->derPublicKey.data,
- cert->derPublicKey.len);
- if (NS_FAILED(rv)) {
- return rv;
- }
- return Base64Encode(nsDependentCSubstring(
- BitwiseCast<char*, unsigned char*>(digest.get().data),
- digest.get().len),
- hashSPKIDigest);
-}
-
-/*
- * Sets certMatchesPinset to true if a given cert matches any fingerprints from
- * the given pinset or the dynamicFingerprints array, or to false otherwise.
- */
-static nsresult
-EvalCert(const CERTCertificate* cert, const StaticFingerprints* fingerprints,
- const nsTArray<nsCString>* dynamicFingerprints,
- /*out*/ bool& certMatchesPinset)
-{
- certMatchesPinset = false;
- if (!fingerprints && !dynamicFingerprints) {
- MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug,
- ("pkpin: No hashes found\n"));
- return NS_ERROR_INVALID_ARG;
- }
-
- nsAutoCString base64Out;
- nsresult rv = GetBase64HashSPKI(cert, base64Out);
- if (NS_FAILED(rv)) {
- MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug,
- ("pkpin: GetBase64HashSPKI failed!\n"));
- return rv;
- }
-
- if (fingerprints) {
- for (size_t i = 0; i < fingerprints->size; i++) {
- if (base64Out.Equals(fingerprints->data[i])) {
- MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug,
- ("pkpin: found pin base_64 ='%s'\n", base64Out.get()));
- certMatchesPinset = true;
- return NS_OK;
- }
- }
- }
- if (dynamicFingerprints) {
- for (size_t i = 0; i < dynamicFingerprints->Length(); i++) {
- if (base64Out.Equals((*dynamicFingerprints)[i])) {
- MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug,
- ("pkpin: found pin base_64 ='%s'\n", base64Out.get()));
- certMatchesPinset = true;
- return NS_OK;
- }
- }
- }
- return NS_OK;
-}
-
-/*
- * Sets certListIntersectsPinset to true if a given chain matches any
- * fingerprints from the given static fingerprints or the
- * dynamicFingerprints array, or to false otherwise.
- */
-static nsresult
-EvalChain(const UniqueCERTCertList& certList,
- const StaticFingerprints* fingerprints,
- const nsTArray<nsCString>* dynamicFingerprints,
- /*out*/ bool& certListIntersectsPinset)
-{
- certListIntersectsPinset = false;
- CERTCertificate* currentCert;
-
- if (!fingerprints && !dynamicFingerprints) {
- MOZ_ASSERT(false, "Must pass in at least one type of pinset");
- return NS_ERROR_FAILURE;
- }
-
- CERTCertListNode* node;
- for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
- node = CERT_LIST_NEXT(node)) {
- currentCert = node->cert;
- MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug,
- ("pkpin: certArray subject: '%s'\n", currentCert->subjectName));
- MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug,
- ("pkpin: certArray issuer: '%s'\n", currentCert->issuerName));
- nsresult rv = EvalCert(currentCert, fingerprints, dynamicFingerprints,
- certListIntersectsPinset);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (certListIntersectsPinset) {
- return NS_OK;
- }
- }
- MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug, ("pkpin: no matches found\n"));
- return NS_OK;
-}
-
-/**
- Comparator for the is public key pinned host.
-*/
-static int
-TransportSecurityPreloadCompare(const void* key, const void* entry) {
- auto keyStr = static_cast<const char*>(key);
- auto preloadEntry = static_cast<const TransportSecurityPreload*>(entry);
-
- return strcmp(keyStr, preloadEntry->mHost);
-}
-
-nsresult
-PublicKeyPinningService::ChainMatchesPinset(const UniqueCERTCertList& certList,
- const nsTArray<nsCString>& aSHA256keys,
- /*out*/ bool& chainMatchesPinset)
-{
- return EvalChain(certList, nullptr, &aSHA256keys, chainMatchesPinset);
-}
-
-// Returns via one of the output parameters the most relevant pinning
-// information that is valid for the given host at the given time.
-// Dynamic pins are prioritized over static pins.
-static nsresult
-FindPinningInformation(const char* hostname, mozilla::pkix::Time time,
- /*out*/ nsTArray<nsCString>& dynamicFingerprints,
- /*out*/ TransportSecurityPreload*& staticFingerprints)
-{
- if (!hostname || hostname[0] == 0) {
- return NS_ERROR_INVALID_ARG;
- }
- staticFingerprints = nullptr;
- dynamicFingerprints.Clear();
- nsCOMPtr<nsISiteSecurityService> sssService =
- do_GetService(NS_SSSERVICE_CONTRACTID);
- if (!sssService) {
- return NS_ERROR_FAILURE;
- }
- TransportSecurityPreload* foundEntry = nullptr;
- char* evalHost = const_cast<char*>(hostname);
- char* evalPart;
- // Notice how the (xx = strchr) prevents pins for unqualified domain names.
- while (!foundEntry && (evalPart = strchr(evalHost, '.'))) {
- MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug,
- ("pkpin: Querying pinsets for host: '%s'\n", evalHost));
- // Attempt dynamic pins first
- nsresult rv;
- bool found;
- bool includeSubdomains;
- nsTArray<nsCString> pinArray;
- rv = sssService->GetKeyPinsForHostname(evalHost, time, pinArray,
- &includeSubdomains, &found);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (found && (evalHost == hostname || includeSubdomains)) {
- MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug,
- ("pkpin: Found dyn match for host: '%s'\n", evalHost));
- dynamicFingerprints = pinArray;
- return NS_OK;
- }
-
- foundEntry = (TransportSecurityPreload *)bsearch(evalHost,
- kPublicKeyPinningPreloadList,
- sizeof(kPublicKeyPinningPreloadList) / sizeof(TransportSecurityPreload),
- sizeof(TransportSecurityPreload),
- TransportSecurityPreloadCompare);
- if (foundEntry) {
- MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug,
- ("pkpin: Found pinset for host: '%s'\n", evalHost));
- if (evalHost != hostname) {
- if (!foundEntry->mIncludeSubdomains) {
- // Does not apply to this host, continue iterating
- foundEntry = nullptr;
- }
- }
- } else {
- MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug,
- ("pkpin: Didn't find pinset for host: '%s'\n", evalHost));
- }
- // Add one for '.'
- evalHost = evalPart + 1;
- }
-
- if (foundEntry && foundEntry->pinset) {
- if (time > TimeFromEpochInSeconds(kPreloadPKPinsExpirationTime /
- PR_USEC_PER_SEC)) {
- return NS_OK;
- }
- staticFingerprints = foundEntry;
- }
- return NS_OK;
-}
-
-// Returns true via the output parameter if the given certificate list meets
-// pinning requirements for the given host at the given time. It must be the
-// case that either there is an intersection between the set of hashes of
-// subject public key info data in the list and the most relevant non-expired
-// pinset for the host or there is no pinning information for the host.
-static nsresult
-CheckPinsForHostname(const UniqueCERTCertList& certList, const char* hostname,
- bool enforceTestMode, mozilla::pkix::Time time,
- /*out*/ bool& chainHasValidPins)
-{
- chainHasValidPins = false;
- if (!certList) {
- return NS_ERROR_INVALID_ARG;
- }
- if (!hostname || hostname[0] == 0) {
- return NS_ERROR_INVALID_ARG;
- }
-
- nsTArray<nsCString> dynamicFingerprints;
- TransportSecurityPreload* staticFingerprints = nullptr;
- nsresult rv = FindPinningInformation(hostname, time, dynamicFingerprints,
- staticFingerprints);
- // If we have no pinning information, the certificate chain trivially
- // validates with respect to pinning.
- if (dynamicFingerprints.Length() == 0 && !staticFingerprints) {
- chainHasValidPins = true;
- return NS_OK;
- }
- if (dynamicFingerprints.Length() > 0) {
- return EvalChain(certList, nullptr, &dynamicFingerprints, chainHasValidPins);
- }
- if (staticFingerprints) {
- bool enforceTestModeResult;
- rv = EvalChain(certList, staticFingerprints->pinset, nullptr,
- enforceTestModeResult);
- if (NS_FAILED(rv)) {
- return rv;
- }
- chainHasValidPins = enforceTestModeResult;
- if (staticFingerprints->mTestMode) {
- if (!enforceTestMode) {
- chainHasValidPins = true;
- }
- }
-
- MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug,
- ("pkpin: Pin check %s for %s host '%s' (mode=%s)\n",
- enforceTestModeResult ? "passed" : "failed",
- staticFingerprints->mIsMoz ? "mozilla" : "non-mozilla",
- hostname, staticFingerprints->mTestMode ? "test" : "production"));
- }
-
- return NS_OK;
-}
-
-nsresult
-PublicKeyPinningService::ChainHasValidPins(const UniqueCERTCertList& certList,
- const char* hostname,
- mozilla::pkix::Time time,
- bool enforceTestMode,
- /*out*/ bool& chainHasValidPins)
-{
- chainHasValidPins = false;
- if (!certList) {
- return NS_ERROR_INVALID_ARG;
- }
- if (!hostname || hostname[0] == 0) {
- return NS_ERROR_INVALID_ARG;
- }
- nsAutoCString canonicalizedHostname(CanonicalizeHostname(hostname));
- return CheckPinsForHostname(certList, canonicalizedHostname.get(),
- enforceTestMode, time, chainHasValidPins);
-}
-
-nsresult
-PublicKeyPinningService::HostHasPins(const char* hostname,
- mozilla::pkix::Time time,
- bool enforceTestMode,
- /*out*/ bool& hostHasPins)
-{
- hostHasPins = false;
- nsAutoCString canonicalizedHostname(CanonicalizeHostname(hostname));
- nsTArray<nsCString> dynamicFingerprints;
- TransportSecurityPreload* staticFingerprints = nullptr;
- nsresult rv = FindPinningInformation(canonicalizedHostname.get(), time,
- dynamicFingerprints, staticFingerprints);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (dynamicFingerprints.Length() > 0) {
- hostHasPins = true;
- } else if (staticFingerprints) {
- hostHasPins = !staticFingerprints->mTestMode || enforceTestMode;
- }
- return NS_OK;
-}
-
-nsAutoCString
-PublicKeyPinningService::CanonicalizeHostname(const char* hostname)
-{
- nsAutoCString canonicalizedHostname(hostname);
- ToLowerCase(canonicalizedHostname);
- while (canonicalizedHostname.Length() > 0 &&
- canonicalizedHostname.Last() == '.') {
- canonicalizedHostname.Truncate(canonicalizedHostname.Length() - 1);
- }
- return canonicalizedHostname;
-}
diff --git a/security/manager/ssl/PublicKeyPinningService.h b/security/manager/ssl/PublicKeyPinningService.h
deleted file mode 100644
index 09fdd8474..000000000
--- a/security/manager/ssl/PublicKeyPinningService.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* 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 PublicKeyPinningService_h
-#define PublicKeyPinningService_h
-
-#include "CertVerifier.h"
-#include "ScopedNSSTypes.h"
-#include "cert.h"
-#include "nsString.h"
-#include "nsTArray.h"
-#include "pkix/Time.h"
-
-namespace mozilla {
-namespace psm {
-
-class PublicKeyPinningService
-{
-public:
- /**
- * Sets chainHasValidPins to true if the given (host, certList) passes pinning
- * checks, or to false otherwise. If the host is pinned, returns true via
- * chainHasValidPins if one of the keys in the given certificate chain matches
- * the pin set specified by the hostname. The certList's head is the EE cert
- * and the tail is the trust anchor.
- * Note: if an alt name is a wildcard, it won't necessarily find a pinset
- * that would otherwise be valid for it
- */
- static nsresult ChainHasValidPins(const UniqueCERTCertList& certList,
- const char* hostname,
- mozilla::pkix::Time time,
- bool enforceTestMode,
- /*out*/ bool& chainHasValidPins);
- /**
- * Sets chainMatchesPinset to true if there is any intersection between the
- * certificate list and the pins specified in the aSHA256keys array.
- * Values passed in are assumed to be in base64 encoded form.
- */
- static nsresult ChainMatchesPinset(const UniqueCERTCertList& certList,
- const nsTArray<nsCString>& aSHA256keys,
- /*out*/ bool& chainMatchesPinset);
-
- /**
- * Returns true via the output parameter hostHasPins if there is pinning
- * information for the given host that is valid at the given time, and false
- * otherwise.
- */
- static nsresult HostHasPins(const char* hostname,
- mozilla::pkix::Time time,
- bool enforceTestMode,
- /*out*/ bool& hostHasPins);
-
- /**
- * Given a hostname of potentially mixed case with potentially multiple
- * trailing '.' (see bug 1118522), canonicalizes it to lowercase with no
- * trailing '.'.
- */
- static nsAutoCString CanonicalizeHostname(const char* hostname);
-};
-
-}} // namespace mozilla::psm
-
-#endif // PublicKeyPinningService_h
diff --git a/security/manager/ssl/StaticHPKPins.h b/security/manager/ssl/StaticHPKPins.h
deleted file mode 100644
index a2313ea72..000000000
--- a/security/manager/ssl/StaticHPKPins.h
+++ /dev/null
@@ -1,712 +0,0 @@
-/* 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/. */
-
-/*****************************************************************************/
-/* This is an automatically generated file. If you're not */
-/* PublicKeyPinningService.cpp, you shouldn't be #including it. */
-/*****************************************************************************/
-#include <stdint.h>
-/* AddTrust External Root */
-static const char kAddTrust_External_RootFingerprint[] =
- "lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=";
-
-/* AddTrust Low-Value Services Root */
-static const char kAddTrust_Low_Value_Services_RootFingerprint[] =
- "BStocQfshOhzA4JFLsKidFF0XXSFpX1vRk4Np6G2ryo=";
-
-/* AddTrust Public Services Root */
-static const char kAddTrust_Public_Services_RootFingerprint[] =
- "OGHXtpYfzbISBFb/b8LrdwSxp0G0vZM6g3b14ZFcppg=";
-
-/* AddTrust Qualified Certificates Root */
-static const char kAddTrust_Qualified_Certificates_RootFingerprint[] =
- "xzr8Lrp3DQy8HuQfJStS6Kk9ErctzOwDHY2DnL+Bink=";
-
-/* AffirmTrust Commercial */
-static const char kAffirmTrust_CommercialFingerprint[] =
- "bEZLmlsjOl6HTadlwm8EUBDS3c/0V5TwtMfkqvpQFJU=";
-
-/* AffirmTrust Networking */
-static const char kAffirmTrust_NetworkingFingerprint[] =
- "lAcq0/WPcPkwmOWl9sBMlscQvYSdgxhJGa6Q64kK5AA=";
-
-/* AffirmTrust Premium */
-static const char kAffirmTrust_PremiumFingerprint[] =
- "x/Q7TPW3FWgpT4IrU3YmBfbd0Vyt7Oc56eLDy6YenWc=";
-
-/* AffirmTrust Premium ECC */
-static const char kAffirmTrust_Premium_ECCFingerprint[] =
- "MhmwkRT/SVo+tusAwu/qs0ACrl8KVsdnnqCHo/oDfk8=";
-
-/* Baltimore CyberTrust Root */
-static const char kBaltimore_CyberTrust_RootFingerprint[] =
- "Y9mvm0exBk1JoQ57f9Vm28jKo5lFm/woKcVxrYxu80o=";
-
-/* COMODO Certification Authority */
-static const char kCOMODO_Certification_AuthorityFingerprint[] =
- "AG1751Vd2CAmRCxPGieoDomhmJy4ezREjtIZTBgZbV4=";
-
-/* COMODO ECC Certification Authority */
-static const char kCOMODO_ECC_Certification_AuthorityFingerprint[] =
- "58qRu/uxh4gFezqAcERupSkRYBlBAvfcw7mEjGPLnNU=";
-
-/* COMODO RSA Certification Authority */
-static const char kCOMODO_RSA_Certification_AuthorityFingerprint[] =
- "grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=";
-
-/* Comodo AAA Services root */
-static const char kComodo_AAA_Services_rootFingerprint[] =
- "vRU+17BDT2iGsXvOi76E7TQMcTLXAqj0+jGPdW7L1vM=";
-
-/* Comodo Secure Services root */
-static const char kComodo_Secure_Services_rootFingerprint[] =
- "RpHL/ehKa2BS3b4VK7DCFq4lqG5XR4E9vA8UfzOFcL4=";
-
-/* Comodo Trusted Services root */
-static const char kComodo_Trusted_Services_rootFingerprint[] =
- "4tiR77c4ZpEF1TDeXtcuKyrD9KZweLU0mz/ayklvXrg=";
-
-/* Cybertrust Global Root */
-static const char kCybertrust_Global_RootFingerprint[] =
- "foeCwVDOOVL4AuY2AjpdPpW7XWjjPoWtsroXgSXOvxU=";
-
-/* DST Root CA X3 */
-static const char kDST_Root_CA_X3Fingerprint[] =
- "Vjs8r4z+80wjNcr1YKepWQboSIRi63WsWXhIMN+eWys=";
-
-/* DigiCert Assured ID Root CA */
-static const char kDigiCert_Assured_ID_Root_CAFingerprint[] =
- "I/Lt/z7ekCWanjD0Cvj5EqXls2lOaThEA0H2Bg4BT/o=";
-
-/* DigiCert Assured ID Root G2 */
-static const char kDigiCert_Assured_ID_Root_G2Fingerprint[] =
- "8ca6Zwz8iOTfUpc8rkIPCgid1HQUT+WAbEIAZOFZEik=";
-
-/* DigiCert Assured ID Root G3 */
-static const char kDigiCert_Assured_ID_Root_G3Fingerprint[] =
- "Fe7TOVlLME+M+Ee0dzcdjW/sYfTbKwGvWJ58U7Ncrkw=";
-
-/* DigiCert Global Root CA */
-static const char kDigiCert_Global_Root_CAFingerprint[] =
- "r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=";
-
-/* DigiCert Global Root G2 */
-static const char kDigiCert_Global_Root_G2Fingerprint[] =
- "i7WTqTvh0OioIruIfFR4kMPnBqrS2rdiVPl/s2uC/CY=";
-
-/* DigiCert Global Root G3 */
-static const char kDigiCert_Global_Root_G3Fingerprint[] =
- "uUwZgwDOxcBXrQcntwu+kYFpkiVkOaezL0WYEZ3anJc=";
-
-/* DigiCert High Assurance EV Root CA */
-static const char kDigiCert_High_Assurance_EV_Root_CAFingerprint[] =
- "WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=";
-
-/* DigiCert Trusted Root G4 */
-static const char kDigiCert_Trusted_Root_G4Fingerprint[] =
- "Wd8xe/qfTwq3ylFNd3IpaqLHZbh2ZNCLluVzmeNkcpw=";
-
-/* End Entity Test Cert */
-static const char kEnd_Entity_Test_CertFingerprint[] =
- "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=";
-
-/* Entrust Root Certification Authority */
-static const char kEntrust_Root_Certification_AuthorityFingerprint[] =
- "bb+uANN7nNc/j7R95lkXrwDg3d9C286sIMF8AnXuIJU=";
-
-/* Entrust Root Certification Authority - EC1 */
-static const char kEntrust_Root_Certification_Authority___EC1Fingerprint[] =
- "/qK31kX7pz11PB7Jp4cMQOH3sMVh6Se5hb9xGGbjbyI=";
-
-/* Entrust Root Certification Authority - G2 */
-static const char kEntrust_Root_Certification_Authority___G2Fingerprint[] =
- "du6FkDdMcVQ3u8prumAo6t3i3G27uMP2EOhR8R0at/U=";
-
-/* Entrust.net Premium 2048 Secure Server CA */
-static const char kEntrust_net_Premium_2048_Secure_Server_CAFingerprint[] =
- "HqPF5D7WbC2imDpCpKebHpBnhs6fG1hiFBmgBGOofTg=";
-
-/* FacebookBackup */
-static const char kFacebookBackupFingerprint[] =
- "q4PO2G2cbkZhZ82+JgmRUyGMoAeozA+BSXVXQWB8XWQ=";
-
-/* GOOGLE_PIN_COMODORSADomainValidationSecureServerCA */
-static const char kGOOGLE_PIN_COMODORSADomainValidationSecureServerCAFingerprint[] =
- "klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=";
-
-/* GOOGLE_PIN_DigiCertECCSecureServerCA */
-static const char kGOOGLE_PIN_DigiCertECCSecureServerCAFingerprint[] =
- "PZXN3lRAy+8tBKk2Ox6F7jIlnzr2Yzmwqc3JnyfXoCw=";
-
-/* GOOGLE_PIN_DigiCertSHA2HighAssuranceServerCA */
-static const char kGOOGLE_PIN_DigiCertSHA2HighAssuranceServerCAFingerprint[] =
- "k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws=";
-
-/* GOOGLE_PIN_Entrust_SSL */
-static const char kGOOGLE_PIN_Entrust_SSLFingerprint[] =
- "nsxRNo6G40YPZsKV5JQt1TCA8nseQQr/LRqp1Oa8fnw=";
-
-/* GOOGLE_PIN_GTECyberTrustGlobalRoot */
-static const char kGOOGLE_PIN_GTECyberTrustGlobalRootFingerprint[] =
- "EGn6R6CqT4z3ERscrqNl7q7RC//zJmDe9uBhS/rnCHU=";
-
-/* GOOGLE_PIN_GoDaddySecure */
-static const char kGOOGLE_PIN_GoDaddySecureFingerprint[] =
- "MrZLZnJ6IGPkBm87lYywqu5Xal7O/ZUzmbuIdHMdlYc=";
-
-/* GOOGLE_PIN_GoogleG2 */
-static const char kGOOGLE_PIN_GoogleG2Fingerprint[] =
- "7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=";
-
-/* GOOGLE_PIN_LetsEncryptAuthorityBackup_X2_X4 */
-static const char kGOOGLE_PIN_LetsEncryptAuthorityBackup_X2_X4Fingerprint[] =
- "sRHdihwgkaib1P1gxX8HFszlD+7/gTfNvuAybgLPNis=";
-
-/* GOOGLE_PIN_LetsEncryptAuthorityPrimary_X1_X3 */
-static const char kGOOGLE_PIN_LetsEncryptAuthorityPrimary_X1_X3Fingerprint[] =
- "YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=";
-
-/* GOOGLE_PIN_RapidSSL */
-static const char kGOOGLE_PIN_RapidSSLFingerprint[] =
- "lT09gPUeQfbYrlxRtpsHrjDblj9Rpz+u7ajfCrg4qDM=";
-
-/* GOOGLE_PIN_SymantecClass3EVG3 */
-static const char kGOOGLE_PIN_SymantecClass3EVG3Fingerprint[] =
- "gMxWOrX4PMQesK9qFNbYBxjBfjUvlkn/vN1n+L9lE5E=";
-
-/* GOOGLE_PIN_UTNDATACorpSGC */
-static const char kGOOGLE_PIN_UTNDATACorpSGCFingerprint[] =
- "QAL80xHQczFWfnG82XHkYEjI3OjRZZcRdTs9qiommvo=";
-
-/* GOOGLE_PIN_VeriSignClass1 */
-static const char kGOOGLE_PIN_VeriSignClass1Fingerprint[] =
- "LclHC+Y+9KzxvYKGCUArt7h72ZY4pkOTTohoLRvowwg=";
-
-/* GOOGLE_PIN_VeriSignClass2_G2 */
-static const char kGOOGLE_PIN_VeriSignClass2_G2Fingerprint[] =
- "2oALgLKofTmeZvoZ1y/fSZg7R9jPMix8eVA6DH4o/q8=";
-
-/* GOOGLE_PIN_VeriSignClass3_G2 */
-static const char kGOOGLE_PIN_VeriSignClass3_G2Fingerprint[] =
- "AjyBzOjnxk+pQtPBUEhwfTXZu1uH9PVExb8bxWQ68vo=";
-
-/* GOOGLE_PIN_VeriSignClass4_G3 */
-static const char kGOOGLE_PIN_VeriSignClass4_G3Fingerprint[] =
- "VnuCEf0g09KD7gzXzgZyy52ZvFtIeljJ1U7Gf3fUqPU=";
-
-/* GeoTrust Global CA */
-static const char kGeoTrust_Global_CAFingerprint[] =
- "h6801m+z8v3zbgkRHpq6L29Esgfzhj89C1SyUCOQmqU=";
-
-/* GeoTrust Global CA 2 */
-static const char kGeoTrust_Global_CA_2Fingerprint[] =
- "F3VaXClfPS1y5vAxofB/QAxYi55YKyLxfq4xoVkNEYU=";
-
-/* GeoTrust Primary Certification Authority */
-static const char kGeoTrust_Primary_Certification_AuthorityFingerprint[] =
- "SQVGZiOrQXi+kqxcvWWE96HhfydlLVqFr4lQTqI5qqo=";
-
-/* GeoTrust Primary Certification Authority - G2 */
-static const char kGeoTrust_Primary_Certification_Authority___G2Fingerprint[] =
- "vPtEqrmtAhAVcGtBIep2HIHJ6IlnWQ9vlK50TciLePs=";
-
-/* GeoTrust Primary Certification Authority - G3 */
-static const char kGeoTrust_Primary_Certification_Authority___G3Fingerprint[] =
- "q5hJUnat8eyv8o81xTBIeB5cFxjaucjmelBPT2pRMo8=";
-
-/* GeoTrust Universal CA */
-static const char kGeoTrust_Universal_CAFingerprint[] =
- "lpkiXF3lLlbN0y3y6W0c/qWqPKC7Us2JM8I7XCdEOCA=";
-
-/* GeoTrust Universal CA 2 */
-static const char kGeoTrust_Universal_CA_2Fingerprint[] =
- "fKoDRlEkWQxgHlZ+UhSOlSwM/+iQAFMP4NlbbVDqrkE=";
-
-/* GlobalSign ECC Root CA - R4 */
-static const char kGlobalSign_ECC_Root_CA___R4Fingerprint[] =
- "CLOmM1/OXvSPjw5UOYbAf9GKOxImEp9hhku9W90fHMk=";
-
-/* GlobalSign ECC Root CA - R5 */
-static const char kGlobalSign_ECC_Root_CA___R5Fingerprint[] =
- "fg6tdrtoGdwvVFEahDVPboswe53YIFjqbABPAdndpd8=";
-
-/* GlobalSign Root CA */
-static const char kGlobalSign_Root_CAFingerprint[] =
- "K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q=";
-
-/* GlobalSign Root CA - R2 */
-static const char kGlobalSign_Root_CA___R2Fingerprint[] =
- "iie1VXtL7HzAMF+/PVPR9xzT80kQxdZeJ+zduCB3uj0=";
-
-/* GlobalSign Root CA - R3 */
-static const char kGlobalSign_Root_CA___R3Fingerprint[] =
- "cGuxAXyFXFkWm61cF4HPWX8S0srS9j0aSqN0k4AP+4A=";
-
-/* Go Daddy Class 2 CA */
-static const char kGo_Daddy_Class_2_CAFingerprint[] =
- "VjLZe/p3W/PJnd6lL8JVNBCGQBZynFLdZSTIqcO0SJ8=";
-
-/* Go Daddy Root Certificate Authority - G2 */
-static const char kGo_Daddy_Root_Certificate_Authority___G2Fingerprint[] =
- "Ko8tivDrEjiY90yGasP6ZpBU4jwXvHqVvQI0GS3GNdA=";
-
-/* GoogleBackup2048 */
-static const char kGoogleBackup2048Fingerprint[] =
- "IPMbDAjLVSGntGO3WP53X/zilCVndez5YJ2+vJvhJsA=";
-
-/* SpiderOak2 */
-static const char kSpiderOak2Fingerprint[] =
- "7Y3UnxbffL8aFPXsOJBpGasgpDmngpIhAxGKdQRklQQ=";
-
-/* SpiderOak3 */
-static const char kSpiderOak3Fingerprint[] =
- "LkER54vOdlygpTsbYvlpMq1CE/lDAG1AP9xmdtwvV2A=";
-
-/* Starfield Class 2 CA */
-static const char kStarfield_Class_2_CAFingerprint[] =
- "FfFKxFycfaIz00eRZOgTf+Ne4POK6FgYPwhBDqgqxLQ=";
-
-/* Starfield Root Certificate Authority - G2 */
-static const char kStarfield_Root_Certificate_Authority___G2Fingerprint[] =
- "gI1os/q0iEpflxrOfRBVDXqVoWN3Tz7Dav/7IT++THQ=";
-
-/* Swehack */
-static const char kSwehackFingerprint[] =
- "FdaffE799rVb3oyAuhJ2mBW/XJwD07Uajb2G6YwSAEw=";
-
-/* SwehackBackup */
-static const char kSwehackBackupFingerprint[] =
- "z6cuswA6E1vgFkCjUsbEYo0Lf3aP8M8YOvwkoiGzDCo=";
-
-/* TestSPKI */
-static const char kTestSPKIFingerprint[] =
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
-
-/* Tor1 */
-static const char kTor1Fingerprint[] =
- "bYz9JTDk89X3qu3fgswG+lBQso5vI0N1f0Rx4go4nLo=";
-
-/* Tor2 */
-static const char kTor2Fingerprint[] =
- "xXCxhTdn7uxXneJSbQCqoAvuW3ZtQl2pDVTf2sewS8w=";
-
-/* Tor3 */
-static const char kTor3Fingerprint[] =
- "CleC1qwUR8JPgH1nXvSe2VHxDe5/KfNs96EusbfSOfo=";
-
-/* TumblrBackup */
-static const char kTumblrBackupFingerprint[] =
- "avlD96PLERV78IN1fD+ab5cupkUDD9wTZWJjHX6VC9w=";
-
-/* Twitter1 */
-static const char kTwitter1Fingerprint[] =
- "vU9M48LzD/CF34wE5PPf4nBwRyosy06X21J0ap8yS5s=";
-
-/* USERTrust ECC Certification Authority */
-static const char kUSERTrust_ECC_Certification_AuthorityFingerprint[] =
- "ICGRfpgmOUXIWcQ/HXPLQTkFPEFPoDyjvH7ohhQpjzs=";
-
-/* USERTrust RSA Certification Authority */
-static const char kUSERTrust_RSA_Certification_AuthorityFingerprint[] =
- "x4QzPSC810K5/cMjb05Qm4k3Bw5zBn4lTdO/nEW/Td4=";
-
-/* UTN USERFirst Email Root CA */
-static const char kUTN_USERFirst_Email_Root_CAFingerprint[] =
- "Laj56jRU0hFGRko/nQKNxMf7tXscUsc8KwVyovWZotM=";
-
-/* UTN USERFirst Hardware Root CA */
-static const char kUTN_USERFirst_Hardware_Root_CAFingerprint[] =
- "TUDnr0MEoJ3of7+YliBMBVFB4/gJsv5zO7IxD9+YoWI=";
-
-/* UTN USERFirst Object Root CA */
-static const char kUTN_USERFirst_Object_Root_CAFingerprint[] =
- "D+FMJksXu28NZT56cOs2Pb9UvhWAOe3a5cJXEd9IwQM=";
-
-/* VeriSign Class 3 Public Primary Certification Authority - G4 */
-static const char kVeriSign_Class_3_Public_Primary_Certification_Authority___G4Fingerprint[] =
- "UZJDjsNp1+4M5x9cbbdflB779y5YRBcV6Z6rBMLIrO4=";
-
-/* VeriSign Class 3 Public Primary Certification Authority - G5 */
-static const char kVeriSign_Class_3_Public_Primary_Certification_Authority___G5Fingerprint[] =
- "JbQbUG5JMJUoI6brnx0x3vZF6jilxsapbXGVfjhN8Fg=";
-
-/* VeriSign Universal Root Certification Authority */
-static const char kVeriSign_Universal_Root_Certification_AuthorityFingerprint[] =
- "lnsM2T/O9/J84sJFdnrpsFp3awZJ+ZZbYpCWhGloaHI=";
-
-/* Verisign Class 1 Public Primary Certification Authority - G3 */
-static const char kVerisign_Class_1_Public_Primary_Certification_Authority___G3Fingerprint[] =
- "IgduWu9Eu5pBaii30cRDItcFn2D+/6XK9sW+hEeJEwM=";
-
-/* Verisign Class 2 Public Primary Certification Authority - G3 */
-static const char kVerisign_Class_2_Public_Primary_Certification_Authority___G3Fingerprint[] =
- "cAajgxHlj7GTSEIzIYIQxmEloOSoJq7VOaxWHfv72QM=";
-
-/* Verisign Class 3 Public Primary Certification Authority - G3 */
-static const char kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint[] =
- "SVqWumuteCQHvVIaALrOZXuzVVVeS7f4FGxxu6V+es4=";
-
-/* YahooBackup1 */
-static const char kYahooBackup1Fingerprint[] =
- "2fRAUXyxl4A1/XHrKNBmc8bTkzA7y4FB/GLJuNAzCqY=";
-
-/* YahooBackup2 */
-static const char kYahooBackup2Fingerprint[] =
- "dolnbtzEBnELx/9lOEQ22e6OZO/QNb6VSSX2XHA3E7A=";
-
-/* thawte Primary Root CA */
-static const char kthawte_Primary_Root_CAFingerprint[] =
- "HXXQgxueCIU5TTLHob/bPbwcKOKw6DkfsTWYHbxbqTY=";
-
-/* thawte Primary Root CA - G2 */
-static const char kthawte_Primary_Root_CA___G2Fingerprint[] =
- "Z9xPMvoQ59AaeaBzqgyeAhLsL/w9d54Kp/nA8OHCyJM=";
-
-/* thawte Primary Root CA - G3 */
-static const char kthawte_Primary_Root_CA___G3Fingerprint[] =
- "GQbGEk27Q4V40A4GbVBUxsN/D6YCjAVUXgmU7drshik=";
-
-/* Pinsets are each an ordered list by the actual value of the fingerprint */
-struct StaticFingerprints {
- const size_t size;
- const char* const* data;
-};
-
-/* PreloadedHPKPins.json pinsets */
-static const char* const kPinset_google_root_pems_Data[] = {
- kEntrust_Root_Certification_Authority___EC1Fingerprint,
- kComodo_Trusted_Services_rootFingerprint,
- kCOMODO_ECC_Certification_AuthorityFingerprint,
- kDigiCert_Assured_ID_Root_G2Fingerprint,
- kCOMODO_Certification_AuthorityFingerprint,
- kAddTrust_Low_Value_Services_RootFingerprint,
- kGlobalSign_ECC_Root_CA___R4Fingerprint,
- kGeoTrust_Global_CA_2Fingerprint,
- kDigiCert_Assured_ID_Root_G3Fingerprint,
- kStarfield_Class_2_CAFingerprint,
- kthawte_Primary_Root_CA___G3Fingerprint,
- kthawte_Primary_Root_CAFingerprint,
- kEntrust_net_Premium_2048_Secure_Server_CAFingerprint,
- kDigiCert_Assured_ID_Root_CAFingerprint,
- kUSERTrust_ECC_Certification_AuthorityFingerprint,
- kVeriSign_Class_3_Public_Primary_Certification_Authority___G5Fingerprint,
- kGlobalSign_Root_CAFingerprint,
- kGo_Daddy_Root_Certificate_Authority___G2Fingerprint,
- kAffirmTrust_Premium_ECCFingerprint,
- kAddTrust_Public_Services_RootFingerprint,
- kComodo_Secure_Services_rootFingerprint,
- kGeoTrust_Primary_Certification_AuthorityFingerprint,
- kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint,
- kUTN_USERFirst_Hardware_Root_CAFingerprint,
- kVeriSign_Class_3_Public_Primary_Certification_Authority___G4Fingerprint,
- kGo_Daddy_Class_2_CAFingerprint,
- kDigiCert_Trusted_Root_G4Fingerprint,
- kDigiCert_High_Assurance_EV_Root_CAFingerprint,
- kBaltimore_CyberTrust_RootFingerprint,
- kthawte_Primary_Root_CA___G2Fingerprint,
- kAffirmTrust_CommercialFingerprint,
- kEntrust_Root_Certification_AuthorityFingerprint,
- kGlobalSign_Root_CA___R3Fingerprint,
- kEntrust_Root_Certification_Authority___G2Fingerprint,
- kGeoTrust_Universal_CA_2Fingerprint,
- kGlobalSign_ECC_Root_CA___R5Fingerprint,
- kCybertrust_Global_RootFingerprint,
- kStarfield_Root_Certificate_Authority___G2Fingerprint,
- kCOMODO_RSA_Certification_AuthorityFingerprint,
- kGeoTrust_Global_CAFingerprint,
- kDigiCert_Global_Root_G2Fingerprint,
- kGlobalSign_Root_CA___R2Fingerprint,
- kAffirmTrust_NetworkingFingerprint,
- kAddTrust_External_RootFingerprint,
- kVeriSign_Universal_Root_Certification_AuthorityFingerprint,
- kGeoTrust_Universal_CAFingerprint,
- kGeoTrust_Primary_Certification_Authority___G3Fingerprint,
- kDigiCert_Global_Root_CAFingerprint,
- kDigiCert_Global_Root_G3Fingerprint,
- kGeoTrust_Primary_Certification_Authority___G2Fingerprint,
- kComodo_AAA_Services_rootFingerprint,
- kAffirmTrust_PremiumFingerprint,
- kUSERTrust_RSA_Certification_AuthorityFingerprint,
- kAddTrust_Qualified_Certificates_RootFingerprint,
-};
-static const StaticFingerprints kPinset_google_root_pems = {
- sizeof(kPinset_google_root_pems_Data) / sizeof(const char*),
- kPinset_google_root_pems_Data
-};
-
-static const char* const kPinset_mozilla_Data[] = {
- kGeoTrust_Global_CA_2Fingerprint,
- kthawte_Primary_Root_CA___G3Fingerprint,
- kthawte_Primary_Root_CAFingerprint,
- kDigiCert_Assured_ID_Root_CAFingerprint,
- kVerisign_Class_1_Public_Primary_Certification_Authority___G3Fingerprint,
- kVeriSign_Class_3_Public_Primary_Certification_Authority___G5Fingerprint,
- kGeoTrust_Primary_Certification_AuthorityFingerprint,
- kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint,
- kVeriSign_Class_3_Public_Primary_Certification_Authority___G4Fingerprint,
- kDigiCert_High_Assurance_EV_Root_CAFingerprint,
- kBaltimore_CyberTrust_RootFingerprint,
- kthawte_Primary_Root_CA___G2Fingerprint,
- kVerisign_Class_2_Public_Primary_Certification_Authority___G3Fingerprint,
- kGeoTrust_Universal_CA_2Fingerprint,
- kGeoTrust_Global_CAFingerprint,
- kVeriSign_Universal_Root_Certification_AuthorityFingerprint,
- kGeoTrust_Universal_CAFingerprint,
- kGeoTrust_Primary_Certification_Authority___G3Fingerprint,
- kDigiCert_Global_Root_CAFingerprint,
- kGeoTrust_Primary_Certification_Authority___G2Fingerprint,
-};
-static const StaticFingerprints kPinset_mozilla = {
- sizeof(kPinset_mozilla_Data) / sizeof(const char*),
- kPinset_mozilla_Data
-};
-
-static const char* const kPinset_mozilla_services_Data[] = {
- kDigiCert_Global_Root_CAFingerprint,
-};
-static const StaticFingerprints kPinset_mozilla_services = {
- sizeof(kPinset_mozilla_services_Data) / sizeof(const char*),
- kPinset_mozilla_services_Data
-};
-
-static const char* const kPinset_mozilla_test_Data[] = {
- kEnd_Entity_Test_CertFingerprint,
-};
-static const StaticFingerprints kPinset_mozilla_test = {
- sizeof(kPinset_mozilla_test_Data) / sizeof(const char*),
- kPinset_mozilla_test_Data
-};
-
-/* Chrome static pinsets */
-static const char* const kPinset_test_Data[] = {
- kTestSPKIFingerprint,
-};
-static const StaticFingerprints kPinset_test = {
- sizeof(kPinset_test_Data) / sizeof(const char*),
- kPinset_test_Data
-};
-
-static const char* const kPinset_google_Data[] = {
- kGOOGLE_PIN_GoogleG2Fingerprint,
- kGoogleBackup2048Fingerprint,
- kGeoTrust_Global_CAFingerprint,
- kGlobalSign_Root_CA___R2Fingerprint,
-};
-static const StaticFingerprints kPinset_google = {
- sizeof(kPinset_google_Data) / sizeof(const char*),
- kPinset_google_Data
-};
-
-static const char* const kPinset_tor_Data[] = {
- kTor3Fingerprint,
- kDigiCert_High_Assurance_EV_Root_CAFingerprint,
- kGOOGLE_PIN_LetsEncryptAuthorityPrimary_X1_X3Fingerprint,
- kTor1Fingerprint,
- kGOOGLE_PIN_RapidSSLFingerprint,
- kGOOGLE_PIN_LetsEncryptAuthorityBackup_X2_X4Fingerprint,
- kTor2Fingerprint,
-};
-static const StaticFingerprints kPinset_tor = {
- sizeof(kPinset_tor_Data) / sizeof(const char*),
- kPinset_tor_Data
-};
-
-static const char* const kPinset_twitterCom_Data[] = {
- kGOOGLE_PIN_VeriSignClass2_G2Fingerprint,
- kGOOGLE_PIN_VeriSignClass3_G2Fingerprint,
- kGeoTrust_Global_CA_2Fingerprint,
- kDigiCert_Assured_ID_Root_CAFingerprint,
- kVerisign_Class_1_Public_Primary_Certification_Authority___G3Fingerprint,
- kVeriSign_Class_3_Public_Primary_Certification_Authority___G5Fingerprint,
- kGOOGLE_PIN_VeriSignClass1Fingerprint,
- kGeoTrust_Primary_Certification_AuthorityFingerprint,
- kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint,
- kVeriSign_Class_3_Public_Primary_Certification_Authority___G4Fingerprint,
- kGOOGLE_PIN_VeriSignClass4_G3Fingerprint,
- kDigiCert_High_Assurance_EV_Root_CAFingerprint,
- kVerisign_Class_2_Public_Primary_Certification_Authority___G3Fingerprint,
- kGeoTrust_Universal_CA_2Fingerprint,
- kGeoTrust_Global_CAFingerprint,
- kVeriSign_Universal_Root_Certification_AuthorityFingerprint,
- kGeoTrust_Universal_CAFingerprint,
- kGeoTrust_Primary_Certification_Authority___G3Fingerprint,
- kDigiCert_Global_Root_CAFingerprint,
- kGeoTrust_Primary_Certification_Authority___G2Fingerprint,
- kTwitter1Fingerprint,
-};
-static const StaticFingerprints kPinset_twitterCom = {
- sizeof(kPinset_twitterCom_Data) / sizeof(const char*),
- kPinset_twitterCom_Data
-};
-
-static const char* const kPinset_twitterCDN_Data[] = {
- kGOOGLE_PIN_VeriSignClass2_G2Fingerprint,
- kComodo_Trusted_Services_rootFingerprint,
- kCOMODO_Certification_AuthorityFingerprint,
- kGOOGLE_PIN_VeriSignClass3_G2Fingerprint,
- kAddTrust_Low_Value_Services_RootFingerprint,
- kUTN_USERFirst_Object_Root_CAFingerprint,
- kGOOGLE_PIN_GTECyberTrustGlobalRootFingerprint,
- kGeoTrust_Global_CA_2Fingerprint,
- kEntrust_net_Premium_2048_Secure_Server_CAFingerprint,
- kDigiCert_Assured_ID_Root_CAFingerprint,
- kVerisign_Class_1_Public_Primary_Certification_Authority___G3Fingerprint,
- kVeriSign_Class_3_Public_Primary_Certification_Authority___G5Fingerprint,
- kGlobalSign_Root_CAFingerprint,
- kUTN_USERFirst_Email_Root_CAFingerprint,
- kGOOGLE_PIN_VeriSignClass1Fingerprint,
- kAddTrust_Public_Services_RootFingerprint,
- kGOOGLE_PIN_UTNDATACorpSGCFingerprint,
- kComodo_Secure_Services_rootFingerprint,
- kGeoTrust_Primary_Certification_AuthorityFingerprint,
- kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint,
- kUTN_USERFirst_Hardware_Root_CAFingerprint,
- kVeriSign_Class_3_Public_Primary_Certification_Authority___G4Fingerprint,
- kGOOGLE_PIN_VeriSignClass4_G3Fingerprint,
- kDigiCert_High_Assurance_EV_Root_CAFingerprint,
- kBaltimore_CyberTrust_RootFingerprint,
- kEntrust_Root_Certification_AuthorityFingerprint,
- kVerisign_Class_2_Public_Primary_Certification_Authority___G3Fingerprint,
- kGlobalSign_Root_CA___R3Fingerprint,
- kEntrust_Root_Certification_Authority___G2Fingerprint,
- kGeoTrust_Universal_CA_2Fingerprint,
- kGeoTrust_Global_CAFingerprint,
- kGlobalSign_Root_CA___R2Fingerprint,
- kAddTrust_External_RootFingerprint,
- kVeriSign_Universal_Root_Certification_AuthorityFingerprint,
- kGeoTrust_Universal_CAFingerprint,
- kGOOGLE_PIN_Entrust_SSLFingerprint,
- kGeoTrust_Primary_Certification_Authority___G3Fingerprint,
- kDigiCert_Global_Root_CAFingerprint,
- kGeoTrust_Primary_Certification_Authority___G2Fingerprint,
- kComodo_AAA_Services_rootFingerprint,
- kTwitter1Fingerprint,
- kAddTrust_Qualified_Certificates_RootFingerprint,
-};
-static const StaticFingerprints kPinset_twitterCDN = {
- sizeof(kPinset_twitterCDN_Data) / sizeof(const char*),
- kPinset_twitterCDN_Data
-};
-
-static const char* const kPinset_dropbox_Data[] = {
- kEntrust_Root_Certification_Authority___EC1Fingerprint,
- kEntrust_net_Premium_2048_Secure_Server_CAFingerprint,
- kDigiCert_Assured_ID_Root_CAFingerprint,
- kGo_Daddy_Root_Certificate_Authority___G2Fingerprint,
- kGOOGLE_PIN_GoDaddySecureFingerprint,
- kGo_Daddy_Class_2_CAFingerprint,
- kDigiCert_High_Assurance_EV_Root_CAFingerprint,
- kEntrust_Root_Certification_AuthorityFingerprint,
- kEntrust_Root_Certification_Authority___G2Fingerprint,
- kDigiCert_Global_Root_CAFingerprint,
-};
-static const StaticFingerprints kPinset_dropbox = {
- sizeof(kPinset_dropbox_Data) / sizeof(const char*),
- kPinset_dropbox_Data
-};
-
-static const char* const kPinset_facebook_Data[] = {
- kGOOGLE_PIN_DigiCertECCSecureServerCAFingerprint,
- kDigiCert_High_Assurance_EV_Root_CAFingerprint,
- kGOOGLE_PIN_SymantecClass3EVG3Fingerprint,
- kFacebookBackupFingerprint,
-};
-static const StaticFingerprints kPinset_facebook = {
- sizeof(kPinset_facebook_Data) / sizeof(const char*),
- kPinset_facebook_Data
-};
-
-static const char* const kPinset_spideroak_Data[] = {
- kSpiderOak2Fingerprint,
- kSpiderOak3Fingerprint,
- kDigiCert_High_Assurance_EV_Root_CAFingerprint,
- kGeoTrust_Global_CAFingerprint,
-};
-static const StaticFingerprints kPinset_spideroak = {
- sizeof(kPinset_spideroak_Data) / sizeof(const char*),
- kPinset_spideroak_Data
-};
-
-static const char* const kPinset_yahoo_Data[] = {
- kYahooBackup1Fingerprint,
- kGOOGLE_PIN_VeriSignClass2_G2Fingerprint,
- kDigiCert_Assured_ID_Root_CAFingerprint,
- kVeriSign_Class_3_Public_Primary_Certification_Authority___G5Fingerprint,
- kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint,
- kVeriSign_Class_3_Public_Primary_Certification_Authority___G4Fingerprint,
- kDigiCert_Trusted_Root_G4Fingerprint,
- kDigiCert_High_Assurance_EV_Root_CAFingerprint,
- kVerisign_Class_2_Public_Primary_Certification_Authority___G3Fingerprint,
- kYahooBackup2Fingerprint,
- kDigiCert_Global_Root_G2Fingerprint,
- kVeriSign_Universal_Root_Certification_AuthorityFingerprint,
- kDigiCert_Global_Root_CAFingerprint,
- kDigiCert_Global_Root_G3Fingerprint,
-};
-static const StaticFingerprints kPinset_yahoo = {
- sizeof(kPinset_yahoo_Data) / sizeof(const char*),
- kPinset_yahoo_Data
-};
-
-static const char* const kPinset_swehackCom_Data[] = {
- kSwehackFingerprint,
- kDST_Root_CA_X3Fingerprint,
- kGOOGLE_PIN_LetsEncryptAuthorityPrimary_X1_X3Fingerprint,
- kGOOGLE_PIN_COMODORSADomainValidationSecureServerCAFingerprint,
- kGOOGLE_PIN_LetsEncryptAuthorityBackup_X2_X4Fingerprint,
- kSwehackBackupFingerprint,
-};
-static const StaticFingerprints kPinset_swehackCom = {
- sizeof(kPinset_swehackCom_Data) / sizeof(const char*),
- kPinset_swehackCom_Data
-};
-
-static const char* const kPinset_ncsccs_Data[] = {
- kCOMODO_ECC_Certification_AuthorityFingerprint,
- kDigiCert_Assured_ID_Root_CAFingerprint,
- kDigiCert_High_Assurance_EV_Root_CAFingerprint,
- kBaltimore_CyberTrust_RootFingerprint,
- kGOOGLE_PIN_LetsEncryptAuthorityPrimary_X1_X3Fingerprint,
- kCOMODO_RSA_Certification_AuthorityFingerprint,
- kAddTrust_External_RootFingerprint,
- kDigiCert_Global_Root_CAFingerprint,
- kGOOGLE_PIN_LetsEncryptAuthorityBackup_X2_X4Fingerprint,
-};
-static const StaticFingerprints kPinset_ncsccs = {
- sizeof(kPinset_ncsccs_Data) / sizeof(const char*),
- kPinset_ncsccs_Data
-};
-
-static const char* const kPinset_tumblr_Data[] = {
- kDigiCert_High_Assurance_EV_Root_CAFingerprint,
- kTumblrBackupFingerprint,
- kGOOGLE_PIN_DigiCertSHA2HighAssuranceServerCAFingerprint,
-};
-static const StaticFingerprints kPinset_tumblr = {
- sizeof(kPinset_tumblr_Data) / sizeof(const char*),
- kPinset_tumblr_Data
-};
-
-/* Domainlist */
-struct TransportSecurityPreload {
- const char* mHost;
- const bool mIncludeSubdomains;
- const bool mTestMode;
- const bool mIsMoz;
- const int32_t mId;
- const StaticFingerprints* pinset;
-};
-
-/* Sort hostnames for binary search. */
-static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
- { "exclude-subdomains.pinning.example.com", false, false, false, 0, &kPinset_mozilla_test },
- { "include-subdomains.pinning.example.com", true, false, false, -1, &kPinset_mozilla_test },
- { "test-mode.pinning.example.com", true, true, false, -1, &kPinset_mozilla_test },
-};
-
-// Pinning Preload List Length = 3;
-
-static const int32_t kUnknownId = -1;
-
-static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1609459199000000);
diff --git a/security/manager/ssl/moz.build b/security/manager/ssl/moz.build
index 8f4c6e9da..151c5b88a 100644
--- a/security/manager/ssl/moz.build
+++ b/security/manager/ssl/moz.build
@@ -132,7 +132,6 @@ UNIFIED_SOURCES += [
'nsTLSSocketProvider.cpp',
'PSMContentListener.cpp',
'PSMRunnable.cpp',
- 'PublicKeyPinningService.cpp',
'SecretDecoderRing.cpp',
'SharedSSLState.cpp',
'SSLServerCertVerification.cpp',
diff --git a/security/manager/ssl/nsISiteSecurityService.idl b/security/manager/ssl/nsISiteSecurityService.idl
index 4286848a9..d0e5f61ed 100644
--- a/security/manager/ssl/nsISiteSecurityService.idl
+++ b/security/manager/ssl/nsISiteSecurityService.idl
@@ -27,7 +27,7 @@ namespace mozilla
interface nsISiteSecurityService : nsISupports
{
const uint32_t HEADER_HSTS = 0;
- const uint32_t HEADER_HPKP = 1;
+ const uint32_t HEADER_HPKP = 1; /* no longer used */
const uint32_t HEADER_OMS = 2;
const uint32_t Success = 0;
@@ -39,10 +39,10 @@ interface nsISiteSecurityService : nsISupports
const uint32_t ERROR_INVALID_MAX_AGE = 6;
const uint32_t ERROR_MULTIPLE_INCLUDE_SUBDOMAINS = 7;
const uint32_t ERROR_INVALID_INCLUDE_SUBDOMAINS = 8;
- const uint32_t ERROR_INVALID_PIN = 9;
- const uint32_t ERROR_MULTIPLE_REPORT_URIS = 10;
- const uint32_t ERROR_PINSET_DOES_NOT_MATCH_CHAIN = 11;
- const uint32_t ERROR_NO_BACKUP_PIN = 12;
+ const uint32_t ERROR_INVALID_PIN = 9; /* no longer used */
+ const uint32_t ERROR_MULTIPLE_REPORT_URIS = 10; /* no longer used */
+ const uint32_t ERROR_PINSET_DOES_NOT_MATCH_CHAIN = 11; /* no longer used */
+ const uint32_t ERROR_NO_BACKUP_PIN = 12; /* no longer used */
const uint32_t ERROR_COULD_NOT_SAVE_STATE = 13;
const uint32_t ERROR_ROOT_NOT_BUILT_IN = 14;
@@ -150,42 +150,6 @@ interface nsISiteSecurityService : nsISupports
* settings.
*/
void clearAll();
-
- /**
- * Returns an array of sha256-hashed key pins for the given domain, if any.
- * If these pins also apply to subdomains of the given domain,
- * aIncludeSubdomains will be true. Pins returned are only for non-built-in
- * pin entries.
- *
- * @param aHostname the hosname (punycode) to be queried about
- * @param the time at which the pins should be valid. This is in
- mozilla::pkix::Time which uses internally seconds since 0 AD.
- * @param aPinArray the set of sha256-hashed key pins for the given domain
- * @param aIncludeSubdomains true if the pins apply to subdomains of the
- * given domain
- */
- [noscript] boolean getKeyPinsForHostname(in string aHostname,
- in mozillaPkixTime evalTime,
- out nsCStringTArrayRef aPinArray,
- out boolean aIncludeSubdomains);
-
- /**
- * Set public-key pins for a host. The resulting pins will be permanent
- * and visible from private and non-private contexts. These pins replace
- * any already set by this mechanism or those built-in to Gecko.
- *
- * @param aHost the hostname (punycode) that pins will apply to
- * @param aIncludeSubdomains whether these pins also apply to subdomains
- * @param aExpires the time this pin should expire (millis since epoch)
- * @param aPinCount number of keys being pinnned
- * @param aSha256Pins array of hashed key fingerprints (SHA-256, base64)
- * @param aIsPreload are these key pins for a preload entry? (false by
- * default)
- */
- boolean setKeyPins(in string aHost, in boolean aIncludeSubdomains,
- in int64_t aExpires, in unsigned long aPinCount,
- [array, size_is(aPinCount)] in string aSha256Pins,
- [optional] in boolean aIsPreload);
};
%{C++
diff --git a/security/manager/ssl/nsSiteSecurityService.cpp b/security/manager/ssl/nsSiteSecurityService.cpp
index f78be1bad..fa2619414 100644
--- a/security/manager/ssl/nsSiteSecurityService.cpp
+++ b/security/manager/ssl/nsSiteSecurityService.cpp
@@ -25,7 +25,6 @@
#include "mozilla/Logging.h"
#include "prnetdb.h"
#include "prprf.h"
-#include "PublicKeyPinningService.h"
#include "ScopedNSSTypes.h"
#include "SharedCertVerifier.h"
@@ -87,122 +86,30 @@ SiteHSTSState::ToString(nsCString& aString)
}
////////////////////////////////////////////////////////////////////////////////
-static bool
-stringIsBase64EncodingOf256bitValue(nsCString& encodedString) {
- nsAutoCString binaryValue;
- nsresult rv = mozilla::Base64Decode(encodedString, binaryValue);
- if (NS_FAILED(rv)) {
- return false;
- }
- if (binaryValue.Length() != SHA256_LENGTH) {
- return false;
- }
- return true;
-}
-
-SiteHPKPState::SiteHPKPState()
- : mExpireTime(0)
- , mState(SecurityPropertyUnset)
- , mIncludeSubdomains(false)
-{
-}
-SiteHPKPState::SiteHPKPState(nsCString& aStateString)
- : mExpireTime(0)
- , mState(SecurityPropertyUnset)
- , mIncludeSubdomains(false)
-{
- uint32_t hpkpState = 0;
- uint32_t hpkpIncludeSubdomains = 0; // PR_sscanf doesn't handle bools.
- const uint32_t MaxMergedHPKPPinSize = 1024;
- char mergedHPKPins[MaxMergedHPKPPinSize];
- memset(mergedHPKPins, 0, MaxMergedHPKPPinSize);
-
- if (aStateString.Length() >= MaxMergedHPKPPinSize) {
- SSSLOG(("SSS: Cannot parse PKPState string, too large\n"));
- return;
- }
-
- int32_t matches = PR_sscanf(aStateString.get(), "%lld,%lu,%lu,%s",
- &mExpireTime, &hpkpState,
- &hpkpIncludeSubdomains, mergedHPKPins);
- bool valid = (matches == 4 &&
- (hpkpIncludeSubdomains == 0 || hpkpIncludeSubdomains == 1) &&
- ((SecurityPropertyState)hpkpState == SecurityPropertyUnset ||
- (SecurityPropertyState)hpkpState == SecurityPropertySet ||
- (SecurityPropertyState)hpkpState == SecurityPropertyKnockout));
-
- SSSLOG(("SSS: loading SiteHPKPState matches=%d\n", matches));
- const uint32_t SHA256Base64Len = 44;
-
- if (valid && (SecurityPropertyState)hpkpState == SecurityPropertySet) {
- // try to expand the merged PKPins
- const char* cur = mergedHPKPins;
- nsAutoCString pin;
- uint32_t collectedLen = 0;
- mergedHPKPins[MaxMergedHPKPPinSize - 1] = 0;
- size_t totalLen = strlen(mergedHPKPins);
- while (collectedLen + SHA256Base64Len <= totalLen) {
- pin.Assign(cur, SHA256Base64Len);
- if (stringIsBase64EncodingOf256bitValue(pin)) {
- mSHA256keys.AppendElement(pin);
- }
- cur += SHA256Base64Len;
- collectedLen += SHA256Base64Len;
- }
- if (mSHA256keys.IsEmpty()) {
- valid = false;
- }
- }
- if (valid) {
- mState = (SecurityPropertyState)hpkpState;
- mIncludeSubdomains = (hpkpIncludeSubdomains == 1);
- } else {
- SSSLOG(("%s is not a valid SiteHPKPState", aStateString.get()));
- mExpireTime = 0;
- mState = SecurityPropertyUnset;
- mIncludeSubdomains = false;
- if (!mSHA256keys.IsEmpty()) {
- mSHA256keys.Clear();
- }
- }
-}
+const uint64_t kSixtyDaysInSeconds = 60 * 24 * 60 * 60;
-SiteHPKPState::SiteHPKPState(PRTime aExpireTime,
- SecurityPropertyState aState,
- bool aIncludeSubdomains,
- nsTArray<nsCString>& aSHA256keys)
- : mExpireTime(aExpireTime)
- , mState(aState)
- , mIncludeSubdomains(aIncludeSubdomains)
- , mSHA256keys(aSHA256keys)
+static bool
+HostIsIPAddress(const char *hostname)
{
+ PRNetAddr hostAddr;
+ return (PR_StringToNetAddr(hostname, &hostAddr) == PR_SUCCESS);
}
-void
-SiteHPKPState::ToString(nsCString& aString)
+nsAutoCString CanonicalizeHostname(const char* hostname)
{
- aString.Truncate();
- aString.AppendInt(mExpireTime);
- aString.Append(',');
- aString.AppendInt(mState);
- aString.Append(',');
- aString.AppendInt(static_cast<uint32_t>(mIncludeSubdomains));
- aString.Append(',');
- for (unsigned int i = 0; i < mSHA256keys.Length(); i++) {
- aString.Append(mSHA256keys[i]);
+ nsAutoCString canonicalizedHostname(hostname);
+ ToLowerCase(canonicalizedHostname);
+ while (canonicalizedHostname.Length() > 0 &&
+ canonicalizedHostname.Last() == '.') {
+ canonicalizedHostname.Truncate(canonicalizedHostname.Length() - 1);
}
+ return canonicalizedHostname;
}
-////////////////////////////////////////////////////////////////////////////////
-
-const uint64_t kSixtyDaysInSeconds = 60 * 24 * 60 * 60;
-
nsSiteSecurityService::nsSiteSecurityService()
- : mMaxMaxAge(kSixtyDaysInSeconds)
- , mUseStsService(true)
+ : mUseStsService(true)
, mPreloadListTimeOffset(0)
- , mHPKPEnabled(false)
{
}
@@ -223,30 +130,16 @@ nsSiteSecurityService::Init()
return NS_ERROR_NOT_SAME_THREAD;
}
- mMaxMaxAge = mozilla::Preferences::GetInt(
- "security.cert_pinning.max_max_age_seconds", kSixtyDaysInSeconds);
- mozilla::Preferences::AddStrongObserver(this,
- "security.cert_pinning.max_max_age_seconds");
- mHPKPEnabled = mozilla::Preferences::GetBool(
- "security.cert_pinning.hpkp.enabled", false);
- mozilla::Preferences::AddStrongObserver(this,
- "security.cert_pinning.hpkp.enabled");
mUseStsService = mozilla::Preferences::GetBool(
"network.stricttransportsecurity.enabled", true);
mozilla::Preferences::AddStrongObserver(this,
"network.stricttransportsecurity.enabled");
- mProcessPKPHeadersFromNonBuiltInRoots = mozilla::Preferences::GetBool(
- "security.cert_pinning.process_headers_from_non_builtin_roots", false);
- mozilla::Preferences::AddStrongObserver(this,
- "security.cert_pinning.process_headers_from_non_builtin_roots");
mPreloadListTimeOffset = mozilla::Preferences::GetInt(
"test.currentTimeOffsetSeconds", 0);
mozilla::Preferences::AddStrongObserver(this,
"test.currentTimeOffsetSeconds");
mSiteStateStorage =
mozilla::DataStorage::Get(NS_LITERAL_STRING("SiteSecurityServiceState.txt"));
- mPreloadStateStorage =
- mozilla::DataStorage::Get(NS_LITERAL_STRING("SecurityPreloadState.txt"));
bool storageWillPersist = false;
nsresult rv = mSiteStateStorage->Init(storageWillPersist);
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -276,7 +169,7 @@ nsSiteSecurityService::GetHost(nsIURI* aURI, nsACString& aResult)
return rv;
}
- aResult.Assign(PublicKeyPinningService::CanonicalizeHostname(host.get()));
+ aResult.Assign(CanonicalizeHostname(host.get()));
if (aResult.IsEmpty()) {
return NS_ERROR_UNEXPECTED;
}
@@ -292,9 +185,6 @@ SetStorageKey(nsAutoCString& storageKey, nsCString& hostname, uint32_t aType)
case nsISiteSecurityService::HEADER_HSTS:
storageKey.AppendLiteral(":HSTS");
break;
- case nsISiteSecurityService::HEADER_HPKP:
- storageKey.AppendLiteral(":HPKP");
- break;
default:
NS_ASSERTION(false, "SSS:SetStorageKey got invalid type");
}
@@ -359,8 +249,7 @@ nsSiteSecurityService::RemoveState(uint32_t aType, nsIURI* aURI, uint32_t aFlags
}
// Only HSTS is supported at the moment.
- NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS ||
- aType == nsISiteSecurityService::HEADER_HPKP,
+ NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS,
NS_ERROR_NOT_IMPLEMENTED);
nsAutoCString hostname;
@@ -379,13 +268,6 @@ nsSiteSecurityService::RemoveState(uint32_t aType, nsIURI* aURI, uint32_t aFlags
return NS_OK;
}
-static bool
-HostIsIPAddress(const char *hostname)
-{
- PRNetAddr hostAddr;
- return (PR_StringToNetAddr(hostname, &hostAddr) == PR_SUCCESS);
-}
-
NS_IMETHODIMP
nsSiteSecurityService::ProcessHeader(uint32_t aType,
nsIURI* aSourceURI,
@@ -396,11 +278,6 @@ nsSiteSecurityService::ProcessHeader(uint32_t aType,
bool* aIncludeSubdomains,
uint32_t* aFailureResult)
{
- // Child processes are not allowed direct access to this.
- if (!XRE_IsParentProcess()) {
- MOZ_CRASH("Child process: no direct access to nsISiteSecurityService::ProcessHeader");
- }
-
if (aFailureResult) {
*aFailureResult = nsISiteSecurityService::ERROR_UNKNOWN;
}
@@ -422,11 +299,6 @@ nsSiteSecurityService::UnsafeProcessHeader(uint32_t aType,
bool* aIncludeSubdomains,
uint32_t* aFailureResult)
{
- // Child processes are not allowed direct access to this.
- if (!XRE_IsParentProcess()) {
- MOZ_CRASH("Child process: no direct access to nsISiteSecurityService::UnsafeProcessHeader");
- }
-
return ProcessHeaderInternal(aType, aSourceURI, aHeader, nullptr, aFlags,
aMaxAge, aIncludeSubdomains, aFailureResult);
}
@@ -444,9 +316,8 @@ nsSiteSecurityService::ProcessHeaderInternal(uint32_t aType,
if (aFailureResult) {
*aFailureResult = nsISiteSecurityService::ERROR_UNKNOWN;
}
- // Only HSTS and HPKP are supported at the moment.
- NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS ||
- aType == nsISiteSecurityService::HEADER_HPKP,
+ // Only HSTS is supported at the moment.
+ NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS,
NS_ERROR_NOT_IMPLEMENTED);
if (aMaxAge != nullptr) {
@@ -494,10 +365,6 @@ nsSiteSecurityService::ProcessHeaderInternal(uint32_t aType,
rv = ProcessSTSHeader(aSourceURI, aHeader, aFlags, aMaxAge,
aIncludeSubdomains, aFailureResult);
break;
- case nsISiteSecurityService::HEADER_HPKP:
- rv = ProcessPKPHeader(aSourceURI, aHeader, aSSLStatus, aFlags, aMaxAge,
- aIncludeSubdomains, aFailureResult);
- break;
default:
MOZ_CRASH("unexpected header type");
}
@@ -513,9 +380,6 @@ ParseSSSHeaders(uint32_t aType,
uint64_t& maxAge,
nsTArray<nsCString>& sha256keys)
{
- // Strict transport security and Public Key Pinning have very similar
- // Header formats.
-
// "Strict-Transport-Security" ":" OWS
// STS-d *( OWS ";" OWS STS-d OWS)
//
@@ -527,26 +391,6 @@ ParseSSSHeaders(uint32_t aType,
// includeSubDomains = [ "includeSubDomains" ]
//
- // "Public-Key-Pins ":" OWS
- // PKP-d *( OWS ";" OWS PKP-d OWS)
- //
- // ; PKP directive
- // PKP-d = maxAge / includeSubDomains / reportUri / pin-directive
- //
- // maxAge = "max-age" "=" delta-seconds v-ext
- //
- // includeSubDomains = [ "includeSubDomains" ]
- //
- // reportURi = "report-uri" "=" quoted-string
- //
- // pin-directive = "pin-" token "=" quoted-string
- //
- // the only valid token currently specified is sha256
- // the quoted string for a pin directive is the base64 encoding
- // of the hash of the public key of the fingerprint
- //
-
- // The order of the directives is not significant.
// All directives must appear only once.
// Directive names are case-insensitive.
// The entire header is invalid if a directive not conforming to the
@@ -558,8 +402,6 @@ ParseSSSHeaders(uint32_t aType,
NS_NAMED_LITERAL_CSTRING(max_age_var, "max-age");
NS_NAMED_LITERAL_CSTRING(include_subd_var, "includesubdomains");
- NS_NAMED_LITERAL_CSTRING(pin_sha256_var, "pin-sha256");
- NS_NAMED_LITERAL_CSTRING(report_uri_var, "report-uri");
nsSecurityHeaderParser parser(aHeader);
nsresult rv = parser.Parse();
@@ -614,29 +456,7 @@ ParseSSSHeaders(uint32_t aType,
directive->mValue.get()));
return nsISiteSecurityService::ERROR_INVALID_INCLUDE_SUBDOMAINS;
}
- } else if (aType == nsISiteSecurityService::HEADER_HPKP &&
- directive->mName.Length() == pin_sha256_var.Length() &&
- directive->mName.EqualsIgnoreCase(pin_sha256_var.get(),
- pin_sha256_var.Length())) {
- SSSLOG(("SSS: found pinning entry '%s' length=%d",
- directive->mValue.get(), directive->mValue.Length()));
- if (!stringIsBase64EncodingOf256bitValue(directive->mValue)) {
- return nsISiteSecurityService::ERROR_INVALID_PIN;
- }
- sha256keys.AppendElement(directive->mValue);
- } else if (aType == nsISiteSecurityService::HEADER_HPKP &&
- directive->mName.Length() == report_uri_var.Length() &&
- directive->mName.EqualsIgnoreCase(report_uri_var.get(),
- report_uri_var.Length())) {
- // We don't support the report-uri yet, but to avoid unrecognized
- // directive warnings, we still have to handle its presence
- if (foundReportURI) {
- SSSLOG(("SSS: found two report-uri directives"));
- return nsISiteSecurityService::ERROR_MULTIPLE_REPORT_URIS;
- }
- SSSLOG(("SSS: found report-uri directive"));
- foundReportURI = true;
- } else {
+ } else {
SSSLOG(("SSS: ignoring unrecognized directive '%s'",
directive->mName.get()));
foundUnrecognizedDirective = true;
@@ -646,194 +466,6 @@ ParseSSSHeaders(uint32_t aType,
}
nsresult
-nsSiteSecurityService::ProcessPKPHeader(nsIURI* aSourceURI,
- const char* aHeader,
- nsISSLStatus* aSSLStatus,
- uint32_t aFlags,
- uint64_t* aMaxAge,
- bool* aIncludeSubdomains,
- uint32_t* aFailureResult)
-{
- if (aFailureResult) {
- *aFailureResult = nsISiteSecurityService::ERROR_UNKNOWN;
- }
- if (!mHPKPEnabled) {
- SSSLOG(("SSS: HPKP disabled: not processing header '%s'", aHeader));
- if (aMaxAge) {
- *aMaxAge = 0;
- }
- if (aIncludeSubdomains) {
- *aIncludeSubdomains = false;
- }
- return NS_OK;
- }
-
- SSSLOG(("SSS: processing HPKP header '%s'", aHeader));
- NS_ENSURE_ARG(aSSLStatus);
-
- const uint32_t aType = nsISiteSecurityService::HEADER_HPKP;
- bool foundMaxAge = false;
- bool foundIncludeSubdomains = false;
- bool foundUnrecognizedDirective = false;
- uint64_t maxAge = 0;
- nsTArray<nsCString> sha256keys;
- uint32_t sssrv = ParseSSSHeaders(aType, aHeader, foundIncludeSubdomains,
- foundMaxAge, foundUnrecognizedDirective,
- maxAge, sha256keys);
- if (sssrv != nsISiteSecurityService::Success) {
- if (aFailureResult) {
- *aFailureResult = sssrv;
- }
- return NS_ERROR_FAILURE;
- }
-
- // after processing all the directives, make sure we came across max-age
- // somewhere.
- if (!foundMaxAge) {
- SSSLOG(("SSS: did not encounter required max-age directive"));
- if (aFailureResult) {
- *aFailureResult = nsISiteSecurityService::ERROR_NO_MAX_AGE;
- }
- return NS_ERROR_FAILURE;
- }
-
- // before we add the pin we need to ensure it will not break the site as
- // currently visited so:
- // 1. recompute a valid chain (no external ocsp)
- // 2. use this chain to check if things would have broken!
- nsAutoCString host;
- nsresult rv = GetHost(aSourceURI, host);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIX509Cert> cert;
- rv = aSSLStatus->GetServerCert(getter_AddRefs(cert));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(cert, NS_ERROR_FAILURE);
- UniqueCERTCertificate nssCert(cert->GetCert());
- NS_ENSURE_TRUE(nssCert, NS_ERROR_FAILURE);
-
- mozilla::pkix::Time now(mozilla::pkix::Now());
- UniqueCERTCertList certList;
- RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
- NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
- // We don't want this verification to cause any network traffic that would
- // block execution. Also, since we don't have access to the original stapled
- // OCSP response, we can't enforce this aspect of the TLS Feature extension.
- // This is ok, because it will have been enforced when we originally connected
- // to the site (or it's disabled, in which case we wouldn't want to enforce it
- // anyway).
- CertVerifier::Flags flags = CertVerifier::FLAG_LOCAL_ONLY |
- CertVerifier::FLAG_TLS_IGNORE_STATUS_REQUEST;
- if (certVerifier->VerifySSLServerCert(nssCert,
- nullptr, // stapledOCSPResponse
- nullptr, // sctsFromTLSExtension
- now, nullptr, // pinarg
- host.get(), // hostname
- certList,
- false, // don't store intermediates
- flags)
- != mozilla::pkix::Success) {
- return NS_ERROR_FAILURE;
- }
-
- CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
- if (CERT_LIST_END(rootNode, certList)) {
- return NS_ERROR_FAILURE;
- }
- bool isBuiltIn = false;
- mozilla::pkix::Result result = IsCertBuiltInRoot(rootNode->cert, isBuiltIn);
- if (result != mozilla::pkix::Success) {
- return NS_ERROR_FAILURE;
- }
-
- if (!isBuiltIn && !mProcessPKPHeadersFromNonBuiltInRoots) {
- if (aFailureResult) {
- *aFailureResult = nsISiteSecurityService::ERROR_ROOT_NOT_BUILT_IN;
- }
- return NS_ERROR_FAILURE;
- }
-
- // If maxAge == 0, we remove dynamic HPKP state for this host. Due to
- // architectural constraints, if this host was preloaded, any future lookups
- // will use the preloaded state (i.e. we can't store a "this host is not HPKP"
- // entry like we can for HSTS).
- if (maxAge == 0) {
- return RemoveState(aType, aSourceURI, aFlags);
- }
-
- // clamp maxAge to the maximum set by pref
- if (maxAge > mMaxMaxAge) {
- maxAge = mMaxMaxAge;
- }
-
- bool chainMatchesPinset;
- rv = PublicKeyPinningService::ChainMatchesPinset(certList, sha256keys,
- chainMatchesPinset);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (!chainMatchesPinset) {
- // is invalid
- SSSLOG(("SSS: Pins provided by %s are invalid no match with certList\n", host.get()));
- if (aFailureResult) {
- *aFailureResult = nsISiteSecurityService::ERROR_PINSET_DOES_NOT_MATCH_CHAIN;
- }
- return NS_ERROR_FAILURE;
- }
-
- // finally we need to ensure that there is a "backup pin" ie. There must be
- // at least one fingerprint hash that does NOT validate against the verified
- // chain (Section 2.5 of the spec)
- bool hasBackupPin = false;
- for (uint32_t i = 0; i < sha256keys.Length(); i++) {
- nsTArray<nsCString> singlePin;
- singlePin.AppendElement(sha256keys[i]);
- rv = PublicKeyPinningService::ChainMatchesPinset(certList, singlePin,
- chainMatchesPinset);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (!chainMatchesPinset) {
- hasBackupPin = true;
- }
- }
- if (!hasBackupPin) {
- // is invalid
- SSSLOG(("SSS: Pins provided by %s are invalid no backupPin\n", host.get()));
- if (aFailureResult) {
- *aFailureResult = nsISiteSecurityService::ERROR_NO_BACKUP_PIN;
- }
- return NS_ERROR_FAILURE;
- }
-
- int64_t expireTime = ExpireTimeFromMaxAge(maxAge);
- SiteHPKPState dynamicEntry(expireTime, SecurityPropertySet,
- foundIncludeSubdomains, sha256keys);
- SSSLOG(("SSS: about to set pins for %s, expires=%ld now=%ld maxAge=%lu\n",
- host.get(), expireTime, PR_Now() / PR_USEC_PER_MSEC, maxAge));
-
- rv = SetHPKPState(host.get(), dynamicEntry, aFlags, false);
- if (NS_FAILED(rv)) {
- SSSLOG(("SSS: failed to set pins for %s\n", host.get()));
- if (aFailureResult) {
- *aFailureResult = nsISiteSecurityService::ERROR_COULD_NOT_SAVE_STATE;
- }
- return rv;
- }
-
- if (aMaxAge != nullptr) {
- *aMaxAge = maxAge;
- }
-
- if (aIncludeSubdomains != nullptr) {
- *aIncludeSubdomains = foundIncludeSubdomains;
- }
-
- return foundUnrecognizedDirective
- ? NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA
- : NS_OK;
-}
-
-nsresult
nsSiteSecurityService::ProcessSTSHeader(nsIURI* aSourceURI,
const char* aHeader,
uint32_t aFlags,
@@ -902,17 +534,11 @@ nsSiteSecurityService::IsSecureURI(uint32_t aType, nsIURI* aURI,
uint32_t aFlags, bool* aCached,
bool* aResult)
{
- // Child processes are not allowed direct access to this.
- if (!XRE_IsParentProcess() && aType != nsISiteSecurityService::HEADER_HSTS) {
- MOZ_CRASH("Child process: no direct access to nsISiteSecurityService::IsSecureURI for non-HSTS entries");
- }
-
NS_ENSURE_ARG(aURI);
NS_ENSURE_ARG(aResult);
- // Only HSTS and HPKP are supported at the moment.
- NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS ||
- aType == nsISiteSecurityService::HEADER_HPKP,
+ // Only HSTS is supported at the moment.
+ NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS,
NS_ERROR_NOT_IMPLEMENTED);
nsAutoCString hostname;
@@ -939,17 +565,11 @@ nsSiteSecurityService::IsSecureHost(uint32_t aType, const char* aHost,
uint32_t aFlags, bool* aCached,
bool* aResult)
{
- // Child processes are not allowed direct access to this.
- if (!XRE_IsParentProcess() && aType != nsISiteSecurityService::HEADER_HSTS) {
- MOZ_CRASH("Child process: no direct access to nsISiteSecurityService::IsSecureHost for non-HSTS entries");
- }
-
NS_ENSURE_ARG(aHost);
NS_ENSURE_ARG(aResult);
- // Only HSTS and HPKP are supported at the moment.
- NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS ||
- aType == nsISiteSecurityService::HEADER_HPKP,
+ // Only HSTS is supported at the moment.
+ NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS,
NS_ERROR_NOT_IMPLEMENTED);
// set default in case if we can't find any STS information
@@ -963,36 +583,14 @@ nsSiteSecurityService::IsSecureHost(uint32_t aType, const char* aHost,
return NS_OK;
}
- /* An IP address never qualifies as a secure URI. */
+ // An IP address never qualifies as a secure URI.
if (HostIsIPAddress(aHost)) {
return NS_OK;
}
- if (aType == nsISiteSecurityService::HEADER_HPKP) {
- RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
- if (!certVerifier) {
- return NS_ERROR_FAILURE;
- }
- if (certVerifier->mPinningMode ==
- CertVerifier::PinningMode::pinningDisabled) {
- return NS_OK;
- }
- bool enforceTestMode = certVerifier->mPinningMode ==
- CertVerifier::PinningMode::pinningEnforceTestMode;
- return PublicKeyPinningService::HostHasPins(aHost, mozilla::pkix::Now(),
- enforceTestMode, *aResult);
- }
-
- // Holepunch chart.apis.google.com and subdomains.
- nsAutoCString host(PublicKeyPinningService::CanonicalizeHostname(aHost));
- if (host.EqualsLiteral("chart.apis.google.com") ||
- StringEndsWith(host, NS_LITERAL_CSTRING(".chart.apis.google.com"))) {
- if (aCached) {
- *aCached = true;
- }
- return NS_OK;
- }
-
+ // Canonicalize the passed host name
+ nsAutoCString host(CanonicalizeHostname(aHost));
+
// First check the exact host. This involves first checking for an entry in
// site security storage. If that entry exists, we don't want to check
// in the preload list. We only want to use the stored value if it is not a
@@ -1088,144 +686,9 @@ nsSiteSecurityService::IsSecureHost(uint32_t aType, const char* aHost,
NS_IMETHODIMP
nsSiteSecurityService::ClearAll()
{
- // Child processes are not allowed direct access to this.
- if (!XRE_IsParentProcess()) {
- MOZ_CRASH("Child process: no direct access to nsISiteSecurityService::ClearAll");
- }
-
return mSiteStateStorage->Clear();
}
-bool entryStateNotOK(SiteHPKPState& state, mozilla::pkix::Time& aEvalTime) {
- return state.mState != SecurityPropertySet || state.IsExpired(aEvalTime) ||
- state.mSHA256keys.Length() < 1;
-}
-
-NS_IMETHODIMP
-nsSiteSecurityService::GetKeyPinsForHostname(const char* aHostname,
- mozilla::pkix::Time& aEvalTime,
- /*out*/ nsTArray<nsCString>& pinArray,
- /*out*/ bool* aIncludeSubdomains,
- /*out*/ bool* aFound) {
- // Child processes are not allowed direct access to this.
- if (!XRE_IsParentProcess()) {
- MOZ_CRASH("Child process: no direct access to nsISiteSecurityService::GetKeyPinsForHostname");
- }
-
- NS_ENSURE_ARG(aFound);
- NS_ENSURE_ARG(aHostname);
-
- if (!mHPKPEnabled) {
- SSSLOG(("HPKP disabled - returning 'pins not found' for %s",
- aHostname));
- *aFound = false;
- return NS_OK;
- }
-
- SSSLOG(("Top of GetKeyPinsForHostname for %s", aHostname));
- *aFound = false;
- *aIncludeSubdomains = false;
- pinArray.Clear();
-
- nsAutoCString host(PublicKeyPinningService::CanonicalizeHostname(aHostname));
- nsAutoCString storageKey;
- SetStorageKey(storageKey, host, nsISiteSecurityService::HEADER_HPKP);
-
- SSSLOG(("storagekey '%s'\n", storageKey.get()));
- mozilla::DataStorageType storageType = mozilla::DataStorage_Persistent;
- nsCString value = mSiteStateStorage->Get(storageKey, storageType);
-
- // decode now
- SiteHPKPState foundEntry(value);
- if (entryStateNotOK(foundEntry, aEvalTime)) {
- // not in permanent storage, try now private
- value = mSiteStateStorage->Get(storageKey, mozilla::DataStorage_Private);
- SiteHPKPState privateEntry(value);
- if (entryStateNotOK(privateEntry, aEvalTime)) {
- // not in private storage, try dynamic preload
- value = mPreloadStateStorage->Get(storageKey,
- mozilla::DataStorage_Persistent);
- SiteHPKPState preloadEntry(value);
- if (entryStateNotOK(preloadEntry, aEvalTime)) {
- return NS_OK;
- }
- foundEntry = preloadEntry;
- } else {
- foundEntry = privateEntry;
- }
- }
- pinArray = foundEntry.mSHA256keys;
- *aIncludeSubdomains = foundEntry.mIncludeSubdomains;
- *aFound = true;
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSiteSecurityService::SetKeyPins(const char* aHost, bool aIncludeSubdomains,
- int64_t aExpires, uint32_t aPinCount,
- const char** aSha256Pins,
- bool aIsPreload,
- /*out*/ bool* aResult)
-{
- // Child processes are not allowed direct access to this.
- if (!XRE_IsParentProcess()) {
- MOZ_CRASH("Child process: no direct access to nsISiteSecurityService::SetKeyPins");
- }
-
- NS_ENSURE_ARG_POINTER(aHost);
- NS_ENSURE_ARG_POINTER(aResult);
- NS_ENSURE_ARG_POINTER(aSha256Pins);
-
-
- if (!mHPKPEnabled) {
- SSSLOG(("SSS: HPKP disabled: not setting pins"));
- *aResult = false;
- return NS_OK;
- }
-
- SSSLOG(("Top of SetPins"));
-
- nsTArray<nsCString> sha256keys;
- for (unsigned int i = 0; i < aPinCount; i++) {
- nsAutoCString pin(aSha256Pins[i]);
- SSSLOG(("SetPins pin=%s\n", pin.get()));
- if (!stringIsBase64EncodingOf256bitValue(pin)) {
- return NS_ERROR_INVALID_ARG;
- }
- sha256keys.AppendElement(pin);
- }
- SiteHPKPState dynamicEntry(aExpires, SecurityPropertySet,
- aIncludeSubdomains, sha256keys);
- // we always store data in permanent storage (ie no flags)
- nsAutoCString host(PublicKeyPinningService::CanonicalizeHostname(aHost));
- return SetHPKPState(host.get(), dynamicEntry, 0, aIsPreload);
-}
-
-nsresult
-nsSiteSecurityService::SetHPKPState(const char* aHost, SiteHPKPState& entry,
- uint32_t aFlags, bool aIsPreload)
-{
- SSSLOG(("Top of SetPKPState"));
- nsAutoCString host(aHost);
- nsAutoCString storageKey;
- SetStorageKey(storageKey, host, nsISiteSecurityService::HEADER_HPKP);
- bool isPrivate = aFlags & nsISocketProvider::NO_PERMANENT_STORAGE;
- mozilla::DataStorageType storageType = isPrivate
- ? mozilla::DataStorage_Private
- : mozilla::DataStorage_Persistent;
- nsAutoCString stateString;
- entry.ToString(stateString);
-
- nsresult rv;
- if (aIsPreload) {
- rv = mPreloadStateStorage->Put(storageKey, stateString, storageType);
- } else {
- rv = mSiteStateStorage->Put(storageKey, stateString, storageType);
- }
- NS_ENSURE_SUCCESS(rv, rv);
- return NS_OK;
-}
-
//------------------------------------------------------------
// nsSiteSecurityService::nsIObserver
//------------------------------------------------------------
@@ -1246,12 +709,6 @@ nsSiteSecurityService::Observe(nsISupports *subject,
"network.stricttransportsecurity.enabled", true);
mPreloadListTimeOffset =
mozilla::Preferences::GetInt("test.currentTimeOffsetSeconds", 0);
- mHPKPEnabled = mozilla::Preferences::GetBool(
- "security.cert_pinning.hpkp.enabled", false);
- mProcessPKPHeadersFromNonBuiltInRoots = mozilla::Preferences::GetBool(
- "security.cert_pinning.process_headers_from_non_builtin_roots", false);
- mMaxMaxAge = mozilla::Preferences::GetInt(
- "security.cert_pinning.max_max_age_seconds", kSixtyDaysInSeconds);
}
return NS_OK;
diff --git a/security/manager/ssl/nsSiteSecurityService.h b/security/manager/ssl/nsSiteSecurityService.h
index 3cc428e2e..9395cd092 100644
--- a/security/manager/ssl/nsSiteSecurityService.h
+++ b/security/manager/ssl/nsSiteSecurityService.h
@@ -39,40 +39,6 @@ enum SecurityPropertyState {
};
/**
- * SiteHPKPState: A utility class that encodes/decodes a string describing
- * the public key pins of a site.
- * HPKP state consists of:
- * - Expiry time (PRTime (aka int64_t) in milliseconds)
- * - A state flag (SecurityPropertyState, default SecurityPropertyUnset)
- * - An include subdomains flag (bool, default false)
- * - An array of sha-256 hashed base 64 encoded fingerprints of required keys
- */
-class SiteHPKPState
-{
-public:
- SiteHPKPState();
- explicit SiteHPKPState(nsCString& aStateString);
- SiteHPKPState(PRTime aExpireTime, SecurityPropertyState aState,
- bool aIncludeSubdomains, nsTArray<nsCString>& SHA256keys);
-
- PRTime mExpireTime;
- SecurityPropertyState mState;
- bool mIncludeSubdomains;
- nsTArray<nsCString> mSHA256keys;
-
- bool IsExpired(mozilla::pkix::Time aTime)
- {
- if (aTime > mozilla::pkix::TimeFromEpochInSeconds(mExpireTime /
- PR_MSEC_PER_SEC)) {
- return true;
- }
- return false;
- }
-
- void ToString(nsCString& aString);
-};
-
-/**
* SiteHSTSState: A utility class that encodes/decodes a string describing
* the security state of a site. Currently only handles HSTS.
* HSTS state consists of:
@@ -137,20 +103,10 @@ private:
nsresult ProcessSTSHeader(nsIURI* aSourceURI, const char* aHeader,
uint32_t flags, uint64_t* aMaxAge,
bool* aIncludeSubdomains, uint32_t* aFailureResult);
- nsresult ProcessPKPHeader(nsIURI* aSourceURI, const char* aHeader,
- nsISSLStatus* aSSLStatus, uint32_t flags,
- uint64_t* aMaxAge, bool* aIncludeSubdomains,
- uint32_t* aFailureResult);
- nsresult SetHPKPState(const char* aHost, SiteHPKPState& entry, uint32_t flags,
- bool aIsPreload);
-
- uint64_t mMaxMaxAge;
+
bool mUseStsService;
int64_t mPreloadListTimeOffset;
- bool mHPKPEnabled;
- bool mProcessPKPHeadersFromNonBuiltInRoots;
RefPtr<mozilla::DataStorage> mSiteStateStorage;
- RefPtr<mozilla::DataStorage> mPreloadStateStorage;
};
#endif // __nsSiteSecurityService_h__
diff --git a/security/manager/tools/PreloadedHPKPins.json b/security/manager/tools/PreloadedHPKPins.json
deleted file mode 100644
index d9c394a1d..000000000
--- a/security/manager/tools/PreloadedHPKPins.json
+++ /dev/null
@@ -1,222 +0,0 @@
-// -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-// 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/.
-
-// The top-level element is a dictionary with two keys: "pinsets" maps details
-// of certificate pinning to a name and "entries" contains the HPKP details for
-// each host.
-//
-// "pinsets" is a list of objects. Each object has the following members:
-// name: (string) the name of the pinset
-// sha256_hashes: (list of strings) the set of allowed SPKIs hashes
-//
-// For a given pinset, a certificate is accepted if at least one of the
-// Subject Public Key Infos (SPKIs) is found in the chain. SPKIs are specified
-// as names, which must match up with the name given in the Mozilla root store.
-//
-// "entries" is a list of objects. Each object has the following members:
-// name: (string) the DNS name of the host in question
-// include_subdomains: (optional bool) whether subdomains of |name| are also covered
-// pins: (string) the |name| member of an object in |pinsets|
-//
-// "extra_certs" is a list of base64-encoded certificates. These are used in
-// pinsets that reference certificates not in our root program (for example,
-// Facebook).
-
-// equifax -> aus3
-// Geotrust Primary -> www.mozilla.org
-// Geotrust Global -> *. addons.mozilla.org
-{
- "chromium_data" : {
- "cert_file_url": "https://chromium.googlesource.com/chromium/src/net/+/master/http/transport_security_state_static.pins?format=TEXT",
- "json_file_url": "https://chromium.googlesource.com/chromium/src/net/+/master/http/transport_security_state_static.json?format=TEXT",
- "substitute_pinsets": {
- // Use the larger google_root_pems pinset instead of google
- "google": "google_root_pems"
- },
- "production_pinsets": [
- "google_root_pems",
- "facebook"
- ],
- "production_domains": [
- // Chrome's test domains.
- "pinningtest.appspot.com",
- "pinning-test.badssl.com",
- // Dropbox
- "dropbox.com",
- "www.dropbox.com",
- // Twitter
- "api.twitter.com",
- "business.twitter.com",
- "dev.twitter.com",
- "mobile.twitter.com",
- "oauth.twitter.com",
- "platform.twitter.com",
- "twimg.com",
- "www.twitter.com",
- // Tor
- "torproject.org",
- "blog.torproject.org",
- "check.torproject.org",
- "dist.torproject.org",
- "www.torproject.org",
- // SpiderOak
- "spideroak.com"
- ],
- "exclude_domains" : [
- // Chrome's entry for twitter.com doesn't include subdomains, so replace
- // it with our own entry below which also uses an expanded pinset.
- "twitter.com"
- ]
- },
- "pinsets": [
- {
- // From bug 772756, mozilla uses GeoTrust, Digicert and Thawte. Our
- // cdn sites use Verisign and Baltimore. We exclude 1024-bit root certs
- // from all providers. geotrust ca info:
- // http://www.geotrust.com/resources/root-certificates/index.html
- "name": "mozilla",
- "sha256_hashes": [
- "Baltimore CyberTrust Root",
- "DigiCert Assured ID Root CA",
- "DigiCert Global Root CA",
- "DigiCert High Assurance EV Root CA",
- "GeoTrust Global CA",
- "GeoTrust Global CA 2",
- "GeoTrust Primary Certification Authority",
- "GeoTrust Primary Certification Authority - G2",
- "GeoTrust Primary Certification Authority - G3",
- "GeoTrust Universal CA",
- "GeoTrust Universal CA 2",
- "thawte Primary Root CA",
- "thawte Primary Root CA - G2",
- "thawte Primary Root CA - G3",
- "Verisign Class 1 Public Primary Certification Authority - G3",
- "Verisign Class 2 Public Primary Certification Authority - G3",
- "Verisign Class 3 Public Primary Certification Authority - G3",
- "VeriSign Class 3 Public Primary Certification Authority - G4",
- "VeriSign Class 3 Public Primary Certification Authority - G5",
- // "Verisign Class 4 Public Primary Certification Authority - G3",
- "VeriSign Universal Root Certification Authority"
- ]
- },
- {
- "name": "mozilla_services",
- "sha256_hashes": [
- "DigiCert Global Root CA"
- ]
- },
- // For pinning tests on pinning.example.com, the certificate must be 'End
- // Entity Test Cert'
- {
- "name": "mozilla_test",
- "sha256_hashes": [
- "End Entity Test Cert"
- ]
- },
- // Google's root PEMs. Chrome pins only to their intermediate certs, but
- // they'd like us to be more liberal. For the initial list, we are using
- // the certs from http://pki.google.com/roots.pem.
- // We have no built-in for commented out CAs.
- {
- "name": "google_root_pems",
- "sha256_hashes": [
- "AddTrust External Root",
- "AddTrust Low-Value Services Root",
- "AddTrust Public Services Root",
- "AddTrust Qualified Certificates Root",
- "AffirmTrust Commercial",
- "AffirmTrust Networking",
- "AffirmTrust Premium",
- "AffirmTrust Premium ECC",
- "Baltimore CyberTrust Root",
- "Comodo AAA Services root",
- "COMODO Certification Authority",
- "COMODO ECC Certification Authority",
- "COMODO RSA Certification Authority",
- "Comodo Secure Services root",
- "Comodo Trusted Services root",
- "Cybertrust Global Root",
- "DigiCert Assured ID Root CA",
- "DigiCert Assured ID Root G2",
- "DigiCert Assured ID Root G3",
- "DigiCert Global Root CA",
- "DigiCert Global Root G2",
- "DigiCert Global Root G3",
- "DigiCert High Assurance EV Root CA",
- "DigiCert Trusted Root G4",
- "Entrust Root Certification Authority",
- "Entrust Root Certification Authority - EC1",
- "Entrust Root Certification Authority - G2",
- "Entrust.net Premium 2048 Secure Server CA",
- // "Equifax Secure Certificate Authority",
- "GeoTrust Global CA",
- "GeoTrust Global CA 2",
- "GeoTrust Primary Certification Authority",
- "GeoTrust Primary Certification Authority - G2",
- "GeoTrust Primary Certification Authority - G3",
- "GeoTrust Universal CA",
- "GeoTrust Universal CA 2",
- "GlobalSign ECC Root CA - R4",
- "GlobalSign ECC Root CA - R5",
- "GlobalSign Root CA",
- "GlobalSign Root CA - R2",
- "GlobalSign Root CA - R3",
- "Go Daddy Class 2 CA",
- "Go Daddy Root Certificate Authority - G2",
- "Starfield Class 2 CA",
- "Starfield Root Certificate Authority - G2",
- "thawte Primary Root CA",
- "thawte Primary Root CA - G2",
- "thawte Primary Root CA - G3",
- "USERTrust ECC Certification Authority",
- "USERTrust RSA Certification Authority",
- "UTN USERFirst Hardware Root CA",
- "Verisign Class 3 Public Primary Certification Authority - G3",
- "VeriSign Class 3 Public Primary Certification Authority - G4",
- "VeriSign Class 3 Public Primary Certification Authority - G5",
- "VeriSign Universal Root Certification Authority"
- ]
- }
- ],
-
- "entries": [
- // Only domains that are operationally crucial to Firefox can have per-host
- // telemetry reporting (the "id") field
- { "name": "addons.mozilla.org", "include_subdomains": true,
- "pins": "mozilla", "test_mode": false, "id": 1 },
- { "name": "addons.mozilla.net", "include_subdomains": true,
- "pins": "mozilla", "test_mode": false, "id": 2 },
- { "name": "aus4.mozilla.org", "include_subdomains": true,
- "pins": "mozilla", "test_mode": true, "id": 3 },
- { "name": "accounts.firefox.com", "include_subdomains": true,
- "pins": "mozilla_services", "test_mode": false, "id": 4 },
- { "name": "api.accounts.firefox.com", "include_subdomains": true,
- "pins": "mozilla_services", "test_mode": false, "id": 5 },
- { "name": "cdn.mozilla.net", "include_subdomains": true,
- "pins": "mozilla", "test_mode": false },
- { "name": "cdn.mozilla.org", "include_subdomains": true,
- "pins": "mozilla", "test_mode": false },
- { "name": "services.mozilla.com", "include_subdomains": true,
- "pins": "mozilla_services", "test_mode": false, "id": 6 },
- { "name": "include-subdomains.pinning.example.com",
- "include_subdomains": true, "pins": "mozilla_test",
- "test_mode": false },
- // Example domain to collect per-host stats for telemetry tests.
- { "name": "exclude-subdomains.pinning.example.com",
- "include_subdomains": false, "pins": "mozilla_test",
- "test_mode": false, "id": 0 },
- { "name": "test-mode.pinning.example.com", "include_subdomains": true,
- "pins": "mozilla_test", "test_mode": true },
- // Expand twitter's pinset to include all of *.twitter.com and use
- // twitterCDN. More specific rules take precedence because we search for
- // exact domain name first.
- { "name": "twitter.com", "include_subdomains": true,
- "pins": "twitterCDN", "test_mode": false },
- { "name": "aus5.mozilla.org", "include_subdomains": true,
- "pins": "mozilla", "test_mode": true, "id": 7 }
- ],
-
- "extra_certificates": []
-}
diff --git a/security/manager/tools/genHPKPStaticPins.js b/security/manager/tools/genHPKPStaticPins.js
deleted file mode 100644
index f2b9dbdda..000000000
--- a/security/manager/tools/genHPKPStaticPins.js
+++ /dev/null
@@ -1,630 +0,0 @@
-/* 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/. */
-
-// How to run this file:
-// 1. [obtain firefox source code]
-// 2. [build/obtain firefox binaries]
-// 3. run `[path to]/run-mozilla.sh [path to]/xpcshell \
-// [path to]/genHPKPStaticpins.js \
-// [absolute path to]/PreloadedHPKPins.json \
-// [an unused argument - see bug 1205406] \
-// [absolute path to]/StaticHPKPins.h
-"use strict";
-
-if (arguments.length != 3) {
- throw new Error("Usage: genHPKPStaticPins.js " +
- "<absolute path to PreloadedHPKPins.json> " +
- "<an unused argument - see bug 1205406> " +
- "<absolute path to StaticHPKPins.h>");
-}
-
-var { 'classes': Cc, 'interfaces': Ci, 'utils': Cu, 'results': Cr } = Components;
-
-var { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
-var { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
-var { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
-
-var gCertDB = Cc["@mozilla.org/security/x509certdb;1"]
- .getService(Ci.nsIX509CertDB);
-
-const BUILT_IN_NICK_PREFIX = "Builtin Object Token:";
-const SHA256_PREFIX = "sha256/";
-const GOOGLE_PIN_PREFIX = "GOOGLE_PIN_";
-
-// Pins expire in 14 weeks (6 weeks on Beta + 8 weeks on stable)
-const PINNING_MINIMUM_REQUIRED_MAX_AGE = 60 * 60 * 24 * 7 * 14;
-
-const FILE_HEADER = "/* This Source Code Form is subject to the terms of the Mozilla Public\n" +
-" * License, v. 2.0. If a copy of the MPL was not distributed with this\n" +
-" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n" +
-"\n" +
-"/*****************************************************************************/\n" +
-"/* This is an automatically generated file. If you're not */\n" +
-"/* PublicKeyPinningService.cpp, you shouldn't be #including it. */\n" +
-"/*****************************************************************************/\n" +
-"#include <stdint.h>" +
-"\n";
-
-const DOMAINHEADER = "/* Domainlist */\n" +
- "struct TransportSecurityPreload {\n" +
- " const char* mHost;\n" +
- " const bool mIncludeSubdomains;\n" +
- " const bool mTestMode;\n" +
- " const bool mIsMoz;\n" +
- " const int32_t mId;\n" +
- " const StaticFingerprints* pinset;\n" +
- "};\n\n";
-
-const PINSETDEF = "/* Pinsets are each an ordered list by the actual value of the fingerprint */\n" +
- "struct StaticFingerprints {\n" +
- " const size_t size;\n" +
- " const char* const* data;\n" +
- "};\n\n";
-
-// Command-line arguments
-var gStaticPins = parseJson(arguments[0]);
-
-// arguments[1] is ignored for now. See bug 1205406.
-
-// Open the output file.
-var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
-file.initWithPath(arguments[2]);
-var gFileOutputStream = FileUtils.openSafeFileOutputStream(file);
-
-function writeString(string) {
- gFileOutputStream.write(string, string.length);
-}
-
-function readFileToString(filename) {
- let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
- file.initWithPath(filename);
- let stream = Cc["@mozilla.org/network/file-input-stream;1"]
- .createInstance(Ci.nsIFileInputStream);
- stream.init(file, -1, 0, 0);
- let buf = NetUtil.readInputStreamToString(stream, stream.available());
- return buf;
-}
-
-function stripComments(buf) {
- let lines = buf.split("\n");
- let entryRegex = /^\s*\/\//;
- let data = "";
- for (let i = 0; i < lines.length; ++i) {
- let match = entryRegex.exec(lines[i]);
- if (!match) {
- data = data + lines[i];
- }
- }
- return data;
-}
-
-function isBuiltinToken(tokenName) {
- return tokenName == "Builtin Object Token";
-}
-
-function isCertBuiltIn(cert) {
- let tokenNames = cert.getAllTokenNames({});
- if (!tokenNames) {
- return false;
- }
- if (tokenNames.some(isBuiltinToken)) {
- return true;
- }
- return false;
-}
-
-function download(filename) {
- let req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
- .createInstance(Ci.nsIXMLHttpRequest);
- req.open("GET", filename, false); // doing the request synchronously
- try {
- req.send();
- }
- catch (e) {
- throw new Error(`ERROR: problem downloading '${filename}': ${e}`);
- }
-
- if (req.status != 200) {
- throw new Error("ERROR: problem downloading '" + filename + "': status " +
- req.status);
- }
-
- let resultDecoded;
- try {
- resultDecoded = atob(req.responseText);
- }
- catch (e) {
- throw new Error("ERROR: could not decode data as base64 from '" + filename +
- "': " + e);
- }
- return resultDecoded;
-}
-
-function downloadAsJson(filename) {
- // we have to filter out '//' comments, while not mangling the json
- let result = download(filename).replace(/^(\s*)?\/\/[^\n]*\n/mg, "");
- let data = null;
- try {
- data = JSON.parse(result);
- }
- catch (e) {
- throw new Error("ERROR: could not parse data from '" + filename + "': " + e);
- }
- return data;
-}
-
-// Returns a Subject Public Key Digest from the given pem, if it exists.
-function getSKDFromPem(pem) {
- let cert = gCertDB.constructX509FromBase64(pem, pem.length);
- return cert.sha256SubjectPublicKeyInfoDigest;
-}
-
-/**
- * Hashes |input| using the SHA-256 algorithm in the following manner:
- * btoa(sha256(atob(input)))
- *
- * @argument {String} input Base64 string to decode and return the hash of.
- * @returns {String} Base64 encoded SHA-256 hash.
- */
-function sha256Base64(input) {
- let decodedValue;
- try {
- decodedValue = atob(input);
- }
- catch (e) {
- throw new Error(`ERROR: could not decode as base64: '${input}': ${e}`);
- }
-
- // Convert |decodedValue| to an array so that it can be hashed by the
- // nsICryptoHash instance below.
- // In most cases across the code base, convertToByteArray() of
- // nsIScriptableUnicodeConverter is used to do this, but the method doesn't
- // seem to work here.
- let data = [];
- for (let i = 0; i < decodedValue.length; i++) {
- data[i] = decodedValue.charCodeAt(i);
- }
-
- let hasher = Cc["@mozilla.org/security/hash;1"]
- .createInstance(Ci.nsICryptoHash);
- hasher.init(hasher.SHA256);
- hasher.update(data, data.length);
-
- // true is passed so that the hasher returns a Base64 encoded string.
- return hasher.finish(true);
-}
-
-// Downloads the static certs file and tries to map Google Chrome nicknames
-// to Mozilla nicknames, as well as storing any hashes for pins for which we
-// don't have root PEMs. Each entry consists of a line containing the name of
-// the pin followed either by a hash in the format "sha256/" + base64(hash),
-// a PEM encoded public key, or a PEM encoded certificate.
-// For certificates that we have in our database,
-// return a map of Google's nickname to ours. For ones that aren't return a
-// map of Google's nickname to SHA-256 values. This code is modeled after agl's
-// https://github.com/agl/transport-security-state-generate, which doesn't
-// live in the Chromium repo because go is not an official language in
-// Chromium.
-// For all of the entries in this file:
-// - If the entry has a hash format, find the Mozilla pin name (cert nickname)
-// and stick the hash into certSKDToName
-// - If the entry has a PEM format, parse the PEM, find the Mozilla pin name
-// and stick the hash in certSKDToName
-// We MUST be able to find a corresponding cert nickname for the Chrome names,
-// otherwise we skip all pinsets referring to that Chrome name.
-function downloadAndParseChromeCerts(filename, certNameToSKD, certSKDToName) {
- // Prefixes that we care about.
- const BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
- const END_CERT = "-----END CERTIFICATE-----";
- const BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----";
- const END_PUB_KEY = "-----END PUBLIC KEY-----";
-
- // Parsing states.
- const PRE_NAME = 0;
- const POST_NAME = 1;
- const IN_CERT = 2;
- const IN_PUB_KEY = 3;
- let state = PRE_NAME;
-
- let lines = download(filename).split("\n");
- let name = "";
- let pemCert = "";
- let pemPubKey = "";
- let hash = "";
- let chromeNameToHash = {};
- let chromeNameToMozName = {};
- let chromeName;
- for (let line of lines) {
- // Skip comments and newlines.
- if (line.length == 0 || line[0] == '#') {
- continue;
- }
- switch (state) {
- case PRE_NAME:
- chromeName = line;
- state = POST_NAME;
- break;
- case POST_NAME:
- if (line.startsWith(SHA256_PREFIX)) {
- hash = line.substring(SHA256_PREFIX.length);
- chromeNameToHash[chromeName] = hash;
- certNameToSKD[chromeName] = hash;
- certSKDToName[hash] = chromeName;
- state = PRE_NAME;
- } else if (line.startsWith(BEGIN_CERT)) {
- state = IN_CERT;
- } else if (line.startsWith(BEGIN_PUB_KEY)) {
- state = IN_PUB_KEY;
- } else {
- throw new Error("ERROR: couldn't parse Chrome certificate file " +
- "line: " + line);
- }
- break;
- case IN_CERT:
- if (line.startsWith(END_CERT)) {
- state = PRE_NAME;
- hash = getSKDFromPem(pemCert);
- pemCert = "";
- let mozName;
- if (hash in certSKDToName) {
- mozName = certSKDToName[hash];
- } else {
- // Not one of our built-in certs. Prefix the name with
- // GOOGLE_PIN_.
- mozName = GOOGLE_PIN_PREFIX + chromeName;
- dump("Can't find hash in builtin certs for Chrome nickname " +
- chromeName + ", inserting " + mozName + "\n");
- certSKDToName[hash] = mozName;
- certNameToSKD[mozName] = hash;
- }
- chromeNameToMozName[chromeName] = mozName;
- } else {
- pemCert += line;
- }
- break;
- case IN_PUB_KEY:
- if (line.startsWith(END_PUB_KEY)) {
- state = PRE_NAME;
- hash = sha256Base64(pemPubKey);
- pemPubKey = "";
- chromeNameToHash[chromeName] = hash;
- certNameToSKD[chromeName] = hash;
- certSKDToName[hash] = chromeName;
- } else {
- pemPubKey += line;
- }
- break;
- default:
- throw new Error("ERROR: couldn't parse Chrome certificate file " + line);
- }
- }
- return [ chromeNameToHash, chromeNameToMozName ];
-}
-
-// We can only import pinsets from chrome if for every name in the pinset:
-// - We have a hash from Chrome's static certificate file
-// - We have a builtin cert
-// If the pinset meets these requirements, we store a map array of pinset
-// objects:
-// {
-// pinset_name : {
-// // Array of names with entries in certNameToSKD
-// sha256_hashes: []
-// }
-// }
-// and an array of imported pinset entries:
-// { name: string, include_subdomains: boolean, test_mode: boolean,
-// pins: pinset_name }
-function downloadAndParseChromePins(filename,
- chromeNameToHash,
- chromeNameToMozName,
- certNameToSKD,
- certSKDToName) {
- let chromePreloads = downloadAsJson(filename);
- let chromePins = chromePreloads.pinsets;
- let chromeImportedPinsets = {};
- let chromeImportedEntries = [];
-
- chromePins.forEach(function(pin) {
- let valid = true;
- let pinset = { name: pin.name, sha256_hashes: [] };
- // Translate the Chrome pinset format to ours
- pin.static_spki_hashes.forEach(function(name) {
- if (name in chromeNameToHash) {
- let hash = chromeNameToHash[name];
- pinset.sha256_hashes.push(certSKDToName[hash]);
-
- // We should have already added hashes for all of these when we
- // imported the certificate file.
- if (!certNameToSKD[name]) {
- throw new Error("ERROR: No hash for name: " + name);
- }
- } else if (name in chromeNameToMozName) {
- pinset.sha256_hashes.push(chromeNameToMozName[name]);
- } else {
- dump("Skipping Chrome pinset " + pinset.name + ", couldn't find " +
- "builtin " + name + " from cert file\n");
- valid = false;
- }
- });
- if (valid) {
- chromeImportedPinsets[pinset.name] = pinset;
- }
- });
-
- // Grab the domain entry lists. Chrome's entry format is similar to
- // ours, except theirs includes a HSTS mode.
- const cData = gStaticPins.chromium_data;
- let entries = chromePreloads.entries;
- entries.forEach(function(entry) {
- // HSTS entry only
- if (!entry.pins) {
- return;
- }
- let pinsetName = cData.substitute_pinsets[entry.pins];
- if (!pinsetName) {
- pinsetName = entry.pins;
- }
-
- // We trim the entry name here to avoid breaking hostname comparisons in the
- // HPKP implementation.
- entry.name = entry.name.trim();
-
- let isProductionDomain =
- (cData.production_domains.indexOf(entry.name) != -1);
- let isProductionPinset =
- (cData.production_pinsets.indexOf(pinsetName) != -1);
- let excludeDomain =
- (cData.exclude_domains.indexOf(entry.name) != -1);
- let isTestMode = !isProductionPinset && !isProductionDomain;
- if (entry.pins && !excludeDomain && chromeImportedPinsets[entry.pins]) {
- chromeImportedEntries.push({
- name: entry.name,
- include_subdomains: entry.include_subdomains,
- test_mode: isTestMode,
- is_moz: false,
- pins: pinsetName });
- }
- });
- return [ chromeImportedPinsets, chromeImportedEntries ];
-}
-
-// Returns a pair of maps [certNameToSKD, certSKDToName] between cert
-// nicknames and digests of the SPKInfo for the mozilla trust store
-function loadNSSCertinfo(extraCertificates) {
- let allCerts = gCertDB.getCerts();
- let enumerator = allCerts.getEnumerator();
- let certNameToSKD = {};
- let certSKDToName = {};
- while (enumerator.hasMoreElements()) {
- let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
- if (!isCertBuiltIn(cert)) {
- continue;
- }
- let name = cert.nickname.substr(BUILT_IN_NICK_PREFIX.length);
- let SKD = cert.sha256SubjectPublicKeyInfoDigest;
- certNameToSKD[name] = SKD;
- certSKDToName[SKD] = name;
- }
-
- for (let cert of extraCertificates) {
- let name = cert.commonName;
- let SKD = cert.sha256SubjectPublicKeyInfoDigest;
- certNameToSKD[name] = SKD;
- certSKDToName[SKD] = name;
- }
-
- {
- // This is the pinning test certificate. The key hash identifies the
- // default RSA key from pykey.
- let name = "End Entity Test Cert";
- let SKD = "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=";
- certNameToSKD[name] = SKD;
- certSKDToName[SKD] = name;
- }
- return [certNameToSKD, certSKDToName];
-}
-
-function parseJson(filename) {
- let json = stripComments(readFileToString(filename));
- return JSON.parse(json);
-}
-
-function nameToAlias(certName) {
- // change the name to a string valid as a c identifier
- // remove non-ascii characters
- certName = certName.replace(/[^[:ascii:]]/g, "_");
- // replace non word characters
- certName = certName.replace(/[^A-Za-z0-9]/g, "_");
-
- return "k" + certName + "Fingerprint";
-}
-
-function compareByName (a, b) {
- return a.name.localeCompare(b.name);
-}
-
-function genExpirationTime() {
- let now = new Date();
- let nowMillis = now.getTime();
- let expirationMillis = nowMillis + (PINNING_MINIMUM_REQUIRED_MAX_AGE * 1000);
- let expirationMicros = expirationMillis * 1000;
- return "static const PRTime kPreloadPKPinsExpirationTime = INT64_C(" +
- expirationMicros + ");\n";
-}
-
-function writeFullPinset(certNameToSKD, certSKDToName, pinset) {
- let prefix = "kPinset_" + pinset.name;
- if (!pinset.sha256_hashes || pinset.sha256_hashes.length == 0) {
- throw new Error(`ERROR: Pinset ${pinset.name} does not contain any hashes`);
- }
- writeFingerprints(certNameToSKD, certSKDToName, pinset.name,
- pinset.sha256_hashes);
-}
-
-function writeFingerprints(certNameToSKD, certSKDToName, name, hashes) {
- let varPrefix = "kPinset_" + name;
- writeString("static const char* const " + varPrefix + "_Data[] = {\n");
- let SKDList = [];
- for (let certName of hashes) {
- if (!(certName in certNameToSKD)) {
- throw new Error(`ERROR: Can't find '${certName}' in certNameToSKD`);
- }
- SKDList.push(certNameToSKD[certName]);
- }
- for (let skd of SKDList.sort()) {
- writeString(" " + nameToAlias(certSKDToName[skd]) + ",\n");
- }
- if (hashes.length == 0) {
- // ANSI C requires that an initialiser list be non-empty.
- writeString(" 0\n");
- }
- writeString("};\n");
- writeString("static const StaticFingerprints " + varPrefix + " = {\n " +
- "sizeof(" + varPrefix + "_Data) / sizeof(const char*),\n " + varPrefix +
- "_Data\n};\n\n");
-}
-
-function writeEntry(entry) {
- let printVal = " { \"" + entry.name + "\",\ ";
- if (entry.include_subdomains) {
- printVal += "true, ";
- } else {
- printVal += "false, ";
- }
- // Default to test mode if not specified.
- let testMode = true;
- if (entry.hasOwnProperty("test_mode")) {
- testMode = entry.test_mode;
- }
- if (testMode) {
- printVal += "true, ";
- } else {
- printVal += "false, ";
- }
- if (entry.is_moz || (entry.pins.indexOf("mozilla") != -1 &&
- entry.pins != "mozilla_test")) {
- printVal += "true, ";
- } else {
- printVal += "false, ";
- }
- if ("id" in entry) {
- if (entry.id >= 256) {
- throw new Error("ERROR: Not enough buckets in histogram");
- }
- if (entry.id >= 0) {
- printVal += entry.id + ", ";
- }
- } else {
- printVal += "-1, ";
- }
- printVal += "&kPinset_" + entry.pins;
- printVal += " },\n";
- writeString(printVal);
-}
-
-function writeDomainList(chromeImportedEntries) {
- writeString("/* Sort hostnames for binary search. */\n");
- writeString("static const TransportSecurityPreload " +
- "kPublicKeyPinningPreloadList[] = {\n");
- let count = 0;
- let mozillaDomains = {};
- gStaticPins.entries.forEach(function(entry) {
- mozillaDomains[entry.name] = true;
- });
- // For any domain for which we have set pins, exclude them from
- // chromeImportedEntries.
- for (let i = chromeImportedEntries.length - 1; i >= 0; i--) {
- if (mozillaDomains[chromeImportedEntries[i].name]) {
- dump("Skipping duplicate pinset for domain " +
- JSON.stringify(chromeImportedEntries[i], undefined, 2) + "\n");
- chromeImportedEntries.splice(i, 1);
- }
- }
- let sortedEntries = gStaticPins.entries;
- sortedEntries.push.apply(sortedEntries, chromeImportedEntries);
- for (let entry of sortedEntries.sort(compareByName)) {
- count++;
- writeEntry(entry);
- }
- writeString("};\n");
-
- writeString("\n// Pinning Preload List Length = " + count + ";\n");
- writeString("\nstatic const int32_t kUnknownId = -1;\n");
-}
-
-function writeFile(certNameToSKD, certSKDToName,
- chromeImportedPinsets, chromeImportedEntries) {
- // Compute used pins from both Chrome's and our pinsets, so we can output
- // them later.
- let usedFingerprints = {};
- let mozillaPins = {};
- gStaticPins.pinsets.forEach(function(pinset) {
- mozillaPins[pinset.name] = true;
- pinset.sha256_hashes.forEach(function (name) {
- usedFingerprints[name] = true;
- });
- });
- for (let key in chromeImportedPinsets) {
- let pinset = chromeImportedPinsets[key];
- pinset.sha256_hashes.forEach(function(name) {
- usedFingerprints[name] = true;
- });
- }
-
- writeString(FILE_HEADER);
-
- // Write actual fingerprints.
- Object.keys(usedFingerprints).sort().forEach(function(certName) {
- if (certName) {
- writeString("/* " + certName + " */\n");
- writeString("static const char " + nameToAlias(certName) + "[] =\n");
- writeString(" \"" + certNameToSKD[certName] + "\";\n");
- writeString("\n");
- }
- });
-
- // Write the pinsets
- writeString(PINSETDEF);
- writeString("/* PreloadedHPKPins.json pinsets */\n");
- gStaticPins.pinsets.sort(compareByName).forEach(function(pinset) {
- writeFullPinset(certNameToSKD, certSKDToName, pinset);
- });
- writeString("/* Chrome static pinsets */\n");
- for (let key in chromeImportedPinsets) {
- if (mozillaPins[key]) {
- dump("Skipping duplicate pinset " + key + "\n");
- } else {
- dump("Writing pinset " + key + "\n");
- writeFullPinset(certNameToSKD, certSKDToName, chromeImportedPinsets[key]);
- }
- }
-
- // Write the domainlist entries.
- writeString(DOMAINHEADER);
- writeDomainList(chromeImportedEntries);
- writeString("\n");
- writeString(genExpirationTime());
-}
-
-function loadExtraCertificates(certStringList) {
- let constructedCerts = [];
- for (let certString of certStringList) {
- constructedCerts.push(gCertDB.constructX509FromBase64(certString));
- }
- return constructedCerts;
-}
-
-var extraCertificates = loadExtraCertificates(gStaticPins.extra_certificates);
-var [ certNameToSKD, certSKDToName ] = loadNSSCertinfo(extraCertificates);
-var [ chromeNameToHash, chromeNameToMozName ] = downloadAndParseChromeCerts(
- gStaticPins.chromium_data.cert_file_url, certNameToSKD, certSKDToName);
-var [ chromeImportedPinsets, chromeImportedEntries ] =
- downloadAndParseChromePins(gStaticPins.chromium_data.json_file_url,
- chromeNameToHash, chromeNameToMozName, certNameToSKD, certSKDToName);
-
-writeFile(certNameToSKD, certSKDToName, chromeImportedPinsets,
- chromeImportedEntries);
-
-FileUtils.closeSafeFileOutputStream(gFileOutputStream);