Bug 1004781: Aurora-specific patch to enable pinning in test mode for facebook (r=cviecco,rbarnes,a=lmandel)
authorMonica Chew <mmc@mozilla.com>
Wed, 27 Aug 2014 14:05:43 -0700
changeset 224756 6f5c35805e16ac68e97fa4570ada2dc8a8f406db
parent 224755 9791801f7cd16657701e55d2554607b2b5699292
child 224757 1723d5f1b514ec9cb0ab61dcce224083105db2ba
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscviecco, rbarnes, lmandel
bugs1004781
milestone34.0a2
Bug 1004781: Aurora-specific patch to enable pinning in test mode for facebook (r=cviecco,rbarnes,a=lmandel)
security/manager/tools/PreloadedHPKPins.json
security/manager/tools/genHPKPStaticPins.js
--- a/security/manager/tools/PreloadedHPKPins.json
+++ b/security/manager/tools/PreloadedHPKPins.json
@@ -14,16 +14,20 @@
 // For a given pinset, a certificate is accepted if at least one of the
 // Subject Public Key Infos (SPKIs) is found in the chain.  SPKIs are specified
 // as names, which must match up with the name given in the Mozilla root store.
 //
 // "entries" is a list of objects. Each object has the following members:
 //   name: (string) the DNS name of the host in question
 //   include_subdomains: (optional bool) whether subdomains of |name| are also covered
 //   pins: (string) the |name| member of an object in |pinsets|
+//
+// "extra_certs" is a list of base64-encoded certificates. These are used in
+// pinsets that reference certificates not in our root program (for example,
+// Facebook).
 
 // equifax -> aus3
 // Geotrust Primary -> www.mozilla.org
 // Geotrust Global -> *. addons.mozilla.org
 {
   "chromium_data" : {
     "cert_file_url": "https://src.chromium.org/chrome/trunk/src/net/http/transport_security_state_static.certs",
     "json_file_url": "https://src.chromium.org/chrome/trunk/src/net/http/transport_security_state_static.json",
@@ -181,23 +185,22 @@
         "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",
         "XRamp Global CA Root"
       ]
     },
-    // For pinning tests on pinning.example.com, the certificate must be 'End
-    // Entity Test Cert'
     {
       "name": "facebook",
       "sha256_hashes": [
         "Verisign Class 3 Public Primary Certification Authority - G3",
-        "DigiCert High Assurance EV Root CA"
+        "DigiCert High Assurance EV Root CA",
+        "DigiCert ECC Secure Server CA"
       ]
     }
   ],
 
   "entries": [
     // Only domains that are operationally crucial to Firefox can have per-host
     // telemetry reporting (the "id") field
     { "name": "addons.mozilla.org", "include_subdomains": true,
@@ -230,10 +233,15 @@
     // Expand twitter's pinset to include all of *.twitter.com and use
     // twitterCDN. More specific rules take precedence because we search for
     // exact domain name first.
     { "name": "twitter.com", "include_subdomains": true,
       "pins": "twitterCDN", "test_mode": false },
     // Facebook (not pinned by Chrome)
     { "name": "facebook.com", "include_subdomains": true,
       "pins": "facebook", "test_mode": true }
+  ],
+
+  "extra_certificates": [
+     // DigiCert ECC Secure Server CA (for Facebook)
+     "MIIDrDCCApSgAwIBAgIQCssoukZe5TkIdnRw883GEjANBgkqhkiG9w0BAQwFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0xMzAzMDgxMjAwMDBaFw0yMzAzMDgxMjAwMDBaMEwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJjAkBgNVBAMTHURpZ2lDZXJ0IEVDQyBTZWN1cmUgU2VydmVyIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE4ghC6nfYJN6gLGSkE85AnCNyqQIKDjc/ITa4jVMU9tWRlUvzlgKNcR7E2Munn17voOZ/WpIRllNv68DLP679Wz9HJOeaBy6Wvqgvu1cYr3GkvXg6HuhbPGtkESvMNCuMo4IBITCCAR0wEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDA9BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAdBgNVHQ4EFgQUo53mH/naOU/AbuiRy5Wl2jHiCp8wHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEMBQADggEBAMeKoENL7HTJxavVHzA1Nm6YVntIrAVjrnuaVyRXzG/63qttnMe2uuzO58pzZNvfBDcKAEmzP58mrZGMIOgfiA4q+2Y3yDDo0sIkp0VILeoBUEoxlBPfjV/aKrtJPGHzecicZpIalir0ezZYoyxBEHQa0+1IttK7igZFcTMQMHp6mCHdJLnsnLWSB62DxsRq+HfmNb4TDydkskO/g+l3VtsIh5RHFPVfKK+jaEyDj2D3loB5hWp2Jp2VDCADjT7ueihlZGak2YPqmXTNbk19HOuNssWvFhtOyPNV6og4ETQdEa8/B6hPatJ0ES8q/HO3X8IVQwVs1n3aAr0im0/T+Xc="
   ]
 }
