mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 772756: Implement sha1 support, import Chrome's pinsets wholesale, add test mode (r=cviecco,keeler)
This commit is contained in:
parent
cd1bc582ed
commit
d1eb9b420d
@ -3,6 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "PublicKeyPinningService.h"
|
||||
#include "pkix/nullptr.h"
|
||||
#include "StaticHPKPins.h" // autogenerated by genHPKPStaticpins.js
|
||||
|
||||
#include "cert.h"
|
||||
@ -29,11 +30,12 @@ PRLogModuleInfo* gPublicKeyPinningLog =
|
||||
of the DER Encoded subject Public Key Info for the given cert
|
||||
*/
|
||||
static SECStatus
|
||||
GetBase64SHA256SPKI(const CERTCertificate* cert,
|
||||
nsACString& aSha256SPKIDigest){
|
||||
aSha256SPKIDigest.Truncate();
|
||||
GetBase64HashSPKI(const CERTCertificate* cert, SECOidTag hashType,
|
||||
nsACString& hashSPKIDigest)
|
||||
{
|
||||
hashSPKIDigest.Truncate();
|
||||
Digest digest;
|
||||
nsresult rv = digest.DigestBuf(SEC_OID_SHA256, cert->derPublicKey.data,
|
||||
nsresult rv = digest.DigestBuf(hashType, cert->derPublicKey.data,
|
||||
cert->derPublicKey.len);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return SECFailure;
|
||||
@ -41,59 +43,100 @@ GetBase64SHA256SPKI(const CERTCertificate* cert,
|
||||
rv = Base64Encode(nsDependentCSubstring(
|
||||
reinterpret_cast<const char*>(digest.get().data),
|
||||
digest.get().len),
|
||||
aSha256SPKIDigest);
|
||||
hashSPKIDigest);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a Pinset and certlist ensure that there is intersection between them
|
||||
/*
|
||||
* Returns true if a given cert matches any hashType fingerprints from the
|
||||
* given pinset, false otherwise.
|
||||
*/
|
||||
static bool
|
||||
EvalPinWithPinset(const CERTCertList* certList, const StaticPinset* pinSet) {
|
||||
SECStatus srv;
|
||||
CERTCertificate* currentCert;
|
||||
EvalCertWithHashType(const CERTCertificate* cert, SECOidTag hashType,
|
||||
const StaticFingerprints* fingerprints)
|
||||
{
|
||||
if (!fingerprints) {
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
|
||||
("pkpin: No hashes found for hash type: %d\n", hashType));
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString base64Out;
|
||||
SECStatus srv = GetBase64HashSPKI(cert, hashType, base64Out);
|
||||
if (srv != SECSuccess) {
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
|
||||
("pkpin: GetBase64HashSPKI failed!\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
|
||||
("pkpin: base_64(hash(key)='%s'\n", base64Out.get()));
|
||||
|
||||
for (size_t i = 0; i < fingerprints->size; i++) {
|
||||
if (base64Out.Equals(fingerprints->data[i])) {
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
|
||||
("pkpin: found pin base_64(hash(key)='%s'\n", base64Out.get()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if a given chain matches any hashType fingerprints from the
|
||||
* given pinset, false otherwise.
|
||||
*/
|
||||
static bool
|
||||
EvalChainWithHashType(const CERTCertList* certList, SECOidTag hashType,
|
||||
const StaticPinset* pinset)
|
||||
{
|
||||
CERTCertificate* currentCert;
|
||||
|
||||
const StaticFingerprints* fingerprints = nullptr;
|
||||
if (hashType == SEC_OID_SHA256) {
|
||||
fingerprints = pinset->sha256;
|
||||
} else if (hashType == SEC_OID_SHA1) {
|
||||
fingerprints = pinset->sha1;
|
||||
}
|
||||
if (!fingerprints) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CERTCertListNode* node;
|
||||
for (node = CERT_LIST_HEAD(certList);
|
||||
!CERT_LIST_END(node, certList);
|
||||
for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
|
||||
node = CERT_LIST_NEXT(node)) {
|
||||
|
||||
currentCert = node->cert;
|
||||
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
|
||||
("pkpin: certArray subject: '%s'\n",
|
||||
currentCert->subjectName));
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
|
||||
("pkpin: certArray common_name: '%s'\n",
|
||||
CERT_GetCommonName(&(currentCert->issuer))));
|
||||
|
||||
// I only need sha256fp for builtins (so far)
|
||||
srv = GetBase64SHA256SPKI(currentCert, base64Out);
|
||||
if (srv != SECSuccess) {
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
|
||||
("pkpin: GetBase64SHA256SPKI failed!\n"));
|
||||
return false;
|
||||
}
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
|
||||
("pkpin: base_64(hash(key)='%s'\n", base64Out.get()));
|
||||
// Compare, linear search for now...
|
||||
for (size_t j = 0; j < pinSet->size; j++){
|
||||
if (base64Out.Equals(pinSet->data[j])) {
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
|
||||
("pkpin: found pin base_64(hash(key)='%s'\n", base64Out.get()));
|
||||
return true;
|
||||
}
|
||||
if (EvalCertWithHashType(currentCert, hashType, fingerprints)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// We found no intersection, we must fail!
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG, ("pkpin: end of evaluation!\n"));
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG, ("pkpin: no matches found\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a pinset and certlist, return true if one of the certificates on
|
||||
* the list matches a fingerprint in the pinset, false otherwise.
|
||||
*/
|
||||
static bool
|
||||
EvalChainWithPinset(const CERTCertList* certList,
|
||||
const StaticPinset* pinset) {
|
||||
// SHA256 is more trustworthy, try that first.
|
||||
if (EvalChainWithHashType(certList, SEC_OID_SHA256, pinset)) {
|
||||
return true;
|
||||
}
|
||||
return EvalChainWithHashType(certList, SEC_OID_SHA1, pinset);
|
||||
}
|
||||
|
||||
/**
|
||||
Comparator for the is public key pinned host.
|
||||
*/
|
||||
@ -126,8 +169,7 @@ CheckPinsForHostname(const CERTCertList *certList, const char *hostname,
|
||||
// Notice how the (xx = strchr) prevents pins for unqualified domain names.
|
||||
while (!foundEntry && (evalPart = strchr(evalHost, '.'))) {
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
|
||||
("pkpin: Iteration Querying for pinning for host: '%s'\n",
|
||||
evalHost));
|
||||
("pkpin: Querying pinsets for host: '%s'\n", evalHost));
|
||||
foundEntry = (TransportSecurityPreload *)bsearch(evalHost,
|
||||
kPublicKeyPinningPreloadList,
|
||||
kPublicKeyPinningPreloadListLength,
|
||||
@ -135,21 +177,30 @@ CheckPinsForHostname(const CERTCertList *certList, const char *hostname,
|
||||
TransportSecurityPreloadCompare);
|
||||
if (foundEntry) {
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
|
||||
("pkpin: iteration found pinning for host: '%s'\n", evalHost));
|
||||
("pkpin: Found pinset for host: '%s'\n", evalHost));
|
||||
if (evalHost != hostname) {
|
||||
if (false == foundEntry->mIncludeSubdomains) {
|
||||
// Does not apply to this host, contninue iterating
|
||||
if (!foundEntry->mIncludeSubdomains) {
|
||||
// Does not apply to this host, continue iterating
|
||||
foundEntry = nullptr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
|
||||
("pkpin: Didn't find pinset for host: '%s'\n", evalHost));
|
||||
}
|
||||
evalHost = evalPart;
|
||||
// Advance past the '.'
|
||||
evalHost++;
|
||||
} // end while
|
||||
// Add one for '.'
|
||||
evalHost = evalPart + 1;
|
||||
}
|
||||
|
||||
if (foundEntry && foundEntry->pinset) {
|
||||
bool result = EvalPinWithPinset(certList, foundEntry->pinset);
|
||||
bool result = EvalChainWithPinset(certList, foundEntry->pinset);
|
||||
if (foundEntry->mTestMode) {
|
||||
// TODO: Accumulate telemetry in test mode.
|
||||
PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
|
||||
("pkpin: Skipping test mode evaluation for host: '%s'\n",
|
||||
evalHost));
|
||||
return true;
|
||||
}
|
||||
Telemetry::Accumulate(Telemetry::CERT_PINNING_EVALUATION_RESULTS,
|
||||
result ? 1 : 0);
|
||||
return result;
|
||||
|
@ -7,146 +7,771 @@
|
||||
/* 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=";
|
||||
|
||||
/* Baltimore CyberTrust Root */
|
||||
static const char kBaltimore_CyberTrust_RootFingerprint[]=
|
||||
static const char kBaltimore_CyberTrust_RootFingerprint[] =
|
||||
"Y9mvm0exBk1JoQ57f9Vm28jKo5lFm/woKcVxrYxu80o=";
|
||||
|
||||
/* COMODO Certification Authority */
|
||||
static const char kCOMODO_Certification_AuthorityFingerprint[] =
|
||||
"AG1751Vd2CAmRCxPGieoDomhmJy4ezREjtIZTBgZbV4=";
|
||||
|
||||
/* 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=";
|
||||
|
||||
/* DigiCert Assured ID Root CA */
|
||||
static const char kDigiCert_Assured_ID_Root_CAFingerprint[]=
|
||||
static const char kDigiCert_Assured_ID_Root_CAFingerprint[] =
|
||||
"I/Lt/z7ekCWanjD0Cvj5EqXls2lOaThEA0H2Bg4BT/o=";
|
||||
|
||||
/* DigiCert Global Root CA */
|
||||
static const char kDigiCert_Global_Root_CAFingerprint[]=
|
||||
static const char kDigiCert_Global_Root_CAFingerprint[] =
|
||||
"r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=";
|
||||
|
||||
/* DigiCert High Assurance EV Root CA */
|
||||
static const char kDigiCert_High_Assurance_EV_Root_CAFingerprint[]=
|
||||
static const char kDigiCert_High_Assurance_EV_Root_CAFingerprint[] =
|
||||
"WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=";
|
||||
|
||||
/* End Entity Test Cert */
|
||||
static const char kEnd_Entity_Test_CertFingerprint[]=
|
||||
"sEIYDccDj1ULE64YxhvqV7ASqc2qfIofVyArzg+62hU=";
|
||||
static const char kEnd_Entity_Test_CertFingerprint[] =
|
||||
"a08RrXscTn7kKTSPR8uZVrmc0o3ryPd+o3menqJHJBw=";
|
||||
|
||||
/* Entrust Root Certification Authority */
|
||||
static const char kEntrust_Root_Certification_AuthorityFingerprint[] =
|
||||
"bb+uANN7nNc/j7R95lkXrwDg3d9C286sIMF8AnXuIJU=";
|
||||
|
||||
/* Entrust.net Premium 2048 Secure Server CA */
|
||||
static const char kEntrust_net_Premium_2048_Secure_Server_CAFingerprint[] =
|
||||
"HqPF5D7WbC2imDpCpKebHpBnhs6fG1hiFBmgBGOofTg=";
|
||||
|
||||
/* Entrust.net Secure Server CA */
|
||||
static const char kEntrust_net_Secure_Server_CAFingerprint[] =
|
||||
"nsxRNo6G40YPZsKV5JQt1TCA8nseQQr/LRqp1Oa8fnw=";
|
||||
|
||||
/* GOOGLE_PIN_AlphaSSL_G2 */
|
||||
static const char kGOOGLE_PIN_AlphaSSL_G2Fingerprint[] =
|
||||
"yxgiWGK++SFB9ySwt3M3qpn5HO0ZLFY5D+h+G/vcT/c=";
|
||||
|
||||
/* GOOGLE_PIN_CryptoCat1 */
|
||||
static const char kGOOGLE_PIN_CryptoCat1Fingerprint[] =
|
||||
"vKaqtTLWmVuXPVJE+0OqN5sRc4VCcSQHI/W3XTDVR24=";
|
||||
|
||||
/* GOOGLE_PIN_Entrust_G2 */
|
||||
static const char kGOOGLE_PIN_Entrust_G2Fingerprint[] =
|
||||
"du6FkDdMcVQ3u8prumAo6t3i3G27uMP2EOhR8R0at/U=";
|
||||
|
||||
/* GOOGLE_PIN_Libertylavabitcom */
|
||||
static const char kGOOGLE_PIN_LibertylavabitcomFingerprint[] =
|
||||
"WnKzsDXgqPtS1KvtImrhQPqcxfpmfssuI2cSJt4LMks=";
|
||||
|
||||
/* GOOGLE_PIN_RapidSSL */
|
||||
static const char kGOOGLE_PIN_RapidSSLFingerprint[] =
|
||||
"lT09gPUeQfbYrlxRtpsHrjDblj9Rpz+u7ajfCrg4qDM=";
|
||||
|
||||
/* GOOGLE_PIN_Tor2web */
|
||||
static const char kGOOGLE_PIN_Tor2webFingerprint[] =
|
||||
"99ogQzjMuUTBkG1ZP7FME0K4kvBEti8Buzu4nZjRItM=";
|
||||
|
||||
/* GTE CyberTrust Global Root */
|
||||
static const char kGTE_CyberTrust_Global_RootFingerprint[] =
|
||||
"EGn6R6CqT4z3ERscrqNl7q7RC//zJmDe9uBhS/rnCHU=";
|
||||
|
||||
/* GeoTrust Global CA */
|
||||
static const char kGeoTrust_Global_CAFingerprint[]=
|
||||
static const char kGeoTrust_Global_CAFingerprint[] =
|
||||
"h6801m+z8v3zbgkRHpq6L29Esgfzhj89C1SyUCOQmqU=";
|
||||
|
||||
/* GeoTrust Global CA 2 */
|
||||
static const char kGeoTrust_Global_CA_2Fingerprint[]=
|
||||
static const char kGeoTrust_Global_CA_2Fingerprint[] =
|
||||
"F3VaXClfPS1y5vAxofB/QAxYi55YKyLxfq4xoVkNEYU=";
|
||||
|
||||
/* GeoTrust Primary Certification Authority */
|
||||
static const char kGeoTrust_Primary_Certification_AuthorityFingerprint[]=
|
||||
static const char kGeoTrust_Primary_Certification_AuthorityFingerprint[] =
|
||||
"SQVGZiOrQXi+kqxcvWWE96HhfydlLVqFr4lQTqI5qqo=";
|
||||
|
||||
/* GeoTrust Primary Certification Authority - G2 */
|
||||
static const char kGeoTrust_Primary_Certification_Authority___G2Fingerprint[]=
|
||||
static const char kGeoTrust_Primary_Certification_Authority___G2Fingerprint[] =
|
||||
"vPtEqrmtAhAVcGtBIep2HIHJ6IlnWQ9vlK50TciLePs=";
|
||||
|
||||
/* GeoTrust Primary Certification Authority - G3 */
|
||||
static const char kGeoTrust_Primary_Certification_Authority___G3Fingerprint[]=
|
||||
static const char kGeoTrust_Primary_Certification_Authority___G3Fingerprint[] =
|
||||
"q5hJUnat8eyv8o81xTBIeB5cFxjaucjmelBPT2pRMo8=";
|
||||
|
||||
/* GeoTrust Universal CA */
|
||||
static const char kGeoTrust_Universal_CAFingerprint[]=
|
||||
static const char kGeoTrust_Universal_CAFingerprint[] =
|
||||
"lpkiXF3lLlbN0y3y6W0c/qWqPKC7Us2JM8I7XCdEOCA=";
|
||||
|
||||
/* GeoTrust Universal CA 2 */
|
||||
static const char kGeoTrust_Universal_CA_2Fingerprint[]=
|
||||
static const char kGeoTrust_Universal_CA_2Fingerprint[] =
|
||||
"fKoDRlEkWQxgHlZ+UhSOlSwM/+iQAFMP4NlbbVDqrkE=";
|
||||
|
||||
/* 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=";
|
||||
|
||||
/* GoogleBackup2048 */
|
||||
static const char kGoogleBackup2048Fingerprint[] =
|
||||
"vq7OyjSnqOco9nyMCDGdy77eijM=";
|
||||
|
||||
/* GoogleG2 */
|
||||
static const char kGoogleG2Fingerprint[] =
|
||||
"Q9rWMO5T+KmAym79hfRqo3mQ4Oo=";
|
||||
|
||||
/* TestSPKI */
|
||||
static const char kTestSPKIFingerprint[] =
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||
|
||||
/* Tor1 */
|
||||
static const char kTor1Fingerprint[] =
|
||||
"juNxSTv9UANmpC9kF5GKpmWNx3Y=";
|
||||
|
||||
/* Tor2 */
|
||||
static const char kTor2Fingerprint[] =
|
||||
"lia43lPolzSPVIq34Dw57uYcLD8=";
|
||||
|
||||
/* Tor3 */
|
||||
static const char kTor3Fingerprint[] =
|
||||
"rzEyQIKOh77j87n5bjWUNguXF8Y=";
|
||||
|
||||
/* Twitter1 */
|
||||
static const char kTwitter1Fingerprint[] =
|
||||
"Vv7zwhR9TtOIN/29MFI4cgHld40=";
|
||||
|
||||
/* UTN DATACorp SGC Root CA */
|
||||
static const char kUTN_DATACorp_SGC_Root_CAFingerprint[] =
|
||||
"QAL80xHQczFWfnG82XHkYEjI3OjRZZcRdTs9qiommvo=";
|
||||
|
||||
/* 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[]=
|
||||
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[]=
|
||||
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[]=
|
||||
static const char kVeriSign_Universal_Root_Certification_AuthorityFingerprint[] =
|
||||
"lnsM2T/O9/J84sJFdnrpsFp3awZJ+ZZbYpCWhGloaHI=";
|
||||
|
||||
/* Verisign Class 1 Public Primary Certification Authority */
|
||||
static const char kVerisign_Class_1_Public_Primary_Certification_AuthorityFingerprint[] =
|
||||
"LclHC+Y+9KzxvYKGCUArt7h72ZY4pkOTTohoLRvowwg=";
|
||||
|
||||
/* Verisign Class 1 Public Primary Certification Authority - G3 */
|
||||
static const char kVerisign_Class_1_Public_Primary_Certification_Authority___G3Fingerprint[]=
|
||||
static const char kVerisign_Class_1_Public_Primary_Certification_Authority___G3Fingerprint[] =
|
||||
"IgduWu9Eu5pBaii30cRDItcFn2D+/6XK9sW+hEeJEwM=";
|
||||
|
||||
/* Verisign Class 2 Public Primary Certification Authority - G2 */
|
||||
static const char kVerisign_Class_2_Public_Primary_Certification_Authority___G2Fingerprint[] =
|
||||
"2oALgLKofTmeZvoZ1y/fSZg7R9jPMix8eVA6DH4o/q8=";
|
||||
|
||||
/* Verisign Class 2 Public Primary Certification Authority - G3 */
|
||||
static const char kVerisign_Class_2_Public_Primary_Certification_Authority___G3Fingerprint[]=
|
||||
static const char kVerisign_Class_2_Public_Primary_Certification_Authority___G3Fingerprint[] =
|
||||
"cAajgxHlj7GTSEIzIYIQxmEloOSoJq7VOaxWHfv72QM=";
|
||||
|
||||
/* Verisign Class 3 Public Primary Certification Authority */
|
||||
static const char kVerisign_Class_3_Public_Primary_Certification_AuthorityFingerprint[] =
|
||||
"sRJBQqWhpaKIGcc1NA7/jJ4vgWj+47oYfyU7waOS1+I=";
|
||||
|
||||
/* Verisign Class 3 Public Primary Certification Authority - G2 */
|
||||
static const char kVerisign_Class_3_Public_Primary_Certification_Authority___G2Fingerprint[] =
|
||||
"AjyBzOjnxk+pQtPBUEhwfTXZu1uH9PVExb8bxWQ68vo=";
|
||||
|
||||
/* Verisign Class 3 Public Primary Certification Authority - G3 */
|
||||
static const char kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint[]=
|
||||
static const char kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint[] =
|
||||
"SVqWumuteCQHvVIaALrOZXuzVVVeS7f4FGxxu6V+es4=";
|
||||
|
||||
/* Verisign Class 4 Public Primary Certification Authority - G3 */
|
||||
static const char kVerisign_Class_4_Public_Primary_Certification_Authority___G3Fingerprint[]=
|
||||
static const char kVerisign_Class_4_Public_Primary_Certification_Authority___G3Fingerprint[] =
|
||||
"VnuCEf0g09KD7gzXzgZyy52ZvFtIeljJ1U7Gf3fUqPU=";
|
||||
|
||||
/* thawte Primary Root CA */
|
||||
static const char kthawte_Primary_Root_CAFingerprint[]=
|
||||
static const char kthawte_Primary_Root_CAFingerprint[] =
|
||||
"HXXQgxueCIU5TTLHob/bPbwcKOKw6DkfsTWYHbxbqTY=";
|
||||
|
||||
/* thawte Primary Root CA - G2 */
|
||||
static const char kthawte_Primary_Root_CA___G2Fingerprint[]=
|
||||
static const char kthawte_Primary_Root_CA___G2Fingerprint[] =
|
||||
"Z9xPMvoQ59AaeaBzqgyeAhLsL/w9d54Kp/nA8OHCyJM=";
|
||||
|
||||
/* thawte Primary Root CA - G3 */
|
||||
static const char kthawte_Primary_Root_CA___G3Fingerprint[]=
|
||||
static const char kthawte_Primary_Root_CA___G3Fingerprint[] =
|
||||
"GQbGEk27Q4V40A4GbVBUxsN/D6YCjAVUXgmU7drshik=";
|
||||
|
||||
/*Now the pinsets, each is an ordered list by the actual value of the FP*/
|
||||
typedef struct {
|
||||
/* Pinsets are each an ordered list by the actual value of the fingerprint */
|
||||
struct StaticFingerprints {
|
||||
const size_t size;
|
||||
const char* const* data;
|
||||
} StaticPinset;
|
||||
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,
|
||||
kVerisign_Class_4_Public_Primary_Certification_Authority___G3Fingerprint,
|
||||
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,
|
||||
};
|
||||
const StaticPinset kPinSet_mozilla = { 21, kPinSet_mozilla_Data};
|
||||
|
||||
static const char* const kPinSet_mozilla_test_Data[] = {
|
||||
kEnd_Entity_Test_CertFingerprint,
|
||||
struct StaticPinset {
|
||||
const StaticFingerprints* sha1;
|
||||
const StaticFingerprints* sha256;
|
||||
};
|
||||
const StaticPinset kPinSet_mozilla_test = { 1, kPinSet_mozilla_test_Data};
|
||||
|
||||
/*Domainlist*/
|
||||
typedef struct {
|
||||
const char *mHost;
|
||||
/* Mozilla static pinsets */
|
||||
static const char* kPinset_mozilla_sha256_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,
|
||||
kVerisign_Class_4_Public_Primary_Certification_Authority___G3Fingerprint,
|
||||
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_sha256 = { 21, kPinset_mozilla_sha256_Data };
|
||||
|
||||
static const StaticPinset kPinset_mozilla = {
|
||||
nullptr,
|
||||
&kPinset_mozilla_sha256
|
||||
};
|
||||
|
||||
static const char* kPinset_mozilla_test_sha256_Data[] = {
|
||||
kEnd_Entity_Test_CertFingerprint,
|
||||
};
|
||||
static const StaticFingerprints kPinset_mozilla_test_sha256 = { 1, kPinset_mozilla_test_sha256_Data };
|
||||
|
||||
static const StaticPinset kPinset_mozilla_test = {
|
||||
nullptr,
|
||||
&kPinset_mozilla_test_sha256
|
||||
};
|
||||
|
||||
/* Chrome static pinsets */
|
||||
static const char* kPinset_test_sha1_Data[] = {
|
||||
kTestSPKIFingerprint,
|
||||
};
|
||||
static const StaticFingerprints kPinset_test_sha1 = { 1, kPinset_test_sha1_Data };
|
||||
|
||||
static const StaticPinset kPinset_test = {
|
||||
&kPinset_test_sha1,
|
||||
nullptr
|
||||
};
|
||||
|
||||
static const char* kPinset_google_sha1_Data[] = {
|
||||
kGoogleG2Fingerprint,
|
||||
kGoogleBackup2048Fingerprint,
|
||||
};
|
||||
static const StaticFingerprints kPinset_google_sha1 = { 2, kPinset_google_sha1_Data };
|
||||
|
||||
static const StaticPinset kPinset_google = {
|
||||
&kPinset_google_sha1,
|
||||
nullptr
|
||||
};
|
||||
|
||||
static const char* kPinset_tor_sha1_Data[] = {
|
||||
kTor1Fingerprint,
|
||||
kTor2Fingerprint,
|
||||
kTor3Fingerprint,
|
||||
};
|
||||
static const StaticFingerprints kPinset_tor_sha1 = { 3, kPinset_tor_sha1_Data };
|
||||
|
||||
static const char* kPinset_tor_sha256_Data[] = {
|
||||
kDigiCert_High_Assurance_EV_Root_CAFingerprint,
|
||||
kGOOGLE_PIN_RapidSSLFingerprint,
|
||||
};
|
||||
static const StaticFingerprints kPinset_tor_sha256 = { 2, kPinset_tor_sha256_Data };
|
||||
|
||||
static const StaticPinset kPinset_tor = {
|
||||
&kPinset_tor_sha1,
|
||||
&kPinset_tor_sha256
|
||||
};
|
||||
|
||||
static const char* kPinset_twitterCom_sha1_Data[] = {
|
||||
kTwitter1Fingerprint,
|
||||
};
|
||||
static const StaticFingerprints kPinset_twitterCom_sha1 = { 1, kPinset_twitterCom_sha1_Data };
|
||||
|
||||
static const char* kPinset_twitterCom_sha256_Data[] = {
|
||||
kVerisign_Class_2_Public_Primary_Certification_Authority___G2Fingerprint,
|
||||
kVerisign_Class_3_Public_Primary_Certification_Authority___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,
|
||||
kVerisign_Class_1_Public_Primary_Certification_AuthorityFingerprint,
|
||||
kGeoTrust_Primary_Certification_AuthorityFingerprint,
|
||||
kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint,
|
||||
kVeriSign_Class_3_Public_Primary_Certification_Authority___G4Fingerprint,
|
||||
kVerisign_Class_4_Public_Primary_Certification_Authority___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,
|
||||
kVerisign_Class_3_Public_Primary_Certification_AuthorityFingerprint,
|
||||
kGeoTrust_Primary_Certification_Authority___G2Fingerprint,
|
||||
};
|
||||
static const StaticFingerprints kPinset_twitterCom_sha256 = { 21, kPinset_twitterCom_sha256_Data };
|
||||
|
||||
static const StaticPinset kPinset_twitterCom = {
|
||||
&kPinset_twitterCom_sha1,
|
||||
&kPinset_twitterCom_sha256
|
||||
};
|
||||
|
||||
static const char* kPinset_twitterCDN_sha1_Data[] = {
|
||||
kTwitter1Fingerprint,
|
||||
};
|
||||
static const StaticFingerprints kPinset_twitterCDN_sha1 = { 1, kPinset_twitterCDN_sha1_Data };
|
||||
|
||||
static const char* kPinset_twitterCDN_sha256_Data[] = {
|
||||
kVerisign_Class_2_Public_Primary_Certification_Authority___G2Fingerprint,
|
||||
kComodo_Trusted_Services_rootFingerprint,
|
||||
kCOMODO_Certification_AuthorityFingerprint,
|
||||
kVerisign_Class_3_Public_Primary_Certification_Authority___G2Fingerprint,
|
||||
kAddTrust_Low_Value_Services_RootFingerprint,
|
||||
kUTN_USERFirst_Object_Root_CAFingerprint,
|
||||
kGTE_CyberTrust_Global_RootFingerprint,
|
||||
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,
|
||||
kVerisign_Class_1_Public_Primary_Certification_AuthorityFingerprint,
|
||||
kAddTrust_Public_Services_RootFingerprint,
|
||||
kUTN_DATACorp_SGC_Root_CAFingerprint,
|
||||
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,
|
||||
kVerisign_Class_4_Public_Primary_Certification_Authority___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,
|
||||
kGOOGLE_PIN_Entrust_G2Fingerprint,
|
||||
kGeoTrust_Universal_CA_2Fingerprint,
|
||||
kGeoTrust_Global_CAFingerprint,
|
||||
kGlobalSign_Root_CA___R2Fingerprint,
|
||||
kAddTrust_External_RootFingerprint,
|
||||
kVeriSign_Universal_Root_Certification_AuthorityFingerprint,
|
||||
kGeoTrust_Universal_CAFingerprint,
|
||||
kEntrust_net_Secure_Server_CAFingerprint,
|
||||
kGeoTrust_Primary_Certification_Authority___G3Fingerprint,
|
||||
kDigiCert_Global_Root_CAFingerprint,
|
||||
kVerisign_Class_3_Public_Primary_Certification_AuthorityFingerprint,
|
||||
kGeoTrust_Primary_Certification_Authority___G2Fingerprint,
|
||||
kComodo_AAA_Services_rootFingerprint,
|
||||
kAddTrust_Qualified_Certificates_RootFingerprint,
|
||||
};
|
||||
static const StaticFingerprints kPinset_twitterCDN_sha256 = { 42, kPinset_twitterCDN_sha256_Data };
|
||||
|
||||
static const StaticPinset kPinset_twitterCDN = {
|
||||
&kPinset_twitterCDN_sha1,
|
||||
&kPinset_twitterCDN_sha256
|
||||
};
|
||||
|
||||
static const char* kPinset_tor2web_sha256_Data[] = {
|
||||
kGOOGLE_PIN_Tor2webFingerprint,
|
||||
kGOOGLE_PIN_AlphaSSL_G2Fingerprint,
|
||||
};
|
||||
static const StaticFingerprints kPinset_tor2web_sha256 = { 2, kPinset_tor2web_sha256_Data };
|
||||
|
||||
static const StaticPinset kPinset_tor2web = {
|
||||
nullptr,
|
||||
&kPinset_tor2web_sha256
|
||||
};
|
||||
|
||||
static const char* kPinset_cryptoCat_sha256_Data[] = {
|
||||
kDigiCert_High_Assurance_EV_Root_CAFingerprint,
|
||||
kGOOGLE_PIN_CryptoCat1Fingerprint,
|
||||
};
|
||||
static const StaticFingerprints kPinset_cryptoCat_sha256 = { 2, kPinset_cryptoCat_sha256_Data };
|
||||
|
||||
static const StaticPinset kPinset_cryptoCat = {
|
||||
nullptr,
|
||||
&kPinset_cryptoCat_sha256
|
||||
};
|
||||
|
||||
static const char* kPinset_lavabit_sha256_Data[] = {
|
||||
kGOOGLE_PIN_LibertylavabitcomFingerprint,
|
||||
};
|
||||
static const StaticFingerprints kPinset_lavabit_sha256 = { 1, kPinset_lavabit_sha256_Data };
|
||||
|
||||
static const StaticPinset kPinset_lavabit = {
|
||||
nullptr,
|
||||
&kPinset_lavabit_sha256
|
||||
};
|
||||
|
||||
/* Domainlist */
|
||||
struct TransportSecurityPreload {
|
||||
const char* mHost;
|
||||
const bool mIncludeSubdomains;
|
||||
const bool mTestMode;
|
||||
const StaticPinset *pinset;
|
||||
} TransportSecurityPreload;
|
||||
|
||||
static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
||||
{ "addons.mozilla.net", true, &kPinSet_mozilla },
|
||||
{ "addons.mozilla.org", true, &kPinSet_mozilla },
|
||||
{ "cdn.mozilla.net", true, &kPinSet_mozilla },
|
||||
{ "cdn.mozilla.org", true, &kPinSet_mozilla },
|
||||
{ "exclude-subdomains.pinning.example.com", false, &kPinSet_mozilla_test },
|
||||
{ "include-subdomains.pinning.example.com", true, &kPinSet_mozilla_test },
|
||||
{ "media.mozilla.com", true, &kPinSet_mozilla },
|
||||
};
|
||||
|
||||
static const int kPublicKeyPinningPreloadListLength = 7;
|
||||
/* Sort hostnames for binary search. */
|
||||
static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
||||
{ "accounts.google.com", true, true, &kPinset_google },
|
||||
{ "addons.mozilla.net", true, true, &kPinset_mozilla },
|
||||
{ "addons.mozilla.org", true, true, &kPinset_mozilla },
|
||||
{ "admin.google.com", true, true, &kPinset_google },
|
||||
{ "android.com", true, true, &kPinset_google },
|
||||
{ "api.twitter.com", true, true, &kPinset_twitterCDN },
|
||||
{ "apis.google.com", true, true, &kPinset_google },
|
||||
{ "appengine.google.com", true, true, &kPinset_google },
|
||||
{ "appspot.com", true, true, &kPinset_google },
|
||||
{ "blog.torproject.org", true, true, &kPinset_tor },
|
||||
{ "business.twitter.com", true, true, &kPinset_twitterCom },
|
||||
{ "cdn.mozilla.net", true, true, &kPinset_mozilla },
|
||||
{ "cdn.mozilla.org", true, true, &kPinset_mozilla },
|
||||
{ "chart.apis.google.com", true, true, &kPinset_google },
|
||||
{ "check.torproject.org", true, true, &kPinset_tor },
|
||||
{ "checkout.google.com", true, true, &kPinset_google },
|
||||
{ "chrome-devtools-frontend.appspot.com", true, true, &kPinset_google },
|
||||
{ "chrome.google.com", true, true, &kPinset_google },
|
||||
{ "chromiumcodereview.appspot.com", true, true, &kPinset_google },
|
||||
{ "cloud.google.com", true, true, &kPinset_google },
|
||||
{ "code.google.com", true, true, &kPinset_google },
|
||||
{ "codereview.appspot.com", true, true, &kPinset_google },
|
||||
{ "codereview.chromium.org", true, true, &kPinset_google },
|
||||
{ "crypto.cat", false, true, &kPinset_cryptoCat },
|
||||
{ "dev.twitter.com", true, true, &kPinset_twitterCom },
|
||||
{ "dist.torproject.org", true, true, &kPinset_tor },
|
||||
{ "dl.google.com", true, true, &kPinset_google },
|
||||
{ "docs.google.com", true, true, &kPinset_google },
|
||||
{ "doubleclick.net", true, true, &kPinset_google },
|
||||
{ "drive.google.com", true, true, &kPinset_google },
|
||||
{ "encrypted.google.com", true, true, &kPinset_google },
|
||||
{ "exclude-subdomains.pinning.example.com", false, false, &kPinset_mozilla_test },
|
||||
{ "g.co", true, true, &kPinset_google },
|
||||
{ "glass.google.com", true, true, &kPinset_google },
|
||||
{ "gmail.com", false, true, &kPinset_google },
|
||||
{ "goo.gl", true, true, &kPinset_google },
|
||||
{ "google-analytics.com", true, true, &kPinset_google },
|
||||
{ "google.ac", true, true, &kPinset_google },
|
||||
{ "google.ad", true, true, &kPinset_google },
|
||||
{ "google.ae", true, true, &kPinset_google },
|
||||
{ "google.af", true, true, &kPinset_google },
|
||||
{ "google.ag", true, true, &kPinset_google },
|
||||
{ "google.am", true, true, &kPinset_google },
|
||||
{ "google.as", true, true, &kPinset_google },
|
||||
{ "google.at", true, true, &kPinset_google },
|
||||
{ "google.az", true, true, &kPinset_google },
|
||||
{ "google.ba", true, true, &kPinset_google },
|
||||
{ "google.be", true, true, &kPinset_google },
|
||||
{ "google.bf", true, true, &kPinset_google },
|
||||
{ "google.bg", true, true, &kPinset_google },
|
||||
{ "google.bi", true, true, &kPinset_google },
|
||||
{ "google.bj", true, true, &kPinset_google },
|
||||
{ "google.bs", true, true, &kPinset_google },
|
||||
{ "google.by", true, true, &kPinset_google },
|
||||
{ "google.ca", true, true, &kPinset_google },
|
||||
{ "google.cat", true, true, &kPinset_google },
|
||||
{ "google.cc", true, true, &kPinset_google },
|
||||
{ "google.cd", true, true, &kPinset_google },
|
||||
{ "google.cf", true, true, &kPinset_google },
|
||||
{ "google.cg", true, true, &kPinset_google },
|
||||
{ "google.ch", true, true, &kPinset_google },
|
||||
{ "google.ci", true, true, &kPinset_google },
|
||||
{ "google.cl", true, true, &kPinset_google },
|
||||
{ "google.cm", true, true, &kPinset_google },
|
||||
{ "google.cn", true, true, &kPinset_google },
|
||||
{ "google.co.ao", true, true, &kPinset_google },
|
||||
{ "google.co.bw", true, true, &kPinset_google },
|
||||
{ "google.co.ck", true, true, &kPinset_google },
|
||||
{ "google.co.cr", true, true, &kPinset_google },
|
||||
{ "google.co.hu", true, true, &kPinset_google },
|
||||
{ "google.co.id", true, true, &kPinset_google },
|
||||
{ "google.co.il", true, true, &kPinset_google },
|
||||
{ "google.co.im", true, true, &kPinset_google },
|
||||
{ "google.co.in", true, true, &kPinset_google },
|
||||
{ "google.co.je", true, true, &kPinset_google },
|
||||
{ "google.co.jp", true, true, &kPinset_google },
|
||||
{ "google.co.ke", true, true, &kPinset_google },
|
||||
{ "google.co.kr", true, true, &kPinset_google },
|
||||
{ "google.co.ls", true, true, &kPinset_google },
|
||||
{ "google.co.ma", true, true, &kPinset_google },
|
||||
{ "google.co.mz", true, true, &kPinset_google },
|
||||
{ "google.co.nz", true, true, &kPinset_google },
|
||||
{ "google.co.th", true, true, &kPinset_google },
|
||||
{ "google.co.tz", true, true, &kPinset_google },
|
||||
{ "google.co.ug", true, true, &kPinset_google },
|
||||
{ "google.co.uk", true, true, &kPinset_google },
|
||||
{ "google.co.uz", true, true, &kPinset_google },
|
||||
{ "google.co.ve", true, true, &kPinset_google },
|
||||
{ "google.co.vi", true, true, &kPinset_google },
|
||||
{ "google.co.za", true, true, &kPinset_google },
|
||||
{ "google.co.zm", true, true, &kPinset_google },
|
||||
{ "google.co.zw", true, true, &kPinset_google },
|
||||
{ "google.com", true, true, &kPinset_google },
|
||||
{ "google.com.af", true, true, &kPinset_google },
|
||||
{ "google.com.ag", true, true, &kPinset_google },
|
||||
{ "google.com.ai", true, true, &kPinset_google },
|
||||
{ "google.com.ar", true, true, &kPinset_google },
|
||||
{ "google.com.au", true, true, &kPinset_google },
|
||||
{ "google.com.bd", true, true, &kPinset_google },
|
||||
{ "google.com.bh", true, true, &kPinset_google },
|
||||
{ "google.com.bn", true, true, &kPinset_google },
|
||||
{ "google.com.bo", true, true, &kPinset_google },
|
||||
{ "google.com.br", true, true, &kPinset_google },
|
||||
{ "google.com.by", true, true, &kPinset_google },
|
||||
{ "google.com.bz", true, true, &kPinset_google },
|
||||
{ "google.com.cn", true, true, &kPinset_google },
|
||||
{ "google.com.co", true, true, &kPinset_google },
|
||||
{ "google.com.cu", true, true, &kPinset_google },
|
||||
{ "google.com.cy", true, true, &kPinset_google },
|
||||
{ "google.com.do", true, true, &kPinset_google },
|
||||
{ "google.com.ec", true, true, &kPinset_google },
|
||||
{ "google.com.eg", true, true, &kPinset_google },
|
||||
{ "google.com.et", true, true, &kPinset_google },
|
||||
{ "google.com.fj", true, true, &kPinset_google },
|
||||
{ "google.com.ge", true, true, &kPinset_google },
|
||||
{ "google.com.gh", true, true, &kPinset_google },
|
||||
{ "google.com.gi", true, true, &kPinset_google },
|
||||
{ "google.com.gr", true, true, &kPinset_google },
|
||||
{ "google.com.gt", true, true, &kPinset_google },
|
||||
{ "google.com.hk", true, true, &kPinset_google },
|
||||
{ "google.com.iq", true, true, &kPinset_google },
|
||||
{ "google.com.jm", true, true, &kPinset_google },
|
||||
{ "google.com.jo", true, true, &kPinset_google },
|
||||
{ "google.com.kh", true, true, &kPinset_google },
|
||||
{ "google.com.kw", true, true, &kPinset_google },
|
||||
{ "google.com.lb", true, true, &kPinset_google },
|
||||
{ "google.com.ly", true, true, &kPinset_google },
|
||||
{ "google.com.mt", true, true, &kPinset_google },
|
||||
{ "google.com.mx", true, true, &kPinset_google },
|
||||
{ "google.com.my", true, true, &kPinset_google },
|
||||
{ "google.com.na", true, true, &kPinset_google },
|
||||
{ "google.com.nf", true, true, &kPinset_google },
|
||||
{ "google.com.ng", true, true, &kPinset_google },
|
||||
{ "google.com.ni", true, true, &kPinset_google },
|
||||
{ "google.com.np", true, true, &kPinset_google },
|
||||
{ "google.com.nr", true, true, &kPinset_google },
|
||||
{ "google.com.om", true, true, &kPinset_google },
|
||||
{ "google.com.pa", true, true, &kPinset_google },
|
||||
{ "google.com.pe", true, true, &kPinset_google },
|
||||
{ "google.com.ph", true, true, &kPinset_google },
|
||||
{ "google.com.pk", true, true, &kPinset_google },
|
||||
{ "google.com.pl", true, true, &kPinset_google },
|
||||
{ "google.com.pr", true, true, &kPinset_google },
|
||||
{ "google.com.py", true, true, &kPinset_google },
|
||||
{ "google.com.qa", true, true, &kPinset_google },
|
||||
{ "google.com.ru", true, true, &kPinset_google },
|
||||
{ "google.com.sa", true, true, &kPinset_google },
|
||||
{ "google.com.sb", true, true, &kPinset_google },
|
||||
{ "google.com.sg", true, true, &kPinset_google },
|
||||
{ "google.com.sl", true, true, &kPinset_google },
|
||||
{ "google.com.sv", true, true, &kPinset_google },
|
||||
{ "google.com.tj", true, true, &kPinset_google },
|
||||
{ "google.com.tn", true, true, &kPinset_google },
|
||||
{ "google.com.tr", true, true, &kPinset_google },
|
||||
{ "google.com.tw", true, true, &kPinset_google },
|
||||
{ "google.com.ua", true, true, &kPinset_google },
|
||||
{ "google.com.uy", true, true, &kPinset_google },
|
||||
{ "google.com.vc", true, true, &kPinset_google },
|
||||
{ "google.com.ve", true, true, &kPinset_google },
|
||||
{ "google.com.vn", true, true, &kPinset_google },
|
||||
{ "google.cv", true, true, &kPinset_google },
|
||||
{ "google.cz", true, true, &kPinset_google },
|
||||
{ "google.de", true, true, &kPinset_google },
|
||||
{ "google.dj", true, true, &kPinset_google },
|
||||
{ "google.dk", true, true, &kPinset_google },
|
||||
{ "google.dm", true, true, &kPinset_google },
|
||||
{ "google.dz", true, true, &kPinset_google },
|
||||
{ "google.ee", true, true, &kPinset_google },
|
||||
{ "google.es", true, true, &kPinset_google },
|
||||
{ "google.fi", true, true, &kPinset_google },
|
||||
{ "google.fm", true, true, &kPinset_google },
|
||||
{ "google.fr", true, true, &kPinset_google },
|
||||
{ "google.ga", true, true, &kPinset_google },
|
||||
{ "google.ge", true, true, &kPinset_google },
|
||||
{ "google.gg", true, true, &kPinset_google },
|
||||
{ "google.gl", true, true, &kPinset_google },
|
||||
{ "google.gm", true, true, &kPinset_google },
|
||||
{ "google.gp", true, true, &kPinset_google },
|
||||
{ "google.gr", true, true, &kPinset_google },
|
||||
{ "google.gy", true, true, &kPinset_google },
|
||||
{ "google.hk", true, true, &kPinset_google },
|
||||
{ "google.hn", true, true, &kPinset_google },
|
||||
{ "google.hr", true, true, &kPinset_google },
|
||||
{ "google.ht", true, true, &kPinset_google },
|
||||
{ "google.hu", true, true, &kPinset_google },
|
||||
{ "google.ie", true, true, &kPinset_google },
|
||||
{ "google.im", true, true, &kPinset_google },
|
||||
{ "google.info", true, true, &kPinset_google },
|
||||
{ "google.iq", true, true, &kPinset_google },
|
||||
{ "google.is", true, true, &kPinset_google },
|
||||
{ "google.it", true, true, &kPinset_google },
|
||||
{ "google.it.ao", true, true, &kPinset_google },
|
||||
{ "google.je", true, true, &kPinset_google },
|
||||
{ "google.jo", true, true, &kPinset_google },
|
||||
{ "google.jobs", true, true, &kPinset_google },
|
||||
{ "google.jp", true, true, &kPinset_google },
|
||||
{ "google.kg", true, true, &kPinset_google },
|
||||
{ "google.ki", true, true, &kPinset_google },
|
||||
{ "google.kz", true, true, &kPinset_google },
|
||||
{ "google.la", true, true, &kPinset_google },
|
||||
{ "google.li", true, true, &kPinset_google },
|
||||
{ "google.lk", true, true, &kPinset_google },
|
||||
{ "google.lt", true, true, &kPinset_google },
|
||||
{ "google.lu", true, true, &kPinset_google },
|
||||
{ "google.lv", true, true, &kPinset_google },
|
||||
{ "google.md", true, true, &kPinset_google },
|
||||
{ "google.me", true, true, &kPinset_google },
|
||||
{ "google.mg", true, true, &kPinset_google },
|
||||
{ "google.mk", true, true, &kPinset_google },
|
||||
{ "google.ml", true, true, &kPinset_google },
|
||||
{ "google.mn", true, true, &kPinset_google },
|
||||
{ "google.ms", true, true, &kPinset_google },
|
||||
{ "google.mu", true, true, &kPinset_google },
|
||||
{ "google.mv", true, true, &kPinset_google },
|
||||
{ "google.mw", true, true, &kPinset_google },
|
||||
{ "google.ne", true, true, &kPinset_google },
|
||||
{ "google.ne.jp", true, true, &kPinset_google },
|
||||
{ "google.net", true, true, &kPinset_google },
|
||||
{ "google.nl", true, true, &kPinset_google },
|
||||
{ "google.no", true, true, &kPinset_google },
|
||||
{ "google.nr", true, true, &kPinset_google },
|
||||
{ "google.nu", true, true, &kPinset_google },
|
||||
{ "google.off.ai", true, true, &kPinset_google },
|
||||
{ "google.pk", true, true, &kPinset_google },
|
||||
{ "google.pl", true, true, &kPinset_google },
|
||||
{ "google.pn", true, true, &kPinset_google },
|
||||
{ "google.ps", true, true, &kPinset_google },
|
||||
{ "google.pt", true, true, &kPinset_google },
|
||||
{ "google.ro", true, true, &kPinset_google },
|
||||
{ "google.rs", true, true, &kPinset_google },
|
||||
{ "google.ru", true, true, &kPinset_google },
|
||||
{ "google.rw", true, true, &kPinset_google },
|
||||
{ "google.sc", true, true, &kPinset_google },
|
||||
{ "google.se", true, true, &kPinset_google },
|
||||
{ "google.sh", true, true, &kPinset_google },
|
||||
{ "google.si", true, true, &kPinset_google },
|
||||
{ "google.sk", true, true, &kPinset_google },
|
||||
{ "google.sm", true, true, &kPinset_google },
|
||||
{ "google.sn", true, true, &kPinset_google },
|
||||
{ "google.so", true, true, &kPinset_google },
|
||||
{ "google.st", true, true, &kPinset_google },
|
||||
{ "google.td", true, true, &kPinset_google },
|
||||
{ "google.tg", true, true, &kPinset_google },
|
||||
{ "google.tk", true, true, &kPinset_google },
|
||||
{ "google.tl", true, true, &kPinset_google },
|
||||
{ "google.tm", true, true, &kPinset_google },
|
||||
{ "google.tn", true, true, &kPinset_google },
|
||||
{ "google.to", true, true, &kPinset_google },
|
||||
{ "google.tp", true, true, &kPinset_google },
|
||||
{ "google.tt", true, true, &kPinset_google },
|
||||
{ "google.us", true, true, &kPinset_google },
|
||||
{ "google.uz", true, true, &kPinset_google },
|
||||
{ "google.vg", true, true, &kPinset_google },
|
||||
{ "google.vu", true, true, &kPinset_google },
|
||||
{ "google.ws", true, true, &kPinset_google },
|
||||
{ "googleadservices.com", true, true, &kPinset_google },
|
||||
{ "googleapis.com", true, true, &kPinset_google },
|
||||
{ "googlecode.com", true, true, &kPinset_google },
|
||||
{ "googlecommerce.com", true, true, &kPinset_google },
|
||||
{ "googlegroups.com", true, true, &kPinset_google },
|
||||
{ "googlemail.com", false, true, &kPinset_google },
|
||||
{ "googleplex.com", true, true, &kPinset_google },
|
||||
{ "googlesyndication.com", true, true, &kPinset_google },
|
||||
{ "googletagmanager.com", true, true, &kPinset_google },
|
||||
{ "googletagservices.com", true, true, &kPinset_google },
|
||||
{ "googleusercontent.com", true, true, &kPinset_google },
|
||||
{ "goto.google.com", true, true, &kPinset_google },
|
||||
{ "groups.google.com", true, true, &kPinset_google },
|
||||
{ "gstatic.com", true, true, &kPinset_google },
|
||||
{ "history.google.com", true, true, &kPinset_google },
|
||||
{ "hostedtalkgadget.google.com", true, true, &kPinset_google },
|
||||
{ "include-subdomains.pinning.example.com", true, false, &kPinset_mozilla_test },
|
||||
{ "liberty.lavabit.com", true, true, &kPinset_lavabit },
|
||||
{ "mail.google.com", true, true, &kPinset_google },
|
||||
{ "market.android.com", true, true, &kPinset_google },
|
||||
{ "media.mozilla.com", true, true, &kPinset_mozilla },
|
||||
{ "mobile.twitter.com", true, true, &kPinset_twitterCom },
|
||||
{ "oauth.twitter.com", true, true, &kPinset_twitterCom },
|
||||
{ "pinningtest.appspot.com", true, true, &kPinset_test },
|
||||
{ "platform.twitter.com", true, true, &kPinset_twitterCDN },
|
||||
{ "play.google.com", false, true, &kPinset_google },
|
||||
{ "plus.google.com", true, true, &kPinset_google },
|
||||
{ "plus.sandbox.google.com", true, true, &kPinset_google },
|
||||
{ "profiles.google.com", true, true, &kPinset_google },
|
||||
{ "script.google.com", true, true, &kPinset_google },
|
||||
{ "security.google.com", true, true, &kPinset_google },
|
||||
{ "sites.google.com", true, true, &kPinset_google },
|
||||
{ "spreadsheets.google.com", true, true, &kPinset_google },
|
||||
{ "ssl.google-analytics.com", true, true, &kPinset_google },
|
||||
{ "talk.google.com", true, true, &kPinset_google },
|
||||
{ "talkgadget.google.com", true, true, &kPinset_google },
|
||||
{ "test-mode.pinning.example.com", true, true, &kPinset_mozilla_test },
|
||||
{ "tor2web.org", true, true, &kPinset_tor2web },
|
||||
{ "torproject.org", false, true, &kPinset_tor },
|
||||
{ "translate.googleapis.com", true, true, &kPinset_google },
|
||||
{ "twimg.com", true, true, &kPinset_twitterCDN },
|
||||
{ "twitter.com", false, true, &kPinset_twitterCom },
|
||||
{ "urchin.com", true, true, &kPinset_google },
|
||||
{ "wallet.google.com", true, true, &kPinset_google },
|
||||
{ "www.gmail.com", false, true, &kPinset_google },
|
||||
{ "www.googlemail.com", false, true, &kPinset_google },
|
||||
{ "www.torproject.org", true, true, &kPinset_tor },
|
||||
{ "www.twitter.com", true, true, &kPinset_twitterCom },
|
||||
{ "youtu.be", true, true, &kPinset_google },
|
||||
{ "youtube.com", true, true, &kPinset_google },
|
||||
{ "ytimg.com", true, true, &kPinset_google },
|
||||
};
|
||||
|
||||
const PRTime kPreloadPKPinsExpirationTime = INT64_C(1410540741649000);
|
||||
static const int kPublicKeyPinningPreloadListLength = 306;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1410801238668000);
|
||||
|
@ -48,6 +48,12 @@ function test_strict() {
|
||||
// This domain serves a cert that doesn't match the pinset, but subdomains
|
||||
// are excluded.
|
||||
add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
|
||||
|
||||
// This domain's pinset is exactly the same as
|
||||
// include-subdomains.pinning.example.com, serves the same cert as
|
||||
// bad.include-subdomains.pinning.example.com, but it should pass because
|
||||
// it's in test_mode.
|
||||
add_connection_test("test-mode.pinning.example.com", Cr.NS_OK);
|
||||
};
|
||||
|
||||
function test_mitm() {
|
||||
@ -67,6 +73,7 @@ function test_mitm() {
|
||||
|
||||
add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
|
||||
add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
|
||||
add_connection_test("test-mode.pinning.example.com", Cr.NS_OK);
|
||||
};
|
||||
|
||||
function test_disabled() {
|
||||
@ -81,6 +88,7 @@ function test_disabled() {
|
||||
add_connection_test("bad.include-subdomains.pinning.example.com", Cr.NS_OK);
|
||||
add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
|
||||
add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
|
||||
add_connection_test("test-mode.pinning.example.com", Cr.NS_OK);
|
||||
};
|
||||
|
||||
function check_pinning_telemetry() {
|
||||
|
Binary file not shown.
@ -43,15 +43,16 @@ const BadCertHost sBadCertHosts[] =
|
||||
{ "inadequatekeyusage.example.com", "inadequatekeyusage" },
|
||||
{ "selfsigned-inadequateEKU.example.com", "selfsigned-inadequateEKU" },
|
||||
{ "self-signed-end-entity-with-cA-true.example.com", "self-signed-EE-with-cA-true" },
|
||||
// All of include-subdomains.pinning.example.com is pinned to End Entity Test
|
||||
// Cert with nick localhostAndExampleCom. Any other nick will only pass
|
||||
// pinning when security.cert_pinning.enforcement.level != strict and otherCA
|
||||
// is added as a user-specified trust anchor. See StaticHPKPins.h.
|
||||
// All of include-subdomains.pinning.example.com is pinned to End Entity
|
||||
// Test Cert with nick localhostAndExampleCom. Any other nick will only
|
||||
// pass pinning when security.cert_pinning.enforcement.level != strict and
|
||||
// otherCA is added as a user-specified trust anchor. See StaticHPKPins.h.
|
||||
{ "include-subdomains.pinning.example.com", "localhostAndExampleCom" },
|
||||
{ "good.include-subdomains.pinning.example.com", "localhostAndExampleCom" },
|
||||
{ "bad.include-subdomains.pinning.example.com", "otherIssuerEE" },
|
||||
{ "exclude-subdomains.pinning.example.com", "localhostAndExampleCom" },
|
||||
{ "sub.exclude-subdomains.pinning.example.com", "otherIssuerEE" },
|
||||
{ "test-mode.pinning.example.com", "otherIssuerEE" },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
|
Binary file not shown.
@ -144,7 +144,7 @@ make_CA otherCA 'CN=Other test CA' other-test-ca.der
|
||||
|
||||
make_EE localhostAndExampleCom 'CN=Test End-entity' testCA "localhost,*.example.com,*.pinning.example.com,*.include-subdomains.pinning.example.com,*.exclude-subdomains.pinning.example.com"
|
||||
# Make an EE cert issued by otherCA
|
||||
make_EE otherIssuerEE 'CN=Wrong CA Pin Test End-Entity' otherCA "*.include-subdomains.pinning.example.com,*.exclude-subdomains.pinning.example.com"
|
||||
make_EE otherIssuerEE 'CN=Wrong CA Pin Test End-Entity' otherCA "*.include-subdomains.pinning.example.com,*.exclude-subdomains.pinning.example.com,*.pinning.example.com"
|
||||
|
||||
$RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -L -n localhostAndExampleCom -r > $OUTPUT_DIR/default-ee.der
|
||||
# A cert that is like localhostAndExampleCom, but with a different serial number for
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
library=
|
||||
name=NSS Internal PKCS #11 Module
|
||||
parameters=configdir='sql:security/manager/ssl/tests/unit/tlsserver' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='security/manager/ssl/tests/unit/tlsserver/' updateCertPrefix='' updateKeyPrefix='' updateid='0' updateTokenDescription=''
|
||||
NSS=trustOrder=75 cipherOrder=100 slotParams={0x00000001=[slotFlags=RSA,RC4,RC2,DES,DH,SHA1,MD5,MD2,SSL,TLS,AES,SHA256,SHA512,Camellia,SEED,RANDOM askpw=any timeout=30 ] } Flags=internal,critical
|
||||
parameters=configdir='sql:./security/manager/ssl/tests/unit/tlsserver' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription=''
|
||||
NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30})
|
||||
|
||||
|
Binary file not shown.
@ -21,61 +21,69 @@
|
||||
// include_subdomains: (optional bool) whether subdomains of |name| are also covered
|
||||
// pins: (string) the |name| member of an object in |pinsets|
|
||||
|
||||
|
||||
// equifax -> aus3
|
||||
// Geotrust Primary -> www.mozilla.org
|
||||
// Geotrust Global -> *. addons.mozilla.org
|
||||
{
|
||||
"pinsets": [
|
||||
{
|
||||
// From bug 772756, mozilla uses GeoTrust, Digicert and Thawte
|
||||
// geotrust ca info: http://www.geotrust.com/resources/root-certificates/index.html
|
||||
// In that same bug we also notice that our cdn sites use Verisign and
|
||||
// Baltimore
|
||||
// This list does not contain any 1024 bit roots for those providers
|
||||
// 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",
|
||||
"static_spki_hashes": [
|
||||
"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 4 Public Primary Certification Authority - G3",
|
||||
"VeriSign Class 3 Public Primary Certification Authority - G5",
|
||||
"VeriSign Universal Root Certification Authority",
|
||||
"VeriSign Class 3 Public Primary Certification Authority - G4",
|
||||
"GeoTrust Primary Certification Authority",
|
||||
"GeoTrust Global CA",
|
||||
"GeoTrust Global CA 2",
|
||||
"GeoTrust Universal CA",
|
||||
"GeoTrust Universal CA 2",
|
||||
"GeoTrust Primary Certification Authority - G2",
|
||||
"GeoTrust Primary Certification Authority - G3",
|
||||
"DigiCert High Assurance EV Root CA",
|
||||
"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",
|
||||
"Baltimore CyberTrust Root"
|
||||
"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"
|
||||
]
|
||||
},
|
||||
// For pinning tests on pinning.example.com, the certificate must be 'End
|
||||
// Entity Test Cert'
|
||||
{
|
||||
"name": "mozilla_test",
|
||||
"static_spki_hashes": [
|
||||
"sha256_hashes": [
|
||||
"End Entity Test Cert"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
"entries": [
|
||||
// from bug 1005653 we learned that addon subdomains include cdn sites
|
||||
{ "name": "addons.mozilla.org", "include_subdomains": true, "pins": "mozilla" },
|
||||
{ "name": "addons.mozilla.net", "include_subdomains": true, "pins": "mozilla" },
|
||||
{ "name": "cdn.mozilla.net", "include_subdomains": true, "pins": "mozilla" },
|
||||
{ "name": "cdn.mozilla.org", "include_subdomains": true, "pins": "mozilla" },
|
||||
{ "name": "media.mozilla.com", "include_subdomains": true, "pins": "mozilla" },
|
||||
{ "name": "include-subdomains.pinning.example.com", "include_subdomains": true, "pins": "mozilla_test" },
|
||||
{ "name": "exclude-subdomains.pinning.example.com", "include_subdomains": false, "pins": "mozilla_test" }
|
||||
{ "name": "addons.mozilla.org", "include_subdomains": true,
|
||||
"pins": "mozilla", "test_mode": true },
|
||||
{ "name": "addons.mozilla.net", "include_subdomains": true,
|
||||
"pins": "mozilla", "test_mode": true },
|
||||
{ "name": "cdn.mozilla.net", "include_subdomains": true,
|
||||
"pins": "mozilla", "test_mode": true},
|
||||
{ "name": "cdn.mozilla.org", "include_subdomains": true,
|
||||
"pins": "mozilla", "test_mode": true },
|
||||
{ "name": "media.mozilla.com", "include_subdomains": true,
|
||||
"pins": "mozilla", "test_mode": true },
|
||||
{ "name": "include-subdomains.pinning.example.com",
|
||||
"include_subdomains": true, "pins": "mozilla_test",
|
||||
"test_mode": false },
|
||||
{ "name": "exclude-subdomains.pinning.example.com",
|
||||
"include_subdomains": false, "pins": "mozilla_test",
|
||||
"test_mode": false },
|
||||
{ "name": "test-mode.pinning.example.com", "include_subdomains": true,
|
||||
"pins": "mozilla_test", "test_mode": true }
|
||||
]
|
||||
}
|
||||
|
@ -12,7 +12,8 @@
|
||||
// [absolute path to]/StaticHPKPins.h
|
||||
|
||||
if (arguments.length != 3) {
|
||||
throw "Usage: genHPKPins.js <absolute path to PreloadedHPKPins.json> " +
|
||||
throw "Usage: genHPKPStaticPins.js " +
|
||||
"<absolute path to PreloadedHPKPins.json> " +
|
||||
"<absolute path to default-ee.der> " +
|
||||
"<absolute path to StaticHPKPins.h>";
|
||||
}
|
||||
@ -23,11 +24,20 @@ let { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
|
||||
let { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
|
||||
let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
const certdb2 = Cc["@mozilla.org/security/x509certdb;1"]
|
||||
.getService(Ci.nsIX509CertDB2);
|
||||
let gCertDB = Cc["@mozilla.org/security/x509certdb;1"]
|
||||
.getService(Ci.nsIX509CertDB2);
|
||||
gCertDB.QueryInterface(Ci.nsIX509CertDB);
|
||||
|
||||
const BUILT_IN_NICK_PREFIX = "Builtin Object Token:";
|
||||
const SHA1_PREFIX = "sha1/";
|
||||
const SHA256_PREFIX = "sha256/";
|
||||
const GOOGLE_PIN_PREFIX = "GOOGLE_PIN_";
|
||||
|
||||
// Pins expire in 18 weeks
|
||||
const PINNING_MINIMUM_REQUIRED_MAX_AGE = 60 * 60 * 24 * 7 * 18;
|
||||
const CHROME_JSON_SOURCE = "https://src.chromium.org/chrome/trunk/src/net/http/transport_security_state_static.json";
|
||||
const CHROME_CERT_SOURCE = "https://src.chromium.org/chrome/trunk/src/net/http/transport_security_state_static.certs";
|
||||
|
||||
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" +
|
||||
@ -38,26 +48,36 @@ const FILE_HEADER = "/* This Source Code Form is subject to the terms of the Moz
|
||||
"/*****************************************************************************/\n" +
|
||||
"#include <stdint.h>" +
|
||||
"\n";
|
||||
const DOMAINHEADER ="/*Domainlist*/\n" +
|
||||
"typedef struct {\n"+
|
||||
" const char *mHost;\n"+
|
||||
" const bool mIncludeSubdomains;\n"+
|
||||
" const StaticPinset *pinset;\n"+
|
||||
"} TransportSecurityPreload;\n"+
|
||||
"\nstatic const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {\n";
|
||||
const PINSETDEF ="/*Now the pinsets, each is an ordered list by the actual value of the FP*/\n"+
|
||||
"typedef struct {\n"+
|
||||
" const size_t size;\n"+
|
||||
" const char* const* data;\n"+
|
||||
"} StaticPinset;\n";
|
||||
|
||||
const DOMAINHEADER = "/* Domainlist */\n" +
|
||||
"struct TransportSecurityPreload {\n" +
|
||||
" const char* mHost;\n" +
|
||||
" const bool mIncludeSubdomains;\n" +
|
||||
" const bool mTestMode;\n" +
|
||||
" const StaticPinset *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" +
|
||||
"struct StaticPinset {\n" +
|
||||
" const StaticFingerprints* sha1;\n" +
|
||||
" const StaticFingerprints* sha256;\n" +
|
||||
"};\n\n";
|
||||
|
||||
// Command-line arguments
|
||||
var gStaticPins = parseJson(arguments[0]);
|
||||
var gTestCertFile = arguments[1];
|
||||
var gOutputFile = arguments[2];
|
||||
|
||||
function writeTo(string, fos) {
|
||||
fos.write(string, string.length);
|
||||
// Open the output file.
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
file.initWithPath(arguments[2]);
|
||||
let gFileOutputStream = FileUtils.openSafeFileOutputStream(file);
|
||||
|
||||
function writeString(string) {
|
||||
gFileOutputStream.write(string, string.length);
|
||||
}
|
||||
|
||||
function readFileToString(filename) {
|
||||
@ -99,39 +119,239 @@ function isCertBuiltIn(cert) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns a pair of maps [certNameToSKD, certSDKToName] between cert
|
||||
function download(filename) {
|
||||
var 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 "ERROR: problem downloading '" + filename + "': " + e;
|
||||
}
|
||||
|
||||
if (req.status != 200) {
|
||||
throw("ERROR: problem downloading '" + filename + "': status " +
|
||||
req.status);
|
||||
}
|
||||
return req.responseText;
|
||||
}
|
||||
|
||||
function downloadAsJson(filename) {
|
||||
// we have to filter out '//' comments
|
||||
var result = download(filename).replace(/\/\/[^\n]*\n/g, "");
|
||||
var data = null;
|
||||
try {
|
||||
data = JSON.parse(result);
|
||||
}
|
||||
catch (e) {
|
||||
throw "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;
|
||||
}
|
||||
|
||||
// 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 "sha1/" + base64(hash), 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 sha1 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, certSKDToName) {
|
||||
// Prefixes that we care about.
|
||||
const BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
|
||||
const END_CERT = "-----END CERTIFICATE-----";
|
||||
|
||||
// Parsing states.
|
||||
const PRE_NAME = 0;
|
||||
const POST_NAME = 1;
|
||||
const IN_CERT = 2;
|
||||
let state = PRE_NAME;
|
||||
|
||||
let lines = download(filename).split("\n");
|
||||
let name = "";
|
||||
let pemCert = "";
|
||||
let hash = "";
|
||||
let chromeNameToHash = {};
|
||||
let chromeNameToMozName = {}
|
||||
for (let i = 0; i < lines.length; ++i) {
|
||||
let line = lines[i];
|
||||
// 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(SHA1_PREFIX) ||
|
||||
line.startsWith(SHA256_PREFIX)) {
|
||||
if (line.startsWith(SHA1_PREFIX)) {
|
||||
hash = line.substring(SHA1_PREFIX.length);
|
||||
} else if (line.startsWith(SHA256_PREFIX)) {
|
||||
hash = line.substring(SHA256_PREFIX);
|
||||
}
|
||||
// Store the entire prefixed hash, so we can disambiguate sha1 from
|
||||
// sha256 later.
|
||||
chromeNameToHash[chromeName] = line;
|
||||
certNameToSKD[chromeName] = hash;
|
||||
certSKDToName[hash] = chromeName;
|
||||
state = PRE_NAME;
|
||||
} else if (line.startsWith(BEGIN_CERT)) {
|
||||
state = IN_CERT;
|
||||
} else {
|
||||
throw "ERROR: couldn't parse Chrome certificate file " + line;
|
||||
}
|
||||
break;
|
||||
case IN_CERT:
|
||||
if (line.startsWith(END_CERT)) {
|
||||
state = PRE_NAME;
|
||||
hash = getSKDFromPem(pemCert);
|
||||
pemCert = "";
|
||||
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;
|
||||
default:
|
||||
throw "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
|
||||
// sha1_hashes: [],
|
||||
// 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, sha1_hashes: [], sha256_hashes: [] };
|
||||
// Translate the Chrome pinset format to ours
|
||||
pin.static_spki_hashes.forEach(function(name) {
|
||||
if (name in chromeNameToHash) {
|
||||
let hash = chromeNameToHash[name];
|
||||
if (hash.startsWith(SHA1_PREFIX)) {
|
||||
hash = hash.substring(SHA1_PREFIX.length);
|
||||
pinset.sha1_hashes.push(certSKDToName[hash]);
|
||||
} else if (hash.startsWith(SHA256_PREFIX)) {
|
||||
hash = hash.substring(SHA256_PREFIX.length);
|
||||
pinset.sha256_hashes.push(certSKDToName[hash]);
|
||||
} else {
|
||||
throw("Unsupported hash type: " + chromeNameToHash[name]);
|
||||
}
|
||||
// We should have already added hashes for all of these when we
|
||||
// imported the certificate file.
|
||||
if (!certNameToSKD[name]) {
|
||||
throw("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.
|
||||
let entries = chromePreloads.entries;
|
||||
entries.forEach(function(entry) {
|
||||
if (entry.pins && chromeImportedPinsets[entry.pins]) {
|
||||
chromeImportedEntries.push({
|
||||
name: entry.name,
|
||||
include_subdomains: entry.include_subdomains,
|
||||
test_mode: true,
|
||||
pins: entry.pins });
|
||||
}
|
||||
});
|
||||
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(derTestFile) {
|
||||
let allCerts = certdb2.getCerts();
|
||||
let allCerts = gCertDB.getCerts();
|
||||
let enumerator = allCerts.getEnumerator();
|
||||
let certNameToSKD = {};
|
||||
let certSDKToName = {};
|
||||
const BUILT_IN_NICK_PREFIX = "Builtin Object Token:";
|
||||
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 SDK = cert.sha256SubjectPublicKeyInfoDigest;
|
||||
certNameToSKD[name] = SDK;
|
||||
certSDKToName[SDK] = name;
|
||||
let SKD = cert.sha256SubjectPublicKeyInfoDigest;
|
||||
certNameToSKD[name] = SKD;
|
||||
certSKDToName[SKD] = name;
|
||||
}
|
||||
{
|
||||
// A certificate for *.example.com.
|
||||
let der = readFileToString(derTestFile);
|
||||
// XPCOM is too dumb to automatically query the parent interface of
|
||||
// nsIX509CertDB2 without a hint.
|
||||
let certdb = certdb2.QueryInterface(Ci.nsIX509CertDB);
|
||||
let testCert = certdb.constructX509(der, der.length);
|
||||
let testCert = gCertDB.constructX509(der, der.length);
|
||||
// We can't include this cert in the previous loop, because it skips
|
||||
// non-builtin certs and the nickname is not built-in to the cert.
|
||||
let name = "End Entity Test Cert";
|
||||
let SDK = testCert.sha256SubjectPublicKeyInfoDigest;
|
||||
certNameToSKD[name] = SDK;
|
||||
certSDKToName[SDK] = name;
|
||||
let SKD = testCert.sha256SubjectPublicKeyInfoDigest;
|
||||
certNameToSKD[name] = SKD;
|
||||
certSKDToName[SKD] = name;
|
||||
}
|
||||
return [certNameToSKD, certSDKToName];
|
||||
return [certNameToSKD, certSKDToName];
|
||||
}
|
||||
|
||||
function parseJson(filename) {
|
||||
@ -158,82 +378,153 @@ function genExpirationTime() {
|
||||
let nowMillis = now.getTime();
|
||||
let expirationMillis = nowMillis + (PINNING_MINIMUM_REQUIRED_MAX_AGE * 1000);
|
||||
let expirationMicros = expirationMillis * 1000;
|
||||
return "const PRTime kPreloadPKPinsExpirationTime = INT64_C(" +
|
||||
return "static const PRTime kPreloadPKPinsExpirationTime = INT64_C(" +
|
||||
expirationMicros +");\n";
|
||||
}
|
||||
|
||||
function writeFile(certNameToSDK, certSDKToName, jsonPins) {
|
||||
try {
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
file.initWithPath(gOutputFile);
|
||||
let fos = FileUtils.openSafeFileOutputStream(file);
|
||||
|
||||
writeTo(FILE_HEADER, fos);
|
||||
|
||||
// compute used keys
|
||||
let usedFingerPrints = {};
|
||||
let pinset = jsonPins["pinsets"];
|
||||
for (let pinsetEntry of pinset) {
|
||||
for (let certName of pinsetEntry.static_spki_hashes) {
|
||||
usedFingerPrints[certName] = true;
|
||||
}
|
||||
}
|
||||
for (let certName of Object.keys(usedFingerPrints).sort()) {
|
||||
writeTo("/* "+ certName + " */\n", fos);
|
||||
writeTo("static const char " + nameToAlias(certName) + "[]=\n", fos);
|
||||
writeTo(" \"" + certNameToSDK[certName] + "\";\n", fos);
|
||||
writeTo("\n", fos);
|
||||
}
|
||||
|
||||
writeTo(PINSETDEF, fos);
|
||||
|
||||
for (let pinset of jsonPins["pinsets"].sort(compareByName)) {
|
||||
writeTo("static const char* const kPinSet_" + pinset.name + "_Data[] = {\n", fos);
|
||||
let certNameList = pinset.static_spki_hashes;
|
||||
let SKDList = [];
|
||||
for (let certName of pinset.static_spki_hashes) {
|
||||
SKDList.push(certNameToSDK[certName]);
|
||||
}
|
||||
for (let sdk of SKDList.sort() ) {
|
||||
writeTo(" " + nameToAlias(certSDKToName[sdk]) + ",\n", fos);
|
||||
}
|
||||
writeTo("};\n", fos);
|
||||
writeTo("const StaticPinset kPinSet_"+ pinset.name +" = { " +
|
||||
pinset.static_spki_hashes.length + ", kPinSet_"+pinset.name +
|
||||
"_Data};\n", fos);
|
||||
writeTo("\n", fos);
|
||||
}
|
||||
|
||||
// now the domainlist entries
|
||||
writeTo(DOMAINHEADER, fos);
|
||||
for (let entry of jsonPins["entries"].sort(compareByName)) {
|
||||
let printVal = " { \""+ entry.name +"\",\t";
|
||||
if (entry.include_subdomains) {
|
||||
printVal += "true,\t";
|
||||
} else {
|
||||
printVal += "false,\t";
|
||||
}
|
||||
printVal += "&kPinSet_"+entry.pins;
|
||||
printVal += " },\n";
|
||||
writeTo(printVal, fos);
|
||||
}
|
||||
writeTo("};\n", fos);
|
||||
writeTo("\n", fos);
|
||||
let domainFooter = "static const int " +
|
||||
"kPublicKeyPinningPreloadListLength = " +
|
||||
jsonPins["entries"].length + ";\n";
|
||||
writeTo(domainFooter, fos);
|
||||
writeTo("\n", fos);
|
||||
writeTo(genExpirationTime(), fos);
|
||||
|
||||
FileUtils.closeSafeFileOutputStream(fos);
|
||||
|
||||
} catch (e) {
|
||||
dump("ERROR: problem writing output to '" + gOutputFile + "': " + e + "\n");
|
||||
function writeFullPinset(certNameToSKD, certSKDToName, pinset) {
|
||||
// We aren't guaranteed to have sha1 hashes in our own imported pins.
|
||||
let prefix = "kPinset_" + pinset.name;
|
||||
let sha1Name = "nullptr";
|
||||
let sha256Name = "nullptr";
|
||||
if (pinset.sha1_hashes && pinset.sha1_hashes.length > 0) {
|
||||
writeFingerprints(certNameToSKD, certSKDToName, pinset.name,
|
||||
pinset.sha1_hashes, "sha1");
|
||||
sha1Name = "&" + prefix + "_sha1";
|
||||
}
|
||||
if (pinset.sha256_hashes && pinset.sha256_hashes.length > 0) {
|
||||
writeFingerprints(certNameToSKD, certSKDToName, pinset.name,
|
||||
pinset.sha256_hashes, "sha256");
|
||||
sha256Name = "&" + prefix + "_sha256";
|
||||
}
|
||||
writeString("static const StaticPinset " + prefix + " = {\n" +
|
||||
" " + sha1Name + ",\n " + sha256Name + "\n};\n\n");
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// This is where the action happens:
|
||||
let [ certNameToSKD, certSDKToName ] = loadNSSCertinfo(gTestCertFile);
|
||||
writeFile(certNameToSKD, certSDKToName, gStaticPins);
|
||||
function writeFingerprints(certNameToSKD, certSKDToName, name, hashes, type) {
|
||||
let varPrefix = "kPinset_" + name + "_" + type;
|
||||
writeString("static const char* " + varPrefix + "_Data[] = {\n");
|
||||
let SKDList = [];
|
||||
for (let certName of hashes) {
|
||||
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 + " = { " +
|
||||
hashes.length + ", " + varPrefix + "_Data };\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, ";
|
||||
}
|
||||
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 sortedEntries = gStaticPins.entries;
|
||||
sortedEntries.push.apply(sortedEntries, chromeImportedEntries);
|
||||
for (let entry of sortedEntries.sort(compareByName)) {
|
||||
count++;
|
||||
writeEntry(entry);
|
||||
}
|
||||
writeString("};\n");
|
||||
|
||||
writeString("\nstatic const int kPublicKeyPinningPreloadListLength = " +
|
||||
count + ";\n");
|
||||
}
|
||||
|
||||
function writeFile(certNameToSKD, certSKDToName,
|
||||
chromeImportedPinsets, chromeImportedEntries) {
|
||||
// Compute used pins from both Chrome's and our pinsets, so we can output
|
||||
// them later.
|
||||
usedFingerprints = {};
|
||||
gStaticPins.pinsets.forEach(function(pinset) {
|
||||
// We aren't guaranteed to have sha1_hashes in our own JSON.
|
||||
if (pinset.sha1_hashes) {
|
||||
pinset.sha1_hashes.forEach(function(name) {
|
||||
usedFingerprints[name] = true;
|
||||
});
|
||||
}
|
||||
if (pinset.sha256_hashes) {
|
||||
pinset.sha256_hashes.forEach(function(name) {
|
||||
usedFingerprints[name] = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
for (let key in chromeImportedPinsets) {
|
||||
let pinset = chromeImportedPinsets[key];
|
||||
pinset.sha1_hashes.forEach(function(name) {
|
||||
usedFingerprints[name] = true;
|
||||
});
|
||||
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("/* Mozilla static pinsets */\n");
|
||||
gStaticPins.pinsets.sort(compareByName).forEach(function(pinset) {
|
||||
writeFullPinset(certNameToSKD, certSKDToName, pinset);
|
||||
});
|
||||
writeString("/* Chrome static pinsets */\n");
|
||||
for (let key in chromeImportedPinsets) {
|
||||
writeFullPinset(certNameToSKD, certSKDToName, chromeImportedPinsets[key]);
|
||||
}
|
||||
|
||||
// Write the domainlist entries.
|
||||
writeString(DOMAINHEADER);
|
||||
writeDomainList(chromeImportedEntries);
|
||||
writeString("\n");
|
||||
writeString(genExpirationTime());
|
||||
}
|
||||
|
||||
let [ certNameToSKD, certSKDToName ] = loadNSSCertinfo(gTestCertFile);
|
||||
let [ chromeNameToHash, chromeNameToMozName ] = downloadAndParseChromeCerts(
|
||||
CHROME_CERT_SOURCE, certSKDToName);
|
||||
let [ chromeImportedPinsets, chromeImportedEntries ] =
|
||||
downloadAndParseChromePins(CHROME_JSON_SOURCE, chromeNameToHash,
|
||||
chromeNameToMozName, certNameToSKD, certSKDToName);
|
||||
|
||||
writeFile(certNameToSKD, certSKDToName, chromeImportedPinsets,
|
||||
chromeImportedEntries);
|
||||
|
||||
FileUtils.closeSafeFileOutputStream(gFileOutputStream);
|
||||
|
Loading…
Reference in New Issue
Block a user