Bug 1441338 - Change pgo certificates to use certspec/keyspec files. r=keeler, r=franziskus, a=jcristau
authorJ.C. Jones <jjones@mozilla.com>
Tue, 01 May 2018 16:31:56 -0700
changeset 357103 303139c887e7bf735f0122597fdc4c76054ead80
parent 357102 3aa0b3f1fe73abdfbb40eb6a2df586456d5952bb
child 357104 f2f38b868a00dbab03349f3b8d7750d2ee140899
push id7671
push userryanvm@gmail.com
push dateMon, 07 May 2018 17:21:51 +0000
treeherdermozilla-esr52@303139c887e7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler, franziskus, jcristau
bugs1441338, 879740, 1204543, 386153
milestone52.8.0
Bug 1441338 - Change pgo certificates to use certspec/keyspec files. r=keeler, r=franziskus, a=jcristau (This also fixes Bug 879740 and Bug 1204543.) build/pgo/certs contains an NSS database set that has a bunch of hand-generated certificates, and many of these hand-generated certificates are specifically depended upon for a variety of unit tests. This patch changes all of these to use the "pycert.py" and "pykey.py" utilities that produce deterministic keys and certificates. The naming convention here is new, and defined in the README. It is based on the mochitest runtest.py naming convention that imports .ca and .client PEM-encoded certificates. Unfortunately, the updates to build/pgo/genpgocert.py to generate these files depends on OpenSSL in order to produce PKCS12 archives for pk11tool to import into NSS. This could be done with pure-NSS tooling, but it'd require some new command line functionality, which is out-of-scope for this change. Note that build/pgo/genpgocert.py no longer takes arguments when run. It's not run automatically anywhere that I can see, but could (reasonably) be, now. (This patch is rebased for ESR52. Updates: * Changed build/pgo/genpgocert.py to use '-d dbm:'-style database arguments to ensure we don't use SQLite. * Back-port two test changes, one for browser_ssl_error_reports.js, the other for browser_clientAuth_ui.js, so as to use the new cert names. * Disable browser_clientAuth_ui.js and browser_clientAuth_connection.js, as they are misbehaving on try with these changes. (I could revert the edits to browser_clientAuth_ui.js given that, but it seems fair to just disable.) * Reverted build/pgo/certs/jartests-object.ca because modules/libjar/test/chrome/test_bug386153.html still exists. * Manually constructed PKCS12 objects for most of the server certspecs; this is necessary for ssltunnel to find the private keys for unknown reasons. ) Differential Revision: https://phabricator.services.mozilla.com/D971
browser/base/content/test/general/browser_ssl_error_reports.js
browser/base/content/test/general/pinning_headers.sjs
browser/base/content/test/general/ssl_error_reports.sjs
build/pgo/certs/README
build/pgo/certs/alternateroot.ca
build/pgo/certs/alternateroot.ca.keyspec
build/pgo/certs/alternateroot.certspec
build/pgo/certs/bug413909cert.certspec
build/pgo/certs/cert8.db
build/pgo/certs/dynamicPinningBad.certspec
build/pgo/certs/dynamicPinningBad.server.keyspec
build/pgo/certs/dynamicPinningGood.certspec
build/pgo/certs/escapeattack1.certspec
build/pgo/certs/evintermediate.ca
build/pgo/certs/evintermediate.ca.keyspec
build/pgo/certs/evintermediate.certspec
build/pgo/certs/expired.certspec
build/pgo/certs/imminently_distrusted.certspec
build/pgo/certs/key3.db
build/pgo/certs/mochitest.certspec
build/pgo/certs/mochitest.client
build/pgo/certs/mochitest.client.keyspec
build/pgo/certs/pgoca.ca
build/pgo/certs/pgoca.ca.keyspec
build/pgo/certs/pgoca.certspec
build/pgo/certs/pgoca.p12
build/pgo/certs/pkcs11.txt
build/pgo/certs/secmod.db
build/pgo/certs/selfsigned.certspec
build/pgo/certs/sha1_end_entity.certspec
build/pgo/certs/sha256_end_entity.certspec
build/pgo/certs/staticPinningBad.certspec
build/pgo/certs/staticPinningBad.server.keyspec
build/pgo/certs/unknown_ca.certspec
build/pgo/certs/untrusted.certspec
build/pgo/certs/untrustedandexpired.certspec
build/pgo/genpgocert.py
security/manager/ssl/tests/mochitest/browser/browser.ini
security/manager/ssl/tests/mochitest/browser/browser_clientAuth_ui.js
security/manager/ssl/tests/unit/pykey.py
testing/mochitest/runtests.py
--- a/browser/base/content/test/general/browser_ssl_error_reports.js
+++ b/browser/base/content/test/general/browser_ssl_error_reports.js
@@ -20,129 +20,128 @@ function cleanup() {
   Services.prefs.clearUserPref(PREF_REPORT_URL);
 }
 
 registerCleanupFunction(() => {
   Services.prefs.clearUserPref("security.cert_pinning.enforcement_level");
   cleanup();
 });
 
-add_task(function* test_send_report_neterror() {
-  yield testSendReportAutomatically(URL_BAD_CHAIN, "succeed", "neterror");
-  yield testSendReportAutomatically(URL_NO_CERT, "nocert", "neterror");
-  yield testSetAutomatic(URL_NO_CERT, "nocert", "neterror");
+add_task(async function test_send_report_neterror() {
+  await testSendReportAutomatically(URL_BAD_CHAIN, "succeed", "neterror");
+  await testSendReportAutomatically(URL_NO_CERT, "nocert", "neterror");
+  await testSetAutomatic(URL_NO_CERT, "nocert", "neterror");
 });
 
-
-add_task(function* test_send_report_certerror() {
-  yield testSendReportAutomatically(URL_BAD_CERT, "badcert", "certerror");
-  yield testSetAutomatic(URL_BAD_CERT, "badcert", "certerror");
+add_task(async function test_send_report_certerror() {
+  await testSendReportAutomatically(URL_BAD_CERT, "badcert", "certerror");
+  await testSetAutomatic(URL_BAD_CERT, "badcert", "certerror");
 });
 
-add_task(function* test_send_disabled() {
+add_task(async function test_send_disabled() {
   Services.prefs.setBoolPref(PREF_REPORT_ENABLED, false);
   Services.prefs.setBoolPref(PREF_REPORT_AUTOMATIC, true);
   Services.prefs.setCharPref(PREF_REPORT_URL, "https://example.com/invalid");
 
   // Check with enabled=false but automatic=true.
-  yield testSendReportDisabled(URL_NO_CERT, "neterror");
-  yield testSendReportDisabled(URL_BAD_CERT, "certerror");
+  await testSendReportDisabled(URL_NO_CERT, "neterror");
+  await testSendReportDisabled(URL_BAD_CERT, "certerror");
 
   Services.prefs.setBoolPref(PREF_REPORT_AUTOMATIC, false);
 
   // Check again with both prefs false.
-  yield testSendReportDisabled(URL_NO_CERT, "neterror");
-  yield testSendReportDisabled(URL_BAD_CERT, "certerror");
+  await testSendReportDisabled(URL_NO_CERT, "neterror");
+  await testSendReportDisabled(URL_BAD_CERT, "certerror");
   cleanup();
 });
 
-function* testSendReportAutomatically(testURL, suffix, errorURISuffix) {
+async function testSendReportAutomatically(testURL, suffix, errorURISuffix) {
   Services.prefs.setBoolPref(PREF_REPORT_ENABLED, true);
   Services.prefs.setBoolPref(PREF_REPORT_AUTOMATIC, true);
   Services.prefs.setCharPref(PREF_REPORT_URL, URL_REPORTS + suffix);
 
   // Add a tab and wait until it's loaded.
-  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
   let browser = tab.linkedBrowser;
 
   // Load the page and wait for the error report submission.
   let promiseStatus = createReportResponseStatusPromise(URL_REPORTS + suffix);
   browser.loadURI(testURL);
-  yield promiseErrorPageLoaded(browser);
+  await BrowserTestUtils.waitForErrorPage(browser);
 
-  ok(!isErrorStatus(yield promiseStatus),
+  ok(!isErrorStatus(await promiseStatus),
      "SSL error report submitted successfully");
 
   // Check that we loaded the right error page.
-  yield checkErrorPage(browser, errorURISuffix);
+  await checkErrorPage(browser, errorURISuffix);
 
   // Cleanup.
   gBrowser.removeTab(tab);
   cleanup();
 }
 
-function* testSetAutomatic(testURL, suffix, errorURISuffix) {
+async function testSetAutomatic(testURL, suffix, errorURISuffix) {
   Services.prefs.setBoolPref(PREF_REPORT_ENABLED, true);
   Services.prefs.setBoolPref(PREF_REPORT_AUTOMATIC, false);
   Services.prefs.setCharPref(PREF_REPORT_URL, URL_REPORTS + suffix);
 
   // Add a tab and wait until it's loaded.
-  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
   let browser = tab.linkedBrowser;
 
   // Load the page.
   browser.loadURI(testURL);
-  yield promiseErrorPageLoaded(browser);
+  await BrowserTestUtils.waitForErrorPage(browser);
 
   // Check that we loaded the right error page.
-  yield checkErrorPage(browser, errorURISuffix);
+  await checkErrorPage(browser, errorURISuffix);
 
   let statusPromise = createReportResponseStatusPromise(URL_REPORTS + suffix);
 
   // Click the checkbox, enable automatic error reports.
-  yield ContentTask.spawn(browser, null, function* () {
+  await ContentTask.spawn(browser, null, async function() {
     content.document.getElementById("automaticallyReportInFuture").click();
   });
 
   // Wait for the error report submission.
-  yield statusPromise;
+  await statusPromise;
 
   let isAutomaticReportingEnabled = () =>
     Services.prefs.getBoolPref(PREF_REPORT_AUTOMATIC);
 
   // Check that the pref was flipped.
   ok(isAutomaticReportingEnabled(), "automatic SSL report submission enabled");
 
   // Disable automatic error reports.
-  yield ContentTask.spawn(browser, null, function* () {
+  await ContentTask.spawn(browser, null, async function() {
     content.document.getElementById("automaticallyReportInFuture").click();
   });
 
   // Check that the pref was flipped.
   ok(!isAutomaticReportingEnabled(), "automatic SSL report submission disabled");
 
   // Cleanup.
   gBrowser.removeTab(tab);
   cleanup();
 }
 
-function* testSendReportDisabled(testURL, errorURISuffix) {
+async function testSendReportDisabled(testURL, errorURISuffix) {
   // Add a tab and wait until it's loaded.
-  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
+  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
   let browser = tab.linkedBrowser;
 
   // Load the page.
   browser.loadURI(testURL);
-  yield promiseErrorPageLoaded(browser);
+  await BrowserTestUtils.waitForErrorPage(browser);
 
   // Check that we loaded the right error page.
-  yield checkErrorPage(browser, errorURISuffix);
+  await checkErrorPage(browser, errorURISuffix);
 
   // Check that the error reporting section is hidden.
-  yield ContentTask.spawn(browser, null, function* () {
+  await ContentTask.spawn(browser, null, async function() {
     let section = content.document.getElementById("certificateErrorReporting");
     Assert.equal(content.getComputedStyle(section).display, "none",
       "error reporting section should be hidden");
   });
 
   // Cleanup.
   gBrowser.removeTab(tab);
 }
@@ -154,21 +153,24 @@ function isErrorStatus(status) {
 // use the observer service to see when a report is sent
 function createReportResponseStatusPromise(expectedURI) {
   return new Promise(resolve => {
     let observer = (subject, topic, data) => {
       subject.QueryInterface(Ci.nsIHttpChannel);
       let requestURI = subject.URI.spec;
       if (requestURI == expectedURI) {
         Services.obs.removeObserver(observer, "http-on-examine-response");
+        console.log(subject.responseStatus);
+        console.log(subject.URI);
+        console.log(requestURI);
         resolve(subject.responseStatus);
       }
     };
-    Services.obs.addObserver(observer, "http-on-examine-response", false);
+    Services.obs.addObserver(observer, "http-on-examine-response");
   });
 }
 
 function checkErrorPage(browser, suffix) {
-  return ContentTask.spawn(browser, { suffix }, function* (args) {
+  return ContentTask.spawn(browser, { suffix }, async function(args) {
     let uri = content.document.documentURI;
-    Assert.ok(uri.startsWith(`about:${args.suffix}`), "correct error page loaded");
+    Assert.ok(uri.startsWith(`about:${args.suffix}`), `correct error page loaded: ${args.suffix}`);
   });
 }
--- a/browser/base/content/test/general/pinning_headers.sjs
+++ b/browser/base/content/test/general/pinning_headers.sjs
@@ -1,11 +1,11 @@
 const INVALIDPIN1 = "pin-sha256=\"d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=\";";
 const INVALIDPIN2 = "pin-sha256=\"AAAAAAAAAAAAAAAAAAAAAAAAAj0e1Md7GkYYkVoZWmM=\";";
-const VALIDPIN = "pin-sha256=\"hXweb81C3HnmM2Ai1dnUzFba40UJMhuu8qZmvN/6WWc=\";";
+const VALIDPIN = "pin-sha256=\"VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=\";";
 
 function handleRequest(request, response)
 {
   // avoid confusing cache behaviors
   response.setHeader("Cache-Control", "no-cache", false);
 
   response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
   switch (request.queryString) {
--- a/browser/base/content/test/general/ssl_error_reports.sjs
+++ b/browser/base/content/test/general/ssl_error_reports.sjs
@@ -1,11 +1,11 @@
 const EXPECTED_CHAIN = [
-  "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"
+  "MIIDHjCCAgagAwIBAgIUf1y0AgcMQaVC6jwUyh6Ixiij2hYwDQYJKoZIhvcNAQELBQAwJjEkMCIGA1UEAwwbQWx0ZXJuYXRlIFRydXN0ZWQgQXV0aG9yaXR5MCIYDzIwMTYxMTI3MDAwMDAwWhgPMjAxOTAyMDUwMDAwMDBaMDExLzAtBgNVBAMMJmluY2x1ZGUtc3ViZG9tYWlucy5waW5uaW5nLmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwXXGUmYJn3cIKmeR8bh2w39c5TiwbErNIrHL1G+mWtoq3UHIwkmKxKOzwfYUh/QbaYlBvYClHDwSAkTFhKTESDMF5ROMAQbPCL6ahidguuai6PNvI8XZgxO53683g0XazlHU1tzSpss8xwbrzTBw7JjM5AqlkdcpWn9xxb5maR0rLf7ISURZC8Wj6kn9k7HXU0BfF3N2mZWGZiVHl+1CaQiICBFCIGmYikP+5Izmh4HdIramnNKDdRMfkysSjOKG+n0lHAYq0n7wFvGHzdVOgys1uJMPdLqQqovHYWckKrH9bWIUDRjEwLjGj8N0hFcyStfehuZVLx0eGR1xIWjTuwIDAQABozUwMzAxBgNVHREEKjAogiZpbmNsdWRlLXN1YmRvbWFpbnMucGlubmluZy5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAXn+yS5JdGRm8dqTCG7hUWrlgHL/85FhSTYQ4wt+m90/mb8ARr+XIZtP9GdTloHfZYepc9dRDT9E8wOC7f/nOAQWzyzLqRHrldYNpMAmQIqBmh1tJ/91aKhqbc+lvm1gAOTF5bh5wpEOJBczH0AqDkXP1rX27DI3PyCMT1lqHvFTjVXVOwiZHSOSWRsI89IqAo8Dlfs+y733bJ6/rAmnTK85IHu3Fod7nHviWXkWVDdrbsblvQ6fjMFKS0mj6Vip10++/PwX9rhXyB1seGI+0uXqZ65t3xDZR+yvPtxhc7tbwPdyiUTbVjh43vPHHMCyuK1HqmPrMbAlxZBX3EqkBHQ==",
+  "MIIC+zCCAeOgAwIBAgIUb/+pohOlRCuQgMy2GJLCUQq+HeMwDQYJKoZIhvcNAQELBQAwJjEkMCIGA1UEAwwbQWx0ZXJuYXRlIFRydXN0ZWQgQXV0aG9yaXR5MCIYDzIwMTAwMTAxMDAwMDAwWhgPMjA1MDAxMDEwMDAwMDBaMCYxJDAiBgNVBAMMG0FsdGVybmF0ZSBUcnVzdGVkIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMF1xlJmCZ93CCpnkfG4dsN/XOU4sGxKzSKxy9RvplraKt1ByMJJisSjs8H2FIf0G2mJQb2ApRw8EgJExYSkxEgzBeUTjAEGzwi+moYnYLrmoujzbyPF2YMTud+vN4NF2s5R1Nbc0qbLPMcG680wcOyYzOQKpZHXKVp/ccW+ZmkdKy3+yElEWQvFo+pJ/ZOx11NAXxdzdpmVhmYlR5ftQmkIiAgRQiBpmIpD/uSM5oeB3SK2ppzSg3UTH5MrEozihvp9JRwGKtJ+8Bbxh83VToMrNbiTD3S6kKqLx2FnJCqx/W1iFA0YxMC4xo/DdIRXMkrX3obmVS8dHhkdcSFo07sCAwEAAaMdMBswCwYDVR0PBAQDAgEGMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAS+qy/sIFV+oia7zsyFhe3Xj3ZHSvmqJ4mxIg5KOPVP2NvDaxD/+pysxGLf69QDRjIsePBdRJz0zZoVl9pSXIn1Kpk0sjzKX2bJtAomog+ZnAZUxtLzoXy/aqaheWm8cRJ8qFOJtSMDRrLISqBXCQLOECqXIxf3Nt3S+Riu2Pam3YymFdtmqUJvLhhekWtEEnXyh/xfAsoUgS3SQ27c4dCYR7XGnFsaXrKXv93QeJmtfvrAZMXEuKaBGPSNHV6QH0S0Loh9Jed2Zp7GxnFtIPYeJ2Q5qtxa8KD/tgGFpAD74eMBdgQ4SxbA/YqqXIt1lLNcr7wm0cPRpP0vIY3hk8k="
   ];
 
 const MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE = -16384;
 
 function parseReport(request) {
   // read the report from the request
   let inputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
   inputStream.init(request.bodyInputStream, 0x01, 0004, 0);
--- a/build/pgo/certs/README
+++ b/build/pgo/certs/README
@@ -1,9 +1,31 @@
-The certificate authority and server certificates here are generated by $topsrcdir/build/pgo/genpgocert.py.
+The certificate authority and server certificates here are generated by
+$topsrcdir/build/pgo/genpgocert.py.
+
+You can regenerate the certificates by running: ./mach python
+build/pgo/genpgocert.py
 
-You can generate a new CA cert by running:
-$objdir/_virtualenv/bin/python $topsrcdir/build/pgo/genpgocert.py --gen-ca
+To add a new CA, add a ${cert_name}.ca.keyspec as well as a corresponding
+${cert_name}.certspec to this folder.
+
+To add new server certificates, add a ${cert_name}.certspec file to this folder.
+If it needs a non-default private key, add a corresponding
+${cert_name}.server.keyspec.
+
+For new client certificates, add a ${cert_name}.client.keyspec and corresponding
+${cert_name}.certspec.
 
-You can generate new server certificates by running:
-$objdir/_virtualenv/bin/python $topsrcdir/build/pgo/genpgocert.py --gen-server
+The naming convention here is because the generated ".client" and ".ca" PEM
+files need to be copied into this folder for Mochitests' runtests.py to import.
+
+These commands will modify cert9.db and key4.db. The changes to these should be
+committed.
+
+Specific notes for certs:
 
-These will place the new files in this directory where you can commit them.
+  dynamicPinningGood: Changing this keyspec will require changing
+  browser/base/content/test/general/pinning_headers.sjs . You can obtain a new
+  valid pin via:
+
+  certutil -L -d . -n dynamicPinningGood -r | openssl x509 -inform der -pubkey \
+  -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary \
+  | openssl enc -base64
--- a/build/pgo/certs/alternateroot.ca
+++ b/build/pgo/certs/alternateroot.ca
@@ -1,18 +1,18 @@
 -----BEGIN CERTIFICATE-----
-MIIC2jCCAcKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDExtBbHRl
-cm5hdGUgVHJ1c3RlZCBBdXRob3JpdHkwHhcNMTQwOTI1MjEyMTU0WhcNMjQwOTI1
-MjEyMTU0WjAmMSQwIgYDVQQDExtBbHRlcm5hdGUgVHJ1c3RlZCBBdXRob3JpdHkw
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBT+BwAhO52IWgSIdZZifU
-9LHOs3IR/+8DCC0WP5d/OuyKlZ6Rqd0tsd3i7durhQyjHSbLf2lJStcnFjcVEbEn
-NI76RuvlN8xLLn5eV+2Ayr4cZYKztudwRmw+DV/iYAiMSy0hs7m3ssfX7qpoi1aN
-RjUanwU0VTCPQhF1bEKAC2du+C5Z8e92zN5t87w7bYr7lt+m8197XliXEu+0s9Rg
-nGwGaZ296BIRz6NOoJYTa43n06LU1I1+Z4d6lPdzUFrSR0GBaMhUSurUBtOin3yW
-iMhg1VHX/KwqGc4als5GyCVXy8HGrA/0zQPOhetxrlhEVAdK/xBt7CZvByj1Rcc7
-AgMBAAGjEzARMA8GA1UdEwQIMAYBAf8CAQAwDQYJKoZIhvcNAQELBQADggEBAJq/
-hogSRqzPWTwX4wTn/DVSNdWwFLv53qep9YrSMJ8ZsfbfK9Es4VP4dBLRQAVMJ0Z5
-mW1I6d/n0KayTanuUBvemYdxPi/qQNSs8UJcllqdhqWzmzAg6a0LxrMnEeKzPBPD
-6q8PwQ7tYP+B4sBN9tnnsnyPgti9ZiNZn5FwXZliHXseQ7FE9/SqHlLw5LXW3YtK
-juti6RmuV6fq3j+D4oeC5vb1mKgIyoTqGN6ze57v8RHi+pQ8Q+kmoUn/L3Z2YmFe
-4SKN/4WoyXr8TdejpThGOCGCAd3565s5gOx5QfSQX11P8NZKO8hcN0tme3VzmGpH
-K0Z/6MTmdpNaTwQ6odk=
+MIIC+zCCAeOgAwIBAgIUb/+pohOlRCuQgMy2GJLCUQq+HeMwDQYJKoZIhvcNAQEL
+BQAwJjEkMCIGA1UEAwwbQWx0ZXJuYXRlIFRydXN0ZWQgQXV0aG9yaXR5MCIYDzIw
+MTAwMTAxMDAwMDAwWhgPMjA1MDAxMDEwMDAwMDBaMCYxJDAiBgNVBAMMG0FsdGVy
+bmF0ZSBUcnVzdGVkIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAMF1xlJmCZ93CCpnkfG4dsN/XOU4sGxKzSKxy9RvplraKt1ByMJJisSj
+s8H2FIf0G2mJQb2ApRw8EgJExYSkxEgzBeUTjAEGzwi+moYnYLrmoujzbyPF2YMT
+ud+vN4NF2s5R1Nbc0qbLPMcG680wcOyYzOQKpZHXKVp/ccW+ZmkdKy3+yElEWQvF
+o+pJ/ZOx11NAXxdzdpmVhmYlR5ftQmkIiAgRQiBpmIpD/uSM5oeB3SK2ppzSg3UT
+H5MrEozihvp9JRwGKtJ+8Bbxh83VToMrNbiTD3S6kKqLx2FnJCqx/W1iFA0YxMC4
+xo/DdIRXMkrX3obmVS8dHhkdcSFo07sCAwEAAaMdMBswCwYDVR0PBAQDAgEGMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAS+qy/sIFV+oia7zsyFhe3X
+j3ZHSvmqJ4mxIg5KOPVP2NvDaxD/+pysxGLf69QDRjIsePBdRJz0zZoVl9pSXIn1
+Kpk0sjzKX2bJtAomog+ZnAZUxtLzoXy/aqaheWm8cRJ8qFOJtSMDRrLISqBXCQLO
+ECqXIxf3Nt3S+Riu2Pam3YymFdtmqUJvLhhekWtEEnXyh/xfAsoUgS3SQ27c4dCY
+R7XGnFsaXrKXv93QeJmtfvrAZMXEuKaBGPSNHV6QH0S0Loh9Jed2Zp7GxnFtIPYe
+J2Q5qtxa8KD/tgGFpAD74eMBdgQ4SxbA/YqqXIt1lLNcr7wm0cPRpP0vIY3hk8k=
 -----END CERTIFICATE-----
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/alternateroot.ca.keyspec
@@ -0,0 +1,1 @@
+alternate
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/alternateroot.certspec
@@ -0,0 +1,7 @@
+issuer:Alternate Trusted Authority
+subject:Alternate Trusted Authority
+validity:20100101-20500101
+extension:keyUsage:keyCertSign,cRLSign
+extension:basicConstraints:cA,
+issuerKey:alternate
+subjectKey:alternate
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/bug413909cert.certspec
@@ -0,0 +1,3 @@
+subject:bug413909.xn--hxajbheg2az3al.xn--jxalpdlp
+issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization
+extension:subjectAlternativeName:bug413909.xn--hxajbheg2az3al.xn--jxalpdlp
index 1e65b619d39e6c4488202b1fef68a72b82ef9323..fc8288eb48304fa46b1f1a6d9beb1f0e5e57e24c
GIT binary patch
literal 65536
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
NARr(hARyDz{|B(gMdttj
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/dynamicPinningBad.certspec
@@ -0,0 +1,5 @@
+subject:bad.include-subdomains.pinning-dynamic.example.com
+issuer:Alternate Trusted Authority
+extension:subjectAlternativeName:bad.include-subdomains.pinning-dynamic.example.com
+subjectKey:alternate
+issuerKey:alternate
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/dynamicPinningBad.server.keyspec
@@ -0,0 +1,1 @@
+alternate
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/dynamicPinningGood.certspec
@@ -0,0 +1,3 @@
+subject:dynamic-pinning.example.com
+issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization
+extension:subjectAlternativeName:*.include-subdomains.pinning-dynamic.example.com,*.pinning-dynamic.example.com
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/escapeattack1.certspec
@@ -0,0 +1,3 @@
+subject:www.bank1.com\00www.bad-guy.com
+issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization
+extension:subjectAlternativeName:www.bank1.com\00www.bad-guy.com
--- a/build/pgo/certs/evintermediate.ca
+++ b/build/pgo/certs/evintermediate.ca
@@ -1,34 +1,26 @@
 -----BEGIN CERTIFICATE-----
-MIIF9zCCBN+gAwIBAgIBAzANBgkqhkiG9w0BAQUFADCB4TELMAkGA1UEBhMCVVMx
-CzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MSMwIQYDVQQKExpN
-b3ppbGxhIC0gRVYgZGVidWcgdGVzdCBDQTEdMBsGA1UECxMUU2VjdXJpdHkgRW5n
-aW5lZXJpbmcxJjAkBgNVBAMTHUVWIFRlc3RpbmcgKHVudHJ1c3R3b3J0aHkpIENB
-MRMwEQYDVQQpEwpldi10ZXN0LWNhMSwwKgYJKoZIhvcNAQkBFh1jaGFybGF0YW5A
-dGVzdGluZy5leGFtcGxlLmNvbTAeFw0xMzAyMTQxNzU5MDlaFw0yMzAyMTIxNzU5
-MDlaMIHRMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50
-YWluIFZpZXcxIzAhBgNVBAoTGk1vemlsbGEgLSBFViBkZWJ1ZyB0ZXN0IENBMR0w
-GwYDVQQLExRTZWN1cml0eSBFbmdpbmVlcmluZzEWMBQGA1UEAxMNaW50ZXJtZWRp
-YXRlMzETMBEGA1UEKRMKZXYtdGVzdC1jYTEsMCoGCSqGSIb3DQEJARYdY2hhcmxh
-dGFuQHRlc3RpbmcuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQDAfzrlJdawr7v8m7lslODk5FTqCiBO7tPxnWhAOEL5g05knLTZTc5J
-3ywmGoW6ae6RwPlWuqRuFd2Ea+yCawyjkUoLOpFH/xziDzvaS6LXNdJoxQqWk/LX
-8YYQVFfmxh8E11fz74IoCzX++mY1byaNONf3bLU2HU8vnVvENr1gy9Bzpm8wUuKm
-HkBYuG0SVzaeym2H/mo5PJICPVhPa+YxfEVS8EIFCigXGH7xrz/bPXnpfgsSJTnN
-4amBNkORfjf7H9x6IWkJGEkIvkVoYKT4iQ9q6/C4YDjWa9p5lA4F/qxnJefezH/I
-6hcqEODSaDsY+I6vsN8ks8r8MTTnd7BjAgMBAAGjggHGMIIBwjAdBgNVHQ4EFgQU
-fluXMAT0ZS21pV13vv46m8k7nRkwggEYBgNVHSMEggEPMIIBC4AUyJg651hwk+3B
-V0rQvQZv9n2bWPahgeekgeQwgeExCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEW
-MBQGA1UEBxMNTW91bnRhaW4gVmlldzEjMCEGA1UEChMaTW96aWxsYSAtIEVWIGRl
-YnVnIHRlc3QgQ0ExHTAbBgNVBAsTFFNlY3VyaXR5IEVuZ2luZWVyaW5nMSYwJAYD
-VQQDEx1FViBUZXN0aW5nICh1bnRydXN0d29ydGh5KSBDQTETMBEGA1UEKRMKZXYt
-dGVzdC1jYTEsMCoGCSqGSIb3DQEJARYdY2hhcmxhdGFuQHRlc3RpbmcuZXhhbXBs
-ZS5jb22CCQCvxT0iZiZJMjAMBgNVHRMEBTADAQH/MDYGA1UdHwQvMC0wK6ApoCeG
-JWh0dHA6Ly9leGFtcGxlLmNvbS9yb290LWV2LXRlc3Rlci5jcmwwPwYDVR0gBDgw
-NjA0BgRVHSAAMCwwKgYIKwYBBQUHAgEWHmh0dHA6Ly9teXRlc3Rkb21haW4ubG9j
-YWwvY3BzOzANBgkqhkiG9w0BAQUFAAOCAQEAC4grNTV5K8yqiAJ/0f6oIkTMqyJ4
-lyHXvvKXMHTpRZ7Jdy0aq5KTSHswx64ZRN7V2ds+czzDWgxX3rBuZZAgOW1JYva3
-Ps3XRYUiaTW8eeaWjuVRFAp7ytRmSsOGeOtHbez8jDmTqPRQ1mTMsMzpY4bFD8do
-5y0xsbz4DYIeeNnX9+XGB5u2ml8t5L8Cj65wwMAx9HlsjTrfQTMIwpwbNle6GuZ3
-9FzmE2piAND73yCgU5W66K2lZg8N6vHBq0UhPDCF72y8MlHxQOpTr3/jIGr4X7k9
-uyYq0Pw5Y/LKyGbyW5iMFdLzabm1ua8IWAf7DSFMH6L3WlK8mngCfJ1icQ==
+MIIEfDCCA2SgAwIBAgIUETbLA86peOWkUFhyKYIuZVGUEygwDQYJKoZIhvcNAQEL
+BQAwgdwxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRh
+aW4gVmlldzEjMCEGA1UEChMaTW96aWxsYSAtIEVWIGRlYnVnIHRlc3QgQ0ExHTAb
+BgNVBAsTFFNlY3VyaXR5IEVuZ2luZWVyaW5nMTYwNAYDVQQDEy1FViBUZXN0aW5n
+ICh1bnRydXN0d29ydGh5KSBDQS9uYW1lPWV2LXRlc3QtY2ExLDAqBgkqhkiG9w0B
+CQEWHWNoYXJsYXRhbkB0ZXN0aW5nLmV4YW1wbGUuY29tMCIYDzIwMTAwMTAxMDAw
+MDAwWhgPMjA1MDAxMDEwMDAwMDBaMIHcMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
+Q0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxIzAhBgNVBAoTGk1vemlsbGEgLSBF
+ViBkZWJ1ZyB0ZXN0IENBMR0wGwYDVQQLExRTZWN1cml0eSBFbmdpbmVlcmluZzE2
+MDQGA1UEAxMtRVYgVGVzdGluZyAodW50cnVzdHdvcnRoeSkgQ0EvbmFtZT1ldi10
+ZXN0LWNhMSwwKgYJKoZIhvcNAQkBFh1jaGFybGF0YW5AdGVzdGluZy5leGFtcGxl
+LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALVJiVydABCNEaH5
+n4ep49Gl21367PGI2le/ZBNojyzkciz/EJA4wXQCyToqRz29KGrtP9zTY89aKRR3
+Ab3YGNdhW/k1a9XTyDNqqowJcTaKBsPNRGG5PlFCThdEuy6q1GqrOM4ZaCGWH4dx
+ShZjaT8JdhzfTWuhJerOx74nDTiPeJ9s33iuMUTtKMReeSk4Y6eiKkiYCjakDnLV
+ecm5Jd/4x5M2L/1ol6fBdUxel8lnw+rdGq6KoszONIoBabgOKKLXDBqWDG8zXy2g
+m5tkP1q/uknoqqmB6WDifYdIC91V3ZQX+hhQn7tVTM+BpDl+i6gSijS98nhlwYnl
+c0+yKQUCAwEAAaMwMC4wCwYDVR0PBAQDAgEGMAwGA1UdEwQFMAMBAf8wEQYDVR0g
+BAowCDAGBgRVHSAAMA0GCSqGSIb3DQEBCwUAA4IBAQArG5slgBRJuytlKFa4qcHW
+pAOfjN9fwi57fDds1yNv6tXhESdkbVPhIgw+GanVbrVcorGdCkfB51+dPJM+cBgH
+HSwEB7TQnNYvm/csA1zH4n+CnX9nBL7dwK63n6dyR9f1uvu6KSB+YJm3amKil85a
+d7HeDWdh+gNhC58lEC2QzuOMivP593aS5vLJHfp8pjc21XJkO8M7SRw44OJKYq9/
+v0k6v4SznbfZzSLg3gM4aSNuCLExUtUY2myxPFwJs9QQ4xx5zJTjJTRlpxUm630Z
+n4IYlseao949U+UbBNU4PZKH7dzSQzfhdFJpvK3dsPOPNnHYiXO0xAhsEvvjq8zQ
 -----END CERTIFICATE-----
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/evintermediate.ca.keyspec
@@ -0,0 +1,1 @@
+ev
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/evintermediate.certspec
@@ -0,0 +1,7 @@
+issuer:printableString/C=US/ST=CA/L=Mountain View/O=Mozilla - EV debug test CA/OU=Security Engineering/CN=EV Testing (untrustworthy) CA/name=ev-test-ca/emailAddress=charlatan@testing.example.com
+subject:printableString/C=US/ST=CA/L=Mountain View/O=Mozilla - EV debug test CA/OU=Security Engineering/CN=EV Testing (untrustworthy) CA/name=ev-test-ca/emailAddress=charlatan@testing.example.com
+subjectKey:ev
+validity:20100101-20500101
+extension:keyUsage:keyCertSign,cRLSign
+extension:basicConstraints:cA,
+extension:certificatePolicies:any
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/expired.certspec
@@ -0,0 +1,4 @@
+subject:expired.example.com
+issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization
+extension:subjectAlternativeName:expired.example.com
+validity:20100105-20100106
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/imminently_distrusted.certspec
@@ -0,0 +1,4 @@
+issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization
+subject:printableString/CN=Imminently Distrusted End Entity
+validity:20100101-20500101
+extension:subjectAlternativeName:imminently-distrusted.example.com
index a45004df89fcb3daea9fcd76101d11a7d4eaf4d8..69b71099245a6df4fc6c9fc4ef631abfdc600f03
GIT binary patch
literal 131072
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
z00000000000000000000000000000000000000000000000000000000000000000
G;J*MrL#PM<
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/mochitest.certspec
@@ -0,0 +1,3 @@
+subject:Mochitest client
+issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization
+serialNumber:3
index 5d72cd2b739b3127724e12d63c0c7e79c62666ed..202dd512537a47bce6d2b98af61f6228a735d3bd
GIT binary patch
literal 2448
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
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/mochitest.client.keyspec
@@ -0,0 +1,1 @@
+default
--- a/build/pgo/certs/pgoca.ca
+++ b/build/pgo/certs/pgoca.ca
@@ -1,15 +1,21 @@
 -----BEGIN CERTIFICATE-----
-MIICXTCCAcagAwIBAgIBATANBgkqhkiG9w0BAQUFADBqMSQwIgYDVQQLExtQcm9m
-aWxlIEd1aWRlZCBPcHRpbWl6YXRpb24xGDAWBgNVBAoTD01vemlsbGEgVGVzdGlu
-ZzEoMCYGA1UEAxMfVGVtcG9yYXJ5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0w
-ODA1MjIwMDM4MDVaFw0xODA1MjIwMDM4MDVaMGoxJDAiBgNVBAsTG1Byb2ZpbGUg
-R3VpZGVkIE9wdGltaXphdGlvbjEYMBYGA1UEChMPTW96aWxsYSBUZXN0aW5nMSgw
-JgYDVQQDEx9UZW1wb3JhcnkgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqG
-SIb3DQEBAQUAA4GNADCBiQKBgQDg6iipAXGZYmgTcHfx8M2hcLqmqDalcj7sZ1A7
-a3LiCBb+1uHKKy9hUxRUe61aJF4NgMAF5oc+HpXN0hpvkiNHxqqD7R6hrkP3gAJ3
-eczEFKsFUI6AqaCL0+xpyhaaZmmarcHxU+PL2h5zq6VssxfBAsO0DkzWzk6E8vM+
-jrku7QIDAQABoxMwETAPBgNVHRMECDAGAQH/AgEAMA0GCSqGSIb3DQEBBQUAA4GB
-ALPbn3Ztg0m8qDt8Vkf5You6HEqIxZe+ffDTrfq/L7ofHk/OXEpL7OWKRHU33pNG
-QS8khBG+sO461C51s6u9giW+eq2PaQv2HGASBpDbvPqc/Hf+zupZsdsXzHv6rt0V
-lu5B6nOpMse1nhA494i1ARSuBNzLv5mas38YWG8Rr6jR
+MIIDgzCCAmugAwIBAgIUQx5pxD+JMg1qPztfSg1Ucw8xsz0wDQYJKoZIhvcNAQEL
+BQAwajEoMCYGA1UEAxMfVGVtcG9yYXJ5IENlcnRpZmljYXRlIEF1dGhvcml0eTEY
+MBYGA1UEChMPTW96aWxsYSBUZXN0aW5nMSQwIgYDVQQLExtQcm9maWxlIEd1aWRl
+ZCBPcHRpbWl6YXRpb24wIhgPMjAxMDAxMDEwMDAwMDBaGA8yMDUwMDEwMTAwMDAw
+MFowajEoMCYGA1UEAxMfVGVtcG9yYXJ5IENlcnRpZmljYXRlIEF1dGhvcml0eTEY
+MBYGA1UEChMPTW96aWxsYSBUZXN0aW5nMSQwIgYDVQQLExtQcm9maWxlIEd1aWRl
+ZCBPcHRpbWl6YXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6
+iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVoV2wke8HHJajg2B+9sZwGm24ahvJr
+4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p0DggKZOrIMNJ5Nu5TMJrbA7tFYIP
+8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKkfbmIYXmQsVeQPdI7xeC4SB+oN9OI
+Q+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZhW7filhLAdTGjDJHdtMr3/K0dJdMJ
+77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EITjbLHCQELL8Wiy/l8Y+ZFzG4s/5J
+I/pyUcQx1QOs2hgKNe2NAgMBAAGjHTAbMAsGA1UdDwQEAwIBBjAMBgNVHRMEBTAD
+AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAYFnzom5ROuxDR3WFQatxHs5ekni4uUbEx
+6pN8fOzcsllEfCwvmMLVCh36ffSguf/UlmR5Hq1s/S7iMiic5mnK4aaVwixzS4Z3
+ug7Dc+fG7j0VOcBTKWU983xUK/1F409ghQ5KlO38KA7hyx1kzjYjzvxLaweDXRqr
+J/RZ1ACP2fKNziEOCbXzzzEx39oc17NBV+LotPFzKZ+pcxMDrtiNts4hwCw/UUw7
+Gp0tKte2CevGJbzjPHP3/6FUzHfOatZSpxEmvAcSTDp5sjdVuOStx4v6jVrwvyAz
+VQzDPzaRWh3NtY5JNasrhExr5qxQlygfBngCMgZ9gESG9FvLG+sx
 -----END CERTIFICATE-----
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/pgoca.ca.keyspec
@@ -0,0 +1,1 @@
+default
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/pgoca.certspec
@@ -0,0 +1,5 @@
+issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization
+subject:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization
+validity:20100101-20500101
+extension:keyUsage:keyCertSign,cRLSign
+extension:basicConstraints:cA,
deleted file mode 100644
index 4867c286bbf6950a51078caedff875a945b2d93c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/pkcs11.txt
@@ -0,0 +1,5 @@
+library=
+name=NSS Internal PKCS #11 Module
+parameters=configdir='/Users/jcjones/hg/mozilla-central/build/pgo/certs' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' 
+NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[ECC,RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30})
+
index a3341f767ce01ccdc4a54adf64e82f9ef6b0c2f1..366c4c5c31b2765dc60702b68ee74c88d46396e7
GIT binary patch
literal 131072
zc%1Ff!HUyR6adiID&y>2h&z#hi>x%vR_JQnNKpo=ACM+#%}kn<qy-fm{R#JOT+g@Y
zFX(T`*l7wgf(ULLkaOU2@4NT$Uh=};-86(S4B_V25I$_ma65!S=p*d!is3Hb*yio1
z-}JG5_bv2>yZGn!2iI{c000000000000000000000000000000000000000000000
z000000000000000000000000000000006-MWf;D{KRf+=dUkr<UjhIC0000000000
z0000000000000000000000000z~9&l(csSDYG=HOd=q{1-t);MdRniFwoa?)XnZ({
z9vmD*&zgK)6`T2&tf^<^JTKc(oKF{zlb2o5cFA#e+|)&vyqYJA=51M3>BFq3S8ZA)
z({)+p$#UK#S<$Y#IJ!tjZ80lfkK#BwDc)Qzx*}UN`6%x5qkI}ivnri;qiDU%(^av(
zHr_1`e>tb`jjx{8x61soe$kv1^^>B@+H$!noBCq1{qe!4Tj!%qzW=*7`_q&BI0pa#
i000000000000000000000000000000000000Db~px$wyV
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/selfsigned.certspec
@@ -0,0 +1,3 @@
+issuer:self-signed.example.com
+subject:self-signed.example.com
+extension:subjectAlternativeName:self-signed.example.com
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/sha1_end_entity.certspec
@@ -0,0 +1,4 @@
+subject:sha1ee.example.com
+issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization
+extension:subjectAlternativeName:sha1ee.example.com
+signature:sha1WithRSAEncryption
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/sha256_end_entity.certspec
@@ -0,0 +1,4 @@
+subject:sha256ee.example.com
+issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization
+extension:subjectAlternativeName:sha256ee.example.com
+signature:sha256WithRSAEncryption
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/staticPinningBad.certspec
@@ -0,0 +1,5 @@
+subject:include-subdomains.pinning.example.com
+issuer:Alternate Trusted Authority
+extension:subjectAlternativeName:include-subdomains.pinning.example.com
+subjectKey:alternate
+issuerKey:alternate
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/staticPinningBad.server.keyspec
@@ -0,0 +1,1 @@
+alternate
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/unknown_ca.certspec
@@ -0,0 +1,5 @@
+issuer:Unknown CA
+subject:Unknown CA
+validity:20100101-20500101
+extension:keyUsage:keyCertSign,cRLSign
+extension:basicConstraints:cA,
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/untrusted.certspec
@@ -0,0 +1,3 @@
+subject:untrusted.example.com
+issuer:Unknown CA
+extension:subjectAlternativeName:untrusted.example.com
new file mode 100644
--- /dev/null
+++ b/build/pgo/certs/untrustedandexpired.certspec
@@ -0,0 +1,4 @@
+subject:untrusted-expired.example.com
+issuer:Unknown CA
+extension:subjectAlternativeName:untrusted-expired.example.com
+validity:20121012-20121012
--- a/build/pgo/genpgocert.py
+++ b/build/pgo/genpgocert.py
@@ -10,19 +10,20 @@
 import mozinfo
 import os
 import random
 import re
 import shutil
 import subprocess
 import sys
 import tempfile
+import distutils
 
 from mozbuild.base import MozbuildObject
-from mozfile import NamedTemporaryFile
+from mozfile import NamedTemporaryFile, TemporaryDirectory
 from mozprofile.permissions import ServerLocations
 
 dbFiles = [
   re.compile("^cert[0-9]+\.db$"),
   re.compile("^key[0-9]+\.db$"),
   re.compile("^secmod\.db$")
 ]
 
@@ -36,157 +37,147 @@ def unlinkDbFiles(path):
 def dbFilesExist(path):
   for root, dirs, files in os.walk(path):
     for name in files:
       for dbFile in dbFiles:
         if dbFile.match(name) and os.path.exists(os.path.join(root, name)):
           return True
   return False
 
-
-def runUtil(util, args, inputdata = None):
+def runUtil(util, args, inputdata = None, outputstream = None):
   env = os.environ.copy()
   if mozinfo.os == "linux":
     pathvar = "LD_LIBRARY_PATH"
     app_path = os.path.dirname(util)
     if pathvar in env:
       env[pathvar] = "%s%s%s" % (app_path, os.pathsep, env[pathvar])
     else:
       env[pathvar] = app_path
   proc = subprocess.Popen([util] + args, env=env,
-                          stdin=subprocess.PIPE if inputdata else None)
+                          stdin=subprocess.PIPE if inputdata else None,
+                          stdout=outputstream)
   proc.communicate(inputdata)
   return proc.returncode
 
-
 def createRandomFile(randomFile):
   for count in xrange(0, 2048):
     randomFile.write(chr(random.randint(0, 255)))
 
-
-def createCertificateAuthority(build, srcDir):
-  certutil = build.get_binary_path(what="certutil")
-  pk12util = build.get_binary_path(what="pk12util")
-
-  #TODO: mozfile.TemporaryDirectory
-  tempDbDir = tempfile.mkdtemp()
-  with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
-    pgoCAModulePathSrc = os.path.join(srcDir, "pgoca.p12")
-    pgoCAPathSrc = os.path.join(srcDir, "pgoca.ca")
-
-    pwfile.write("\n")
-
-    # Create temporary certification database for CA generation
-    status = runUtil(certutil, ["-N", "-d", tempDbDir, "-f", pwfile.name])
-    if status:
-      return status
-
-    createRandomFile(rndfile)
-    status = runUtil(certutil, ["-S", "-d", tempDbDir, "-s", "CN=Temporary Certificate Authority, O=Mozilla Testing, OU=Profile Guided Optimization", "-t", "C,,", "-x", "-m", "1", "-v", "120", "-n", "pgo temporary ca", "-2", "-f", pwfile.name, "-z", rndfile.name], "Y\n0\nN\n")
-    if status:
-      return status
-
-    status = runUtil(certutil, ["-L", "-d", tempDbDir, "-n", "pgo temporary ca", "-a", "-o", pgoCAPathSrc, "-f", pwfile.name])
-    if status:
-      return status
-
-    status = runUtil(pk12util, ["-o", pgoCAModulePathSrc, "-n", "pgo temporary ca", "-d", tempDbDir, "-w", pwfile.name, "-k", pwfile.name])
-    if status:
-      return status
-
-  shutil.rmtree(tempDbDir)
-  return 0
-
-
-def createSSLServerCertificate(build, srcDir):
-  certutil = build.get_binary_path(what="certutil")
-  pk12util = build.get_binary_path(what="pk12util")
-
-  with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
-    pgoCAPath = os.path.join(srcDir, "pgoca.p12")
-
-    pwfile.write("\n")
-
-    if not dbFilesExist(srcDir):
-      # Make sure all DB files from src are really deleted
-      unlinkDbFiles(srcDir)
-
-      # Create certification database for ssltunnel
-      status = runUtil(certutil, ["-N", "-d", srcDir, "-f", pwfile.name])
-      if status:
-        return status
-
-      status = runUtil(pk12util, ["-i", pgoCAPath, "-w", pwfile.name, "-d", srcDir, "-k", pwfile.name])
-      if status:
-        return status
-
-    # Generate automatic certificate
+def writeCertspecForServerLocations(fd):
     locations = ServerLocations(os.path.join(build.topsrcdir,
                                              "build", "pgo",
                                              "server-locations.txt"))
-    iterator = iter(locations)
+    SAN=[]
+    for loc in [i for i in iter(locations) if i.scheme == "https" and "nocert" not in i.options]:
+      customCertOption = False
+      customCertRE = re.compile("^cert=(?:\w+)")
+      for _ in [i for i in loc.options if customCertRE.match(i)]:
+        customCertOption = True
+        break
+
+      if not customCertOption:
+        SAN.append(loc.host)
 
-    # Skips the first entry, I don't know why: bug 879740
-    iterator.next()
+    fd.write("issuer:printableString/CN=Temporary Certificate Authority/O=Mozilla Testing/OU=Profile Guided Optimization\n")
+    fd.write("subject:{}\n".format(SAN[0]))
+    fd.write("extension:subjectAlternativeName:{}\n".format(",".join(SAN)))
+
+def constructCertDatabase(build, srcDir):
+  certutil = build.get_binary_path(what="certutil")
+  pk12util = build.get_binary_path(what="pk12util")
+  openssl = distutils.spawn.find_executable("openssl")
+  pycert = os.path.join(build.topsrcdir, "security", "manager", "ssl", "tests",
+                        "unit", "pycert.py")
+  pykey = os.path.join(build.topsrcdir, "security", "manager", "ssl", "tests",
+                        "unit", "pykey.py")
+
 
-    locationsParam = ""
-    firstLocation = ""
-    for loc in iterator:
-      if loc.scheme == "https" and "nocert" not in loc.options:
-        customCertOption = False
-        customCertRE = re.compile("^cert=(?:\w+)")
-        for option in loc.options:
-          match = customCertRE.match(option)
-          if match:
-            customCertOption = True
-            break
+  with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile, TemporaryDirectory() as pemfolder:
+    pgoCAPath = os.path.join(srcDir, "pgoca.p12")
+
+    pwfile.write("\n")
+    pwfile.flush()
+
+    if dbFilesExist(srcDir):
+      # Make sure all DB files from src are really deleted
+      unlinkDbFiles(srcDir)
+
+    # Copy  all .certspec and .keyspec files to a temporary directory
+    for root, dirs, files in os.walk(srcDir):
+      for spec in [i for i in files if i.endswith(".certspec") or i.endswith(".keyspec")]:
+        shutil.copyfile(os.path.join(root, spec), os.path.join(pemfolder, spec))
+
+    # Write a certspec for the "server-locations.txt" file to that temporary directory
+    pgoserver_certspec = os.path.join(pemfolder, "pgoserver.certspec")
+    if os.path.exists(pgoserver_certspec):
+      raise Exception("{} already exists, which isn't allowed".format(pgoserver_certspec))
+    with open(pgoserver_certspec, "w") as fd:
+      writeCertspecForServerLocations(fd)
+
+    # Generate certs for all certspecs
+    for root, dirs, files in os.walk(pemfolder):
+      for certspec in [i for i in files if i.endswith(".certspec")]:
+        name = certspec.split(".certspec")[0]
+        pem = os.path.join(pemfolder, "{}.cert.pem".format(name))
 
-        if not customCertOption:
-          if len(locationsParam) > 0:
-            locationsParam += ","
-          locationsParam += loc.host
+        print("Generating public certificate {} (pem={})".format(name, pem))
+
+        with open(os.path.join(root, certspec), "r") as certspec_file:
+          certspec_data = certspec_file.read()
+          with open(pem, "w") as pem_file:
+            status = runUtil(pycert, [], inputdata=certspec_data, outputstream=pem_file)
+            if status:
+              return status
 
-          if firstLocation == "":
-            firstLocation = loc.host
+        status = runUtil(certutil, ["-A", "-n", name, "-t", "P,,", "-i", pem, "-d", "dbm:"+srcDir, "-f", pwfile.name])
+        if status:
+          return status
+
+
+      for keyspec in [i for i in files if i.endswith(".keyspec")]:
+        parts = keyspec.split(".")
+        name = parts[0]
+        key_type = parts[1]
+        if key_type not in ["ca", "client", "server"]:
+          raise Exception("{}: keyspec filenames must be of the form XXX.client.keyspec or XXX.ca.keyspec (key_type={})".format(keyspec, key_type))
+        key_pem = os.path.join(pemfolder, "{}.key.pem".format(name))
+
+        print("Generating private key {} (pem={})".format(name, key_pem))
 
-    if not firstLocation:
-      print "Nothing to generate, no automatic secure hosts specified"
-    else:
-      createRandomFile(rndfile)
+        with open(os.path.join(root, keyspec), "r") as keyspec_file:
+          keyspec_data = keyspec_file.read()
+          with open(key_pem, "w") as pem_file:
+            status = runUtil(pykey, [], inputdata=keyspec_data, outputstream=pem_file)
+            if status:
+              return status
+
+        cert_pem = os.path.join(pemfolder, "{}.cert.pem".format(name))
+        if not os.path.exists(cert_pem):
+          raise Exception("There has to be a corresponding certificate named {} for the keyspec {}".format(cert_pem, keyspec))
 
-      runUtil(certutil, ["-D", "-n", "pgo server certificate", "-d", srcDir, "-z", rndfile.name, "-f", pwfile.name])
-      # Ignore the result, the certificate may not be present when new database is being built
+        p12 = os.path.join(pemfolder, "{}.key.p12".format(name))
+        print("Converting private key {} to PKCS12 (p12={})".format(key_pem, p12))
+        status = runUtil(openssl, ["pkcs12", "-export", "-inkey", key_pem, "-in", cert_pem, "-name", name, "-out", p12, "-passout", "file:"+pwfile.name])
+        if status:
+          return status
 
-      status = runUtil(certutil, ["-S", "-s", "CN=%s" % firstLocation, "-t", "Pu,,", "-c", "pgo temporary ca", "-m", "2", "-8", locationsParam, "-v", "120", "-n", "pgo server certificate", "-d", srcDir, "-z", rndfile.name, "-f", pwfile.name])
-      if status:
-        return status
+        print("Importing private key {} to database".format(key_pem))
+        status = runUtil(pk12util, ["-i", p12, "-d", "dbm:"+srcDir, "-w", pwfile.name, "-k", pwfile.name])
+        if status:
+          return status
+
+        if key_type == "ca":
+          shutil.copyfile(cert_pem, os.path.join(srcDir, "{}.ca".format(name)))
+        elif key_type == "client":
+          shutil.copyfile(p12, os.path.join(srcDir, "{}.client".format(name)))
+        elif key_type == "server":
+          pass # Nothing to do for server keys
+        else:
+          raise Exception("State error: Unknown keyspec key_type: {}".format(key_type))
 
   return 0
 
-if len(sys.argv) == 1:
-  print "Specify --gen-server or --gen-ca"
-  sys.exit(1)
-
 build = MozbuildObject.from_environment()
 certdir = os.path.join(build.topsrcdir, "build", "pgo", "certs")
-if sys.argv[1] == "--gen-server":
-  certificateStatus = createSSLServerCertificate(build, certdir)
-  if certificateStatus:
-    print "TEST-UNEXPECTED-FAIL | SSL Server Certificate generation"
-
-  sys.exit(certificateStatus)
-
-if sys.argv[1] == "--gen-ca":
-  certificateStatus = createCertificateAuthority(build, certdir)
-  if certificateStatus:
-    print "TEST-UNEXPECTED-FAIL | Certificate Authority generation"
-  else:
-    print "\n\n"
-    print "==================================================="
-    print " IMPORTANT:"
-    print " To use this new certificate authority in tests"
-    print " run 'make' at testing/mochitest"
-    print "==================================================="
-
-  sys.exit(certificateStatus)
-
-print "Invalid option specified"
-sys.exit(1)
+certificateStatus = constructCertDatabase(build, certdir)
+if certificateStatus:
+  print "TEST-UNEXPECTED-FAIL | SSL Server Certificate generation"
+sys.exit(certificateStatus)
--- a/security/manager/ssl/tests/mochitest/browser/browser.ini
+++ b/security/manager/ssl/tests/mochitest/browser/browser.ini
@@ -3,16 +3,18 @@ tags = psm
 support-files =
   head.js
   *.pem
 
 [browser_bug627234_perwindowpb.js]
 [browser_certificateManagerLeak.js]
 [browser_certViewer.js]
 [browser_clientAuth_connection.js]
+disabled = Disable in bug 1441338 (This is only for ESR52 branch)
 [browser_clientAuth_ui.js]
+disabled = Disable in bug 1441338 (This is only for ESR 52 branch)
 [browser_deleteCert_ui.js]
 [browser_downloadCert_ui.js]
 [browser_editCACertTrust.js]
 # An earlier attempt at landing this test resulted in frequent intermittent
 # failures, almost entirely on Linux. See Bug 1309519.
 skip-if = os == "linux"
 [browser_exportP12_passwordUI.js]
--- a/security/manager/ssl/tests/mochitest/browser/browser_clientAuth_ui.js
+++ b/security/manager/ssl/tests/mochitest/browser/browser_clientAuth_ui.js
@@ -65,38 +65,38 @@ function checkDialogContents(win, notBef
   Assert.equal(win.document.getElementById("organization").textContent,
                `Organization: \u201C${TEST_ORG}\u201D`,
                "Actual and expected organization should be equal");
   Assert.equal(win.document.getElementById("issuer").textContent,
                `Issued Under: \u201C${TEST_ISSUER_ORG}\u201D`,
                "Actual and expected issuer organization should be equal");
 
   Assert.equal(win.document.getElementById("nicknames").label,
-               "test client certificate [03]",
+               "mochitest [03]",
                "Actual and expected selected cert nickname and serial should " +
                "be equal");
 
   let [subject, serialNum, validity, issuer, tokenName] =
     win.document.getElementById("details").value.split("\n");
   Assert.equal(subject, "Issued to: CN=Mochitest client",
                "Actual and expected subject should be equal");
   Assert.equal(serialNum, "Serial number: 03",
                "Actual and expected serial number should be equal");
   Assert.equal(validity, `Valid from ${notBefore} to ${notAfter}`,
                "Actual and expected validity should be equal");
   Assert.equal(issuer,
-               "Issued by: CN=Temporary Certificate Authority,O=Mozilla " +
-               "Testing,OU=Profile Guided Optimization",
+               "Issued by: OU=Profile Guided Optimization,O=Mozilla Testing," +
+               "CN=Temporary Certificate Authority",
                "Actual and expected issuer should be equal");
   Assert.equal(tokenName, "Stored on: Software Security Device",
                "Actual and expected token name should be equal");
 }
 
 add_task(function* setup() {
-  cert = certDB.findCertByNickname("test client certificate");
+  cert = certDB.findCertByNickname("mochitest");
   Assert.notEqual(cert, null, "Should be able to find the test client cert");
 });
 
 // Test that the contents of the dialog correspond to the details of the
 // provided cert.
 add_task(function* testContents() {
   let [win, retVals] = yield openClientAuthDialog(cert);
   checkDialogContents(win, cert.validity.notBeforeLocalTime,
--- a/security/manager/ssl/tests/unit/pykey.py
+++ b/security/manager/ssl/tests/unit/pykey.py
@@ -698,9 +698,9 @@ def keyFromSpecification(specification):
 # read the specification and output the key as ASCII-encoded PKCS #8.
 def main(output, inputPath):
     with open(inputPath) as configStream:
         output.write(keyFromSpecification(configStream.read().strip()).toPEM())
 
 # When run as a standalone program, this will read a specification from
 # stdin and output the certificate as PEM to stdout.
 if __name__ == '__main__':
-    print keyFromSpecification(sys.stdin.read()).toPEM()
+    print keyFromSpecification(sys.stdin.read().strip()).toPEM()
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -579,17 +579,17 @@ class SSLTunnel:
             prefix="ssltunnel", suffix=".cfg")
         with os.fdopen(configFd, "w") as config:
             config.write("httpproxy:1\n")
             config.write("certdbdir:%s\n" % self.certPath)
             config.write("forward:127.0.0.1:%s\n" % self.httpPort)
             config.write(
                 "websocketserver:%s:%s\n" %
                 (self.webServer, self.webSocketPort))
-            config.write("listen:*:%s:pgo server certificate\n" % self.sslPort)
+            config.write("listen:*:%s:pgoserver\n" % self.sslPort)
 
             for loc in locations:
                 if loc.scheme == "https" and "nocert" not in loc.options:
                     self.writeLocation(config, loc)
 
     def start(self):
         """ Starts the SSL Tunnel """