--- a/security/manager/tools/genHPKPStaticPins.js
+++ b/security/manager/tools/genHPKPStaticPins.js
@@ -331,31 +331,39 @@ function downloadAndParseChromePins(file
         pins: pinsetName });
     }
   });
   return [ chromeImportedPinsets, chromeImportedEntries ];
 }
 
 // Returns a pair of maps [certNameToSKD, certSKDToName] between cert
 // nicknames and digests of the SPKInfo for the mozilla trust store
-function loadNSSCertinfo(derTestFile) {
+function loadNSSCertinfo(derTestFile, extraCertificates) {
   let allCerts = gCertDB.getCerts();
   let enumerator = allCerts.getEnumerator();
   let certNameToSKD = {};
   let certSKDToName = {};
   while (enumerator.hasMoreElements()) {
     let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
     if (!isCertBuiltIn(cert)) {
       continue;
     }
     let name = cert.nickname.substr(BUILT_IN_NICK_PREFIX.length);
     let SKD = cert.sha256SubjectPublicKeyInfoDigest;
     certNameToSKD[name] = SKD;
     certSKDToName[SKD] = name;
   }
+
+  for (let cert of extraCertificates) {
+    let name = cert.commonName;
+    let SKD = cert.sha256SubjectPublicKeyInfoDigest;
+    certNameToSKD[name] = SKD;
+    certSKDToName[SKD] = name;
+  }
+
   {
     // A certificate for *.example.com.
     let der = readFileToString(derTestFile);
     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 SKD  = testCert.sha256SubjectPublicKeyInfoDigest;
@@ -540,17 +548,27 @@ function writeFile(certNameToSKD, certSK
 
   // Write the domainlist entries.
   writeString(DOMAINHEADER);
   writeDomainList(chromeImportedEntries);
   writeString("\n");
   writeString(genExpirationTime());
 }
 
-let [ certNameToSKD, certSKDToName ] = loadNSSCertinfo(gTestCertFile);
+function loadExtraCertificates(certStringList) {
+  let constructedCerts = [];
+  for (let certString of certStringList) {
+    constructedCerts.push(gCertDB.constructX509FromBase64(certString));
+  }
+  return constructedCerts;
+}
+
+let extraCertificates = loadExtraCertificates(gStaticPins.extra_certificates);
+let [ certNameToSKD, certSKDToName ] = loadNSSCertinfo(gTestCertFile,
+                                                       extraCertificates);
 let [ chromeNameToHash, chromeNameToMozName ] = downloadAndParseChromeCerts(
   gStaticPins.chromium_data.cert_file_url, certSKDToName);
 let [ chromeImportedPinsets, chromeImportedEntries ] =
   downloadAndParseChromePins(gStaticPins.chromium_data.json_file_url,
     chromeNameToHash, chromeNameToMozName, certNameToSKD, certSKDToName);
 
 writeFile(certNameToSKD, certSKDToName, chromeImportedPinsets,
           chromeImportedEntries);