diff options
Diffstat (limited to 'security/manager/ssl')
-rw-r--r-- | security/manager/ssl/PublicKeyPinningService.cpp | 333 | ||||
-rw-r--r-- | security/manager/ssl/PublicKeyPinningService.h | 64 | ||||
-rw-r--r-- | security/manager/ssl/StaticHPKPins.h | 712 | ||||
-rw-r--r-- | security/manager/ssl/moz.build | 1 | ||||
-rw-r--r-- | security/manager/ssl/nsISiteSecurityService.idl | 46 | ||||
-rw-r--r-- | security/manager/ssl/nsSiteSecurityService.cpp | 595 | ||||
-rw-r--r-- | security/manager/ssl/nsSiteSecurityService.h | 46 |
7 files changed, 32 insertions, 1765 deletions
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__ |