merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Wed, 20 Jul 2016 16:55:12 +0200
changeset 347928 d224fc999cb6accb208af0a105f14433375e2e77
parent 347906 03269dd72a7259f582977714559f0f4ef19988aa (current diff)
parent 347927 da701570fa3f6147f56b4d83c190da120470f560 (diff)
child 347934 a71e7db89da62e577f8995c886cc74272997a1bb
child 347963 63a62a6c3cddfefae733a428c24def6063d320d1
child 348016 f90a9f8af37c202842f5d9c5b2928004124ab5e1
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone50.0a1
first release with
nightly linux32
d224fc999cb6 / 50.0a1 / 20160721030216 / files
nightly linux64
d224fc999cb6 / 50.0a1 / 20160721030216 / files
nightly mac
d224fc999cb6 / 50.0a1 / 20160721030203 / files
nightly win32
d224fc999cb6 / 50.0a1 / 20160721030216 / files
nightly win64
d224fc999cb6 / 50.0a1 / 20160721030216 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
dom/plugins/ipc/interpose/plugin_child_quirks.mm
security/nss/.travis.yml
security/nss/circle.yml
testing/web-platform/meta/fetch/nosniff/importscripts.html.ini
testing/web-platform/meta/fetch/nosniff/parsing-nosniff.html.ini
testing/web-platform/meta/fetch/nosniff/script.html.ini
testing/web-platform/meta/fetch/nosniff/stylesheet.html.ini
toolkit/xre/MacQuirks.h
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -12,20 +12,16 @@
 #include <stdlib.h>
 #include <io.h>
 #include <fcntl.h>
 #elif defined(XP_UNIX)
 #include <sys/resource.h>
 #include <unistd.h>
 #endif
 
-#ifdef XP_MACOSX
-#include "MacQuirks.h"
-#endif
-
 #include <stdio.h>
 #include <stdarg.h>
 #include <time.h>
 
 #include "nsCOMPtr.h"
 #include "nsIFile.h"
 #include "nsStringGlue.h"
 
@@ -350,20 +346,16 @@ int main(int argc, char* argv[], char* e
     NS_LogTerm();
 
     return result;
   }
 #endif
 
   mozilla::TimeStamp start = mozilla::TimeStamp::Now();
 
-#ifdef XP_MACOSX
-  TriggerQuirks();
-#endif
-
   nsIFile *xreDirectory;
 
 #ifdef HAS_DLL_BLOCKLIST
   DllBlocklist_Initialize();
 
 #ifdef DEBUG
   // In order to be effective against AppInit DLLs, the blocklist must be
   // initialized before user32.dll is loaded into the process (bug 932100).
--- a/browser/base/content/test/urlbar/browser_tabMatchesInAwesomebar.js
+++ b/browser/base/content/test/urlbar/browser_tabMatchesInAwesomebar.js
@@ -9,165 +9,138 @@ requestLongerTimeout(2);
 const TEST_URL_BASES = [
   "http://example.org/browser/browser/base/content/test/urlbar/dummy_page.html#tabmatch",
   "http://example.org/browser/browser/base/content/test/urlbar/moz.png#tabmatch"
 ];
 
 var gController = Cc["@mozilla.org/autocomplete/controller;1"].
                   getService(Ci.nsIAutoCompleteController);
 
-var gTabWaitCount = 0;
 var gTabCounter = 0;
 
-var gTestSteps = [
-  function() {
-    info("Running step 1");
-    let maxResults = Services.prefs.getIntPref("browser.urlbar.maxRichResults");
-    for (let i = 0; i < maxResults - 1; i++) {
-      let tab = gBrowser.addTab();
-      loadTab(tab, TEST_URL_BASES[0] + (++gTabCounter));
-    }
-  },
-  function() {
-    info("Running step 2");
-    gBrowser.selectTabAtIndex(1);
-    gBrowser.removeCurrentTab();
-    gBrowser.selectTabAtIndex(1);
-    gBrowser.removeCurrentTab();
-    for (let i = 1; i < gBrowser.tabs.length; i++)
-      loadTab(gBrowser.tabs[i], TEST_URL_BASES[1] + (++gTabCounter));
-  },
-  function() {
-    info("Running step 3");
-    for (let i = 1; i < gBrowser.tabs.length; i++)
-      loadTab(gBrowser.tabs[i], TEST_URL_BASES[0] + gTabCounter);
-  },
-  function() {
-    info("Running step 4 - ensure we don't register subframes as open pages");
+add_task(function* step_1() {
+  info("Running step 1");
+  let maxResults = Services.prefs.getIntPref("browser.urlbar.maxRichResults");
+  let promises = [];
+  for (let i = 0; i < maxResults - 1; i++) {
     let tab = gBrowser.addTab();
-    tab.linkedBrowser.addEventListener("load", function () {
-      tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
-      // Start the sub-document load.
-      executeSoon(function () {
-        tab.linkedBrowser.addEventListener("load", function (e) {
-          tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
-            ensure_opentabs_match_db(nextStep);
-        }, true);
-        tab.linkedBrowser.contentDocument.querySelector("iframe").src = "http://test2.example.org/";
-      });
-    }, true);
-    tab.linkedBrowser.loadURI('data:text/html,<body><iframe src=""></iframe></body>');
-  },
-  function() {
-    info("Running step 5 - remove tab immediately");
-    let tab = gBrowser.addTab("about:logo");
-    gBrowser.removeTab(tab);
-    ensure_opentabs_match_db(nextStep);
-  },
-  function() {
-    info("Running step 6 - check swapBrowsersAndCloseOther preserves registered switch-to-tab result");
-    let tabToKeep = gBrowser.addTab();
-    let tab = gBrowser.addTab();
-    tab.linkedBrowser.addEventListener("load", function () {
-      tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
-      gBrowser.updateBrowserRemoteness(tabToKeep.linkedBrowser, tab.linkedBrowser.isRemoteBrowser);
-      gBrowser.swapBrowsersAndCloseOther(tabToKeep, tab);
-      ensure_opentabs_match_db(function () {
-        gBrowser.removeTab(tabToKeep);
-        ensure_opentabs_match_db(nextStep);
-      });
-    }, true);
-    tab.linkedBrowser.loadURI("about:mozilla");
-  },
-  function() {
-    info("Running step 7 - close all tabs");
+    promises.push(loadTab(tab, TEST_URL_BASES[0] + (++gTabCounter)));
+  }
+
+  yield Promise.all(promises);
+  yield ensure_opentabs_match_db();
+});
+
+add_task(function* step_2() {
+  info("Running step 2");
+  gBrowser.selectTabAtIndex(1);
+  gBrowser.removeCurrentTab();
+  gBrowser.selectTabAtIndex(1);
+  gBrowser.removeCurrentTab();
+
+  let promises = [];
+  for (let i = 1; i < gBrowser.tabs.length; i++)
+    promises.push(loadTab(gBrowser.tabs[i], TEST_URL_BASES[1] + (++gTabCounter)));
+
+  yield Promise.all(promises);
+  yield ensure_opentabs_match_db();
+});
+
+add_task(function* step_3() {
+  info("Running step 3");
+  let promises = [];
+  for (let i = 1; i < gBrowser.tabs.length; i++)
+    promises.push(loadTab(gBrowser.tabs[i], TEST_URL_BASES[0] + gTabCounter));
+
+  yield Promise.all(promises);
+  yield ensure_opentabs_match_db();
+});
+
+add_task(function* step_4() {
+  info("Running step 4 - ensure we don't register subframes as open pages");
+  let tab = gBrowser.addTab();
+  tab.linkedBrowser.loadURI('data:text/html,<body><iframe src=""></iframe></body>');
+  yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+
+  yield ContentTask.spawn(tab.linkedBrowser, null, function* () {
+    let iframe_loaded = ContentTaskUtils.waitForEvent(content.document, "load", true);
+    content.document.querySelector("iframe").src = "http://test2.example.org/";
+    yield iframe_loaded;
+  });
 
-    Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand");
+  yield ensure_opentabs_match_db();
+});
+
+add_task(function* step_5() {
+  info("Running step 5 - remove tab immediately");
+  let tab = gBrowser.addTab("about:logo");
+  yield BrowserTestUtils.removeTab(tab);
+  yield ensure_opentabs_match_db();
+});
+
+add_task(function* step_6() {
+  info("Running step 6 - check swapBrowsersAndCloseOther preserves registered switch-to-tab result");
+  let tabToKeep = gBrowser.addTab();
+  let tab = gBrowser.addTab();
+  tab.linkedBrowser.loadURI("about:mozilla");
+  yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+
+  gBrowser.updateBrowserRemoteness(tabToKeep.linkedBrowser, tab.linkedBrowser.isRemoteBrowser);
+  gBrowser.swapBrowsersAndCloseOther(tabToKeep, tab);
+
+  yield ensure_opentabs_match_db()
+
+  yield BrowserTestUtils.removeTab(tabToKeep);
 
-    gBrowser.addTab("about:blank", {skipAnimation: true});
-    while (gBrowser.tabs.length > 1) {
-      info("Removing tab: " + gBrowser.tabs[0].linkedBrowser.currentURI.spec);
-      gBrowser.selectTabAtIndex(0);
-      gBrowser.removeCurrentTab();
-    }
-    ensure_opentabs_match_db(nextStep);
+  yield ensure_opentabs_match_db();
+});
+
+add_task(function* step_7() {
+  info("Running step 7 - close all tabs");
+
+  Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand");
+
+  gBrowser.addTab("about:blank", {skipAnimation: true});
+  while (gBrowser.tabs.length > 1) {
+    info("Removing tab: " + gBrowser.tabs[0].linkedBrowser.currentURI.spec);
+    gBrowser.selectTabAtIndex(0);
+    gBrowser.removeCurrentTab();
   }
-];
 
-
+  yield ensure_opentabs_match_db();
+});
 
-function test() {
-  waitForExplicitFinish();
-  nextStep();
-}
+add_task(function* cleanup() {
+  info("Cleaning up");
+
+  yield PlacesTestUtils.clearHistory();
+});
 
 function loadTab(tab, url) {
   // Because adding visits is async, we will not be notified immediately.
-  let visited = false;
-  let loaded = false;
-
-  function maybeCheckResults() {
-    if (visited && loaded && --gTabWaitCount == 0) {
-      ensure_opentabs_match_db(nextStep);
-    }
-  }
-
-  tab.linkedBrowser.addEventListener("load", function () {
-    tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
-    loaded = true;
-    maybeCheckResults();
-  }, true);
-
-  if (!visited) {
+  let loaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+  let visited = new Promise(resolve => {
     Services.obs.addObserver(
-      function (aSubject, aTopic, aData) {
+      function observer(aSubject, aTopic, aData) {
         if (url != aSubject.QueryInterface(Ci.nsIURI).spec)
           return;
-        Services.obs.removeObserver(arguments.callee, aTopic);
-        visited = true;
-        maybeCheckResults();
+        Services.obs.removeObserver(observer, aTopic);
+        resolve();
       },
       "uri-visit-saved",
       false
     );
-  }
+  });
 
-  gTabWaitCount++;
   info("Loading page: " + url);
   tab.linkedBrowser.loadURI(url);
-}
-
-function waitForRestoredTab(tab) {
-  gTabWaitCount++;
-
-  tab.linkedBrowser.addEventListener("load", function () {
-    tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
-    if (--gTabWaitCount == 0) {
-      ensure_opentabs_match_db(nextStep);
-    }
-  }, true);
+  return Promise.all([ loaded, visited ]);
 }
 
-
-function nextStep() {
-  if (gTestSteps.length == 0) {
-    while (gBrowser.tabs.length > 1) {
-      gBrowser.selectTabAtIndex(1);
-      gBrowser.removeCurrentTab();
-    }
-
-    PlacesTestUtils.clearHistory().then(finish);
-    return;
-  }
-
-  var stepFunc = gTestSteps.shift();
-  stepFunc();
-}
-
-function ensure_opentabs_match_db(aCallback) {
+function ensure_opentabs_match_db() {
   var tabs = {};
 
   var winEnum = Services.wm.getEnumerator("navigator:browser");
   while (winEnum.hasMoreElements()) {
     let browserWin = winEnum.getNext();
     // skip closed-but-not-destroyed windows
     if (browserWin.closed)
       continue;
@@ -179,17 +152,19 @@ function ensure_opentabs_match_db(aCallb
         continue;
       if (!(url in tabs))
         tabs[url] = 1;
       else
         tabs[url]++;
     }
   }
 
-  checkAutocompleteResults(tabs, aCallback);
+  return new Promise(resolve => {
+    checkAutocompleteResults(tabs, resolve);
+  });
 }
 
 function checkAutocompleteResults(aExpected, aCallback)
 {
   gController.input = {
     timeout: 10,
     textValue: "",
     searches: ["unifiedcomplete"],
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -1089,38 +1089,43 @@ const CustomizableWidgets = [
     }
   }, {
     id: "email-link-button",
     tooltiptext: "email-link-button.tooltiptext3",
     onCommand: function(aEvent) {
       let win = aEvent.view;
       win.MailIntegration.sendLinkForBrowser(win.gBrowser.selectedBrowser)
     }
-  }];
-
-if (Services.prefs.getBoolPref("privacy.userContext.enabled")) {
-  CustomizableWidgets.push({
+  }, {
     id: "containers-panelmenu",
     type: "view",
     viewId: "PanelUI-containers",
+    hasObserver: false,
     onCreated: function(aNode) {
       let doc = aNode.ownerDocument;
       let win = doc.defaultView;
       let items = doc.getElementById("PanelUI-containersItems");
 
       let onItemCommand = function (aEvent) {
         let item = aEvent.target;
         let userContextId = parseInt(item.getAttribute("usercontextid"));
         win.openUILinkIn(win.BROWSER_NEW_TAB_URL, "tab", {userContextId});
       };
       items.addEventListener("command", onItemCommand);
 
       if (PrivateBrowsingUtils.isWindowPrivate(win)) {
         aNode.setAttribute("disabled", "true");
       }
+
+      this.updateVisibility(aNode);
+
+      if (!this.hasObserver) {
+        Services.prefs.addObserver("privacy.userContext.enabled", this, true);
+        this.hasObserver = true;
+      }
     },
     onViewShowing: function(aEvent) {
       let doc = aEvent.detail.ownerDocument;
 
       let items = doc.getElementById("PanelUI-containersItems");
 
       while (items.firstChild) {
         items.firstChild.remove();
@@ -1137,19 +1142,36 @@ if (Services.prefs.getBoolPref("privacy.
         item.setAttribute("usercontextid", identity.userContextId);
         item.setAttribute("class", "subviewbutton");
         item.setAttribute("image", identity.icon);
 
         fragment.appendChild(item);
       });
 
       items.appendChild(fragment);
-    }
-  });
-}
+    },
+
+    updateVisibility(aNode) {
+      aNode.hidden = !Services.prefs.getBoolPref("privacy.userContext.enabled");
+    },
+
+    observe(aSubject, aTopic, aData) {
+      let {instances} = CustomizableUI.getWidget("containers-panelmenu");
+      for (let {node} of instances) {
+	if (node) {
+	  this.updateVisibility(node);
+	}
+      }
+    },
+
+    QueryInterface: XPCOMUtils.generateQI([
+      Ci.nsISupportsWeakReference,
+      Ci.nsIObserver
+    ]),
+  }];
 
 let preferencesButton = {
   id: "preferences-button",
   defaultArea: CustomizableUI.AREA_PANEL,
   onCommand: function(aEvent) {
     let win = aEvent.target.ownerGlobal;
     if (typeof win.openPreferences == "function") {
       win.openPreferences();
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -56,16 +56,19 @@ var gPrivacyPane = {
   /**
    * Show the Containers UI depending on the privacy.userContext.ui.enabled pref.
    */
   _initBrowserContainers: function () {
     if (!Services.prefs.getBoolPref("privacy.userContext.ui.enabled")) {
       return;
     }
 
+    let link = document.getElementById("browserContainersLearnMore");
+    link.href = Services.urlFormatter.formatURLPref("app.support.baseURL") + "containers";
+
     document.getElementById("browserContainersbox").hidden = false;
   },
 
   /**
    * Sets up the UI for the number of days of history to keep, and updates the
    * label of the "Clear Now..." button.
    */
   init: function ()
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -287,15 +287,18 @@
   <label class="text-link" onclick="if (event.button == 0) gotoPref('search')">
     &suggestionSettings.label;
   </label>
 </groupbox>
 
 <!-- Containers -->
 <groupbox id="browserContainersGroup" data-category="panePrivacy" hidden="true">
   <vbox id="browserContainersbox" hidden="true">
-    <caption><label>&browserContainersHeader.label;</label></caption>
+    <caption><label>&browserContainersHeader.label;
+      <label id="browserContainersLearnMore" class="text-link"
+             value="&browserContainersLearnMore.label;"/>
+    </label></caption>
     <checkbox id="browserContainersCheckbox"
               label="&browserContainersEnabled.label;"
               accesskey="&browserContainersEnabled.accesskey;"
               preference="privacy.userContext.enabled"/>
   </vbox>
 </groupbox>
--- a/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
@@ -42,17 +42,17 @@
 
 <!ENTITY  suggestionSettings.label      "Change preferences for search engine suggestions…">
 <!ENTITY  suggestionSettings.accesskey  "g">
 
 <!ENTITY  acceptCookies.label           "Accept cookies from sites">
 <!ENTITY  acceptCookies.accesskey       "A">
 
 <!ENTITY  acceptThirdParty.pre.label      "Accept third-party cookies:">
-<!ENTITY  acceptThirdParty.pre.accesskey  "c">
+<!ENTITY  acceptThirdParty.pre.accesskey  "y">
 <!ENTITY  acceptThirdParty.always.label   "Always">
 <!ENTITY  acceptThirdParty.never.label    "Never">
 <!ENTITY  acceptThirdParty.visited.label  "From visited">
 
 <!ENTITY  keepUntil.label               "Keep until:">
 <!ENTITY  keepUntil.accesskey           "u">
 
 <!ENTITY  expire.label                  "they expire">
@@ -101,10 +101,11 @@
 
 <!ENTITY  clearOnClose.label             "Clear history when &brandShortName; closes">
 <!ENTITY  clearOnClose.accesskey         "r">
 
 <!ENTITY  clearOnCloseSettings.label     "Settings…">
 <!ENTITY  clearOnCloseSettings.accesskey "t">
 
 <!ENTITY  browserContainersHeader.label         "Container Tabs">
+<!ENTITY  browserContainersLearnMore.label      "Learn more">
 <!ENTITY  browserContainersEnabled.label        "Enable Container Tabs">
-<!ENTITY  browserContainersEnabled.accesskey    "a">
+<!ENTITY  browserContainersEnabled.accesskey    "n">
--- a/browser/themes/shared/incontentprefs/preferences.inc.css
+++ b/browser/themes/shared/incontentprefs/preferences.inc.css
@@ -218,17 +218,18 @@ treecol {
 
 .actionsMenu > menupopup > menuitem > .menu-iconic-left {
   margin-inline-end: 8px !important;
 }
 
 /* Privacy pane */
 
 #trackingProtectionPBMLearnMore,
-#trackingProtectionLearnMore {
+#trackingProtectionLearnMore,
+#browserContainersLearnMore {
   margin-inline-start: 1.5em !important;
   margin-top: 0;
   font-weight: normal;
 }
 
 .doNotTrackLearnMore {
   margin-inline-start: calc(1em + 30px);
   margin-bottom: 1em;
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -3619,32 +3619,40 @@ nsContentUtils::IsChildOfSameType(nsIDoc
   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(aDoc->GetDocShell());
   nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
   if (docShellAsItem) {
     docShellAsItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
   }
   return sameTypeParent != nullptr;
 }
 
+bool 
+nsContentUtils::IsScriptType(const nsACString& aContentType)
+{
+  // NOTE: if you add a type here, add it to the CONTENTDLF_CATEGORIES
+  // define in nsContentDLF.h as well. 
+  return aContentType.EqualsLiteral(APPLICATION_JAVASCRIPT) ||
+         aContentType.EqualsLiteral(APPLICATION_XJAVASCRIPT) ||
+         aContentType.EqualsLiteral(TEXT_ECMASCRIPT) ||
+         aContentType.EqualsLiteral(APPLICATION_ECMASCRIPT) ||
+         aContentType.EqualsLiteral(TEXT_JAVASCRIPT) ||
+         aContentType.EqualsLiteral(APPLICATION_JSON) ||
+         aContentType.EqualsLiteral(TEXT_JSON);
+}
+
 bool
 nsContentUtils::IsPlainTextType(const nsACString& aContentType)
 {
   // NOTE: if you add a type here, add it to the CONTENTDLF_CATEGORIES
   // define in nsContentDLF.h as well.
   return aContentType.EqualsLiteral(TEXT_PLAIN) ||
          aContentType.EqualsLiteral(TEXT_CSS) ||
          aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST) ||
-         aContentType.EqualsLiteral(APPLICATION_JAVASCRIPT) ||
-         aContentType.EqualsLiteral(APPLICATION_XJAVASCRIPT) ||
-         aContentType.EqualsLiteral(TEXT_ECMASCRIPT) ||
-         aContentType.EqualsLiteral(APPLICATION_ECMASCRIPT) ||
-         aContentType.EqualsLiteral(TEXT_JAVASCRIPT) ||
-         aContentType.EqualsLiteral(APPLICATION_JSON) ||
-         aContentType.EqualsLiteral(TEXT_JSON) ||
-         aContentType.EqualsLiteral(TEXT_VTT);
+         aContentType.EqualsLiteral(TEXT_VTT) ||
+         IsScriptType(aContentType);
 }
 
 bool
 nsContentUtils::GetWrapperSafeScriptFilename(nsIDocument *aDocument,
                                              nsIURI *aURI,
                                              nsACString& aScriptURI)
 {
   bool scriptFileNameModified = false;
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -990,16 +990,21 @@ public:
   static bool IsChromeDoc(nsIDocument *aDocument);
 
   /**
    * Returns true if aDocument is in a docshell whose parent is the same type
    */
   static bool IsChildOfSameType(nsIDocument* aDoc);
 
   /**
+  '* Returns true if the content-type is any of the supported script types.
+   */
+  static bool IsScriptType(const nsACString& aContentType);
+
+  /**
   '* Returns true if the content-type will be rendered as plain-text.
    */
   static bool IsPlainTextType(const nsACString& aContentType);
 
   /**
    * Get the script file name to use when compiling the script
    * referenced by aURI. In cases where there's no need for any extra
    * security wrapper automation the script file name that's returned
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -1243,30 +1243,29 @@ ContentChild::DeallocPAPZChild(PAPZChild
 }
 
 bool
 ContentChild::RecvInitCompositor(Endpoint<PCompositorBridgeChild>&& aEndpoint)
 {
   return CompositorBridgeChild::InitForContent(Move(aEndpoint));
 }
 
+bool
+ContentChild::RecvInitImageBridge(Endpoint<PImageBridgeChild>&& aEndpoint)
+{
+  return ImageBridgeChild::InitForContent(Move(aEndpoint));
+}
+
 PSharedBufferManagerChild*
 ContentChild::AllocPSharedBufferManagerChild(mozilla::ipc::Transport* aTransport,
                                               base::ProcessId aOtherProcess)
 {
   return SharedBufferManagerChild::StartUpInChildProcess(aTransport, aOtherProcess);
 }
 
-PImageBridgeChild*
-ContentChild::AllocPImageBridgeChild(mozilla::ipc::Transport* aTransport,
-                                     base::ProcessId aOtherProcess)
-{
-  return ImageBridgeChild::StartUpInChildProcess(aTransport, aOtherProcess);
-}
-
 gfx::PVRManagerChild*
 ContentChild::AllocPVRManagerChild(Transport* aTransport,
                                    ProcessId aOtherProcess)
 {
   return gfx::VRManagerChild::StartUpInChildProcess(aTransport, aOtherProcess);
 }
 
 PBackgroundChild*
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -145,25 +145,23 @@ public:
 
   PAPZChild*
   AllocPAPZChild(const TabId& aTabId) override;
   bool
   DeallocPAPZChild(PAPZChild* aActor) override;
 
   bool
   RecvInitCompositor(Endpoint<PCompositorBridgeChild>&& aEndpoint) override;
+  bool
+  RecvInitImageBridge(Endpoint<PImageBridgeChild>&& aEndpoint) override;
 
   PSharedBufferManagerChild*
   AllocPSharedBufferManagerChild(mozilla::ipc::Transport* aTransport,
                                   base::ProcessId aOtherProcess) override;
 
-  PImageBridgeChild*
-  AllocPImageBridgeChild(mozilla::ipc::Transport* aTransport,
-                         base::ProcessId aOtherProcess) override;
-
   PProcessHangMonitorChild*
   AllocPProcessHangMonitorChild(Transport* aTransport,
                                 ProcessId aOtherProcess) override;
 
   PVRManagerChild*
   AllocPVRManagerChild(Transport* aTransport,
                        ProcessId aOtherProcess) override;
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2427,27 +2427,36 @@ ContentParent::InitInternal(ProcessPrior
     // we send.  The CompositorBridgeChild must be created before any
     // PBrowsers are created, because they rely on the Compositor
     // already being around.  (Creation is async, so can't happen
     // on demand.)
     bool useOffMainThreadCompositing = !!CompositorThreadHolder::Loop();
     if (useOffMainThreadCompositing) {
       GPUProcessManager* gpm = GPUProcessManager::Get();
 
-      Endpoint<PCompositorBridgeChild> endpoint;
-      DebugOnly<bool> opened =
-        gpm->CreateContentCompositorBridge(OtherPid(), &endpoint);
-      MOZ_ASSERT(opened);
-      Unused << SendInitCompositor(Move(endpoint));
-
-      opened = PImageBridge::Open(this);
-      MOZ_ASSERT(opened);
-
-      opened = gfx::PVRManager::Open(this);
-      MOZ_ASSERT(opened);
+      {
+        Endpoint<PCompositorBridgeChild> endpoint;
+        DebugOnly<bool> opened =
+          gpm->CreateContentCompositorBridge(OtherPid(), &endpoint);
+        MOZ_ASSERT(opened);
+        Unused << SendInitCompositor(Move(endpoint));
+      }
+
+      {
+        Endpoint<PImageBridgeChild> endpoint;
+        DebugOnly<bool> opened =
+          gpm->CreateContentImageBridge(OtherPid(), &endpoint);
+        MOZ_ASSERT(opened);
+        Unused << SendInitImageBridge(Move(endpoint));
+      }
+
+      {
+        DebugOnly<bool> opened = gfx::PVRManager::Open(this);
+        MOZ_ASSERT(opened);
+      }
     }
 #ifdef MOZ_WIDGET_GONK
     DebugOnly<bool> opened = PSharedBufferManager::Open(this);
     MOZ_ASSERT(opened);
 #endif
   }
 
   if (gAppData) {
@@ -3234,23 +3243,16 @@ ContentParent::DeallocPAPZParent(PAPZPar
 
 gfx::PVRManagerParent*
 ContentParent::AllocPVRManagerParent(Transport* aTransport,
                                      ProcessId aOtherProcess)
 {
   return gfx::VRManagerParent::CreateCrossProcess(aTransport, aOtherProcess);
 }
 
-PImageBridgeParent*
-ContentParent::AllocPImageBridgeParent(mozilla::ipc::Transport* aTransport,
-                                       base::ProcessId aOtherProcess)
-{
-  return ImageBridgeParent::Create(aTransport, aOtherProcess);
-}
-
 PBackgroundParent*
 ContentParent::AllocPBackgroundParent(Transport* aTransport,
                                       ProcessId aOtherProcess)
 {
   return BackgroundParent::Alloc(this, aTransport, aOtherProcess);
 }
 
 PProcessHangMonitorParent*
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -740,20 +740,16 @@ private:
   AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport,
                          base::ProcessId aOtherProcess) override;
 
   PAPZParent*
   AllocPAPZParent(const TabId& aTabId) override;
   bool
   DeallocPAPZParent(PAPZParent* aActor) override;
 
-  PImageBridgeParent*
-  AllocPImageBridgeParent(mozilla::ipc::Transport* aTransport,
-                          base::ProcessId aOtherProcess) override;
-
   PSharedBufferManagerParent*
   AllocPSharedBufferManagerParent(mozilla::ipc::Transport* aTranport,
                                    base::ProcessId aOtherProcess) override;
 
   PBackgroundParent*
   AllocPBackgroundParent(Transport* aTransport, ProcessId aOtherProcess)
                          override;
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -381,17 +381,16 @@ struct BlobURLRegistrationData
 };
 
 prio(normal upto urgent) sync protocol PContent
 {
     parent spawns PPluginModule;
 
     parent opens PProcessHangMonitor;
     parent opens PSharedBufferManager;
-    parent opens PImageBridge;
     parent opens PGMPService;
     parent opens PVRManager;
     child opens PBackground;
 
     manages PAPZ;
     manages PBlob;
     manages PBluetooth;
     manages PBrowser;
@@ -465,18 +464,19 @@ both:
     // For parent->child, aBrowser must be non-null; aOuterWindowID can
     // be 0 to indicate the browser's current root document, or nonzero
     // to persist a subdocument.  For child->parent, arguments are
     // ignored and should be null/zero.
     async PWebBrowserPersistDocument(nullable PBrowser aBrowser,
                                      uint64_t aOuterWindowID);
 
 child:
-    // Give the content process its endpoint to the compositor.
+    // Give the content process its endpoints to the compositor.
     async InitCompositor(Endpoint<PCompositorBridgeChild> compositor);
+    async InitImageBridge(Endpoint<PImageBridgeChild> bridge);
 
     /**
      * Enable system-level sandboxing features, if available.  Can
      * usually only be performed zero or one times.  The child may
      * abnormally exit if this fails; the details are OS-specific.
      */
     async SetProcessSandbox(MaybeFileDesc aBroker);
 
--- a/dom/locales/en-US/chrome/security/security.properties
+++ b/dom/locales/en-US/chrome/security/security.properties
@@ -67,8 +67,14 @@ IntegrityMismatch=None of the “%1$S” hashes in the integrity attribute match the content of the subresource.
 IneligibleResource=“%1$S” is not eligible for integrity checks since it’s neither CORS-enabled nor same-origin.
 # LOCALIZATION NOTE: Do not translate "integrity". "%1$S" is the invalid hash algorithm found in the attribute.
 UnsupportedHashAlg=Unsupported hash algorithm in the integrity attribute: “%1$S”
 # LOCALIZATION NOTE: Do not translate "integrity"
 NoValidMetadata=The integrity attribute does not contain any valid metadata.
 
 # LOCALIZATION NOTE: Do not translate "RC4".
 WeakCipherSuiteWarning=This site uses the cipher RC4 for encryption, which is deprecated and insecure.
+
+#XCTO: nosniff
+# LOCALIZATION NOTE: Do not translate "X-Content-Type-Options: nosniff".
+MimeTypeMismatch=The resource from “%1$S” was blocked due to MIME type mismatch (X-Content-Type-Options: nosniff).
+# LOCALIZATION NOTE: Do not translate "X-Content-Type-Options" and also do not trasnlate "nosniff".
+XCTOHeaderValueMissing=X-Content-Type-Options header warning: value was “%1$S”; did you mean to send “nosniff”?
--- a/dom/plugins/ipc/interpose/moz.build
+++ b/dom/plugins/ipc/interpose/moz.build
@@ -3,15 +3,11 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 SharedLibrary('plugin_child_interpose')
 
 UNIFIED_SOURCES += [ "%s.mm" % (LIBRARY_NAME) ]
 
-UNIFIED_SOURCES += [
-    'plugin_child_quirks.mm',
-]
-
 OS_LIBS += ['-framework Carbon']
 
 DIST_INSTALL = True
deleted file mode 100644
--- a/dom/plugins/ipc/interpose/plugin_child_quirks.mm
+++ /dev/null
@@ -1,20 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#import "CoreFoundation/CoreFoundation.h"
-#import "CoreServices/CoreServices.h"
-#import "Carbon/Carbon.h"
-#define int32_t int32_t
-#define uint32_t uint32_t
-
-#include "MacQuirks.h"
-
-int static_init() {
-  TriggerQuirks();
-  return 0;
-}
-int run = static_init();
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_upgrade_insecure_docwrite_iframe.sjs
@@ -0,0 +1,54 @@
+// custom *.sjs for Bug 1273430
+// META CSP: upgrade-insecure-requests
+
+// important: the IFRAME_URL is *http* and needs to be upgraded to *https* by upgrade-insecure-requests
+const IFRAME_URL =
+  "http://example.com/tests/dom/security/test/csp/file_upgrade_insecure_docwrite_iframe.sjs?docwriteframe";
+
+const TEST_FRAME = `
+  <!DOCTYPE HTML>
+  <html><head><meta charset="utf-8">
+  <title>TEST_FRAME</title>
+  <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
+  </head>
+  <body>
+  <script type="text/javascript">
+    document.write('<iframe src="` + IFRAME_URL + `"/>');
+  </script>
+  </body>
+  </html>`;
+
+
+// doc.write(iframe) sends a post message to the parent indicating the current
+// location so the parent can make sure the request was upgraded to *https*.
+const DOC_WRITE_FRAME = `
+  <!DOCTYPE HTML>
+  <html><head><meta charset="utf-8">
+  <title>DOC_WRITE_FRAME</title>
+  </head>
+  <body onload="window.parent.parent.postMessage({result: document.location.href}, '*');">
+  </body>
+  </html>`;
+
+function handleRequest(request, response)
+{
+  // avoid confusing cache behaviors
+  response.setHeader("Cache-Control", "no-cache", false);
+  response.setHeader("Content-Type", "text/html", false);
+
+  var queryString = request.queryString;
+
+  if (queryString === "testframe") {
+    response.write(TEST_FRAME);
+    return;
+  }
+
+  if (queryString === "docwriteframe") {
+    response.write(DOC_WRITE_FRAME);
+    return;
+  }
+
+  // we should never get here, but just in case
+  // return something unexpected
+  response.write("do'h");
+}
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -180,16 +180,17 @@ support-files =
   file_sandbox_8.html
   file_sandbox_9.html
   file_sandbox_10.html
   file_sandbox_11.html
   file_sandbox_12.html
   file_require_sri_meta.sjs
   file_require_sri_meta.js
   file_sendbeacon.html
+  file_upgrade_insecure_docwrite_iframe.sjs
 
 [test_base-uri.html]
 [test_blob_data_schemes.html]
 [test_connect-src.html]
 [test_CSP.html]
 [test_allow_https_schemes.html]
 skip-if = buildapp == 'b2g' #no ssl support
 [test_bug663567.html]
@@ -272,8 +273,9 @@ tags = mcb
 [test_form_action_blocks_url.html]
 [test_meta_whitespace_skipping.html]
 [test_iframe_sandbox.html]
 [test_iframe_sandbox_top_1.html]
 [test_sandbox.html]
 [test_ping.html]
 [test_require_sri_meta.html]
 [test_sendbeacon.html]
+[test_upgrade_insecure_docwrite_iframe.html]
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/test_upgrade_insecure_docwrite_iframe.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Bug 1273430 - Test CSP upgrade-insecure-requests for doc.write(iframe)</title>
+  <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="testframe"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+/* Description of the test:
+ * Load an iframe which ships with a CSP of upgrade-insecure-requests.
+ * Within that iframe a script performs doc.write(iframe) using an
+ * *http* URL. Make sure, the URL is upgraded to *https*.
+ *
+ * +-----------------------------------------+
+ * |                                         |
+ * | http(s); csp: upgrade-insecure-requests |       |
+ * | +---------------------------------+     |
+ * | |                                 |     |
+ * | | doc.write(<iframe src='http'>); | <--------- upgrade to https
+ * | |                                 |     |
+ * | +---------------------------------+     |
+ * |                                         |
+ * +-----------------------------------------+
+ *
+ */
+
+const TEST_FRAME_URL =
+  "https://example.com/tests/dom/security/test/csp/file_upgrade_insecure_docwrite_iframe.sjs?testframe";
+
+// important: the RESULT should have a scheme of *https*
+const RESULT =
+  "https://example.com/tests/dom/security/test/csp/file_upgrade_insecure_docwrite_iframe.sjs?docwriteframe";
+
+window.addEventListener("message", receiveMessage, false);
+function receiveMessage(event) {
+  is(event.data.result, RESULT, "doc.write(iframe) of http should be upgraded to https!");
+  window.removeEventListener("message", receiveMessage, false);
+  SimpleTest.finish();
+}
+
+// start the test
+SimpleTest.waitForExplicitFinish();
+var testframe = document.getElementById("testframe");
+testframe.src = TEST_FRAME_URL;
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/general/file_nosniff_testserver.sjs
@@ -0,0 +1,60 @@
+"use strict";
+Components.utils.importGlobalProperties(["URLSearchParams"]);
+
+const SCRIPT = "var foo = 24;";
+const CSS = "body { background-color: green; }";
+
+// small red image
+const IMG = atob(
+  "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12" +
+  "P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==");
+
+function handleRequest(request, response) {
+  const query = new URLSearchParams(request.queryString);
+
+  // avoid confusing cache behaviors
+  response.setHeader("Cache-Control", "no-cache", false);
+
+  // set the nosniff header
+  response.setHeader("X-Content-Type-Options", "  NoSniFF  , foo  ", false);
+
+  if (query.has("cssCorrectType")) {
+    response.setHeader("Content-Type", "teXt/cSs", false);
+    response.write(CSS);
+    return;
+  }
+
+  if (query.has("cssWrongType")) {
+    response.setHeader("Content-Type", "text/html", false);
+    response.write(CSS);
+    return;
+  }
+
+  if (query.has("scriptCorrectType")) {
+    response.setHeader("Content-Type", "appLIcation/jAvaScriPt;blah", false);
+    response.write(SCRIPT);
+    return;
+  }
+
+  if (query.has("scriptWrongType")) {
+    response.setHeader("Content-Type", "text/html", false);
+    response.write(SCRIPT);
+    return;
+  }
+
+  if (query.has("imgCorrectType")) {
+    response.setHeader("Content-Type", "iMaGe/pnG;blah", false);
+    response.write(IMG);
+    return;
+  }
+
+  if (query.has("imgtWrongType")) {
+    response.setHeader("Content-Type", "text/html", false);
+    response.write(IMG);
+    return;
+  }
+
+  // we should never get here, but just in case
+  response.setHeader("Content-Type", "text/html", false);
+  response.write("do'h");
+}
--- a/dom/security/test/general/mochitest.ini
+++ b/dom/security/test/general/mochitest.ini
@@ -1,5 +1,7 @@
 [DEFAULT]
 support-files =
   file_contentpolicytype_targeted_link_iframe.sjs
+  file_nosniff_testserver.sjs
 
 [test_contentpolicytype_targeted_link_iframe.html]
+[test_nosniff.html]
new file mode 100644
--- /dev/null
+++ b/dom/security/test/general/test_nosniff.html
@@ -0,0 +1,115 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 471020 - Add X-Content-Type-Options: nosniff support to Firefox</title>
+  <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+  <!-- add the two css tests -->
+  <link rel="stylesheet" id="cssCorrectType">
+  <link rel="stylesheet" id="cssWrongType">
+</head>
+<body>
+
+<!-- add the two script tests -->
+<script id="scriptCorrectType"></script>
+<script id="scriptWrongType"></script>
+
+<!-- add the two img tests -->
+<img id="imgCorrectType" />
+<img id="imgWrongType" />
+
+<script class="testbody" type="text/javascript">
+/* Description of the test:
+ * We load 2 css files, 2 script files and 2 image files, where
+ * the sever either responds with the right mime type or
+ * the wrong mime type for each test.
+ */
+
+SimpleTest.waitForExplicitFinish();
+const NUM_TESTS = 6;
+
+var testCounter = 0;
+function checkFinish() {
+	testCounter++;
+	if (testCounter === NUM_TESTS) {
+		SimpleTest.finish();
+	}
+}
+
+// 1) Test CSS with correct mime type
+var cssCorrectType = document.getElementById("cssCorrectType");
+cssCorrectType.onload = function() {
+  ok(true, "style nosniff correct type should load");
+  checkFinish();
+}
+cssCorrectType.onerror = function() {
+  ok(false, "style nosniff correct type should load");
+  checkFinish();
+}
+cssCorrectType.href = "file_nosniff_testserver.sjs?cssCorrectType";
+
+// 2) Test CSS with wrong mime type
+var cssWrongType = document.getElementById("cssWrongType");
+cssWrongType.onload = function() {
+  ok(false, "style nosniff wrong type should not load");
+  checkFinish();
+}
+cssWrongType.onerror = function() {
+  ok(true, "style nosniff wrong type should not load");
+  checkFinish();
+}
+cssWrongType.href = "file_nosniff_testserver.sjs?cssWrongType";
+
+// 3) Test SCRIPT with correct mime type
+var scriptCorrectType = document.getElementById("scriptCorrectType");
+scriptCorrectType.onload = function() {
+  ok(true, "script nosniff correct type should load");
+  checkFinish();
+}
+scriptCorrectType.onerror = function() {
+  ok(false, "script nosniff correct type should load");
+  checkFinish();
+}
+scriptCorrectType.src = "file_nosniff_testserver.sjs?scriptCorrectType";
+
+// 4) Test SCRIPT with wrong mime type
+var scriptWrongType = document.getElementById("scriptWrongType");
+scriptWrongType.onload = function() {
+  ok(false, "script nosniff wrong type should not load");
+  checkFinish();
+}
+scriptWrongType.onerror = function() {
+  ok(true, "script nosniff wrong type should not load");
+  checkFinish();
+}
+scriptWrongType.src = "file_nosniff_testserver.sjs?scriptWrongType";
+
+// 5) Test IMG with correct mime type
+var imgCorrectType = document.getElementById("imgCorrectType");
+imgCorrectType.onload = function() {
+  ok(true, "img nosniff correct type should load");
+  checkFinish();
+}
+imgCorrectType.onerror = function() {
+  ok(false, "img nosniff correct type should load");
+  checkFinish();
+}
+imgCorrectType.src = "file_nosniff_testserver.sjs?imgCorrectType";
+
+// 6) Test IMG with wrong mime type
+var imgWrongType = document.getElementById("imgWrongType");
+imgWrongType.onload = function() {
+  ok(false, "img nosniff wrong type should not load");
+  checkFinish();
+}
+imgWrongType.onerror = function() {
+  ok(true, "img nosniff wrong type should not load");
+  checkFinish();
+}
+imgWrongType.src = "file_nosniff_testserver.sjs?imgWrongType";
+
+</script>
+</body>
+</html>
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -8,16 +8,17 @@
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
 #include "GPUProcessHost.h"
 #include "VsyncBridgeParent.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/ipc/ProcessChild.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/layers/CompositorThread.h"
+#include "mozilla/layers/ImageBridgeParent.h"
 
 namespace mozilla {
 namespace gfx {
 
 using namespace ipc;
 using namespace layers;
 
 GPUParent::GPUParent()
@@ -57,16 +58,23 @@ GPUParent::RecvInit(nsTArray<GfxPrefSett
 bool
 GPUParent::RecvInitVsyncBridge(Endpoint<PVsyncBridgeParent>&& aVsyncEndpoint)
 {
   VsyncBridgeParent::Start(Move(aVsyncEndpoint));
   return true;
 }
 
 bool
+GPUParent::RecvInitImageBridge(Endpoint<PImageBridgeParent>&& aEndpoint)
+{
+  ImageBridgeParent::CreateForGPUProcess(Move(aEndpoint));
+  return true;
+}
+
+bool
 GPUParent::RecvUpdatePref(const GfxPrefSetting& setting)
 {
   gfxPrefs::Pref* pref = gfxPrefs::all()[setting.index()];
   pref->SetCachedValue(setting.value());
   return true;
 }
 
 static void
@@ -93,16 +101,22 @@ GPUParent::RecvNewWidgetCompositor(Endpo
 }
 
 bool
 GPUParent::RecvNewContentCompositorBridge(Endpoint<PCompositorBridgeParent>&& aEndpoint)
 {
   return CompositorBridgeParent::CreateForContent(Move(aEndpoint));
 }
 
+bool
+GPUParent::RecvNewContentImageBridge(Endpoint<PImageBridgeParent>&& aEndpoint)
+{
+  return ImageBridgeParent::CreateForContent(Move(aEndpoint));
+}
+
 void
 GPUParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   if (AbnormalShutdown == aWhy) {
     NS_WARNING("Shutting down GPU process early due to a crash!");
     ProcessChild::QuickExit();
   }
 
--- a/gfx/ipc/GPUParent.h
+++ b/gfx/ipc/GPUParent.h
@@ -21,23 +21,25 @@ public:
   ~GPUParent();
 
   bool Init(base::ProcessId aParentPid,
             MessageLoop* aIOLoop,
             IPC::Channel* aChannel);
 
   bool RecvInit(nsTArray<GfxPrefSetting>&& prefs) override;
   bool RecvInitVsyncBridge(Endpoint<PVsyncBridgeParent>&& aVsyncEndpoint) override;
+  bool RecvInitImageBridge(Endpoint<PImageBridgeParent>&& aEndpoint) override;
   bool RecvUpdatePref(const GfxPrefSetting& pref) override;
   bool RecvNewWidgetCompositor(
     Endpoint<PCompositorBridgeParent>&& aEndpoint,
     const CSSToLayoutDeviceScale& aScale,
     const bool& aUseExternalSurface,
     const IntSize& aSurfaceSize) override;
   bool RecvNewContentCompositorBridge(Endpoint<PCompositorBridgeParent>&& aEndpoint) override;
+  bool RecvNewContentImageBridge(Endpoint<PImageBridgeParent>&& aEndpoint) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
 private:
   RefPtr<VsyncBridgeParent> mVsyncBridge;
 };
 
 } // namespace gfx
--- a/gfx/ipc/GPUProcessManager.cpp
+++ b/gfx/ipc/GPUProcessManager.cpp
@@ -2,16 +2,18 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=99: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "GPUProcessManager.h"
 #include "GPUProcessHost.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
+#include "mozilla/layers/ImageBridgeChild.h"
+#include "mozilla/layers/ImageBridgeParent.h"
 #include "mozilla/layers/InProcessCompositorSession.h"
 #include "mozilla/layers/RemoteCompositorSession.h"
 #include "mozilla/widget/PlatformWidgetTypes.h"
 #ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
 # include "mozilla/widget/CompositorWidgetChild.h"
 #endif
 #include "nsBaseWidget.h"
 #include "nsContentUtils.h"
@@ -127,16 +129,44 @@ GPUProcessManager::EnsureGPUReady()
       // removed the process.
       MOZ_ASSERT(!mProcess && !mGPUChild);
       return;
     }
   }
 }
 
 void
+GPUProcessManager::EnsureImageBridgeChild()
+{
+  if (ImageBridgeChild::IsCreated()) {
+    return;
+  }
+
+  if (!mGPUChild) {
+    ImageBridgeChild::InitSameProcess();
+    return;
+  }
+
+  ipc::Endpoint<PImageBridgeParent> parentPipe;
+  ipc::Endpoint<PImageBridgeChild> childPipe;
+  nsresult rv = PImageBridge::CreateEndpoints(
+    mGPUChild->OtherPid(),
+    base::GetCurrentProcId(),
+    &parentPipe,
+    &childPipe);
+  if (NS_FAILED(rv)) {
+    DisableGPUProcess("Failed to create PImageBridge endpoints");
+    return;
+  }
+
+  mGPUChild->SendInitImageBridge(Move(parentPipe));
+  ImageBridgeChild::InitWithGPUProcess(Move(childPipe));
+}
+
+void
 GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost)
 {
   MOZ_ASSERT(mProcess && mProcess == aHost);
 
   if (!mProcess->IsConnected()) {
     DisableGPUProcess("Failed to launch GPU process");
     return;
   }
@@ -222,16 +252,18 @@ GPUProcessManager::CreateTopLevelComposi
                                             ClientLayerManager* aLayerManager,
                                             CSSToLayoutDeviceScale aScale,
                                             bool aUseAPZ,
                                             bool aUseExternalSurfaceSize,
                                             const gfx::IntSize& aSurfaceSize)
 {
   uint64_t layerTreeId = AllocateLayerTreeId();
 
+  EnsureImageBridgeChild();
+
   if (mGPUChild) {
     RefPtr<CompositorSession> session = CreateRemoteSession(
       aWidget,
       aLayerManager,
       layerTreeId,
       aScale,
       aUseAPZ,
       aUseExternalSurfaceSize,
@@ -289,28 +321,31 @@ GPUProcessManager::CreateRemoteSession(n
   CompositorWidgetInitData initData;
   aWidget->GetCompositorWidgetInitData(&initData);
 
   bool ok = mGPUChild->SendNewWidgetCompositor(
     Move(parentPipe),
     aScale,
     aUseExternalSurfaceSize,
     aSurfaceSize);
-  if (!ok)
+  if (!ok) {
     return nullptr;
+  }
 
   RefPtr<CompositorVsyncDispatcher> dispatcher = aWidget->GetCompositorVsyncDispatcher();
   RefPtr<CompositorWidgetVsyncObserver> observer =
     new CompositorWidgetVsyncObserver(mVsyncBridge, aRootLayerTreeId);
 
   CompositorWidgetChild* widget = new CompositorWidgetChild(dispatcher, observer);
-  if (!child->SendPCompositorWidgetConstructor(widget, initData))
+  if (!child->SendPCompositorWidgetConstructor(widget, initData)) {
     return nullptr;
-  if (!child->SendInitialize(aRootLayerTreeId))
+  }
+  if (!child->SendInitialize(aRootLayerTreeId)) {
     return nullptr;
+  }
 
   RefPtr<RemoteCompositorSession> session =
     new RemoteCompositorSession(child, widget, aRootLayerTreeId);
   return session.forget();
 #else
   gfxCriticalNote << "Platform does not support out-of-process compositing";
   return nullptr;
 #endif
@@ -335,18 +370,53 @@ GPUProcessManager::CreateContentComposit
   if (NS_FAILED(rv)) {
     gfxCriticalNote << "Could not create content compositor bridge: " << hexa(int(rv));
     return false;
   }
 
   if (mGPUChild) {
     mGPUChild->SendNewContentCompositorBridge(Move(parentPipe));
   } else {
-    if (!CompositorBridgeParent::CreateForContent(Move(parentPipe)))
+    if (!CompositorBridgeParent::CreateForContent(Move(parentPipe))) {
       return false;
+    }
+  }
+
+  *aOutEndpoint = Move(childPipe);
+  return true;
+}
+
+bool
+GPUProcessManager::CreateContentImageBridge(base::ProcessId aOtherProcess,
+                                            ipc::Endpoint<PImageBridgeChild>* aOutEndpoint)
+{
+  EnsureImageBridgeChild();
+
+  base::ProcessId gpuPid = mGPUChild
+                           ? mGPUChild->OtherPid()
+                           : base::GetCurrentProcId();
+
+  ipc::Endpoint<PImageBridgeParent> parentPipe;
+  ipc::Endpoint<PImageBridgeChild> childPipe;
+  nsresult rv = PImageBridge::CreateEndpoints(
+    gpuPid,
+    aOtherProcess,
+    &parentPipe,
+    &childPipe);
+  if (NS_FAILED(rv)) {
+    gfxCriticalNote << "Could not create content compositor bridge: " << hexa(int(rv));
+    return false;
+  }
+
+  if (mGPUChild) {
+    mGPUChild->SendNewContentImageBridge(Move(parentPipe));
+  } else {
+    if (!ImageBridgeParent::CreateForContent(Move(parentPipe))) {
+      return false;
+    }
   }
 
   *aOutEndpoint = Move(childPipe);
   return true;
 }
 
 already_AddRefed<APZCTreeManager>
 GPUProcessManager::GetAPZCTreeManagerForLayers(uint64_t aLayersId)
--- a/gfx/ipc/GPUProcessManager.h
+++ b/gfx/ipc/GPUProcessManager.h
@@ -23,17 +23,17 @@ class nsBaseWidget;
 
 namespace mozilla {
 namespace layers {
 class APZCTreeManager;
 class CompositorSession;
 class ClientLayerManager;
 class CompositorUpdateObserver;
 class PCompositorBridgeChild;
-class PCompositorBridgeParent;
+class PImageBridgeChild;
 } // namespace layers
 namespace widget {
 class CompositorWidget;
 } // namespace widget
 namespace dom {
 class ContentParent;
 class TabParent;
 } // namespace dom
@@ -51,16 +51,17 @@ class VsyncIOThreadHolder;
 // to the compositor via CompositorBridgeParent.
 class GPUProcessManager final : public GPUProcessHost::Listener
 {
   typedef layers::APZCTreeManager APZCTreeManager;
   typedef layers::ClientLayerManager ClientLayerManager;
   typedef layers::CompositorSession CompositorSession;
   typedef layers::CompositorUpdateObserver CompositorUpdateObserver;
   typedef layers::PCompositorBridgeChild PCompositorBridgeChild;
+  typedef layers::PImageBridgeChild PImageBridgeChild;
 
 public:
   static void Initialize();
   static void Shutdown();
   static GPUProcessManager* Get();
 
   ~GPUProcessManager();
 
@@ -78,16 +79,19 @@ public:
     CSSToLayoutDeviceScale aScale,
     bool aUseAPZ,
     bool aUseExternalSurfaceSize,
     const gfx::IntSize& aSurfaceSize);
 
   bool CreateContentCompositorBridge(base::ProcessId aOtherProcess,
                                      ipc::Endpoint<PCompositorBridgeChild>* aOutEndpoint);
 
+  bool CreateContentImageBridge(base::ProcessId aOtherProcess,
+                                ipc::Endpoint<PImageBridgeChild>* aOutEndpoint);
+
   // This returns a reference to the APZCTreeManager to which
   // pan/zoom-related events can be sent.
   already_AddRefed<APZCTreeManager> GetAPZCTreeManagerForLayers(uint64_t aLayersId);
 
   // Allocate an ID that can be used to refer to a layer tree and
   // associated resources that live only on the compositor thread.
   //
   // Must run on the content main thread.
@@ -138,16 +142,18 @@ private:
 
   // Shutdown the GPU process.
   void CleanShutdown();
   void DestroyProcess();
 
   void EnsureVsyncIOThread();
   void ShutdownVsyncIOThread();
 
+  void EnsureImageBridgeChild();
+
   RefPtr<CompositorSession> CreateRemoteSession(
     nsBaseWidget* aWidget,
     ClientLayerManager* aLayerManager,
     const uint64_t& aRootLayerTreeId,
     CSSToLayoutDeviceScale aScale,
     bool aUseAPZ,
     bool aUseExternalSurfaceSize,
     const gfx::IntSize& aSurfaceSize);
--- a/gfx/ipc/PGPU.ipdl
+++ b/gfx/ipc/PGPU.ipdl
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PCompositorBridge;
+include protocol PImageBridge;
 include protocol PVsyncBridge;
 
 using mozilla::CSSToLayoutDeviceScale from "Units.h";
 using mozilla::gfx::IntSize from "mozilla/gfx/2D.h";
 
 namespace mozilla {
 namespace gfx {
 
@@ -25,25 +26,27 @@ struct GfxPrefSetting {
 };
 
 sync protocol PGPU
 {
 parent:
   // Sent by the UI process to initiate core settings.
   async Init(GfxPrefSetting[] prefs);
 
-  async InitVsyncBridge(Endpoint<PVsyncBridgeParent> vsyncEndpoint);
+  async InitVsyncBridge(Endpoint<PVsyncBridgeParent> endpoint);
+  async InitImageBridge(Endpoint<PImageBridgeParent> endpoint);
 
   // Called to update a gfx preference.
   async UpdatePref(GfxPrefSetting pref);
 
   // Create a new top-level compositor.
   async NewWidgetCompositor(Endpoint<PCompositorBridgeParent> endpoint,
                             CSSToLayoutDeviceScale scale,
                             bool useExternalSurface,
                             IntSize surfaceSize);
 
   // Create a new content-process compositor bridge.
   async NewContentCompositorBridge(Endpoint<PCompositorBridgeParent> endpoint);
+  async NewContentImageBridge(Endpoint<PImageBridgeParent> endpoint);
 };
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -386,23 +386,18 @@ ImageBridgeChild::CancelWaitForRecycle(u
   if (!client) {
     return;
   }
   mTexturesWaitingRecycled.Remove(aTextureId);
 }
 
 // Singleton
 static StaticRefPtr<ImageBridgeChild> sImageBridgeChildSingleton;
-static StaticRefPtr<ImageBridgeParent> sImageBridgeParentSingleton;
 static Thread *sImageBridgeChildThread = nullptr;
 
-void ReleaseImageBridgeParentSingleton() {
-  sImageBridgeParentSingleton = nullptr;
-}
-
 void
 ImageBridgeChild::FallbackDestroyActors() {
   if (mTxn && !mTxn->mDestroyedActors.IsEmpty()) {
     mTxn->FallbackDestroyActors();
   }
 }
 
 // dispatched function
@@ -499,16 +494,17 @@ ImageBridgeChild::ImageBridgeChild()
 #ifdef MOZ_WIDGET_GONK
   , mWaitingFenceHandleMutex("ImageBridgeChild::mWaitingFenceHandleMutex")
 #endif
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   mTxn = new CompositableTransaction();
 }
+
 ImageBridgeChild::~ImageBridgeChild()
 {
   delete mTxn;
 }
 
 void
 ImageBridgeChild::MarkShutDown()
 {
@@ -563,44 +559,20 @@ ImageBridgeChild* ImageBridgeChild::GetS
   return sImageBridgeChildSingleton;
 }
 
 bool ImageBridgeChild::IsCreated()
 {
   return GetSingleton() != nullptr;
 }
 
-void ImageBridgeChild::StartUp()
-{
-  NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
-  ImageBridgeChild::StartUpOnThread(new ImageBridgeThread());
-}
-
 #ifdef MOZ_NUWA_PROCESS
 #include "ipc/Nuwa.h"
 #endif
 
-static void
-ConnectImageBridgeInChildProcess(Transport* aTransport,
-                                 ProcessId aOtherPid)
-{
-  // Bind the IPC channel to the image bridge thread.
-  sImageBridgeChildSingleton->Open(aTransport, aOtherPid,
-                                   XRE_GetIOMessageLoop(),
-                                   ipc::ChildSide);
-#ifdef MOZ_NUWA_PROCESS
-  if (IsNuwaProcess()) {
-    sImageBridgeChildThread
-      ->message_loop()->PostTask(NewRunnableFunction(NuwaMarkCurrentThread,
-                                                     (void (*)(void *))nullptr,
-                                                     (void *)nullptr));
-  }
-#endif
-}
-
 static void ReleaseImageClientNow(ImageClient* aClient,
                                   PImageContainerChild* aChild)
 {
   MOZ_ASSERT(InImageBridgeChildThread());
   if (aClient) {
     aClient->Release();
   }
 
@@ -915,40 +887,46 @@ ImageBridgeChild::SendImageBridgeThreadI
 }
 
 static void CallSendImageBridgeThreadId(ImageBridgeChild* aImageBridgeChild)
 {
   MOZ_ASSERT(InImageBridgeChildThread());
   aImageBridgeChild->SendImageBridgeThreadId();
 }
 
-PImageBridgeChild*
-ImageBridgeChild::StartUpInChildProcess(Transport* aTransport,
-                                        ProcessId aOtherPid)
+bool
+ImageBridgeChild::InitForContent(Endpoint<PImageBridgeChild>&& aEndpoint)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   gfxPlatform::GetPlatform();
 
   sImageBridgeChildThread = new ImageBridgeThread();
   if (!sImageBridgeChildThread->Start()) {
-    return nullptr;
+    return false;
   }
 
   sImageBridgeChildSingleton = new ImageBridgeChild();
-  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
-    NewRunnableFunction(ConnectImageBridgeInChildProcess,
-                        aTransport, aOtherPid));
-  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
-    NewRunnableFunction(CallSendImageBridgeThreadId,
-                        sImageBridgeChildSingleton.get()));
+
+  MessageLoop* loop = sImageBridgeChildSingleton->GetMessageLoop();
+
+  loop->PostTask(NewRunnableMethod<Endpoint<PImageBridgeChild>&&>(
+    sImageBridgeChildSingleton, &ImageBridgeChild::Bind, Move(aEndpoint)));
+  loop->PostTask(NewRunnableFunction(
+    CallSendImageBridgeThreadId, sImageBridgeChildSingleton.get()));
 
   return sImageBridgeChildSingleton;
 }
 
+void
+ImageBridgeChild::Bind(Endpoint<PImageBridgeChild>&& aEndpoint)
+{
+  aEndpoint.Bind(this, nullptr);
+}
+
 void ImageBridgeChild::ShutDown()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   sIsShutDown = true;
 
   if (ImageBridgeChild::IsCreated()) {
     MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
@@ -979,35 +957,55 @@ void ImageBridgeChild::ShutDown()
 
     sImageBridgeChildSingleton = nullptr;
 
     delete sImageBridgeChildThread;
     sImageBridgeChildThread = nullptr;
   }
 }
 
-bool ImageBridgeChild::StartUpOnThread(Thread* aThread)
+void
+ImageBridgeChild::InitSameProcess()
 {
-  MOZ_ASSERT(aThread, "ImageBridge needs a thread.");
-  if (sImageBridgeChildSingleton == nullptr) {
-    sImageBridgeChildThread = aThread;
-    if (!aThread->IsRunning()) {
-      aThread->Start();
-    }
-    sImageBridgeChildSingleton = new ImageBridgeChild();
-    sImageBridgeParentSingleton = new ImageBridgeParent(
-      CompositorThreadHolder::Loop(), base::GetCurrentProcId());
-    sImageBridgeChildSingleton->ConnectAsync(sImageBridgeParentSingleton);
-    sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
-      NewRunnableFunction(CallSendImageBridgeThreadId,
-                          sImageBridgeChildSingleton.get()));
-    return true;
-  } else {
-    return false;
+  NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
+
+  MOZ_ASSERT(!sImageBridgeChildSingleton);
+  MOZ_ASSERT(!sImageBridgeChildThread);
+
+  sImageBridgeChildThread = new ImageBridgeThread();
+  if (!sImageBridgeChildThread->IsRunning()) {
+    sImageBridgeChildThread->Start();
   }
+
+  sImageBridgeChildSingleton = new ImageBridgeChild();
+  RefPtr<ImageBridgeParent> parent = ImageBridgeParent::CreateSameProcess();
+
+  sImageBridgeChildSingleton->ConnectAsync(parent);
+  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
+    NewRunnableFunction(CallSendImageBridgeThreadId,
+                        sImageBridgeChildSingleton.get()));
+}
+
+/* static */ void
+ImageBridgeChild::InitWithGPUProcess(Endpoint<PImageBridgeChild>&& aEndpoint)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!sImageBridgeChildSingleton);
+  MOZ_ASSERT(!sImageBridgeChildThread);
+
+  sImageBridgeChildThread = new ImageBridgeThread();
+  if (!sImageBridgeChildThread->IsRunning()) {
+    sImageBridgeChildThread->Start();
+  }
+
+  sImageBridgeChildSingleton = new ImageBridgeChild();
+
+  MessageLoop* loop = sImageBridgeChildSingleton->GetMessageLoop();
+  loop->PostTask(NewRunnableMethod<Endpoint<PImageBridgeChild>&&>(
+    sImageBridgeChildSingleton, &ImageBridgeChild::Bind, Move(aEndpoint)));
 }
 
 bool InImageBridgeChildThread()
 {
   return ImageBridgeChild::IsCreated() &&
     sImageBridgeChildThread->thread_id() == PlatformThread::CurrentId();
 }
 
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -114,36 +114,31 @@ public:
   virtual ShmemAllocator* AsShmemAllocator() override { return this; }
 
   /**
    * Creates the image bridge with a dedicated thread for ImageBridgeChild.
    *
    * We may want to use a specifi thread in the future. In this case, use
    * CreateWithThread instead.
    */
-  static void StartUp();
+  static void InitSameProcess();
 
-  static PImageBridgeChild*
-  StartUpInChildProcess(Transport* aTransport, ProcessId aOtherProcess);
+  static void InitWithGPUProcess(Endpoint<PImageBridgeChild>&& aEndpoint);
+  static bool InitForContent(Endpoint<PImageBridgeChild>&& aEndpoint);
 
   /**
    * Destroys the image bridge by calling DestroyBridge, and destroys the
    * ImageBridge's thread.
    *
    * If you don't want to destroy the thread, call DestroyBridge directly
    * instead.
    */
   static void ShutDown();
 
   /**
-   * Creates the ImageBridgeChild manager protocol.
-   */
-  static bool StartUpOnThread(base::Thread* aThread);
-
-  /**
    * Returns true if the singleton has been created.
    *
    * Can be called from any thread.
    */
   static bool IsCreated();
   /**
    * Returns true if the singleton's ShutDown() was called.
    *
@@ -344,23 +339,27 @@ public:
   virtual bool IsSameProcess() const override;
 
   virtual void UpdateFwdTransactionId() override { ++mFwdTransactionId; }
   virtual uint64_t GetFwdTransactionId() override { return mFwdTransactionId; }
 
   void MarkShutDown();
 
   void FallbackDestroyActors();
+
 protected:
   ImageBridgeChild();
   bool DispatchAllocShmemInternal(size_t aSize,
                                   SharedMemory::SharedMemoryType aType,
                                   Shmem* aShmem,
                                   bool aUnsafe);
 
+  void Bind(Endpoint<PImageBridgeChild>&& aEndpoint);
+
+private:
   CompositableTransaction* mTxn;
   Atomic<bool> mShuttingDown;
   static Atomic<bool> sIsShutDown;
 
   /**
    * Transaction id of CompositableForwarder.
    * It is incrementaed by UpdateFwdTransactionId() in each BeginTransaction() call.
    */
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -58,31 +58,61 @@ ImageBridgeParent::ImageBridgeParent(Mes
   MOZ_ASSERT(NS_IsMainThread());
   sMainLoop = MessageLoop::current();
 
   // creates the map only if it has not been created already, so it is safe
   // with several bridges
   CompositableMap::Create();
   sImageBridges[aChildProcessId] = this;
   SetOtherProcessId(aChildProcessId);
-  // DeferredDestroy clears mSelfRef.
-  mSelfRef = this;
 }
 
 ImageBridgeParent::~ImageBridgeParent()
 {
   nsTArray<PImageContainerParent*> parents;
   ManagedPImageContainerParent(parents);
   for (PImageContainerParent* p : parents) {
     delete p;
   }
 
   sImageBridges.erase(OtherPid());
 }
 
+static StaticRefPtr<ImageBridgeParent> sImageBridgeParentSingleton;
+
+void ReleaseImageBridgeParentSingleton() {
+  sImageBridgeParentSingleton = nullptr;
+}
+
+/* static */ ImageBridgeParent*
+ImageBridgeParent::CreateSameProcess()
+{
+  RefPtr<ImageBridgeParent> parent =
+    new ImageBridgeParent(CompositorThreadHolder::Loop(), base::GetCurrentProcId());
+  parent->mSelfRef = parent;
+
+  sImageBridgeParentSingleton = parent;
+  return parent;
+}
+
+/* static */ bool
+ImageBridgeParent::CreateForGPUProcess(Endpoint<PImageBridgeParent>&& aEndpoint)
+{
+  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
+
+  MessageLoop* loop = CompositorThreadHolder::Loop();
+  RefPtr<ImageBridgeParent> parent = new ImageBridgeParent(loop, aEndpoint.OtherPid());
+
+  loop->PostTask(NewRunnableMethod<Endpoint<PImageBridgeParent>&&>(
+    parent, &ImageBridgeParent::Bind, Move(aEndpoint)));
+
+  sImageBridgeParentSingleton = parent;
+  return true;
+}
+
 void
 ImageBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   // Can't alloc/dealloc shmems from now on.
   mClosed = true;
 
   MessageLoop::current()->PostTask(NewRunnableMethod(this, &ImageBridgeParent::DeferredDestroy));
 
@@ -168,33 +198,34 @@ ImageBridgeParent::RecvUpdateNoSwap(Edit
                                     const uint64_t& aFwdTransactionId)
 {
   InfallibleTArray<EditReply> noReplies;
   bool success = RecvUpdate(Move(aEdits), Move(aToDestroy), aFwdTransactionId, &noReplies);
   MOZ_ASSERT(noReplies.Length() == 0, "RecvUpdateNoSwap requires a sync Update to carry Edits");
   return success;
 }
 
-static void
-ConnectImageBridgeInParentProcess(ImageBridgeParent* aBridge,
-                                  Transport* aTransport,
-                                  base::ProcessId aOtherPid)
+/* static */ bool
+ImageBridgeParent::CreateForContent(Endpoint<PImageBridgeParent>&& aEndpoint)
 {
-  aBridge->Open(aTransport, aOtherPid, XRE_GetIOMessageLoop(), ipc::ParentSide);
+  MessageLoop* loop = CompositorThreadHolder::Loop();
+
+  RefPtr<ImageBridgeParent> bridge = new ImageBridgeParent(loop, aEndpoint.OtherPid());
+  loop->PostTask(NewRunnableMethod<Endpoint<PImageBridgeParent>&&>(
+    bridge, &ImageBridgeParent::Bind, Move(aEndpoint)));
+
+  return true;
 }
 
-/*static*/ PImageBridgeParent*
-ImageBridgeParent::Create(Transport* aTransport, ProcessId aChildProcessId)
+void
+ImageBridgeParent::Bind(Endpoint<PImageBridgeParent>&& aEndpoint)
 {
-  MessageLoop* loop = CompositorThreadHolder::Loop();
-  RefPtr<ImageBridgeParent> bridge = new ImageBridgeParent(loop, aChildProcessId);
-
-  loop->PostTask(NewRunnableFunction(ConnectImageBridgeInParentProcess,
-                                     bridge.get(), aTransport, aChildProcessId));
-  return bridge.get();
+  if (!aEndpoint.Bind(this, nullptr))
+    return;
+  mSelfRef = this;
 }
 
 bool ImageBridgeParent::RecvWillClose()
 {
   // If there is any texture still alive we have to force it to deallocate the
   // device data (GL textures, etc.) now because shortly after SenStop() returns
   // on the child side the widget will be destroyed along with it's associated
   // GL context.
@@ -334,29 +365,17 @@ ImageBridgeParent::GetInstance(ProcessId
   return sImageBridges[aId];
 }
 
 IToplevelProtocol*
 ImageBridgeParent::CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
                                  base::ProcessHandle aPeerProcess,
                                  mozilla::ipc::ProtocolCloneContext* aCtx)
 {
-  for (unsigned int i = 0; i < aFds.Length(); i++) {
-    if (aFds[i].protocolId() == unsigned(GetProtocolId())) {
-      UniquePtr<Transport> transport =
-        OpenDescriptor(aFds[i].fd(), Transport::MODE_SERVER);
-      PImageBridgeParent* bridge = Create(transport.get(), base::GetProcId(aPeerProcess));
-      bridge->CloneManagees(this, aCtx);
-      bridge->IToplevelProtocol::SetTransport(Move(transport));
-      // The reference to the compositor thread is held in OnChannelConnected().
-      // We need to do this for cloned actors, too.
-      bridge->OnChannelConnected(base::GetProcId(aPeerProcess));
-      return bridge;
-    }
-  }
+  MOZ_ASSERT_UNREACHABLE("Not supported");
   return nullptr;
 }
 
 void
 ImageBridgeParent::OnChannelConnected(int32_t aPid)
 {
   mCompositorThreadHolder = GetCompositorThreadHolder();
 }
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -41,26 +41,30 @@ class ImageBridgeParent final : public P
                                 public CompositableParentManager,
                                 public ShmemAllocator
 {
 public:
   typedef InfallibleTArray<CompositableOperation> EditArray;
   typedef InfallibleTArray<OpDestroy> OpDestroyArray;
   typedef InfallibleTArray<EditReply> EditReplyArray;
 
+protected:
   ImageBridgeParent(MessageLoop* aLoop, ProcessId aChildProcessId);
+
+public:
   ~ImageBridgeParent();
 
+  static ImageBridgeParent* CreateSameProcess();
+  static bool CreateForGPUProcess(Endpoint<PImageBridgeParent>&& aEndpoint);
+  static bool CreateForContent(Endpoint<PImageBridgeParent>&& aEndpoint);
+
   virtual ShmemAllocator* AsShmemAllocator() override { return this; }
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
-  static PImageBridgeParent*
-  Create(Transport* aTransport, ProcessId aChildProcessId);
-
   // CompositableParentManager
   virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
 
   virtual void NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId) override;
 
   virtual base::ProcessId GetChildProcessId() override
   {
     return OtherPid();
@@ -138,16 +142,18 @@ public:
 
   virtual bool UsesImageBridge() const override { return true; }
 
   virtual bool IPCOpen() const override { return !mClosed; }
 
 protected:
   void OnChannelConnected(int32_t pid) override;
 
+  void Bind(Endpoint<PImageBridgeParent>&& aEndpoint);
+
 private:
   void DeferredDestroy();
   MessageLoop* mMessageLoop;
   // This keeps us alive until ActorDestroy(), at which point we do a
   // deferred destruction of ourselves.
   RefPtr<ImageBridgeParent> mSelfRef;
 
   bool mSetChildThreadPriority;
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -883,40 +883,36 @@ gfxPlatform::InitLayersIPC()
     sLayersIPCIsUp = true;
 
     if (XRE_IsParentProcess())
     {
         layers::CompositorThreadHolder::Start();
 #ifdef MOZ_WIDGET_GONK
         SharedBufferManagerChild::StartUp();
 #endif
-        mozilla::layers::ImageBridgeChild::StartUp();
         gfx::VRManagerChild::StartUpSameProcess();
     }
 }
 
 /* static */ void
 gfxPlatform::ShutdownLayersIPC()
 {
     if (!sLayersIPCIsUp) {
       return;
     }
     sLayersIPCIsUp = false;
 
     if (XRE_IsContentProcess()) {
-
         gfx::VRManagerChild::ShutDown();
         // cf bug 1215265.
         if (gfxPrefs::ChildProcessShutdown()) {
           layers::CompositorBridgeChild::ShutDown();
           layers::ImageBridgeChild::ShutDown();
         }
-
     } else if (XRE_IsParentProcess()) {
-
         gfx::VRManagerChild::ShutDown();
         layers::CompositorBridgeChild::ShutDown();
         layers::ImageBridgeChild::ShutDown();
 
 #ifdef MOZ_WIDGET_GONK
         layers::SharedBufferManagerChild::ShutDown();
 #endif
 
--- a/image/Decoder.cpp
+++ b/image/Decoder.cpp
@@ -1,9 +1,8 @@
-
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Decoder.h"
 
 #include "mozilla/gfx/2D.h"
@@ -101,56 +100,57 @@ Decoder::Init()
   // Implementation-specific initialization.
   nsresult rv = InitInternal();
 
   mInitialized = true;
 
   return rv;
 }
 
-nsresult
+LexerResult
 Decoder::Decode(IResumable* aOnResume /* = nullptr */)
 {
   MOZ_ASSERT(mInitialized, "Should be initialized here");
   MOZ_ASSERT(mIterator, "Should have a SourceBufferIterator");
 
   // If we're already done, don't attempt to keep decoding.
   if (GetDecodeDone()) {
-    return HasError() ? NS_ERROR_FAILURE : NS_OK;
+    return LexerResult(HasError() ? TerminalState::FAILURE
+                                  : TerminalState::SUCCESS);
   }
 
   LexerResult lexerResult(TerminalState::FAILURE);
   {
     PROFILER_LABEL("ImageDecoder", "Decode", js::ProfileEntry::Category::GRAPHICS);
     AutoRecordDecoderTelemetry telemetry(this);
 
     lexerResult =  DoDecode(*mIterator, aOnResume);
   };
 
   if (lexerResult.is<Yield>()) {
-    // We need more data to continue. If @aOnResume was non-null, the
-    // SourceBufferIterator will automatically reschedule us. Otherwise, it's up
-    // to the caller.
-    MOZ_ASSERT(lexerResult.as<Yield>() == Yield::NEED_MORE_DATA);
-    return NS_OK;
+    // We either need more data to continue (in which case either @aOnResume or
+    // the caller will reschedule us to run again later), or the decoder is
+    // yielding to allow the caller access to some intermediate output.
+    return lexerResult;
   }
 
   // We reached a terminal state; we're now done decoding.
   MOZ_ASSERT(lexerResult.is<TerminalState>());
   mReachedTerminalState = true;
 
   // If decoding failed, record that fact.
   if (lexerResult.as<TerminalState>() == TerminalState::FAILURE) {
     PostError();
   }
 
   // Perform final cleanup.
   CompleteDecode();
 
-  return HasError() ? NS_ERROR_FAILURE : NS_OK;
+  return LexerResult(HasError() ? TerminalState::FAILURE
+                                : TerminalState::SUCCESS);
 }
 
 bool
 Decoder::ShouldSyncDecode(size_t aByteLimit)
 {
   MOZ_ASSERT(aByteLimit > 0);
   MOZ_ASSERT(mIterator, "Should have a SourceBufferIterator");
 
@@ -441,22 +441,16 @@ Decoder::PostFrameStop(Opacity aFrameOpa
   mProgress |= FLAG_FRAME_COMPLETE;
 
   // If we're not sending partial invalidations, then we send an invalidation
   // here when the first frame is complete.
   if (!ShouldSendPartialInvalidations() && mFrameCount == 1) {
     mInvalidRect.UnionRect(mInvalidRect,
                            gfx::IntRect(gfx::IntPoint(0, 0), GetSize()));
   }
-
-  // If we are going to keep decoding we should notify now about the first frame being done.
-  if (mImage && mFrameCount == 1 && HasAnimation()) {
-    MOZ_ASSERT(HasProgress());
-    IDecodingTask::NotifyProgress(WrapNotNull(this));
-  }
 }
 
 void
 Decoder::PostInvalidation(const nsIntRect& aRect,
                           const Maybe<nsIntRect>& aRectAtTargetSize
                             /* = Nothing() */)
 {
   // We should be mid-frame
--- a/image/Decoder.h
+++ b/image/Decoder.h
@@ -43,19 +43,24 @@ public:
   nsresult Init();
 
   /**
    * Decodes, reading all data currently available in the SourceBuffer.
    *
    * If more data is needed and @aOnResume is non-null, Decode() will schedule
    * @aOnResume to be called when more data is available.
    *
-   * Any errors are reported by setting the appropriate state on the decoder.
+   * @return a LexerResult which may indicate:
+   *   - the image has been successfully decoded (TerminalState::SUCCESS), or
+   *   - the image has failed to decode (TerminalState::FAILURE), or
+   *   - the decoder is yielding until it gets more data (Yield::NEED_MORE_DATA), or
+   *   - the decoder is yielding to allow the caller to access intermediate
+   *     output (Yield::OUTPUT_AVAILABLE).
    */
-  nsresult Decode(IResumable* aOnResume = nullptr);
+  LexerResult Decode(IResumable* aOnResume = nullptr);
 
   /**
    * Given a maximum number of bytes we're willing to decode, @aByteLimit,
    * returns true if we should attempt to run this decoder synchronously.
    */
   bool ShouldSyncDecode(size_t aByteLimit);
 
   /**
--- a/image/IDecodingTask.cpp
+++ b/image/IDecodingTask.cpp
@@ -14,18 +14,18 @@
 
 namespace mozilla {
 namespace image {
 
 ///////////////////////////////////////////////////////////////////////////////
 // Helpers for sending notifications to the image associated with a decoder.
 ///////////////////////////////////////////////////////////////////////////////
 
-/* static */ void
-IDecodingTask::NotifyProgress(NotNull<Decoder*> aDecoder)
+static void
+NotifyProgress(NotNull<Decoder*> aDecoder)
 {
   MOZ_ASSERT(aDecoder->HasProgress() && !aDecoder->IsMetadataDecode());
 
   // Synchronously notify if we can.
   if (NS_IsMainThread() &&
       !(aDecoder->GetDecoderFlags() & DecoderFlags::ASYNC_NOTIFY)) {
     aDecoder->GetImage()->NotifyProgress(aDecoder->TakeProgress(),
                                          aDecoder->TakeInvalidRect(),
@@ -80,30 +80,41 @@ DecodingTask::DecodingTask(NotNull<Decod
 {
   MOZ_ASSERT(!mDecoder->IsMetadataDecode(),
              "Use MetadataDecodingTask for metadata decodes");
 }
 
 void
 DecodingTask::Run()
 {
-  nsresult rv = mDecoder->Decode(WrapNotNull(this));
+  while (true) {
+    LexerResult result = mDecoder->Decode(WrapNotNull(this));
 
-  if (NS_SUCCEEDED(rv) && !mDecoder->GetDecodeDone()) {
+    if (result.is<TerminalState>()) {
+      NotifyDecodeComplete(mDecoder);
+      return;  // We're done.
+    }
+
+    MOZ_ASSERT(result.is<Yield>());
+
     // Notify for the progress we've made so far.
     if (mDecoder->HasProgress()) {
       NotifyProgress(mDecoder);
     }
 
-    // We don't need to do anything else for this case. The decoder itself will
-    // ensure that we get reenqueued when more data is available.
-    return;
+    if (result == LexerResult(Yield::NEED_MORE_DATA)) {
+      // We can't make any more progress right now. The decoder itself will
+      // ensure that we get reenqueued when more data is available; just return
+      // for now.
+      return;
+    }
+
+    // Right now we don't do anything special for other kinds of yields, so just
+    // keep working.
   }
-
-  NotifyDecodeComplete(mDecoder);
 }
 
 bool
 DecodingTask::ShouldPreferSyncRun() const
 {
   return mDecoder->ShouldSyncDecode(gfxPrefs::ImageMemDecodeBytesAtATime());
 }
 
@@ -117,38 +128,59 @@ MetadataDecodingTask::MetadataDecodingTa
 {
   MOZ_ASSERT(mDecoder->IsMetadataDecode(),
              "Use DecodingTask for non-metadata decodes");
 }
 
 void
 MetadataDecodingTask::Run()
 {
-  nsresult rv = mDecoder->Decode(WrapNotNull(this));
+  LexerResult result = mDecoder->Decode(WrapNotNull(this));
 
-  if (NS_SUCCEEDED(rv) && !mDecoder->GetDecodeDone()) {
-    // It's important that metadata decode results are delivered atomically, so
-    // we'll wait until NotifyDecodeComplete() to report any progress.  We don't
-    // need to do anything else for this case. The decoder itself will ensure
-    // that we get reenqueued when more data is available.
+  if (result.is<TerminalState>()) {
+    NotifyDecodeComplete(mDecoder);
+    return;  // We're done.
+  }
+
+  if (result == LexerResult(Yield::NEED_MORE_DATA)) {
+    // We can't make any more progress right now. We also don't want to report
+    // any progress, because it's important that metadata decode results are
+    // delivered atomically. The decoder itself will ensure that we get
+    // reenqueued when more data is available; just return for now.
     return;
   }
 
-  NotifyDecodeComplete(mDecoder);
+  MOZ_ASSERT_UNREACHABLE("Metadata decode yielded for an unexpected reason");
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////
 // AnonymousDecodingTask implementation.
 ///////////////////////////////////////////////////////////////////////////////
 
 AnonymousDecodingTask::AnonymousDecodingTask(NotNull<Decoder*> aDecoder)
   : mDecoder(aDecoder)
 { }
 
 void
 AnonymousDecodingTask::Run()
 {
-  mDecoder->Decode(WrapNotNull(this));
+  while (true) {
+    LexerResult result = mDecoder->Decode(WrapNotNull(this));
+
+    if (result.is<TerminalState>()) {
+      return;  // We're done.
+    }
+
+    if (result == LexerResult(Yield::NEED_MORE_DATA)) {
+      // We can't make any more progress right now. Let the caller decide how to
+      // handle it.
+      return;
+    }
+
+    // Right now we don't do anything special for other kinds of yields, so just
+    // keep working.
+    MOZ_ASSERT(result.is<Yield>());
+  }
 }
 
 } // namespace image
 } // namespace mozilla
--- a/image/IDecodingTask.h
+++ b/image/IDecodingTask.h
@@ -45,21 +45,16 @@ public:
 
   /// A default implementation of IResumable which resubmits the task to the
   /// DecodePool. Subclasses can override this if they need different behavior.
   void Resume() override;
 
   /// @return a non-null weak pointer to the Decoder associated with this task.
   virtual NotNull<Decoder*> GetDecoder() const = 0;
 
-  // Notify the Image associated with a Decoder of its progress, sending a
-  // runnable to the main thread if necessary.
-  // XXX(seth): This is a hack that will be removed soon.
-  static void NotifyProgress(NotNull<Decoder*> aDecoder);
-
 protected:
   virtual ~IDecodingTask() { }
 };
 
 
 /**
  * An IDecodingTask implementation for full decodes of images.
  */
--- a/image/decoders/nsGIFDecoder2.cpp
+++ b/image/decoders/nsGIFDecoder2.cpp
@@ -470,16 +470,18 @@ nsGIFDecoder2::DoDecode(SourceBufferIter
       case State::SCREEN_DESCRIPTOR:
         return ReadScreenDescriptor(aData);
       case State::GLOBAL_COLOR_TABLE:
         return ReadGlobalColorTable(aData, aLength);
       case State::FINISHED_GLOBAL_COLOR_TABLE:
         return FinishedGlobalColorTable();
       case State::BLOCK_HEADER:
         return ReadBlockHeader(aData);
+      case State::BLOCK_HEADER_AFTER_YIELD:
+        return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
       case State::EXTENSION_HEADER:
         return ReadExtensionHeader(aData);
       case State::GRAPHIC_CONTROL_EXTENSION:
         return ReadGraphicControlExtension(aData);
       case State::APPLICATION_IDENTIFIER:
         return ReadApplicationIdentifier(aData);
       case State::NETSCAPE_EXTENSION_SUB_BLOCK:
         return ReadNetscapeExtensionSubBlock(aData);
@@ -970,17 +972,17 @@ nsGIFDecoder2::ReadImageDataBlock(const 
 
 LexerTransition<nsGIFDecoder2::State>
 nsGIFDecoder2::ReadImageDataSubBlock(const char* aData)
 {
   const uint8_t subBlockLength = aData[0];
   if (subBlockLength == 0) {
     // We hit the block terminator.
     EndImageFrame();
-    return Transition::To(State::BLOCK_HEADER, BLOCK_HEADER_LEN);
+    return Transition::ToAfterYield(State::BLOCK_HEADER_AFTER_YIELD);
   }
 
   if (mGIFStruct.pixels_remaining == 0) {
     // We've already written to the entire image; we should've hit the block
     // terminator at this point. This image is corrupt, but we'll tolerate it.
 
     if (subBlockLength == GIF_TRAILER) {
       // This GIF is missing the block terminator for the final block; we'll put
--- a/image/decoders/nsGIFDecoder2.h
+++ b/image/decoders/nsGIFDecoder2.h
@@ -75,16 +75,17 @@ private:
   {
     FAILURE,
     SUCCESS,
     GIF_HEADER,
     SCREEN_DESCRIPTOR,
     GLOBAL_COLOR_TABLE,
     FINISHED_GLOBAL_COLOR_TABLE,
     BLOCK_HEADER,
+    BLOCK_HEADER_AFTER_YIELD,
     EXTENSION_HEADER,
     GRAPHIC_CONTROL_EXTENSION,
     APPLICATION_IDENTIFIER,
     NETSCAPE_EXTENSION_SUB_BLOCK,
     NETSCAPE_EXTENSION_DATA,
     IMAGE_DESCRIPTOR,
     LOCAL_COLOR_TABLE,
     FINISHED_LOCAL_COLOR_TABLE,
--- a/image/decoders/nsICODecoder.cpp
+++ b/image/decoders/nsICODecoder.cpp
@@ -640,20 +640,24 @@ nsICODecoder::WriteToContainedDecoder(co
   mContainedSourceBuffer->Append(aBuffer, aCount);
 
   bool succeeded = true;
 
   // Write to the contained decoder. If we run out of data, the ICO decoder will
   // get resumed when there's more data available, as usual, so we don't need
   // the contained decoder to get resumed too. To avoid that, we provide an
   // IResumable which just does nothing.
-  if (NS_FAILED(mContainedDecoder->Decode())) {
+  LexerResult result = mContainedDecoder->Decode();
+  if (result == LexerResult(TerminalState::FAILURE)) {
     succeeded = false;
   }
 
+  MOZ_ASSERT(result != LexerResult(Yield::OUTPUT_AVAILABLE),
+             "Unexpected yield");
+
   // Make our state the same as the state of the contained decoder, and
   // propagate errors.
   mProgress |= mContainedDecoder->TakeProgress();
   mInvalidRect.UnionRect(mInvalidRect, mContainedDecoder->TakeInvalidRect());
   if (mContainedDecoder->HasError()) {
     succeeded = false;
   }
 
--- a/image/decoders/nsPNGDecoder.cpp
+++ b/image/decoders/nsPNGDecoder.cpp
@@ -21,16 +21,18 @@
 #include "png.h"
 #include "RasterImage.h"
 #include "SurfacePipeFactory.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla::gfx;
 
+using std::min;
+
 namespace mozilla {
 namespace image {
 
 static LazyLogModule sPNGLog("PNGDecoder");
 static LazyLogModule sPNGDecoderAccountingLog("PNGDecoderAccounting");
 
 // Limit image dimensions (bug #251381, #591822, and #967656)
 #ifndef MOZ_PNG_MAX_DIMENSION
@@ -95,16 +97,18 @@ const uint8_t
 nsPNGDecoder::pngSignatureBytes[] = { 137, 80, 78, 71, 13, 10, 26, 10 };
 
 nsPNGDecoder::nsPNGDecoder(RasterImage* aImage)
  : Decoder(aImage)
  , mLexer(Transition::ToUnbuffered(State::FINISHED_PNG_DATA,
                                    State::PNG_DATA,
                                    SIZE_MAX),
           Transition::TerminateSuccess())
+ , mNextTransition(Transition::ContinueUnbuffered(State::PNG_DATA))
+ , mLastChunkLength(0)
  , mPNG(nullptr)
  , mInfo(nullptr)
  , mCMSLine(nullptr)
  , interlacebuf(nullptr)
  , mInProfile(nullptr)
  , mTransform(nullptr)
  , format(gfx::SurfaceFormat::UNKNOWN)
  , mCMSMode(0)
@@ -172,67 +176,66 @@ nsPNGDecoder::PostHasTransparencyIfNeede
         PostHasTransparency();
       }
       return;
   }
 }
 
 // CreateFrame() is used for both simple and animated images.
 nsresult
-nsPNGDecoder::CreateFrame(SurfaceFormat aFormat,
-                          const IntRect& aFrameRect,
-                          bool aIsInterlaced)
+nsPNGDecoder::CreateFrame(const FrameInfo& aFrameInfo)
 {
   MOZ_ASSERT(HasSize());
   MOZ_ASSERT(!IsMetadataDecode());
 
   // Check if we have transparency, and send notifications if needed.
-  auto transparency = GetTransparencyType(aFormat, aFrameRect);
+  auto transparency = GetTransparencyType(aFrameInfo.mFormat, aFrameInfo.mFrameRect);
   PostHasTransparencyIfNeeded(transparency);
   SurfaceFormat format = transparency == TransparencyType::eNone
                        ? SurfaceFormat::B8G8R8X8
                        : SurfaceFormat::B8G8R8A8;
 
   // Make sure there's no animation or padding if we're downscaling.
   MOZ_ASSERT_IF(mDownscaler, mNumFrames == 0);
   MOZ_ASSERT_IF(mDownscaler, !GetImageMetadata().HasAnimation());
   MOZ_ASSERT_IF(mDownscaler, transparency != TransparencyType::eFrameRect);
 
   IntSize targetSize = mDownscaler ? mDownscaler->TargetSize()
                                    : GetSize();
 
   // If this image is interlaced, we can display better quality intermediate
   // results to the user by post processing them with ADAM7InterpolatingFilter.
-  SurfacePipeFlags pipeFlags = aIsInterlaced
+  SurfacePipeFlags pipeFlags = aFrameInfo.mIsInterlaced
                              ? SurfacePipeFlags::ADAM7_INTERPOLATE
                              : SurfacePipeFlags();
 
   if (mNumFrames == 0) {
     // The first frame may be displayed progressively.
     pipeFlags |= SurfacePipeFlags::PROGRESSIVE_DISPLAY;
   }
 
   Maybe<SurfacePipe> pipe =
-    SurfacePipeFactory::CreateSurfacePipe(this, mNumFrames, GetSize(), targetSize,
-                                          aFrameRect, format, pipeFlags);
+    SurfacePipeFactory::CreateSurfacePipe(this, mNumFrames, GetSize(),
+                                          targetSize, aFrameInfo.mFrameRect,
+                                          format, pipeFlags);
 
   if (!pipe) {
     mPipe = SurfacePipe();
     return NS_ERROR_FAILURE;
   }
 
   mPipe = Move(*pipe);
 
-  mFrameRect = aFrameRect;
+  mFrameRect = aFrameInfo.mFrameRect;
   mPass = 0;
 
   MOZ_LOG(sPNGDecoderAccountingLog, LogLevel::Debug,
          ("PNGDecoderAccounting: nsPNGDecoder::CreateFrame -- created "
           "image frame with %dx%d pixels for decoder %p",
-          aFrameRect.width, aFrameRect.height, this));
+          mFrameRect.width, mFrameRect.height, this));
 
 #ifdef PNG_APNG_SUPPORTED
   if (png_get_valid(mPNG, mInfo, PNG_INFO_acTL)) {
     mAnimInfo = AnimFrameInfo(mPNG, mInfo);
 
     if (mAnimInfo.mDispose == DisposalMethod::CLEAR) {
       // We may have to display the background under this image during
       // animation playback, so we regard it as transparent.
@@ -363,36 +366,47 @@ nsPNGDecoder::DoDecode(SourceBufferItera
     }
     MOZ_CRASH("Unknown State");
   });
 }
 
 LexerTransition<nsPNGDecoder::State>
 nsPNGDecoder::ReadPNGData(const char* aData, size_t aLength)
 {
+  // If we were waiting until after returning from a yield to call
+  // CreateFrame(), call it now.
+  if (mNextFrameInfo) {
+    if (NS_FAILED(CreateFrame(*mNextFrameInfo))) {
+      return Transition::TerminateFailure();
+    }
+
+    MOZ_ASSERT(mImageData, "Should have a buffer now");
+    mNextFrameInfo = Nothing();
+  }
+
   // libpng uses setjmp/longjmp for error handling.
   if (setjmp(png_jmpbuf(mPNG))) {
     return Transition::TerminateFailure();
   }
 
   // Pass the data off to libpng.
+  mLastChunkLength = aLength;
+  mNextTransition = Transition::ContinueUnbuffered(State::PNG_DATA);
   png_process_data(mPNG, mInfo,
                    reinterpret_cast<unsigned char*>(const_cast<char*>((aData))),
                    aLength);
 
-  if (HasError()) {
-    return Transition::TerminateFailure();
-  }
+  // Make sure that we've reached a terminal state if decoding is done.
+  MOZ_ASSERT_IF(GetDecodeDone(), mNextTransition.NextStateIsTerminal());
+  MOZ_ASSERT_IF(HasError(), mNextTransition.NextStateIsTerminal());
 
-  if (GetDecodeDone()) {
-    return Transition::TerminateSuccess();
-  }
-
-  // Keep reading data.
-  return Transition::ContinueUnbuffered(State::PNG_DATA);
+  // Continue with whatever transition the callback code requested. We
+  // initialized this to Transition::ContinueUnbuffered(State::PNG_DATA) above,
+  // so by default we just continue the unbuffered read.
+  return mNextTransition;
 }
 
 LexerTransition<nsPNGDecoder::State>
 nsPNGDecoder::FinishedPNGData()
 {
   // Since we set up an unbuffered read for SIZE_MAX bytes, if we actually read
   // all that data something is really wrong.
   MOZ_ASSERT_UNREACHABLE("Read the entire address space?");
@@ -678,31 +692,32 @@ nsPNGDecoder::info_callback(png_structp 
     // call PostHasTransparency in the metadata decode if we need to. So it's okay
     // to pass IntRect(0, 0, width, height) here for animated images; they will
     // call with the proper first frame rect in the full decode.
     auto transparency = decoder->GetTransparencyType(decoder->format, frameRect);
     decoder->PostHasTransparencyIfNeeded(transparency);
 
     // We have the metadata we're looking for, so stop here, before we allocate
     // buffers below.
-    png_process_data_pause(png_ptr, /* save = */ false);
-    return;
+    return decoder->DoTerminate(png_ptr, TerminalState::SUCCESS);
   }
 
 #ifdef PNG_APNG_SUPPORTED
   if (isAnimated) {
     png_set_progressive_frame_fn(png_ptr, nsPNGDecoder::frame_info_callback,
                                  nullptr);
   }
 
   if (png_get_first_frame_is_hidden(png_ptr, info_ptr)) {
     decoder->mFrameIsHidden = true;
   } else {
 #endif
-    nsresult rv = decoder->CreateFrame(decoder->format, frameRect, isInterlaced);
+    nsresult rv = decoder->CreateFrame(FrameInfo{ decoder->format,
+                                                  frameRect,
+                                                  isInterlaced });
     if (NS_FAILED(rv)) {
       png_longjmp(decoder->mPNG, 5); // NS_ERROR_OUT_OF_MEMORY
     }
     MOZ_ASSERT(decoder->mImageData, "Should have a buffer now");
 #ifdef PNG_APNG_SUPPORTED
   }
 #endif
 
@@ -894,50 +909,83 @@ nsPNGDecoder::WriteRow(uint8_t* aRow)
       png_longjmp(mPNG, 1);  // Abort the decode.
   }
 
   MOZ_ASSERT(WriteState(result) != WriteState::FAILURE);
 
   PostInvalidationIfNeeded();
 }
 
+void
+nsPNGDecoder::DoTerminate(png_structp aPNGStruct, TerminalState aState)
+{
+  // Stop processing data. Note that we intentionally ignore the return value of
+  // png_process_data_pause(), which tells us how many bytes of the data that
+  // was passed to png_process_data() have not been consumed yet, because now
+  // that we've reached a terminal state, we won't do any more decoding or call
+  // back into libpng anymore.
+  png_process_data_pause(aPNGStruct, /* save = */ false);
+
+  mNextTransition = aState == TerminalState::SUCCESS
+                  ? Transition::TerminateSuccess()
+                  : Transition::TerminateFailure();
+}
+
+void
+nsPNGDecoder::DoYield(png_structp aPNGStruct)
+{
+  // Pause data processing. png_process_data_pause() returns how many bytes of
+  // the data that was passed to png_process_data() have not been consumed yet.
+  // We use this information to tell StreamingLexer where to place us in the
+  // input stream when we come back from the yield.
+  png_size_t pendingBytes = png_process_data_pause(aPNGStruct, /* save = */ false);
+
+  MOZ_ASSERT(pendingBytes < mLastChunkLength);
+  size_t consumedBytes = mLastChunkLength - min(pendingBytes, mLastChunkLength);
+
+  mNextTransition =
+    Transition::ContinueUnbufferedAfterYield(State::PNG_DATA, consumedBytes);
+}
+
 #ifdef PNG_APNG_SUPPORTED
 // got the header of a new frame that's coming
 void
 nsPNGDecoder::frame_info_callback(png_structp png_ptr, png_uint_32 frame_num)
 {
   nsPNGDecoder* decoder =
                static_cast<nsPNGDecoder*>(png_get_progressive_ptr(png_ptr));
 
   // old frame is done
   decoder->EndImageFrame();
 
   if (!decoder->mFrameIsHidden && decoder->IsFirstFrameDecode()) {
     // We're about to get a second non-hidden frame, but we only want the first.
     // Stop decoding now. (And avoid allocating the unnecessary buffers below.)
     decoder->PostDecodeDone();
-    png_process_data_pause(png_ptr, /* save = */ false);
-    return;
+    return decoder->DoTerminate(png_ptr, TerminalState::SUCCESS);
   }
 
   // Only the first frame can be hidden, so unhide unconditionally here.
   decoder->mFrameIsHidden = false;
 
+  // Save the information necessary to create the frame; we'll actually create
+  // it when we return from the yield.
   const IntRect frameRect(png_get_next_frame_x_offset(png_ptr, decoder->mInfo),
                           png_get_next_frame_y_offset(png_ptr, decoder->mInfo),
                           png_get_next_frame_width(png_ptr, decoder->mInfo),
                           png_get_next_frame_height(png_ptr, decoder->mInfo));
 
   const bool isInterlaced = bool(decoder->interlacebuf);
 
-  nsresult rv = decoder->CreateFrame(decoder->format, frameRect, isInterlaced);
-  if (NS_FAILED(rv)) {
-    png_longjmp(decoder->mPNG, 5); // NS_ERROR_OUT_OF_MEMORY
-  }
-  MOZ_ASSERT(decoder->mImageData, "Should have a buffer now");
+  decoder->mNextFrameInfo = Some(FrameInfo{ decoder->format,
+                                            frameRect,
+                                            isInterlaced });
+
+  // Yield to the caller to notify them that the previous frame is now complete.
+  return decoder->DoYield(png_ptr);
 }
 #endif
 
 void
 nsPNGDecoder::end_callback(png_structp png_ptr, png_infop info_ptr)
 {
   /* libpng comments:
    *
@@ -960,19 +1008,20 @@ nsPNGDecoder::end_callback(png_structp p
   int32_t loop_count = 0;
 #ifdef PNG_APNG_SUPPORTED
   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL)) {
     int32_t num_plays = png_get_num_plays(png_ptr, info_ptr);
     loop_count = num_plays - 1;
   }
 #endif
 
-  // Send final notifications
+  // Send final notifications.
   decoder->EndImageFrame();
   decoder->PostDecodeDone(loop_count);
+  return decoder->DoTerminate(png_ptr, TerminalState::SUCCESS);
 }
 
 
 void
 nsPNGDecoder::error_callback(png_structp png_ptr, png_const_charp error_msg)
 {
   MOZ_LOG(sPNGLog, LogLevel::Error, ("libpng error: %s\n", error_msg));
   png_longjmp(png_ptr, 1);
--- a/image/decoders/nsPNGDecoder.h
+++ b/image/decoders/nsPNGDecoder.h
@@ -31,19 +31,25 @@ public:
   bool IsValidICO() const;
 
 private:
   friend class DecoderFactory;
 
   // Decoders should only be instantiated via DecoderFactory.
   explicit nsPNGDecoder(RasterImage* aImage);
 
-  nsresult CreateFrame(gfx::SurfaceFormat aFormat,
-                       const gfx::IntRect& aFrameRect,
-                       bool aIsInterlaced);
+  /// The information necessary to create a frame.
+  struct FrameInfo
+  {
+    gfx::SurfaceFormat mFormat;
+    gfx::IntRect mFrameRect;
+    bool mIsInterlaced;
+  };
+
+  nsresult CreateFrame(const FrameInfo& aFrameInfo);
   void EndImageFrame();
 
   enum class TransparencyType
   {
     eNone,
     eAlpha,
     eFrameRect
   };
@@ -51,27 +57,46 @@ private:
   TransparencyType GetTransparencyType(gfx::SurfaceFormat aFormat,
                                        const gfx::IntRect& aFrameRect);
   void PostHasTransparencyIfNeeded(TransparencyType aTransparencyType);
 
   void PostInvalidationIfNeeded();
 
   void WriteRow(uint8_t* aRow);
 
+  // Convenience methods to make interacting with StreamingLexer from inside
+  // a libpng callback easier.
+  void DoTerminate(png_structp aPNGStruct, TerminalState aState);
+  void DoYield(png_structp aPNGStruct);
+
   enum class State
   {
     PNG_DATA,
     FINISHED_PNG_DATA
   };
 
   LexerTransition<State> ReadPNGData(const char* aData, size_t aLength);
   LexerTransition<State> FinishedPNGData();
 
   StreamingLexer<State> mLexer;
 
+  // The next lexer state transition. We need to store it here because we can't
+  // directly return arbitrary values from libpng callbacks.
+  LexerTransition<State> mNextTransition;
+
+  // We yield to the caller every time we finish decoding a frame. When this
+  // happens, we need to allocate the next frame after returning from the yield.
+  // |mNextFrameInfo| is used to store the information needed to allocate the
+  // next frame.
+  Maybe<FrameInfo> mNextFrameInfo;
+
+  // The length of the last chunk of data passed to ReadPNGData(). We use this
+  // to arrange to arrive back at the correct spot in the data after yielding.
+  size_t mLastChunkLength;
+
 public:
   png_structp mPNG;
   png_infop mInfo;
   nsIntRect mFrameRect;
   uint8_t* mCMSLine;
   uint8_t* interlacebuf;
   qcms_profile* mInProfile;
   qcms_transform* mTransform;
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -517,16 +517,20 @@ public:
     }
 
     ~Endpoint() {
         if (mValid) {
             CloseDescriptor(mTransport);
         }
     }
 
+    ProcessId OtherPid() const {
+        return mOtherPid;
+    }
+
     // This method binds aActor to this endpoint. After this call, the actor can
     // be used to send and receive messages. The endpoint becomes invalid. The
     // |aProcessActor| parameter is used to associate protocols with content
     // processes. In practice, this parameter should always be a ContentParent
     // or ContentChild, depending on which process you are in. It is used to
     // find all the channels that need to be "frozen" or "revived" when creating
     // or cloning the Nuwa process.
     bool Bind(PFooSide* aActor, IToplevelProtocol* aProcessActor)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1287416.js
@@ -0,0 +1,3 @@
+for (var i = 0; i < 1; i++) {
+    "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".split("x");
+};
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -1487,21 +1487,24 @@ IonBuilder::inlineConstantStringSplitStr
     }
 
     JSValueType unboxedType = GetBoxedOrUnboxedType(templateObject);
 
     // Store all values, no need to initialize the length after each as
     // jsop_initelem_array is doing because we do not expect to bailout
     // because the memory is supposed to be allocated by now.
     for (uint32_t i = 0; i < initLength; i++) {
-       MConstant* value = arrayValues[i];
-       current->add(value);
-
-       if (!initializeArrayElement(array, i, value, unboxedType, /* addResumePoint = */ false))
-           return InliningStatus_Error;
+        if (!alloc().ensureBallast())
+            return InliningStatus_Error;
+
+        MConstant* value = arrayValues[i];
+        current->add(value);
+
+        if (!initializeArrayElement(array, i, value, unboxedType, /* addResumePoint = */ false))
+            return InliningStatus_Error;
     }
 
     MInstruction* setLength = setInitializedLength(array, unboxedType, initLength);
     if (!resumeAfter(setLength))
         return InliningStatus_Error;
 
     return InliningStatus_Inlined;
 }
--- a/js/xpconnect/src/xpc.msg
+++ b/js/xpconnect/src/xpc.msg
@@ -134,17 +134,17 @@ XPC_MSG_DEF(NS_BINDING_ABORTED          
 XPC_MSG_DEF(NS_BINDING_REDIRECTED                   , "The async request has been redirected to a different async request")
 XPC_MSG_DEF(NS_BINDING_RETARGETED                   , "The async request has been retargeted to a different handler")
 XPC_MSG_DEF(NS_ERROR_MALFORMED_URI                  , "The URI is malformed")
 XPC_MSG_DEF(NS_ERROR_UNKNOWN_PROTOCOL               , "The URI scheme corresponds to an unknown protocol handler")
 XPC_MSG_DEF(NS_ERROR_NO_CONTENT                     , "Channel opened successfully but no data will be returned")
 XPC_MSG_DEF(NS_ERROR_IN_PROGRESS                    , "The requested action could not be completed while the object is busy")
 XPC_MSG_DEF(NS_ERROR_ALREADY_OPENED                 , "Channel is already open")
 XPC_MSG_DEF(NS_ERROR_INVALID_CONTENT_ENCODING       , "The content encoding of the source document is incorrect")
-XPC_MSG_DEF(NS_ERROR_CORRUPTED_CONTENT              , "Corrupted content was received from server")
+XPC_MSG_DEF(NS_ERROR_CORRUPTED_CONTENT              , "Corrupted content received from server (potentially MIME type mismatch because of 'X-Content-Type-Options: nosniff')")
 XPC_MSG_DEF(NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY, "Couldn't extract first component from potentially corrupted header field")
 XPC_MSG_DEF(NS_ERROR_ALREADY_CONNECTED              , "The connection is already established")
 XPC_MSG_DEF(NS_ERROR_NOT_CONNECTED                  , "The connection does not exist")
 XPC_MSG_DEF(NS_ERROR_CONNECTION_REFUSED             , "The connection was refused")
 XPC_MSG_DEF(NS_ERROR_PROXY_CONNECTION_REFUSED       , "The connection to the proxy server was refused")
 XPC_MSG_DEF(NS_ERROR_NET_TIMEOUT                    , "The connection has timed out")
 XPC_MSG_DEF(NS_ERROR_OFFLINE                        , "The requested action could not be completed in the offline state")
 XPC_MSG_DEF(NS_ERROR_PORT_ACCESS_NOT_ALLOWED        , "Establishing a connection to an unsafe or otherwise banned port was prohibited")
--- a/netwerk/protocol/http/nsHttpAtomList.h
+++ b/netwerk/protocol/http/nsHttpAtomList.h
@@ -85,12 +85,13 @@ HTTP_ATOM(Trailer,                   "Tr
 HTTP_ATOM(Transfer_Encoding,         "Transfer-Encoding")
 HTTP_ATOM(URI,                       "URI")
 HTTP_ATOM(Upgrade,                   "Upgrade")
 HTTP_ATOM(User_Agent,                "User-Agent")
 HTTP_ATOM(Vary,                      "Vary")
 HTTP_ATOM(Version,                   "Version")
 HTTP_ATOM(WWW_Authenticate,          "WWW-Authenticate")
 HTTP_ATOM(Warning,                   "Warning")
+HTTP_ATOM(X_Content_Type_Options,    "X-Content-Type-Options")
 HTTP_ATOM(X_Firefox_Spdy,            "X-Firefox-Spdy")
 HTTP_ATOM(X_Firefox_Spdy_Proxy,      "X-Firefox-Spdy-Proxy")
 
 // methods are case sensitive and do not use atom table
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -79,23 +79,25 @@
 #include "nsISiteSecurityService.h"
 #include "nsString.h"
 #include "nsCRT.h"
 #include "CacheObserver.h"
 #include "mozilla/dom/Performance.h"
 #include "mozilla/Telemetry.h"
 #include "AlternateServices.h"
 #include "InterceptedChannel.h"
+#include "imgLoader.h"
 #include "nsIHttpPushListener.h"
 #include "nsIX509Cert.h"
 #include "ScopedNSSTypes.h"
 #include "nsNullPrincipal.h"
 #include "nsIPackagedAppService.h"
 #include "nsIDeprecationWarner.h"
 #include "nsIDocument.h"
+#include "nsIDOMDocument.h"
 #include "nsICompressConvStats.h"
 #include "nsCORSListenerProxy.h"
 #include "nsISocketProvider.h"
 #include "mozilla/net/Predictor.h"
 #include "CacheControlParser.h"
 
 namespace mozilla { namespace net {
 
@@ -929,26 +931,129 @@ CallTypeSniffers(void *aClosure, const u
 
   nsAutoCString newType;
   NS_SniffContent(NS_CONTENT_SNIFFER_CATEGORY, chan, aData, aCount, newType);
   if (!newType.IsEmpty()) {
     chan->SetContentType(newType);
   }
 }
 
+// Check and potentially enforce X-Content-Type-Options: nosniff
+nsresult
+ProcessXCTO(nsHttpResponseHead* aResponseHead, nsILoadInfo* aLoadInfo)
+{
+    if (!aResponseHead || !aLoadInfo) {
+        // if there is no response head or no loadInfo, then there is nothing to do
+        return NS_OK;
+    }
+
+    // 1) Query the XCTO header and check if 'nosniff' is the first value.
+    nsAutoCString contentTypeOptionsHeader;
+    aResponseHead->GetHeader(nsHttp::X_Content_Type_Options, contentTypeOptionsHeader);
+    if (contentTypeOptionsHeader.IsEmpty()) {
+        // if there is no XCTO header, then there is nothing to do.
+        return NS_OK;
+    }
+    // XCTO header might contain multiple values which are comma separated, so:
+    // a) let's skip all subsequent values
+    //     e.g. "   NoSniFF   , foo " will be "   NoSniFF   "
+    int32_t idx = contentTypeOptionsHeader.Find(",");
+    if (idx > 0) {
+      contentTypeOptionsHeader = Substring(contentTypeOptionsHeader, 0, idx);
+    }
+    // b) let's trim all surrounding whitespace
+    //    e.g. "   NoSniFF   " -> "NoSniFF"
+    contentTypeOptionsHeader.StripWhitespace();
+    // c) let's compare the header (ignoring case)
+    //    e.g. "NoSniFF" -> "nosniff"
+    //    if it's not 'nosniff' then there is nothing to do here
+    if (!contentTypeOptionsHeader.EqualsIgnoreCase("nosniff")) {
+        // since we are getting here, the XCTO header was sent;
+        // a non matching value most likely means a mistake happenend;
+        // e.g. sending 'nosnif' instead of 'nosniff', let's log a warning.
+        NS_ConvertUTF8toUTF16 char16_header(contentTypeOptionsHeader);
+        const char16_t* params[] = { char16_header.get() };
+        nsCOMPtr<nsIDocument> doc;
+        nsCOMPtr<nsIDOMDocument> domDoc;
+        aLoadInfo->GetLoadingDocument(getter_AddRefs(domDoc));
+        if (domDoc) {
+          doc = do_QueryInterface(domDoc);
+        }
+        nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
+                                        NS_LITERAL_CSTRING("XCTO"),
+                                        doc,
+                                        nsContentUtils::eSECURITY_PROPERTIES,
+                                        "XCTOHeaderValueMissing",
+                                        params, ArrayLength(params));
+        return NS_OK;
+    }
+
+    // 2) Query the content type from the channel
+    nsAutoCString contentType;
+    aResponseHead->ContentType(contentType);
+
+    // 3) Compare the expected MIME type with the actual type
+    if (aLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_STYLESHEET) {
+        if (contentType.EqualsLiteral(TEXT_CSS)) {
+            return NS_OK;
+        }
+        return NS_ERROR_CORRUPTED_CONTENT;
+    }
+
+    if (aLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_IMAGE) {
+        if (imgLoader::SupportImageWithMimeType(contentType.get(),
+                                                AcceptedMimeTypes::IMAGES_AND_DOCUMENTS)) {
+            return NS_OK;
+        }
+        return NS_ERROR_CORRUPTED_CONTENT;
+    }
+
+    if (aLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_SCRIPT) {
+        if (nsContentUtils::IsScriptType(contentType)) {
+            return NS_OK;
+        }
+        return NS_ERROR_CORRUPTED_CONTENT;
+    }
+    return NS_OK;
+}
+
 nsresult
 nsHttpChannel::CallOnStartRequest()
 {
     MOZ_RELEASE_ASSERT(!(mRequireCORSPreflight &&
                          mInterceptCache != INTERCEPTED) ||
                        mIsCorsPreflightDone,
                        "CORS preflight must have been finished by the time we "
                        "call OnStartRequest");
 
-    nsresult rv;
+    nsresult rv = ProcessXCTO(mResponseHead, mLoadInfo);
+    if (NS_FAILED(rv)) {
+        LOG(("XCTO: nosniff verification failed.\n"));
+        // log a warning to the console that loading the resrouce was
+        // blocked due to MIME type mismatch.
+        nsAutoCString spec;
+        mURI->GetSpec(spec);
+        NS_ConvertUTF8toUTF16 specUTF16(spec);
+        const char16_t* params[] = { specUTF16.get() };
+        nsCOMPtr<nsIDocument> doc;
+        if (mLoadInfo) {
+            nsCOMPtr<nsIDOMDocument> domDoc;
+            mLoadInfo->GetLoadingDocument(getter_AddRefs(domDoc));
+            if (domDoc) {
+                doc = do_QueryInterface(domDoc);
+            }
+        }
+        nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
+                                        NS_LITERAL_CSTRING("XCTO"),
+                                        doc,
+                                        nsContentUtils::eSECURITY_PROPERTIES,
+                                        "MimeTypeMismatch",
+                                        params, ArrayLength(params));
+        return rv;
+    }
 
     if (mOnStartRequestCalled) {
         // This can only happen when a range request loading rest of the data
         // after interrupted concurrent cache read asynchronously failed, e.g.
         // the response range bytes are not as expected or this channel has
         // been externally canceled.
         //
         // It's legal to bypass CallOnStartRequest for that case since we've
deleted file mode 100644
--- a/security/nss/.travis.yml
+++ /dev/null
@@ -1,75 +0,0 @@
-sudo: required
-dist: trusty
-
-addons:
-  apt:
-    sources:
-    # add PPAs with more up-to-date toolchains
-    - ubuntu-toolchain-r-test
-    - llvm-toolchain-precise-3.8
-    packages:
-    # install toolchains
-    - gcc-5
-    - g++-5
-    - clang-3.8
-    # install additional tools
-    - clang-format-3.8
-
-matrix:
-  include:
-    - os: osx
-      compiler: clang-3.8
-      env:
-        - CC=clang-3.8
-        - CCC=clang++-3.8
-    - os: osx
-      compiler: clang-3.8
-      env:
-        - CC=clang-3.8
-        - CCC=clang++-3.8
-        - BUILD_OPT=1
-    - os: linux
-      compiler: gcc
-      env:
-        - CC=gcc-5
-        - CCC=g++-5
-    - os: linux
-      compiler: gcc
-      env:
-        - CC=gcc-5
-        - CCC=g++-5
-        - BUILD_OPT=1
-    - os: linux
-      compiler: gcc
-      env:
-        - CC=gcc-5
-        - CCC=g++-5
-        - USE_ASAN=1
-    - os: linux
-      env: CLANG_FORMAT=1
-  allow_failures:
-    - env: CLANG_FORMAT=1
-
-env:
-  global:
-    - USE_64=1
-    - NSS_ENABLE_TLS_1_3=1
-
-install:
-  - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update; brew install llvm38; fi
-
-before_script:
-  - hg clone https://hg.mozilla.org/projects/nspr ../nspr
-
-script:
-  - if [ -n "$CLANG_FORMAT" ]; then automation/travis/validate-formatting.sh lib/ssl; exit $?; fi
-  - make nss_build_all
-  - cd tests; NSS_TESTS="ssl_gtests gtests" NSS_CYCLES=standard ./all.sh
-
-notifications:
-  irc:
-    channels:
-      - "irc.mozilla.org:6697/#nssbot"
-    nick: travisci
-    on_success: change
-    on_failure: always
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-NSS_3.26_BETA2
+NSS_3_26_RC0
--- a/security/nss/automation/taskcluster/graph/windows/_build_base.yml
+++ b/security/nss/automation/taskcluster/graph/windows/_build_base.yml
@@ -1,33 +1,33 @@
 ---
 reruns: 2
 
 task:
   created: !from_now 0
   deadline: !from_now 24
   provisionerId: aws-provisioner-v1
-  workerType: ttaubert-win2012r2
+  workerType: nss-win2012r2
   schedulerId: task-graph-scheduler
 
   metadata:
     owner: !env TC_OWNER
     source: !env TC_SOURCE
 
   payload:
     maxRunTime: 3600
 
     artifacts:
       - type: directory
         path: "public\\build"
         expires: !from_now 24
 
     command:
-      - "time /t && hg clone -r %NSS_HEAD_REVISION% %NSS_HEAD_REPOSITORY% nss"
-      - "time /t && bash -c nss/automation/taskcluster/windows/build.sh"
+      - "hg clone -r %NSS_HEAD_REVISION% %NSS_HEAD_REPOSITORY% nss"
+      - "bash -c nss/automation/taskcluster/windows/build.sh"
 
     env:
       PATH: "c:\\mozilla-build\\python;c:\\mozilla-build\\msys\\local\\bin;c:\\mozilla-build\\7zip;c:\\mozilla-build\\info-zip;c:\\mozilla-build\\python\\Scripts;c:\\mozilla-build\\yasm;c:\\mozilla-build\\msys\\bin;c:\\Windows\\system32;c:\\mozilla-build\\upx391w;c:\\mozilla-build\\moztools-x64\\bin;c:\\mozilla-build\\wget"
       NSS_HEAD_REPOSITORY: !env NSS_HEAD_REPOSITORY
       NSS_HEAD_REVISION: !env NSS_HEAD_REVISION
       DOMSUF: localdomain
       HOST: localhost
 
--- a/security/nss/automation/taskcluster/graph/windows/_test_base.yml
+++ b/security/nss/automation/taskcluster/graph/windows/_test_base.yml
@@ -1,20 +1,20 @@
 ---
 reruns: 2
 
 task:
   created: !from_now 0
   deadline: !from_now 24
   provisionerId: aws-provisioner-v1
-  workerType: ttaubert-win2012r2
+  workerType: nss-win2012r2
   schedulerId: task-graph-scheduler
 
   metadata:
     owner: !env TC_OWNER
     source: !env TC_SOURCE
 
   payload:
     maxRunTime: 3600
 
     command:
-      - "time /t && hg clone -r %NSS_HEAD_REVISION% %NSS_HEAD_REPOSITORY% nss"
-      - "time /t && bash -c nss/automation/taskcluster/windows/run_tests.sh"
+      - "hg clone -r %NSS_HEAD_REVISION% %NSS_HEAD_REPOSITORY% nss"
+      - "bash -c nss/automation/taskcluster/windows/run_tests.sh"
--- a/security/nss/automation/taskcluster/scripts/run_scan_build.sh
+++ b/security/nss/automation/taskcluster/scripts/run_scan_build.sh
@@ -17,26 +17,35 @@ if [ ! -d "nspr" ]; then
     hg clone https://hg.mozilla.org/projects/nspr
 fi
 
 # Build.
 cd nss && make nss_build_all
 
 # we run scan-build on these folders
 declare -a scan=("lib/ssl" "lib/freebl")
+# corresponds to the number of errors that are expected in the |scan| folder
+declare -a ignore=(1 0)
 
 for i in "${scan[@]}"
 do
    echo "cleaning $i ..."
    find "$i" -name "*.OBJ" | xargs rm -fr
 done
 
 # run scan-build
 scan-build -o /home/worker/artifacts/ make nss_build_all && cd ..
 
 # print errors we found
 set +v +x
-for i in "${scan[@]}"
+STATUS=0
+for i in "${!scan[@]}"
 do
-   n=$(grep -Rn "${i#*/}/" /home/worker/artifacts/*/index.html | wc -l)
-   # TODO: print FAILED/PASSED and set exit code for folders we expect to be clean
-   echo "$(date '+%T') WARNING - TEST-UNEXPECTED-FAIL: $i contains $n scan-build errors"
+   n=$(grep -Rn "${scan[i]}" /home/worker/artifacts/*/report-*.html | wc -l)
+   if [ $n -ne ${ignore[$i]} ]; then
+     STATUS=1
+     echo "$(date '+%T') WARNING - TEST-UNEXPECTED-FAIL: ${scan[$i]} contains $n scan-build errors"
+   elif [ $n -ne 0 ]; then
+     echo "$(date '+%T') WARNING - TEST-UNEXPECTED-FAIL: ${scan[$i]} contains $n scan-build errors (nonfatal!)"
+   fi
+
 done
+exit $STATUS
deleted file mode 100644
--- a/security/nss/circle.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-checkout:
-    post:
-        - cd ..; hg clone https://hg.mozilla.org/projects/nspr
-
-test:
-    override:
-        - make nss_build_all
-        - cd tests; NSS_TESTS="ssl_gtests gtests" NSS_CYCLES=standard ./all.sh
-        - BUILD_OPT=1 make nss_build_all
-        - cd tests; BUILD_OPT=1 NSS_TESTS="ssl_gtests gtests" NSS_CYCLES=standard ./all.sh
-
-machine:
-    environment:
-        { USE_64: 1,
-          NSS_ENABLE_TLS_1_3: 1,
-        }
-    hosts:
-
-
new file mode 100644
--- /dev/null
+++ b/security/nss/cmd/ectest/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY).   #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL)          #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL)       #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL).      #
+#######################################################################
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL)                              #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL)                           #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL).                              #
+#######################################################################
+
+
+include ../platrules.mk
+
new file mode 100644
--- /dev/null
+++ b/security/nss/cmd/ectest/ectest.c
@@ -0,0 +1,184 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "blapi.h"
+#include "ec.h"
+#include "ecl-curve.h"
+#include "nss.h"
+#include "secutil.h"
+#include "secitem.h"
+#include "nspr.h"
+#include <stdio.h>
+
+typedef struct {
+    ECCurveName curve;
+    char *privhex;
+    char *our_pubhex;
+    char *their_pubhex;
+    char *common_key;
+    char *name;
+} ECDH_KAT;
+
+#include "testvecs.h"
+
+/*
+ * Initializes a SECItem from a hexadecimal string
+ *
+ */
+static SECItem *
+hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
+{
+    int i = 0;
+    int byteval = 0;
+    int tmp = PORT_Strlen(str);
+
+    PORT_Assert(arena);
+    PORT_Assert(item);
+
+    if ((tmp % 2) != 0) {
+        return NULL;
+    }
+
+    item = SECITEM_AllocItem(arena, item, tmp / 2);
+    if (item == NULL) {
+        return NULL;
+    }
+
+    while (str[i]) {
+        if ((str[i] >= '0') && (str[i] <= '9')) {
+            tmp = str[i] - '0';
+        } else if ((str[i] >= 'a') && (str[i] <= 'f')) {
+            tmp = str[i] - 'a' + 10;
+        } else if ((str[i] >= 'A') && (str[i] <= 'F')) {
+            tmp = str[i] - 'A' + 10;
+        } else {
+            /* item is in arena and gets freed by the caller */
+            return NULL;
+        }
+
+        byteval = byteval * 16 + tmp;
+        if ((i % 2) != 0) {
+            item->data[i / 2] = byteval;
+            byteval = 0;
+        }
+        i++;
+    }
+
+    return item;
+}
+
+SECStatus
+ectest_ecdh_kat(ECDH_KAT *kat)
+{
+    ECCurveName curve = kat->curve;
+    ECParams ecParams = { 0 };
+    ECPrivateKey *ecPriv = NULL;
+    SECItem theirKey = { siBuffer, NULL, 0 };
+    SECStatus rv = SECFailure;
+    PLArenaPool *arena;
+    SECItem seed = { siBuffer, NULL, 0 };
+    SECItem answer = { siBuffer, NULL, 0 };
+    SECItem answer2 = { siBuffer, NULL, 0 };
+    SECItem derived = { siBuffer, NULL, 0 };
+    char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
+    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+    if (!arena) {
+        return SECFailure;
+    }
+
+    if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) {
+        PORT_FreeArena(arena, PR_FALSE);
+        return SECFailure;
+    }
+
+    ecParams.name = curve;
+    ecParams.type = ec_params_named;
+    ecParams.curveOID.data = NULL;
+    ecParams.curveOID.len = 0;
+    ecParams.curve.seed.data = NULL;
+    ecParams.curve.seed.len = 0;
+    ecParams.DEREncoding.data = NULL;
+    ecParams.DEREncoding.len = 0;
+
+    ecParams.fieldID.size = ecCurve_map[curve]->size;
+    ecParams.fieldID.type = ec_field_GFp;
+    hexString2SECItem(arena, &ecParams.fieldID.u.prime, ecCurve_map[curve]->irr);
+    hexString2SECItem(arena, &ecParams.curve.a, ecCurve_map[curve]->curvea);
+    hexString2SECItem(arena, &ecParams.curve.b, ecCurve_map[curve]->curveb);
+    genenc[0] = '0';
+    genenc[1] = '4';
+    genenc[2] = '\0';
+    strcat(genenc, ecCurve_map[curve]->genx);
+    strcat(genenc, ecCurve_map[curve]->geny);
+    hexString2SECItem(arena, &ecParams.base, genenc);
+    hexString2SECItem(arena, &ecParams.order, ecCurve_map[curve]->order);
+    ecParams.cofactor = ecCurve_map[curve]->cofactor;
+
+    hexString2SECItem(arena, &answer, kat->our_pubhex);
+    hexString2SECItem(arena, &seed, kat->privhex);
+    rv = EC_NewKeyFromSeed(&ecParams, &ecPriv, seed.data, seed.len);
+    if (rv != SECSuccess) {
+        rv = SECFailure;
+        goto cleanup;
+    }
+    if (SECITEM_CompareItem(&answer, &ecPriv->publicValue) != SECEqual) {
+        rv = SECFailure;
+        goto cleanup;
+    }
+
+    hexString2SECItem(arena, &theirKey, kat->their_pubhex);
+    hexString2SECItem(arena, &answer2, kat->common_key);
+    rv = ECDH_Derive(&theirKey, &ecParams, &ecPriv->privateValue, PR_TRUE, &derived);
+    if (rv != SECSuccess) {
+        rv = SECFailure;
+        goto cleanup;
+    }
+
+    if (SECITEM_CompareItem(&answer2, &derived) != SECEqual) {
+        rv = SECFailure;
+        goto cleanup;
+    }
+cleanup:
+    PORT_FreeArena(arena, PR_FALSE);
+    PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE);
+    SECITEM_FreeItem(&derived, PR_FALSE);
+    return rv;
+}
+
+/* Performs tests of elliptic curve cryptography over prime fields If
+ * tests fail, then it prints an error message, aborts, and returns an
+ * error code. Otherwise, returns 0. */
+int
+main(int argv, char **argc)
+{
+    SECStatus rv = SECSuccess;
+    int numkats = 0;
+    int i = 0;
+    rv = NSS_NoDB_Init(NULL);
+    if (rv != SECSuccess) {
+        SECU_PrintError("Error:", "NSS_NoDB_Init");
+        goto cleanup;
+    }
+
+    while (ecdh_testvecs[numkats].curve != ECCurve_pastLastCurve) {
+        numkats++;
+    }
+    printf("1..%d\n", numkats);
+    for (i = 0; ecdh_testvecs[i].curve != ECCurve_pastLastCurve; i++) {
+        rv = ectest_ecdh_kat(&ecdh_testvecs[i]);
+        if (rv != SECSuccess) {
+            printf("not okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
+        } else {
+            printf("okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
+        }
+    }
+
+cleanup:
+    rv |= NSS_Shutdown();
+
+    if (rv != SECSuccess) {
+        printf("Error: exiting with error value\n");
+    }
+    return rv;
+}
new file mode 100644
--- /dev/null
+++ b/security/nss/cmd/ectest/manifest.mn
@@ -0,0 +1,18 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH = ../..
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
+
+CSRCS = ectest.c
+
+PROGRAM = ectest
+
+USE_STATIC_LIBS = 1
new file mode 100644
--- /dev/null
+++ b/security/nss/cmd/ectest/testvecs.h
@@ -0,0 +1,728 @@
+static ECDH_KAT ecdh_testvecs[] = {
+    { ECCurve_NIST_P256,
+      "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534",
+      "04ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b23028af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141",
+      "04700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac",
+      "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b",
+      "curve: P256 vector: 0" },
+
+    { ECCurve_NIST_P256,
+      "38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5",
+      "04119f2f047902782ab0c9e27a54aff5eb9b964829ca99c06b02ddba95b0a3f6d08f52b726664cac366fc98ac7a012b2682cbd962e5acb544671d41b9445704d1d",
+      "04809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7aeb29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3",
+      "057d636096cb80b67a8c038c890e887d1adfa4195e9b3ce241c8a778c59cda67",
+      "curve: P256 vector: 1" },
+
+    { ECCurve_NIST_P256,
+      "1accfaf1b97712b85a6f54b148985a1bdc4c9bec0bd258cad4b3d603f49f32c8",
+      "04d9f2b79c172845bfdb560bbb01447ca5ecc0470a09513b6126902c6b4f8d1051f815ef5ec32128d3487834764678702e64e164ff7315185e23aff5facd96d7bc",
+      "04a2339c12d4a03c33546de533268b4ad667debf458b464d77443636440ee7fec3ef48a3ab26e20220bcda2c1851076839dae88eae962869a497bf73cb66faf536",
+      "2d457b78b4614132477618a5b077965ec90730a8c81a1c75d6d4ec68005d67ec",
+      "curve: P256 vector: 2" },
+
+    { ECCurve_NIST_P256,
+      "207c43a79bfee03db6f4b944f53d2fb76cc49ef1c9c4d34d51b6c65c4db6932d",
+      "0424277c33f450462dcb3d4801d57b9ced05188f16c28eda873258048cd1607e0dc4789753e2b1f63b32ff014ec42cd6a69fac81dfe6d0d6fd4af372ae27c46f88",
+      "04df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4",
+      "96441259534b80f6aee3d287a6bb17b5094dd4277d9e294f8fe73e48bf2a0024",
+      "curve: P256 vector: 3" },
+
+    { ECCurve_NIST_P256,
+      "59137e38152350b195c9718d39673d519838055ad908dd4757152fd8255c09bf",
+      "04a8c5fdce8b62c5ada598f141adb3b26cf254c280b2857a63d2ad783a73115f6b806e1aafec4af80a0d786b3de45375b517a7e5b51ffb2c356537c9e6ef227d4a",
+      "0441192d2813e79561e6a1d6f53c8bc1a433a199c835e141b05a74a97b0faeb9221af98cc45e98a7e041b01cf35f462b7562281351c8ebf3ffa02e33a0722a1328",
+      "19d44c8d63e8e8dd12c22a87b8cd4ece27acdde04dbf47f7f27537a6999a8e62",
+      "curve: P256 vector: 4" },
+
+    { ECCurve_NIST_P256,
+      "f5f8e0174610a661277979b58ce5c90fee6c9b3bb346a90a7196255e40b132ef",
+      "047b861dcd2844a5a8363f6b8ef8d493640f55879217189d80326aad9480dfc149c4675b45eeb306405f6c33c38bc69eb2bdec9b75ad5af4706aab84543b9cc63a",
+      "0433e82092a0f1fb38f5649d5867fba28b503172b7035574bf8e5b7100a3052792f2cf6b601e0a05945e335550bf648d782f46186c772c0f20d3cd0d6b8ca14b2f",
+      "664e45d5bba4ac931cd65d52017e4be9b19a515f669bea4703542a2c525cd3d3",
+      "curve: P256 vector: 5" },
+
+    { ECCurve_NIST_P256,
+      "3b589af7db03459c23068b64f63f28d3c3c6bc25b5bf76ac05f35482888b5190",
+      "049fb38e2d58ea1baf7622e96720101cae3cde4ba6c1e9fa26d9b1de0899102863d5561b900406edf50802dd7d73e89395f8aed72fba0e1d1b61fe1d22302260f0",
+      "046a9e0c3f916e4e315c91147be571686d90464e8bf981d34a90b6353bca6eeba740f9bead39c2f2bcc2602f75b8a73ec7bdffcbcead159d0174c6c4d3c5357f05",
+      "ca342daa50dc09d61be7c196c85e60a80c5cb04931746820be548cdde055679d",
+      "curve: P256 vector: 6" },
+
+    { ECCurve_NIST_P256,
+      "d8bf929a20ea7436b2461b541a11c80e61d826c0a4c9d322b31dd54e7f58b9c8",
+      "0420f07631e4a6512a89ad487c4e9d63039e579cb0d7a556cb9e661cd59c1e7fa46de91846b3eee8a5ec09c2ab1f41e21bd83620ccdd1bdce3ab7ea6e02dd274f5",
+      "04a9c0acade55c2a73ead1a86fb0a9713223c82475791cd0e210b046412ce224bbf6de0afa20e93e078467c053d241903edad734c6b403ba758c2b5ff04c9d4229",
+      "35aa9b52536a461bfde4e85fc756be928c7de97923f0416c7a3ac8f88b3d4489",
+      "curve: P256 vector: 7" },
+
+    { ECCurve_NIST_P256,
+      "0f9883ba0ef32ee75ded0d8bda39a5146a29f1f2507b3bd458dbea0b2bb05b4d",
+      "04abb61b423be5d6c26e21c605832c9142dc1dfe5a5fff28726737936e6fbf516d733d2513ef58beab202090586fac91bf0fee31e80ab33473ab23a2d89e58fad6",
+      "0494e94f16a98255fff2b9ac0c9598aac35487b3232d3231bd93b7db7df36f9eb9d8049a43579cfa90b8093a94416cbefbf93386f15b3f6e190b6e3455fedfe69a",
+      "605c16178a9bc875dcbff54d63fe00df699c03e8a888e9e94dfbab90b25f39b4",
+      "curve: P256 vector: 8" },
+
+    { ECCurve_NIST_P256,
+      "2beedb04b05c6988f6a67500bb813faf2cae0d580c9253b6339e4a3337bb6c08",
+      "043d63e429cb5fa895a9247129bf4e48e89f35d7b11de8158efeb3e106a2a873950cae9e477ef41e7c8c1064379bb7b554ddcbcae79f9814281f1e50f0403c61f3",
+      "04e099bf2a4d557460b5544430bbf6da11004d127cb5d67f64ab07c94fcdf5274fd9c50dbe70d714edb5e221f4e020610eeb6270517e688ca64fb0e98c7ef8c1c5",
+      "f96e40a1b72840854bb62bc13c40cc2795e373d4e715980b261476835a092e0b",
+      "curve: P256 vector: 9" },
+
+    { ECCurve_NIST_P256,
+      "77c15dcf44610e41696bab758943eff1409333e4d5a11bbe72c8f6c395e9f848",
+      "04ad5d13c3db508ddcd38457e5991434a251bed49cf5ddcb59cdee73865f138c9f62cec1e70588aa4fdfc7b9a09daa678081c04e1208b9d662b8a2214bf8e81a21",
+      "04f75a5fe56bda34f3c1396296626ef012dc07e4825838778a645c8248cff0165833bbdf1b1772d8059df568b061f3f1122f28a8d819167c97be448e3dc3fb0c3c",
+      "8388fa79c4babdca02a8e8a34f9e43554976e420a4ad273c81b26e4228e9d3a3",
+      "curve: P256 vector: 10" },
+
+    { ECCurve_NIST_P256,
+      "42a83b985011d12303db1a800f2610f74aa71cdf19c67d54ce6c9ed951e9093e",
+      "04ab48caa61ea35f13f8ed07ffa6a13e8db224dfecfae1a7df8b1bb6ebaf0cb97d1274530ca2c385a3218bddfbcbf0b4024c9badd5243bff834ebff24a8618dccb",
+      "042db4540d50230756158abf61d9835712b6486c74312183ccefcaef2797b7674d62f57f314e3f3495dc4e099012f5e0ba71770f9660a1eada54104cdfde77243e",
+      "72877cea33ccc4715038d4bcbdfe0e43f42a9e2c0c3b017fc2370f4b9acbda4a",
+      "curve: P256 vector: 11" },
+
+    { ECCurve_NIST_P256,
+      "ceed35507b5c93ead5989119b9ba342cfe38e6e638ba6eea343a55475de2800b",
+      "049a8cd9bd72e71752df91440f77c547509a84df98114e7de4f26cdb39234a625dd07cfc84c8e144fab2839f5189bb1d7c88631d579bbc58012ed9a2327da52f62",
+      "04cd94fc9497e8990750309e9a8534fd114b0a6e54da89c4796101897041d14ecbc3def4b5fe04faee0a11932229fff563637bfdee0e79c6deeaf449f85401c5c4",
+      "e4e7408d85ff0e0e9c838003f28cdbd5247cdce31f32f62494b70e5f1bc36307",
+      "curve: P256 vector: 12" },
+
+    { ECCurve_NIST_P256,
+      "43e0e9d95af4dc36483cdd1968d2b7eeb8611fcce77f3a4e7d059ae43e509604",
+      "04f989cf8ee956a82e7ebd9881cdbfb2fd946189b08db53559bc8cfdd48071eb145eff28f1a18a616b04b7d337868679f6dd84f9a7b3d7b6f8af276c19611a541d",
+      "0415b9e467af4d290c417402e040426fe4cf236bae72baa392ed89780dfccdb471cdf4e9170fb904302b8fd93a820ba8cc7ed4efd3a6f2d6b05b80b2ff2aee4e77",
+      "ed56bcf695b734142c24ecb1fc1bb64d08f175eb243a31f37b3d9bb4407f3b96",
+      "curve: P256 vector: 13" },
+
+    { ECCurve_NIST_P256,
+      "b2f3600df3368ef8a0bb85ab22f41fc0e5f4fdd54be8167a5c3cd4b08db04903",
+      "0469c627625b36a429c398b45c38677cb35d8beb1cf78a571e40e99fe4eac1cd4e81690112b0a88f20f7136b28d7d47e5fbc2ada3c8edd87589bc19ec9590637bd",
+      "0449c503ba6c4fa605182e186b5e81113f075bc11dcfd51c932fb21e951eee2fa18af706ff0922d87b3f0c5e4e31d8b259aeb260a9269643ed520a13bb25da5924",
+      "bc5c7055089fc9d6c89f83c1ea1ada879d9934b2ea28fcf4e4a7e984b28ad2cf",
+      "curve: P256 vector: 14" },
+
+    { ECCurve_NIST_P256,
+      "4002534307f8b62a9bf67ff641ddc60fef593b17c3341239e95bdb3e579bfdc8",
+      "045fe964671315a18aa68a2a6e3dd1fde7e23b8ce7181471cfac43c99e1ae80262d5827be282e62c84de531b963884ba832db5d6b2c3a256f0e604fe7e6b8a7f72",
+      "0419b38de39fdd2f70f7091631a4f75d1993740ba9429162c2a45312401636b29c09aed7232b28e060941741b6828bcdfa2bc49cc844f3773611504f82a390a5ae",
+      "9a4e8e657f6b0e097f47954a63c75d74fcba71a30d83651e3e5a91aa7ccd8343",
+      "curve: P256 vector: 15" },
+
+    { ECCurve_NIST_P256,
+      "4dfa12defc60319021b681b3ff84a10a511958c850939ed45635934ba4979147",
+      "04c9b2b8496f1440bd4a2d1e52752fd372835b364885e154a7dac49295f281ec7cfbe6b926a8a4de26ccc83b802b1212400754be25d9f3eeaf008b09870ae76321",
+      "042c91c61f33adfe9311c942fdbff6ba47020feff416b7bb63cec13faf9b0999546cab31b06419e5221fca014fb84ec870622a1b12bab5ae43682aa7ea73ea08d0",
+      "3ca1fc7ad858fb1a6aba232542f3e2a749ffc7203a2374a3f3d3267f1fc97b78",
+      "curve: P256 vector: 16" },
+
+    { ECCurve_NIST_P256,
+      "1331f6d874a4ed3bc4a2c6e9c74331d3039796314beee3b7152fcdba5556304e",
+      "0459e1e101521046ad9cf1d082e9d2ec7dd22530cce064991f1e55c5bcf5fcb591482f4f673176c8fdaa0bb6e59b15a3e47454e3a04297d3863c9338d98add1f37",
+      "04a28a2edf58025668f724aaf83a50956b7ac1cfbbff79b08c3bf87dfd2828d767dfa7bfffd4c766b86abeaf5c99b6e50cb9ccc9d9d00b7ffc7804b0491b67bc03",
+      "1aaabe7ee6e4a6fa732291202433a237df1b49bc53866bfbe00db96a0f58224f",
+      "curve: P256 vector: 17" },
+
+    { ECCurve_NIST_P256,
+      "dd5e9f70ae740073ca0204df60763fb6036c45709bf4a7bb4e671412fad65da3",
+      "0430b9db2e2e977bcdc98cb87dd736cbd8e78552121925cf16e1933657c2fb23146a45028800b81291bce5c2e1fed7ded650620ebbe6050c6f3a7f0dfb4673ab5c",
+      "04a2ef857a081f9d6eb206a81c4cf78a802bdf598ae380c8886ecd85fdc1ed7644563c4c20419f07bc17d0539fade1855e34839515b892c0f5d26561f97fa04d1a",
+      "430e6a4fba4449d700d2733e557f66a3bf3d50517c1271b1ddae1161b7ac798c",
+      "curve: P256 vector: 18" },
+
+    { ECCurve_NIST_P256,
+      "5ae026cfc060d55600717e55b8a12e116d1d0df34af831979057607c2d9c2f76",
+      "0446c9ebd1a4a3c8c0b6d572b5dcfba12467603208a9cb5d2acfbb733c40cf639146c913a27d044185d38b467ace011e04d4d9bbbb8cb9ae25fa92aaf15a595e86",
+      "04ccd8a2d86bc92f2e01bce4d6922cf7fe1626aed044685e95e2eebd464505f01fe9ddd583a9635a667777d5b8a8f31b0f79eba12c75023410b54b8567dddc0f38",
+      "1ce9e6740529499f98d1f1d71329147a33df1d05e4765b539b11cf615d6974d3",
+      "curve: P256 vector: 19" },
+
+    { ECCurve_NIST_P256,
+      "b601ac425d5dbf9e1735c5e2d5bdb79ca98b3d5be4a2cfd6f2273f150e064d9d",
+      "047c9e950841d26c8dde8994398b8f5d475a022bc63de7773fcf8d552e01f1ba0acc42b9885c9b3bee0f8d8c57d3a8f6355016c019c4062fa22cff2f209b5cc2e1",
+      "04c188ffc8947f7301fb7b53e36746097c2134bf9cc981ba74b4e9c4361f595e4ebf7d2f2056e72421ef393f0c0f2b0e00130e3cac4abbcc00286168e85ec55051",
+      "4690e3743c07d643f1bc183636ab2a9cb936a60a802113c49bb1b3f2d0661660",
+      "curve: P256 vector: 20" },
+
+    { ECCurve_NIST_P256,
+      "fefb1dda1845312b5fce6b81b2be205af2f3a274f5a212f66c0d9fc33d7ae535",
+      "0438b54db85500cb20c61056edd3d88b6a9dc26780a047f213a6e1b900f76596eb6387e4e5781571e4eb8ae62991a33b5dc33301c5bc7e125d53794a39160d8fd0",
+      "04317e1020ff53fccef18bf47bb7f2dd7707fb7b7a7578e04f35b3beed222a0eb609420ce5a19d77c6fe1ee587e6a49fbaf8f280e8df033d75403302e5a27db2ae",
+      "30c2261bd0004e61feda2c16aa5e21ffa8d7e7f7dbf6ec379a43b48e4b36aeb0",
+      "curve: P256 vector: 21" },
+
+    { ECCurve_NIST_P256,
+      "334ae0c4693d23935a7e8e043ebbde21e168a7cba3fa507c9be41d7681e049ce",
+      "043f2bf1589abf3047bf3e54ac9a95379bff95f8f55405f64eca36a7eebe8ffca75212a94e66c5ae9a8991872f66a72723d80ec5b2e925745c456f5371943b3a06",
+      "0445fb02b2ceb9d7c79d9c2fa93e9c7967c2fa4df5789f9640b24264b1e524fcb15c6e8ecf1f7d3023893b7b1ca1e4d178972ee2a230757ddc564ffe37f5c5a321",
+      "2adae4a138a239dcd93c243a3803c3e4cf96e37fe14e6a9b717be9599959b11c",
+      "curve: P256 vector: 22" },
+
+    { ECCurve_NIST_P256,
+      "2c4bde40214fcc3bfc47d4cf434b629acbe9157f8fd0282540331de7942cf09d",
+      "0429c0807f10cbc42fb45c9989da50681eead716daa7b9e91fd32e062f5eb92ca0ff1d6d1955d7376b2da24fe1163a271659136341bc2eb1195fc706dc62e7f34d",
+      "04a19ef7bff98ada781842fbfc51a47aff39b5935a1c7d9625c8d323d511c92de6e9c184df75c955e02e02e400ffe45f78f339e1afe6d056fb3245f4700ce606ef",
+      "2e277ec30f5ea07d6ce513149b9479b96e07f4b6913b1b5c11305c1444a1bc0b",
+      "curve: P256 vector: 23" },
+
+    { ECCurve_NIST_P256,
+      "85a268f9d7772f990c36b42b0a331adc92b5941de0b862d5d89a347cbf8faab0",
+      "049cf4b98581ca1779453cc816ff28b4100af56cf1bf2e5bc312d83b6b1b21d3337a5504fcac5231a0d12d658218284868229c844a04a3450d6c7381abe080bf3b",
+      "04356c5a444c049a52fee0adeb7e5d82ae5aa83030bfff31bbf8ce2096cf161c4b57d128de8b2a57a094d1a001e572173f96e8866ae352bf29cddaf92fc85b2f92",
+      "1e51373bd2c6044c129c436e742a55be2a668a85ae08441b6756445df5493857",
+      "curve: P256 vector: 24" },
+
+    { ECCurve_NIST_P384,
+      "3cc3122a68f0d95027ad38c067916ba0eb8c38894d22e1b15618b6818a661774ad463b205da88cf699ab4d43c9cf98a1",
+      "049803807f2f6d2fd966cdd0290bd410c0190352fbec7ff6247de1302df86f25d34fe4a97bef60cff548355c015dbb3e5"
+      "fba26ca69ec2f5b5d9dad20cc9da711383a9dbe34ea3fa5a2af75b46502629ad54dd8b7d73a8abb06a3a3be47d650cc99",
+      "04a7c76b970c3b5fe8b05d2838ae04ab47697b9eaf52e764592efda27fe7513272734466b400091adbf2d68c58e0c5006"
+      "6ac68f19f2e1cb879aed43a9969b91a0839c4c38a49749b661efedf243451915ed0905a32b060992b468c64766fc8437a",
+      "5f9d29dc5e31a163060356213669c8ce132e22f57c9a04f40ba7fcead493b457e5621e766c40a2e3d4d6a04b25e533f1",
+      "curve: P384 vector: 0" },
+
+    { ECCurve_NIST_P384,
+      "92860c21bde06165f8e900c687f8ef0a05d14f290b3f07d8b3a8cc6404366e5d5119cd6d03fb12dc58e89f13df9cd783",
+      "04ea4018f5a307c379180bf6a62fd2ceceebeeb7d4df063a66fb838aa35243419791f7e2c9d4803c9319aa0eb03c416b"
+      "6668835a91484f05ef028284df6436fb88ffebabcdd69ab0133e6735a1bcfb37203d10d340a8328a7b68770ca75878a1a6",
+      "0430f43fcf2b6b00de53f624f1543090681839717d53c7c955d1d69efaf0349b7363acb447240101cbb3af6641ce4b88e0"
+      "25e46c0c54f0162a77efcc27b6ea792002ae2ba82714299c860857a68153ab62e525ec0530d81b5aa15897981e858757",
+      "a23742a2c267d7425fda94b93f93bbcc24791ac51cd8fd501a238d40812f4cbfc59aac9520d758cf789c76300c69d2ff",
+      "curve: P384 vector: 1" },
+
+    { ECCurve_NIST_P384,
+      "12cf6a223a72352543830f3f18530d5cb37f26880a0b294482c8a8ef8afad09aa78b7dc2f2789a78c66af5d1cc553853",
+      "04fcfcea085e8cf74d0dced1620ba8423694f903a219bbf901b0b59d6ac81baad316a242ba32bde85cb248119b852fab6"
+      "6972e3c68c7ab402c5836f2a16ed451a33120a7750a6039f3ff15388ee622b7065f7122bf6d51aefbc29b37b03404581b",
+      "041aefbfa2c6c8c855a1a216774550b79a24cda37607bb1f7cc906650ee4b3816d68f6a9c75da6e4242cebfb6652f65180"
+      "419d28b723ebadb7658fcebb9ad9b7adea674f1da3dc6b6397b55da0f61a3eddacb4acdb14441cb214b04a0844c02fa3",
+      "3d2e640f350805eed1ff43b40a72b2abed0a518bcebe8f2d15b111b6773223da3c3489121db173d414b5bd5ad7153435",
+      "curve: P384 vector: 2" },
+
+    { ECCurve_NIST_P384,
+      "8dd48063a3a058c334b5cc7a4ce07d02e5ee6d8f1f3c51a1600962cbab462690ae3cd974fb39e40b0e843daa0fd32de1",
+      "04e38c9846248123c3421861ea4d32669a7b5c3c08376ad28104399494c84ff5efa3894adb2c6cbe8c3c913ef2eec5bd3"
+      "c9fa84024a1028796df84021f7b6c9d02f0f4bd1a612a03cbf75a0beea43fef8ae84b48c60172aadf09c1ad016d0bf3ce",
+      "048bc089326ec55b9cf59b34f0eb754d93596ca290fcb3444c83d4de3a5607037ec397683f8cef07eab2fe357eae36c44"
+      "9d9d16ce8ac85b3f1e94568521aae534e67139e310ec72693526aa2e927b5b322c95a1a033c229cb6770c957cd3148dd7",
+      "6a42cfc392aba0bfd3d17b7ccf062b91fc09bbf3417612d02a90bdde62ae40c54bb2e56e167d6b70db670097eb8db854",
+      "curve: P384 vector: 3" },
+
+    { ECCurve_NIST_P384,
+      "84ece6cc3429309bd5b23e959793ed2b111ec5cb43b6c18085fcaea9efa0685d98a6262ee0d330ee250bc8a67d0e733f",
+      "043222063a2997b302ee60ee1961108ff4c7acf1c0ef1d5fb0d164b84bce71c431705cb9aea9a45f5d73806655a058bee"
+      "3e61fa9e7fbe7cd43abf99596a3d3a039e99fa9dc93b0bdd9cad81966d17eeaf557068afa7c78466bb5b22032d1100fa6",
+      "04eb952e2d9ac0c20c6cc48fb225c2ad154f53c8750b003fd3b4ed8ed1dc0defac61bcdde02a2bcfee7067d75d342ed2b"
+      "0f1828205baece82d1b267d0d7ff2f9c9e15b69a72df47058a97f3891005d1fb38858f5603de840e591dfa4f6e7d489e1",
+      "ce7ba454d4412729a32bb833a2d1fd2ae612d4667c3a900e069214818613447df8c611de66da200db7c375cf913e4405",
+      "curve: P384 vector: 4" },
+
+    { ECCurve_NIST_P384,
+      "68fce2121dc3a1e37b10f1dde309f9e2e18fac47cd1770951451c3484cdb77cb136d00e731260597cc2859601c01a25b",
+      "04868be0e694841830e424d913d8e7d86b84ee1021d82b0ecf523f09fe89a76c0c95c49f2dfbcf829c1e39709d55efbb"
+      "3b9195eb183675b40fd92f51f37713317e4a9b4f715c8ab22e0773b1bc71d3a219f05b8116074658ee86b52e36f3897116",
+      "04441d029e244eb7168d647d4df50db5f4e4974ab3fdaf022aff058b3695d0b8c814cc88da6285dc6df1ac55c55388500"
+      "3e8025ac23a41d4b1ea2aa46c50c6e479946b59b6d76497cd9249977e0bfe4a6262622f13d42a3c43d66bdbb30403c345",
+      "ba69f0acdf3e1ca95caaac4ecaf475bbe51b54777efce01ca381f45370e486fe87f9f419b150c61e329a286d1aa265ec",
+      "curve: P384 vector: 5" },
+
+    { ECCurve_NIST_P384,
+      "b1764c54897e7aae6de9e7751f2f37de849291f88f0f91093155b858d1cc32a3a87980f706b86cc83f927bdfdbeae0bd",
+      "04c371222feaa6770c6f3ea3e0dac9740def4fcf821378b7f91ff937c21e0470f70f3a31d5c6b2912195f10926942b48ae"
+      "047d6b4d765123563f81116bc665b7b8cc6207830d805fd84da7cb805a65baa7c12fd592d1b5b5e3e65d9672a9ef7662",
+      "043d4e6bf08a73404accc1629873468e4269e82d90d832e58ad72142639b5a056ad8d35c66c60e8149fac0c797bceb7c2"
+      "f9b0308dc7f0e6d29f8c277acbc65a21e5adb83d11e6873bc0a07fda0997f482504602f59e10bc5cb476b83d0a4f75e71",
+      "1a6688ee1d6e59865d8e3ada37781d36bb0c2717eef92e61964d3927cb765c2965ea80f7f63e58c322ba0397faeaf62b",
+      "curve: P384 vector: 6" },
+
+    { ECCurve_NIST_P384,
+      "f0f7a96e70d98fd5a30ad6406cf56eb5b72a510e9f192f50e1f84524dbf3d2439f7287bb36f5aa912a79deaab4adea82",
+      "0499c8c41cb1ab5e0854a346e4b08a537c1706a61553387c8d94943ab15196d40dbaa55b8210a77a5d00915f2c4ea69e"
+      "ab5531065bdcf17bfb3cb55a02e41a57c7f694c383ad289f900fbd656c2233a93c92e933e7a26f54cbb56f0ad875c51bb0",
+      "04f5f6bef1d110da03be0017eac760cc34b24d092f736f237bc7054b3865312a813bcb62d297fb10a4f7abf54708fe2d3d"
+      "06fdf8d7dc032f4e10010bf19cbf6159321252ff415fb91920d438f24e67e60c2eb0463204679fa356af44cea9c9ebf5",
+      "d06a568bf2336b90cbac325161be7695eacb2295f599500d787f072612aca313ee5d874f807ddef6c1f023fe2b6e7cd0",
+      "curve: P384 vector: 7" },
+
+    { ECCurve_NIST_P384,
+      "9efb87ddc61d43c482ba66e1b143aef678fbd0d1bebc2000941fabe677fe5b706bf78fce36d100b17cc787ead74bbca2",
+      "044c34efee8f0c95565d2065d1bbac2a2dd25ae964320eb6bccedc5f3a9b42a881a1afca1bb6b880584fa27b01c193cd9"
+      "2d8fb01dbf7cd0a3868c26b951f393c3c56c2858cee901f7793ff5d271925d13a41f8e52409f4eba1990f33acb0bac669",
+      "047cdec77e0737ea37c67b89b7137fe38818010f4464438ee4d1d35a0c488cad3fde2f37d00885d36d3b795b9f93d23a6"
+      "728c42ee8d6027c56cf979ba4c229fdb01d234944f8ac433650112c3cf0f02844e888a3569dfef7828a8a884589aa055e",
+      "bb3b1eda9c6560d82ff5bee403339f1e80342338a991344853b56b24f109a4d94b92f654f0425edd4c205903d7586104",
+      "curve: P384 vector: 8" },
+
+    { ECCurve_NIST_P384,
+      "d787a57fde22ec656a0a525cf3c738b30d73af61e743ea90893ecb2d7b622add2f94ee25c2171467afb093f3f84d0018",
+      "04171546923b87b2cbbad664f01ce932bf09d6a6118168678446bfa9f0938608cb4667a98f4ec8ac1462285c2508f7486"
+      "2fa41cb4db68ae71f1f8a3e8939dc52c2dec61a83c983beb2a02baf29ec49278088882ed0cf56c74b5c173b552ccf63cf",
+      "048eeea3a319c8df99fbc29cb55f243a720d95509515ee5cc587a5c5ae22fbbd009e626db3e911def0b99a4f7ae304b1b"
+      "a73877dc94db9adddc0d9a4b24e8976c22d73c844370e1ee857f8d1b129a3bd5f63f40caf3bd0533e38a5f5777074ff9e",
+      "1e97b60add7cb35c7403dd884c0a75795b7683fff8b49f9d8672a8206bfdcf0a106b8768f983258c74167422e44e4d14",
+      "curve: P384 vector: 9" },
+
+    { ECCurve_NIST_P384,
+      "83d70f7b164d9f4c227c767046b20eb34dfc778f5387e32e834b1e6daec20edb8ca5bb4192093f543b68e6aeb7ce788b",
+      "0457cd770f3bbcbe0c78c770eab0b169bc45e139f86378ffae1c2b16966727c2f2eb724572b8f3eb228d130db4ff862c"
+      "637ec5c8813b685558d83e924f14bc719f6eb7ae0cbb2c474227c5bda88637a4f26c64817929af999592da6f787490332f",
+      "04a721f6a2d4527411834b13d4d3a33c29beb83ab7682465c6cbaf6624aca6ea58c30eb0f29dd842886695400d7254f20f"
+      "14ba6e26355109ad35129366d5e3a640ae798505a7fa55a96a36b5dad33de00474f6670f522214dd7952140ab0a7eb68",
+      "1023478840e54775bfc69293a3cf97f5bc914726455c66538eb5623e218feef7df4befa23e09d77145ad577db32b41f9",
+      "curve: P384 vector: 10" },
+
+    { ECCurve_NIST_P384,
+      "8f558e05818b88ed383d5fca962e53413db1a0e4637eda194f761944cbea114ab9d5da175a7d57882550b0e432f395a9",
+      "049a2f57f4867ce753d72b0d95195df6f96c1fae934f602efd7b6a54582f556cfa539d89005ca2edac08ad9b72dd1f60b"
+      "ad9b94ee82da9cc601f346044998ba387aee56404dc6ecc8ab2b590443319d0b2b6176f9d0eac2d44678ed561607d09a9",
+      "04d882a8505c2d5cb9b8851fc676677bb0087681ad53faceba1738286b45827561e7da37b880276c656cfc38b32ade847"
+      "e34b314bdc134575654573cffaf40445da2e6aaf987f7e913cd4c3091523058984a25d8f21da8326192456c6a0fa5f60c",
+      "6ad6b9dc8a6cf0d3691c501cbb967867f6e4bbb764b60dbff8fcff3ed42dbba39d63cf325b4b4078858495ddee75f954",
+      "curve: P384 vector: 11" },
+
+    { ECCurve_NIST_P384,
+      "0f5dee0affa7bbf239d5dff32987ebb7cf84fcceed643e1d3c62d0b3352aec23b6e5ac7fa4105c8cb26126ad2d1892cb",
+      "0423346bdfbc9d7c7c736e02bdf607671ff6082fdd27334a8bc75f3b23681ebe614d0597dd614fae58677c835a9f0b273"
+      "b82ba36290d2f94db41479eb45ab4eaf67928a2315138d59eecc9b5285dfddd6714f77557216ea44cc6fc119d8243efaf",
+      "04815c9d773dbf5fb6a1b86799966247f4006a23c92e68c55e9eaa998b17d8832dd4d84d927d831d4f68dac67c6488219f"
+      "e79269948b2611484560fd490feec887cb55ef99a4b524880fa7499d6a07283aae2afa33feab97deca40bc606c4d8764",
+      "cc9e063566d46b357b3fcae21827377331e5e290a36e60cd7c39102b828ae0b918dc5a02216b07fe6f1958d834e42437",
+      "curve: P384 vector: 12" },
+
+    { ECCurve_NIST_P384,
+      "037b633b5b8ba857c0fc85656868232e2febf59578718391b81da8541a00bfe53c30ae04151847f27499f8d7abad8cf4",
+      "048878ac8a947f7d5cb2b47aad24fbb8210d86126585399a2871f84aa9c5fde3074ae540c6bf82275ca822d0feb862bc7"
+      "4632f5cd2f900c2711c32f8930728eb647d31edd8d650f9654e7d33e5ed1b475489d08daa30d8cbcba6bfc3b60d9b5a37",
+      "041c0eeda7a2be000c5bdcda0478aed4db733d2a9e341224379123ad847030f29e3b168fa18e89a3c0fba2a6ce1c28fc3"
+      "bec8c1c83c118c4dbea94271869f2d868eb65e8b44e21e6f14b0f4d9b38c068daefa27114255b9a41d084cc4a1ad85456",
+      "deff7f03bd09865baf945e73edff6d5122c03fb561db87dec8662e09bed4340b28a9efe118337bb7d3d4f7f568635ff9",
+      "curve: P384 vector: 13" },
+
+    { ECCurve_NIST_P384,
+      "e3d07106bedcc096e7d91630ffd3094df2c7859db8d7edbb2e37b4ac47f429a637d06a67d2fba33838764ef203464991",
+      "04e74a1a2b85f1cbf8dbbdf050cf1aff8acb02fda2fb6591f9d3cfe4e79d0ae938a9c1483e7b75f8db24505d65065cdb1"
+      "81773ee591822f7abaa856a1a60bc0a5203548dbd1cb5025466eff8481bd07614eaa04a16c3db76905913e972a5b6b59d",
+      "04c95c185e256bf997f30b311548ae7f768a38dee43eeeef43083f3077be70e2bf39ac1d4daf360c514c8c6be623443d1"
+      "a3e63a663eaf75d8a765ab2b9a35513d7933fa5e26420a5244550ec6c3b6f033b96db2aca3d6ac6aab052ce929595aea5",
+      "c8b1038f735ad3bb3e4637c3e47eab487637911a6b7950a4e461948329d3923b969e5db663675623611a457fcda35a71",
+      "curve: P384 vector: 14" },
+
+    { ECCurve_NIST_P384,
+      "f3f9b0c65a49a506632c8a45b10f66b5316f9eeb06fae218f2da62333f99905117b141c760e8974efc4af10570635791",
+      "04a4ad77aa7d86e5361118a6b921710c820721210712f4c347985fdee58aa4effa1e28be80a17b120b139f96300f89b4"
+      "9b1ddf22e07e03f1560d8f45a480094560dba9fae7f9531130c1b57ebb95982496524f31d3797793396fa823f22bdb4328",
+      "043497238a7e6ad166df2dac039aa4dac8d17aa925e7c7631eb3b56e3aaa1c545fcd54d2e5985807910fb202b1fc191d2a"
+      "a49e5c487dcc7aa40a8f234c979446040d9174e3ad357d404d7765183195aed3f913641b90c81a306ebf0d8913861316",
+      "d337eaa32b9f716b8747b005b97a553c59dab0c51df41a2d49039cdae705aa75c7b9e7bc0b6a0e8c578c902bc4fff23e",
+      "curve: P384 vector: 15" },
+
+    { ECCurve_NIST_P384,
+      "59fce7fad7de28bac0230690c95710c720e528f9a4e54d3a6a8cd5fc5c5f21637031ce1c5b4e3d39647d8dcb9b794664",
+      "049c43bf971edf09402876ee742095381f78b1bd3aa39b5132af75dbfe7e98bd78bde10fe2e903c2b6379e1deee175a1b"
+      "0a6c58ecea5a477bb01bd543b339f1cc49f1371a2cda4d46eb4e53e250597942351a99665a122ffea9bde0636c375daf2",
+      "0490a34737d45b1aa65f74e0bd0659bc118f8e4b774b761944ffa6573c6df4f41dec0d11b697abd934d390871d4b453240"
+      "9b590719bb3307c149a7817be355d684893a307764b512eeffe07cb699edb5a6ffbf8d6032e6c79d5e93e94212c2aa4e",
+      "32d292b695a4488e42a7b7922e1ae537d76a3d21a0b2e36875f60e9f6d3e8779c2afb3a413b9dd79ae18e70b47d337c1",
+      "curve: P384 vector: 16" },
+
+    { ECCurve_NIST_P384,
+      "3e49fbf950a424c5d80228dc4bc35e9f6c6c0c1d04440998da0a609a877575dbe437d6a5cedaa2ddd2a1a17fd112aded",
+      "045a949594228b1a3d6f599eb3db0d06070fbc551c657b58234ba164ce3fe415fa5f3eb823c08dc29b8c341219c77b6b3"
+      "d2baad447c8c290cfed25edd9031c41d0b76921457327f42db31122b81f337bbf0b1039ec830ce9061a3761953c75e4a8",
+      "04dda546acfc8f903d11e2e3920669636d44b2068aeb66ff07aa266f0030e1535b0ed0203cb8a460ac990f1394faf22f1"
+      "d15bbb2597913035faadf413476f4c70f7279769a40c986f470c427b4ee4962abdf8173bbad81874772925fd32f0b159f",
+      "1220e7e6cad7b25df98e5bbdcc6c0b65ca6c2a50c5ff6c41dca71e475646fd489615979ca92fb4389aeadefde79a24f1",
+      "curve: P384 vector: 17" },
+
+    { ECCurve_NIST_P384,
+      "50ccc1f7076e92f4638e85f2db98e0b483e6e2204c92bdd440a6deea04e37a07c6e72791c190ad4e4e86e01efba84269",
+      "04756c07df0ce32c839dac9fb4733c9c28b70113a676a7057c38d223f22a3a9095a8d564653af528e04c7e1824be4a651"
+      "217c2ce6962cbd2a2e066297b39d57dd9bb4680f0191d390f70b4e461419b2972ce68ad46127fdda6c39195774ea86df3",
+      "04788be2336c52f4454d63ee944b1e49bfb619a08371048e6da92e584eae70bde1f171c4df378bd1f3c0ab03048a237802"
+      "4673ebd8db604eaf41711748bab2968a23ca4476ce144e728247f08af752929157b5830f1e26067466bdfa8b65145a33",
+      "793bb9cd22a93cf468faf804a38d12b78cb12189ec679ddd2e9aa21fa9a5a0b049ab16a23574fe04c1c3c02343b91beb",
+      "curve: P384 vector: 18" },
+
+    { ECCurve_NIST_P384,
+      "06f132b71f74d87bf99857e1e4350a594e5fe35533b888552ceccbc0d8923c902e36141d7691e28631b8bc9bafe5e064",
+      "042a3cc6b8ff5cde926e7e3a189a1bd029c9b586351af8838f4f201cb8f4b70ef3b0da06d352c80fc26baf8f42b784459"
+      "ebf9985960176da6d23c7452a2954ffcbbcb24249b43019a2a023e0b3dabd461f19ad3e775c364f3f11ad49f3099400d3",
+      "04d09bb822eb99e38060954747c82bb3278cf96bbf36fece3400f4c873838a40c135eb3babb9293bd1001bf3ecdee7bf2"
+      "6d416db6e1b87bbb7427788a3b6c7a7ab2c165b1e366f9608df512037584f213a648d47f16ac326e19aae972f63fd76c9",
+      "012d191cf7404a523678c6fc075de8285b243720a903047708bb33e501e0dbee5bcc40d7c3ef6c6da39ea24d830da1e8",
+      "curve: P384 vector: 19" },
+
+    { ECCurve_NIST_P384,
+      "12048ebb4331ec19a1e23f1a2c773b664ccfe90a28bfb846fc12f81dff44b7443c77647164bf1e9e67fd2c07a6766241",
+      "04bc18836bc7a9fdf54b5352f37d7528ab8fa8ec544a8c6180511cbfdd49cce377c39e34c031b5240dc9980503ed2f26"
+      "2c8086cbe338191080f0b7a16c7afc4c7b0326f9ac66f58552ef4bb9d24de3429ed5d3277ed58fcf48f2b5f61326bec6c6",
+      "0413741262ede5861dad71063dfd204b91ea1d3b7c631df68eb949969527d79a1dc59295ef7d2bca6743e8cd77b04d1"
+      "b580baaeadc7e19d74a8a04451a135f1be1b02fe299f9dc00bfdf201e83d995c6950bcc1cb89d6f7b30bf54656b9a4da586",
+      "ad0fd3ddffe8884b9263f3c15fe1f07f2a5a22ffdc7e967085eea45f0cd959f20f18f522763e28bcc925e496a52dda98",
+      "curve: P384 vector: 20" },
+
+    { ECCurve_NIST_P384,
+      "34d61a699ca576169fcdc0cc7e44e4e1221db0fe63d16850c8104029f7d48449714b9884328cae189978754ab460b486",
+      "04867f81104ccd6b163a7902b670ef406042cb0cce7dcdc63d1dfc91b2c40e3cdf7595834bf9eceb79849f1636fc8462f"
+      "c9d4bde8e875ec49697d258d1d59465f8431c6f5531e1c59e9f9ebe3cf164a8d9ce10a12f1979283a959bad244dd83863",
+      "049e22cbc18657f516a864b37b783348b66f1aa9626cd631f4fa1bd32ad88cf11db52057c660860d39d11fbf024fabd44"
+      "46b0d53c79681c28116df71e9cee74fd56c8b7f04b39f1198cc72284e98be9562e35926fb4f48a9fbecafe729309e8b6f",
+      "dc4ca392dc15e20185f2c6a8ea5ec31dfc96f56153a47394b3072b13d0015f5d4ae13beb3bed54d65848f9b8383e6c95",
+      "curve: P384 vector: 21" },
+
+    { ECCurve_NIST_P384,
+      "dc60fa8736d702135ff16aab992bb88eac397f5972456c72ec447374d0d8ce61153831bfc86ad5a6eb5b60bfb96a862c",
+      "04b69beede85d0f829fec1b893ccb9c3e052ff692e13b974537bc5b0f9feaf7b22e84f03231629b24866bdb4b8cf9089"
+      "1466f85e2bfcaba2843285b0e14ebc07ef7dafff8b424416fee647b59897b619f20eed95a632e6a4206bf7da429c04c560",
+      "042db5da5f940eaa884f4db5ec2139b0469f38e4e6fbbcc52df15c0f7cf7fcb1808c749764b6be85d2fdc5b16f58ad5d"
+      "c022e8b02dcf33e1b5a083849545f84ad5e43f77cb71546dbbac0d11bdb2ee202e9d3872e8d028c08990746c5e1dde9989",
+      "d765b208112d2b9ed5ad10c4046e2e3b0dbf57c469329519e239ac28b25c7d852bf757d5de0ee271cadd021d86cfd347",
+      "curve: P384 vector: 22" },
+
+    { ECCurve_NIST_P384,
+      "6fa6a1c704730987aa634b0516a826aba8c6d6411d3a4c89772d7a62610256a2e2f289f5c3440b0ec1e70fa339e251ce",
+      "0453de1fc1328e8de14aecab29ad8a40d6b13768f86f7d298433d20fec791f86f8bc73f358098b256a298bb488de257bf"
+      "4ac28944fd27f17b82946c04c66c41f0053d3692f275da55cd8739a95bd8cd3af2f96e4de959ea8344d8945375905858b",
+      "04329647baa354224eb4414829c5368c82d7893b39804e08cbb2180f459befc4b347a389a70c91a23bd9d30c83be5295d"
+      "3cc8f61923fad2aa8e505d6cfa126b9fabd5af9dce290b75660ef06d1caa73681d06089c33bc4246b3aa30dbcd2435b12",
+      "d3778850aeb58804fbe9dfe6f38b9fa8e20c2ca4e0dec335aafceca0333e3f2490b53c0c1a14a831ba37c4b9d74be0f2",
+      "curve: P384 vector: 23" },
+
+    { ECCurve_NIST_P384,
+      "74ad8386c1cb2ca0fcdeb31e0869bb3f48c036afe2ef110ca302bc8b910f621c9fcc54cec32bb89ec7caa84c7b8e54a8",
+      "0427a3e83cfb9d5122e73129d801615857da7cc089cccc9c54ab3032a19e0a0a9f677346e37f08a0b3ed8da6e5dd69106"
+      "38d60e44aa5e0fd30c918456796af37f0e41957901645e5c596c6d989f5859b03a0bd7d1f4e77936fff3c74d204e5388e",
+      "0429d8a36d22200a75b7aea1bb47cdfcb1b7fd66de967041434728ab5d533a060df732130600fe6f75852a871fb2938e3"
+      "9e19b53db528395de897a45108967715eb8cb55c3fcbf23379372c0873a058d57544b102ecce722b2ccabb1a603774fd5",
+      "81e1e71575bb4505498de097350186430a6242fa6c57b85a5f984a23371123d2d1424eefbf804258392bc723e4ef1e35",
+      "curve: P384 vector: 24" },
+
+    { ECCurve_NIST_P521,
+      "017eecc07ab4b329068fba65e56a1f8890aa935e57134ae0ffcce802735151f4eac6564f6ee9974c5e6887a1fefee5743"
+      "ae2241bfeb95d5ce31ddcb6f9edb4d6fc47",
+      "0400602f9d0cf9e526b29e22381c203c48a886c2b0673033366314f1ffbcba240ba42f4ef38a76174635f91e6b4ed3427"
+      "5eb01c8467d05ca80315bf1a7bbd945f550a501b7c85f26f5d4b2d7355cf6b02117659943762b6d1db5ab4f1dbc44ce7b2"
+      "946eb6c7de342962893fd387d1b73d7a8672d1f236961170b7eb3579953ee5cdc88cd2d",
+      "0400685a48e86c79f0f0875f7bc18d25eb5fc8c0b07e5da4f4370f3a9490340854334b1e1b87fa395464c60626124a4e70"
+      "d0f785601d37c09870ebf176666877a2046d01ba52c56fc8776d9e8f5db4f0cc27636d0b741bbe05400697942e80b739884"
+      "a83bde99e0f6716939e632bc8986fa18dccd443a348b6c3e522497955a4f3c302f676",
+      "005fc70477c3e63bc3954bd0df3ea0d1f41ee21746ed95fc5e1fdf90930d5e136672d72cc770742d1711c3c3a4c334a0ad9"
+      "759436a4d3c5bf6e74b9578fac148c831",
+      "curve: P521 vector: 0" },
+
+    { ECCurve_NIST_P521,
+      "00816f19c1fb10ef94d4a1d81c156ec3d1de08b66761f03f06ee4bb9dcebbbfe1eaa1ed49a6a990838d8ed318c14d74cc"
+      "872f95d05d07ad50f621ceb620cd905cfb8",
+      "0400d45615ed5d37fde699610a62cd43ba76bedd8f85ed31005fe00d6450fbbd101291abd96d4945a8b57bc73b3fe9f46"
+      "71105309ec9b6879d0551d930dac8ba45d25501425332844e592b440c0027972ad1526431c06732df19cd46a242172d4d"
+      "d67c2c8c99dfc22e49949a56cf90c6473635ce82f25b33682fb19bc33bd910ed8ce3a7fa",
+      "0401df277c152108349bc34d539ee0cf06b24f5d3500677b4445453ccc21409453aafb8a72a0be9ebe54d12270aa51b3a"
+      "b7f316aa5e74a951c5e53f74cd95fc29aee7a013d52f33a9f3c14384d1587fa8abe7aed74bc33749ad9c570b471776422c"
+      "7d4505d9b0a96b3bfac041e4c6a6990ae7f700e5b4a6640229112deafa0cd8bb0d089b0",
+      "000b3920ac830ade812c8f96805da2236e002acbbf13596a9ab254d44d0e91b6255ebf1229f366fb5a05c5884ef46032c2"
+      "6d42189273ca4efa4c3db6bd12a6853759",
+      "curve: P521 vector: 1" },
+
+    { ECCurve_NIST_P521,
+      "012f2e0c6d9e9d117ceb9723bced02eb3d4eebf5feeaf8ee0113ccd8057b13ddd416e0b74280c2d0ba8ed291c443bc1b14"
+      "1caf8afb3a71f97f57c225c03e1e4d42b0",
+      "0400717fcb3d4a40d103871ede044dc803db508aaa4ae74b70b9fb8d8dfd84bfecfad17871879698c292d2fd5e17b4f9343"
+      "636c531a4fac68a35a93665546b9a87867900f3d96a8637036993ab5d244500fff9d2772112826f6436603d3eb234a44d5c"
+      "4e5c577234679c4f9df725ee5b9118f23d8a58d0cc01096daf70e8dfec0128bdc2e8",
+      "040092db3142564d27a5f0006f819908fba1b85038a5bc2509906a497daac67fd7aee0fc2daba4e4334eeaef0e0019204b4"
+      "71cd88024f82115d8149cc0cf4f7ce1a4d5016bad0623f517b158d9881841d2571efbad63f85cbe2e581960c5d670601a67"
+      "60272675a548996217e4ab2b8ebce31d71fca63fcc3c08e91c1d8edd91cf6fe845f8",
+      "006b380a6e95679277cfee4e8353bf96ef2a1ebdd060749f2f046fe571053740bbcc9a0b55790bc9ab56c3208aa05ddf746"
+      "a10a3ad694daae00d980d944aabc6a08f",
+      "curve: P521 vector: 2" },
+
+    { ECCurve_NIST_P521,
+      "00e548a79d8b05f923b9825d11b656f222e8cb98b0f89de1d317184dc5a698f7c71161ee7dc11cd31f4f4f8ae3a981e1a3e7"
+      "8bdebb97d7c204b9261b4ef92e0918e0",
+      "04000ce800217ed243dd10a79ad73df578aa8a3f9194af528cd1094bbfee27a3b5481ad5862c8876c0c3f91294c0ab3aa806"
+      "d9020cbaa2ed72b7fecdc5a09a6dad6f3201543c9ab45b12469232918e21d5a351f9a4b9cbf9efb2afcc402fa9b31650bec2d6"
+      "41a05c440d35331c0893d11fb13151335988b303341301a73dc5f61d574e67d9",
+      "0400fdd40d9e9d974027cb3bae682162eac1328ad61bc4353c45bf5afe76bf607d2894c8cce23695d920f2464fda4773d4693b"
+      "e4b3773584691bdb0329b7f4c86cc2990034ceac6a3fef1c3e1c494bfe8d872b183832219a7e14da414d4e3474573671ec19b03"
+      "3be831b915435905925b44947c592959945b4eb7c951c3b9c8cf52530ba23",
+      "00fbbcd0b8d05331fef6086f22a6cce4d35724ab7a2f49dd8458d0bfd57a0b8b70f246c17c4468c076874b0dff7a0336823b19e"
+      "98bf1cec05e4beffb0591f97713c6",
+      "curve: P521 vector: 3" },
+
+    { ECCurve_NIST_P521,
+      "01c8aae94bb10b8ca4f7be577b4fb32bb2381032c4942c24fc2d753e7cc5e47b483389d9f3b956d20ee9001b1eef9f23545f72"
+      "c5602140046839e963313c3decc864",
+      "040106a14e2ee8ff970aa8ab0c79b97a33bba2958e070b75b94736b77bbe3f777324fa52872771aa88a63a9e8490c3378df4dc"
+      "760cd14d62be700779dd1a4377943656002366ce3941e0b284b1aa81215d0d3b9778fce23c8cd1e4ed6fa0abf62156c91d4b3eb"
+      "55999c3471bed275e9e60e5aa9d690d310bfb15c9c5bbd6f5e9eb39682b74",
+      "040098d99dee0816550e84dbfced7e88137fddcf581a725a455021115fe49f8dc3cf233cd9ea0e6f039dc7919da973cdceaca20"
+      "5da39e0bd98c8062536c47f258f44b500cd225c8797371be0c4297d2b457740100c774141d8f214c23b61aa2b6cd4806b9b70722"
+      "aa4965fb622f42b7391e27e5ec21c5679c5b06b59127372997d421adc1e",
+      "0145cfa38f25943516c96a5fd4bfebb2f645d10520117aa51971eff442808a23b4e23c187e639ff928c3725fbd1c0c2ad0d4aeb2"
+      "07bc1a6fb6cb6d467888dc044b3c",
+      "curve: P521 vector: 4" },
+
+    { ECCurve_NIST_P521,
+      "009b0af137c9696c75b7e6df7b73156bb2d45f482e5a4217324f478b10ceb76af09724cf86afa316e7f89918d31d54824a5c33"
+      "107a483c15c15b96edc661340b1c0e",
+      "0400748cdbb875d35f4bccb62abe20e82d32e4c14dc2feb5b87da2d0ccb11c9b6d4b7737b6c46f0dfb4d896e2db92fcf53cdbb"
+      "ae2a404c0babd564ad7adeac6273efa301984acab8d8f173323de0bb60274b228871609373bb22a17287e9dec7495873abc09a"
+      "8915b54c8455c8e02f654f602e23a2bbd7a9ebb74f3009bd65ecc650814cc0",
+      "04007ae115adaaf041691ab6b7fb8c921f99d8ed32d283d67084e80b9ad9c40c56cd98389fb0a849d9ecf7268c297b6f934061"
+      "19f40e32b5773ed25a28a9a85c4a758801a28e004e37eeaefe1f4dbb71f1878696141af3a10a9691c4ed93487214643b761fa4b"
+      "0fbeeb247cf6d3fba7a60697536ad03f49b80a9d1cb079673654977c5fa94",
+      "005c5721e96c273319fd60ecc46b5962f698e974b429f28fe6962f4ac656be2eb8674c4aafc037eab48ece612953b1e8d86101"
+      "6b6ad0c79805784c67f73ada96f351",
+      "curve: P521 vector: 5" },
+
+    { ECCurve_NIST_P521,
+      "01e48faacee6dec83ffcde944cf6bdf4ce4bae72747888ebafee455b1e91584971efb49127976a52f4142952f7c207ec0265f2b"
+      "718cf3ead96ea4f62c752e4f7acd3",
+      "04010eb1b4d9172bcc23f4f20cc9560fc54928c3f34ea61c00391dc766c76ed9fa608449377d1e4fadd1236025417330b4b91086"
+      "704ace3e4e6484c606e2a943478c860149413864069825ee1d0828da9f4a97713005e9bd1adbc3b38c5b946900721a960fe96ad2c"
+      "1b3a44fe3de9156136d44cb17cbc2415729bb782e16bfe2deb3069e43",
+      "04012588115e6f7f7bdcfdf57f03b169b479758baafdaf569d04135987b2ce6164c02a57685eb5276b5dae6295d3fe90620f38b55"
+      "35c6d2260c173e61eb888ca92020301542c169cf97c2596fe2ddd848a222e367c5f7e6267ebc1bcd9ab5dcf49158f1a48e4af29a89"
+      "7b7e6a82091c2db874d8e7abf0f58064691344154f396dbaed188b6",
+      "01736d9717429b4f412e903febe2f9e0fffd81355d6ce2c06ff3f66a3be15ceec6e65e308347593f00d7f33591da4043c30763d72"
+      "749f72cdceebe825e4b34ecd570",
+      "curve: P521 vector: 6" },
+
+    { ECCurve_NIST_P521,
+      "00c29aa223ea8d64b4a1eda27f39d3bc98ea0148dd98c1cbe595f8fd2bfbde119c9e017a50f5d1fc121c08c1cef31b75885955"
+      "6eb3e0e042d8dd6aaac57a05ca61e3",
+      "04001511c848ef60d5419a98d10204db0fe58224124370061bcfa4e9249d50618c56bf3722471b259f38263bb7b280d23caf2a"
+      "1ee8737f9371cdb2732cdc958369930c01d461681ae6d8c49b4c5f4d6016143fb1bd7491573e3ed0e6c48b82e821644f87f82f0"
+      "e5f08fd16f1f98fa17586200ab02ed8c627b35c3f27617ec5fd92f456203f",
+      "040169491d55bd09049fdf4c2a53a660480fee4c03a0538675d1cd09b5bba78dac48543ef118a1173b3fbf8b20e39ce0e6b8"
+      "90a163c50f9645b3d21d1cbb3b60a6fff40083494b2eba76910fed33c761804515011fab50e3b377abd8a8a045d886d2238d2"
+      "c268ac1b6ec88bd71b7ba78e2c33c152e4bf7da5d565e4acbecf5e92c7ad662bb",
+      "018f2ae9476c771726a77780208dedfefa205488996b18fecc50bfd4c132753f5766b2cd744afa9918606de2e016effc63622"
+      "e9029e76dc6e3f0c69f7aeced565c2c",
+      "curve: P521 vector: 7" },
+
+    { ECCurve_NIST_P521,
+      "0028692be2bf5c4b48939846fb3d5bce74654bb2646e15f8389e23708a1afadf561511ea0d9957d0b53453819d60fba8f65a1"
+      "8f7b29df021b1bb01cd163293acc3cc",
+      "0401cfdc10c799f5c79cb6930a65fba351748e07567993e5e410ef4cacc4cd8a25784991eb4674e41050f930c7190ac812b92"
+      "45f48a7973b658daf408822fe5b85f6680180d9ddfc9af77b9c4a6f02a834db15e535e0b3845b2cce30388301b51cecbe32763"
+      "07ef439b5c9e6a72dc2d94d879bc395052dbb4a5787d06efb280210fb8be037",
+      "04008415f5bbd0eee387d6c09d0ef8acaf29c66db45d6ba101860ae45d3c60e1e0e3f7247a4626a60fdd404965c3566c79f644"
+      "9e856ce0bf94619f97da8da24bd2cfb600fdd7c59c58c361bc50a7a5d0d36f723b17c4f2ad2b03c24d42dc50f74a8c465a0afc"
+      "4683f10fab84652dfe9e928c2626b5456453e1573ff60be1507467d431fbb2",
+      "0105a346988b92ed8c7a25ce4d79d21bc86cfcc7f99c6cd19dbb4a39f48ab943b79e4f0647348da0b80bd864b85c6b8d92536"
+      "d6aa544dc7537a00c858f8b66319e25",
+      "curve: P521 vector: 8" },
+
+    { ECCurve_NIST_P521,
+      "01194d1ee613f5366cbc44b504d21a0cf6715e209cd358f2dd5f3e71cc0d67d0e964168c42a084ebda746f9863a86bacffc81"
+      "9f1edf1b8c727ccfb3047240a57c435",
+      "04016bd15c8a58d366f7f2b2f298cc87b7485e9ee70d11d12448b8377c0a82c7626f67aff7f97be7a3546bf417eeeddf75a93"
+      "c130191c84108042ea2fca17fd3f80d1401560502d04b74fce1743aab477a9d1eac93e5226981fdb97a7478ce4ce566ff72439"
+      "31284fad850b0c2bcae0ddd2d97790160c1a2e77c3ed6c95ecc44b89e2637fc",
+      "0401c721eea805a5cba29f34ba5758775be0cf6160e6c08723f5ab17bf96a1ff2bd9427961a4f34b07fc0b14ca4b2bf6845de"
+      "bd5a869f124ebfa7aa72fe565050b7f1800b6e89eb0e1dcf181236f7c548fd1a8c16b258b52c1a9bfd3fe8f22841b26763265"
+      "f074c4ccf2d634ae97b701956f67a11006c52d97197d92f585f5748bc2672eeb",
+      "004531b3d2c6cd12f21604c8610e6723dbf4daf80b5a459d6ba5814397d1c1f7a21d7c114be964e27376aaebe3a7bc3d6af7"
+      "a7f8c7befb611afe487ff032921f750f",
+      "curve: P521 vector: 9" },
+
+    { ECCurve_NIST_P521,
+      "01fd90e3e416e98aa3f2b6afa7f3bf368e451ad9ca5bd54b5b14aee2ed6723dde5181f5085b68169b09fbec721372ccf6b"
+      "284713f9a6356b8d560a8ff78ca3737c88",
+      "0401ebea1b10d3e3b971b7efb69fc878de11c7f472e4e4d384c31b8d6288d8071517acade9b39796c7af5163bcf71aeda7"
+      "77533f382c6cf0a4d9bbb938c85f44b78037016b0e3e19c2996b2cbd1ff64730e7ca90edca1984f9b2951333535e5748baa"
+      "34a99f61ff4d5f812079e0f01e87789f34efdad8098015ee74a4f846dd190d16dc6e1",
+      "0401c35823e440a9363ab98d9fc7a7bc0c0532dc7977a79165599bf1a9cc64c00fb387b42cca365286e8430360bfad3643"
+      "bc31354eda50dc936c329ecdb60905c40fcb00d9e7f433531e44df4f6d514201cbaabb06badd6783e01111726d815531d23"
+      "3c5cdb722893ffbb2027259d594de77438809738120c6f783934f926c3fb69b40c409",
+      "0100c8935969077bae0ba89ef0df8161d975ec5870ac811ae7e65ca5394efba4f0633d41bf79ea5e5b9496bbd7aae000b05"
+      "94baa82ef8f244e6984ae87ae1ed124b7",
+      "curve: P521 vector: 10" },
+
+    { ECCurve_NIST_P521,
+      "009012ecfdadc85ced630afea534cdc8e9d1ab8be5f3753dcf5f2b09b40eda66fc6858549bc36e6f8df55998cfa9a0703a"
+      "ecf6c42799c245011064f530c09db98369",
+      "0400234e32be0a907131d2d128a6477e0caceb86f02479745e0fe245cb332de631c078871160482eeef584e274df7fa412c"
+      "ea3e1e91f71ecba8781d9205d48386341ad01cf86455b09b1c005cffba8d76289a3759628c874beea462f51f30bd581e380"
+      "3134307dedbb771b3334ee15be2e242cd79c3407d2f58935456c6941dd9b6d155a46",
+      "0400093057fb862f2ad2e82e581baeb3324e7b32946f2ba845a9beeed87d6995f54918ec6619b9931955d5a89d4d74adf10"
+      "46bb362192f2ef6bd3e3d2d04dd1f87054a00aa3fb2448335f694e3cda4ae0cc71b1b2f2a206fa802d7262f19983c44674f"
+      "e15327acaac1fa40424c395a6556cb8167312527fae5865ecffc14bbdc17da78cdcf",
+      "017f36af19303841d13a389d95ec0b801c7f9a679a823146c75c17bc44256e9ad422a4f8b31f14647b2c7d317b933f7c294"
+      "6c4b8abd1d56d620fab1b5ff1a3adc71f",
+      "curve: P521 vector: 11" },
+
+    { ECCurve_NIST_P521,
+      "01b5ff847f8eff20b88cfad42c06e58c3742f2f8f1fdfd64b539ba48c25926926bd5e332b45649c0b184f77255e9d58fe8"
+      "afa1a6d968e2cb1d4637777120c765c128",
+      "0401de3dc9263bc8c4969dc684be0eec54befd9a9f3dba194d8658a789341bf0d78d84da6735227cafaf093519516911975"
+      "73c8c360a11e5285712b8bbdf5ac91b977c00812de58cd095ec2e5a9b247eb3ed41d8bef6aeace194a7a05b65aa5d289fbc9"
+      "b1770ec84bb6be0c2c64cc37c1d54a7f5d71377a9adbe20f26f6f2b544a821ea831",
+      "040083192ed0b1cb31f75817794937f66ad91cf74552cd510cedb9fd641310422af5d09f221cad249ee814d16dd7ac84ded"
+      "9eacdc28340fcfc9c0c06abe30a2fc28cd8002212ed868c9ba0fb2c91e2c39ba93996a3e4ebf45f2852d0928c48930e875c"
+      "c7b428d0e7f3f4d503e5d60c68cb49b13c2480cd486bed9200caddaddfe4ff8e3562",
+      "00062f9fc29ae1a68b2ee0dcf956cbd38c88ae5f645eaa546b00ebe87a7260bf724be20d34b9d02076655c933d056b21e30"
+      "4c24ddb1dedf1dd76de611fc4a2340336",
+      "curve: P521 vector: 12" },
+
+    { ECCurve_NIST_P521,
+      "011a6347d4e801c91923488354cc533e7e35fddf81ff0fb7f56bb0726e0c29ee5dcdc5f394ba54cf57269048aab6e055895c"
+      "8da24b8b0639a742314390cc04190ed6",
+      "0400fe30267f33ba5cdefc25cbb3c9320dad9ccb1d7d376644620ca4fadee5626a3cede25ad254624def727a7048f7145f761"
+      "62aa98042f9b123b2076f8e8cf59b3fdf001145dc6631953b6e2945e94301d6cbb098fe4b04f7ee9b09411df104dc82d7d79e"
+      "c46a01ed0f2d3e7db6eb680694bdeb107c1078aec6cabd9ebee3d342fe7e54df",
+      "0401a89b636a93e5d2ba6c2292bf23033a84f06a3ac1220ea71e806afbe097a804cc67e9baa514cfb6c12c9194be30212bf7a"
+      "ae7fdf6d376c212f0554e656463ffab7e0182efcaf70fc412d336602e014da47256a0b606f2addcce8053bf817ac8656bb4e4"
+      "2f14c8cbf2a68f488ab35dcdf64056271dee1f606a440ba4bd4e5a11b8b8e54f",
+      "0128ab09bfec5406799e610f772ba17e892249fa8e0e7b18a04b9197034b250b48294f1867fb9641518f92766066a07a8b917"
+      "b0e76879e1011e51ccbd9f540c54d4f",
+      "curve: P521 vector: 13" },
+
+    { ECCurve_NIST_P521,
+      "0022b6d2a22d71dfaa811d2d9f9f31fbed27f2e1f3d239538ddf3e4cc8c39a330266db25b7bc0a9704f17bde7f3592bf5f1f2d"
+      "4b56013aacc3d8d1bc02f00d3146cc",
+      "0400ba38cfbf9fd2518a3f61d43549e7a6a6d28b2be57ffd3e0faceb636b34ed17e044a9f249dae8fc132e937e2d9349cd2ed7"
+      "7bb1049ceb692a2ec5b17ad61502a64c001ec91d3058573fa6c0564a02a1a010160c313bc7c73510dc983e5461682b5be00dbc"
+      "e7e2c682ad73f29ca822cdc111f68fabe33a7b384a648342c3cdb9f050bcdb",
+      "04017200b3f16a68cbaed2bf78ba8cddfb6cffac262bba00fbc25f9dc72a07ce59372904899f364c44cb264c097b647d4412be"
+      "e3e519892d534d9129f8a28f7500fee700baba8d672a4f4a3b63de48b96f56e18df5d68f7d70d5109833f43770d6732e06b39ad"
+      "60d93e5b43db8789f1ec0aba47286a39ea584235acea757dbf13d53b58364",
+      "0101e462e9d9159968f6440e956f11dcf2227ae4aea81667122b6af9239a291eb5d6cf5a4087f358525fcacfa46bb2db01a75a"
+      "f1ba519b2d31da33eda87a9d565748",
+      "curve: P521 vector: 14" },
+
+    { ECCurve_NIST_P521,
+      "005bacfff268acf6553c3c583b464ea36a1d35e2b257a5d49eb3419d5a095087c2fb4d15cf5bf5af816d0f3ff7586490ccd3ddc1"
+      "a98b39ce63749c6288ce0dbdac7d",
+      "040036e488da7581472a9d8e628c58d6ad727311b7e6a3f6ae33a8544f34b09280249020be7196916fafd90e2ec54b66b5468d23"
+      "61b99b56fa00d7ac37abb8c6f16653011edb9fb8adb6a43f4f5f5fdc1421c9fe04fc8ba46c9b66334e3af927c8befb4307104f299"
+      "acec4e30f812d9345c9720d19869dbfffd4ca3e7d2713eb5fc3f42615",
+      "04004efd5dbd2f979e3831ce98f82355d6ca14a5757842875882990ab85ab9b7352dd6b9b2f4ea9a1e95c3880d65d1f3602f9ca6"
+      "53dc346fac858658d75626f4d4fb080061cf15dbdaa7f31589c98400373da284506d70c89f074ed262a9e28140796b7236c2eef99"
+      "016085e71552ff488c72b7339fefb7915c38459cb20ab85aec4e45052",
+      "0141d6a4b719ab67eaf04a92c0a41e2dda78f4354fb90bdc35202cc7699b9b04d49616f82255debf7bbec045ae58f982a66905fc"
+      "fae69d689785e38c868eb4a27e7b",
+      "curve: P521 vector: 15" },
+
+    { ECCurve_NIST_P521,
+      "008e2c93c5423876223a637cad367c8589da69a2d0fc68612f31923ae50219df2452e7cc92615b67f17b57ffd2f52b19154bb40"
+      "d7715336420fde2e89fee244f59dc",
+      "0400fa3b35118d6c422570f724a26f90b2833b19239174cea081c53133f64db60d6940ea1261299c04c1f4587cdb0c4c39616"
+      "479c1bb0c146799a118032dcf98f899c00069f040229006151fa32b51f679c8816f7c17506b403809dc77cd58a2aec430d94d"
+      "13b6c916de99f355aa45fcfbc6853d686c71be496a067d24bfaea4818fc51f75",
+      "040129891de0cf3cf82e8c2cf1bf90bb296fe00ab08ca45bb7892e0e227a504fdd05d2381a4448b68adff9c4153c87eacb783"
+      "30d8bd52515f9f9a0b58e85f446bb4e10009edd679696d3d1d0ef327f200383253f6413683d9e4fcc87bb35f112c2f110098d"
+      "15e5701d7ceee416291ff5fed85e687f727388b9afe26a4f6feed560b218e6bb",
+      "00345e26e0abb1aac12b75f3a9cf41efe1c336396dffa4a067a4c2cfeb878c68b2b045faa4e5b4e6fa4678f5b603c351903b1"
+      "4bf9a6a70c439257199a640890b61d1",
+      "curve: P521 vector: 16" },
+
+    { ECCurve_NIST_P521,
+      "0004d49d39d40d8111bf16d28c5936554326b197353eebbcf47545393bc8d3aaf98f14f5be7074bfb38e6cc97b989754074da"
+      "ddb3045f4e4ce745669fdb3ec0d5fa8",
+      "04012ec226d050ce07c79b3df4d0f0891f9f7adf462e8c98dbc1a2a14f5e53a3f5ad894433587cc429a8be9ea1d84fa33b180"
+      "3690dae04da7218d30026157fc995cf52004837dfbf3426f57b5c793269130abb9a38f618532211931154db4eeb9aede88e57"
+      "290f842ea0f2ea9a5f74c6203a3920fe4e305f6118f676b154e1d75b9cb5eb88",
+      "0401a3c20240e59f5b7a3e17c275d2314ba1741210ad58b71036f8c83cc1f6b0f409dfdd9113e94b67ec39c3291426c23ffc"
+      "c447054670d2908ff8fe67dc2306034c5c01d2825bfd3af8b1e13205780c137fe938f84fde40188e61ea02cead81badfdb425"
+      "c29f7d7fb0324debadc10bbb93de68f62c35069268283f5265865db57a79f7bf7",
+      "006fe9de6fb8e672e7fd150fdc5e617fabb0d43906354ccfd224757c7276f7a1010091b17ed072074f8d10a5ec971eb35a5c"
+      "b7076603b7bc38d432cbc059f80f9488",
+      "curve: P521 vector: 17" },
+
+    { ECCurve_NIST_P521,
+      "011a5d1cc79cd2bf73ea106f0e60a5ace220813b53e27b739864334a07c03367efda7a4619fa6eef3a9746492283b3c445610"
+      "a023a9cc49bf4591140384fca5c8bb5",
+      "0400eb07c7332eedb7d3036059d35f7d2288d4377d5f42337ad3964079fb120ccd4c8bd384b585621055217023acd9a94fcb3"
+      "b965bfb394675e788ade41a1de73e620c00491a835de2e6e7deb7e090f4a11f2c460c0b1f3d5e94ee8d751014dc720784fd3b"
+      "54500c86ebaef18429f09e8e876d5d1538968a030d7715dde99f0d8f06e29d59",
+      "04007e2d138f2832e345ae8ff65957e40e5ec7163f016bdf6d24a2243daa631d878a4a16783990c722382130f9e51f0c1bd6"
+      "ff5ac96780e48b68f5dec95f42e6144bb500b0de5c896791f52886b0f09913e26e78dd0b69798fc4df6d95e3ca708ecbcbcce1c1895f"
+      "5561bbabaae372e9e67e6e1a3be60e19b470cdf673ec1fc393d3426e20",
+      "01e4e759ecedce1013baf73e6fcc0b92451d03bdd50489b78871c333114990c9ba6a9b2fc7b1a2d9a1794c1b60d9279af6f"
+      "146f0bbfb0683140403bfa4ccdb524a29",
+      "curve: P521 vector: 18" },
+
+    { ECCurve_NIST_P521,
+      "010c908caf1be74c616b625fc8c1f514446a6aec83b5937141d6afbb0a8c7666a7746fa1f7a6664a2123e8cdf6cd8bf836c5"
+      "6d3c0ebdcc980e43a186f938f3a78ae7",
+      "040031890f4c7abec3f723362285d77d2636f876817db3bbc88b01e773597b969ff6f013ea470c854ab4a7739004eb8cbea6"
+      "9b82ddf36acadd406871798ecb2ac3aa7f00d8b429ae3250266b9643c0c765a60dc10155bc2531cf8627296f4978b6640a9e"
+      "600e19d0037d58503fa80799546a814d7478a550aa90e5ebeb052527faaeae5d08",
+      "0400118c36022209b1af8ebad1a12b566fc48744576e1199fe80de1cdf851cdf03e5b9091a8f7e079e83b7f827259b691d0"
+      "c22ee29d6bdf73ec7bbfd746f2cd97a357d00da5ff4904548a342e2e7ba6a1f4ee5f840411a96cf63e6fe622f22c13e614e"
+      "0a847c11a1ab3f1d12cc850c32e095614ca8f7e2721477b486e9ff40372977c3f65c",
+      "0163c9191d651039a5fe985a0eea1eba018a40ab1937fcd2b61220820ee8f2302e9799f6edfc3f5174f369d672d377ea895"
+      "4a8d0c8b851e81a56fda95212a6578f0e",
+      "curve: P521 vector: 19" },
+
+    { ECCurve_NIST_P521,
+      "01b37d6b7288de671360425d3e5ac1ccb21815079d8d73431e9b74a6f0e7ae004a357575b11ad66642ce8b775593eba9d98"
+      "bf25c75ef0b4d3a2098bbc641f59a2b77",
+      "0400189a5ee34de7e35aefeaeef9220c18071b4c29a4c3bd9d954458bd3e82a7a34da34cff5579b8101c065b1f2f527cf45"
+      "81501e28ef5671873e65267733d003520af01eb4bc50a7b4d4599d7e3fa773ddb9eb252c9b3422872e544bdf75c7bf60f51"
+      "66ddc11eb08fa7c30822dabaee373ab468eb2d922e484e2a527fff2ebb804b7d9a37",
+      "0401780edff1ca1c03cfbe593edc6c049bcb2860294a92c355489d9afb2e702075ade1c953895a456230a0cde905de4a3f"
+      "38573dbfcccd67ad6e7e93f0b5581e926a5d00a5481962c9162962e7f0ebdec936935d0eaa813e8226d40d7f6119bfd940"
+      "602380c86721e61db1830f51e139f210000bcec0d8edd39e54d73a9a129f95cd5fa979",
+      "015d613e267a36342e0d125cdad643d80d97ed0600afb9e6b9545c9e64a98cc6da7c5aaa3a8da0bdd9dd3b97e9788218a8"
+      "0abafc106ef065c8f1c4e1119ef58d298b",
+      "curve: P521 vector: 20" },
+
+    { ECCurve_NIST_P521,
+      "00f2661ac762f60c5fff23be5d969ccd4ec6f98e4e72618d12bdcdb9b4102162333788c0bae59f91cdfc172c7a1681ee44d9"
+      "6ab2135a6e5f3415ebbcd55165b1afb0",
+      "0400a8e25a6902d687b4787cdc94c364ac7cecc5c495483ed363dc0aa95ee2bd739c4c4d46b17006c728b076350d7d7e54c"
+      "6822f52f47162a25109aaaba690cab696ec0168d2f08fe19e4dc9ee7a195b03c9f7fe6676f9f520b6270557504e72ca4394"
+      "a2c6918625e15ac0c51b8f95cd560123653fb8e8ee6db961e2c4c62cc54e92e2a2a9",
+      "04016dacffa183e5303083a334f765de724ec5ec9402026d4797884a9828a0d321a8cfac74ab737fe20a7d6befcfc73b6a3"
+      "5c1c7b01d373e31abc192d48a4241a35803011e5327cac22d305e7156e559176e19bee7e4f2f59e86f1a9d0b6603b6a7df"
+      "1069bde6387feb71587b8ffce5b266e1bae86de29378a34e5c74b6724c4d40a719923",
+      "014d6082a3b5ced1ab8ca265a8106f302146c4acb8c30bb14a4c991e3c82a9731288bdb91e0e85bda313912d06384fc44"
+      "f2153fb13506fa9cf43c9aab5750988c943",
+      "curve: P521 vector: 21" },
+
+    { ECCurve_NIST_P521,
+      "00f430ca1261f09681a9282e9e970a9234227b1d5e58d558c3cc6eff44d1bdf53de16ad5ee2b18b92d62fc79586116b0e"
+      "fc15f79340fb7eaf5ce6c44341dcf8dde27",
+      "04006c1d9b5eca87de1fb871a0a32f807c725adccde9b3967453a71347d608f0c030cd09e338cdecbf4a02015bc8a6e8"
+      "d3e2595fe773ffc2fc4e4a55d0b1a2cc00323b01141b2109e7f4981c952aa818a2b9f6f5c41feccdb7a7a45b9b4b6729"
+      "37771b008cae5f934dfe3fed10d383ab1f38769c92ce88d9be5414817ecb073a31ab368ccb",
+      "0400a091421d3703e3b341e9f1e7d58f8cf7bdbd1798d001967b801d1cec27e605c580b2387c1cb464f55ce7ac803341"
+      "02ab03cfb86d88af76c9f4129c01bedd3bbfc4008c9c577a8e6fc446815e9d40baa66025f15dae285f19eb668ee60ae9"
+      "c98e7ecdbf2b2a68e22928059f67db188007161d3ecf397e0883f0c4eb7eaf7827a62205cc",
+      "0020c00747cb8d492fd497e0fec54644bf027d418ab686381f109712a99cabe328b9743d2225836f9ad66e5d7fed1de2"
+      "47e0da92f60d5b31f9e47672e57f710598f4",
+      "curve: P521 vector: 22" },
+
+    { ECCurve_NIST_P521,
+      "005dc33aeda03c2eb233014ee468dff753b72f73b00991043ea353828ae69d4cd0fadeda7bb278b535d7c57406ff2e6e"
+      "473a5a4ff98e90f90d6dadd25100e8d85666",
+      "0400c825ba307373cec8dd2498eef82e21fd9862168dbfeb83593980ca9f82875333899fe94f137daf1c4189eb502937"
+      "c3a367ea7951ed8b0f3377fcdf2922021d46a5016b8a2540d5e65493888bc337249e67c0a68774f3e8d81e3b4574a012"
+      "5165f0bd58b8af9de74b35832539f95c3cd9f1b759408560aa6851ae3ac7555347b0d3b13b",
+      "04004f38816681771289ce0cb83a5e29a1ab06fc91f786994b23708ff08a08a0f675b809ae99e9f9967eb1a49f196057"
+      "d69e50d6dedb4dd2d9a81c02bdcc8f7f518460009efb244c8b91087de1eed766500f0e81530752d469256ef79f6b965d"
+      "8a2232a0c2dbc4e8e1d09214bab38485be6e357c4200d073b52f04e4a16fc6f5247187aecb",
+      "00c2bfafcd7fbd3e2fd1c750fdea61e70bd4787a7e68468c574ee99ebc47eedef064e8944a73bcb7913dbab5d93dca6"
+      "60d216c553622362794f7a2acc71022bdb16f",
+      "curve: P521 vector: 23" },
+
+    { ECCurve_NIST_P521,
+      "00df14b1f1432a7b0fb053965fd8643afee26b2451ecb6a8a53a655d5fbe16e4c64ce8647225eb11e7fdcb23627471"
+      "dffc5c2523bd2ae89957cba3a57a23933e5a78",
+      "04004e8583bbbb2ecd93f0714c332dff5ab3bc6396e62f3c560229664329baa5138c3bb1c36428abd4e23d17fcb7"
+      "a2cfcc224b2e734c8941f6f121722d7b6b9415457601cf0874f204b0363f020864672fadbf87c8811eb147758b254b"
+      "74b14fae742159f0f671a018212bbf25b8519e126d4cad778cfff50d288fd39ceb0cac635b175ec0",
+      "0401a32099b02c0bd85371f60b0dd20890e6c7af048c8179890fda308b359dbbc2b7a832bb8c6526c4af99a7ea3f0"
+      "b3cb96ae1eb7684132795c478ad6f962e4a6f446d017627357b39e9d7632a1370b3e93c1afb5c851b910eb4ead0c9"
+      "d387df67cde85003e0e427552f1cd09059aad0262e235cce5fba8cedc4fdc1463da76dcd4b6d1a46",
+      "01aaf24e5d47e4080c18c55ea35581cd8da30f1a079565045d2008d51b12d0abb4411cda7a0785b15d149ed301a36"
+      "97062f42da237aa7f07e0af3fd00eb1800d9c41",
+      "curve: P521 vector: 24" },
+
+    { ECCurve_pastLastCurve, NULL, NULL, NULL, NULL, NULL }
+};
--- a/security/nss/cmd/httpserv/httpserv.c
+++ b/security/nss/cmd/httpserv/httpserv.c
@@ -273,17 +273,17 @@ launch_threads(
         slot->c = c;
         slot->startFunc = startFunc;
         slot->prThread = PR_CreateThread(PR_USER_THREAD,
                                          thread_wrapper, slot, PR_PRIORITY_NORMAL,
                                          (PR_TRUE ==
                                           local)
                                              ? PR_LOCAL_THREAD
                                              : PR_GLOBAL_THREAD,
-                                         PR_UNJOINABLE_THREAD, 0);
+                                         PR_JOINABLE_THREAD, 0);
         if (slot->prThread == NULL) {
             printf("httpserv: Failed to launch thread!\n");
             slot->state = rs_idle;
             rv = SECFailure;
             break;
         }
 
         ++threadCount;
@@ -302,23 +302,34 @@ launch_threads(
     if (name) {               \
         PZ_DestroyLock(name); \
         name = NULL;          \
     }
 
 void
 terminateWorkerThreads(void)
 {
-    VLOG(("httpserv: server_thead: waiting on stopping"));
+    int i;
+
+    VLOG(("httpserv: server_thread: waiting on stopping"));
     PZ_Lock(qLock);
     PZ_NotifyAllCondVar(jobQNotEmptyCv);
-    while (threadCount > 0) {
-        PZ_WaitCondVar(threadCountChangeCv, PR_INTERVAL_NO_TIMEOUT);
+    PZ_Unlock(qLock);
+
+    /* Wait for worker threads to terminate. */
+    for (i = 0; i < maxThreads; ++i) {
+        perThread *slot = threads + i;
+        if (slot->prThread) {
+            PR_JoinThread(slot->prThread);
+        }
     }
+
     /* The worker threads empty the jobQ before they terminate. */
+    PZ_Lock(qLock);
+    PORT_Assert(threadCount == 0);
     PORT_Assert(PR_CLIST_IS_EMPTY(&jobQ));
     PZ_Unlock(qLock);
 
     DESTROY_CONDVAR(jobQNotEmptyCv);
     DESTROY_CONDVAR(freeListNotEmptyCv);
     DESTROY_CONDVAR(threadCountChangeCv);
 
     PR_DestroyLock(lastLoadedCrlLock);
--- a/security/nss/cmd/manifest.mn
+++ b/security/nss/cmd/manifest.mn
@@ -38,16 +38,17 @@ NSS_SRCDIRS = \
  certutil  \
  chktest  \
  crlutil  \
  crmftest \
  dbtest \
  derdump  \
  digest  \
  ecperf \
+ ectest \
  httpserv  \
  listsuites \
  makepqg  \
  multinit \
  ocspclnt  \
  ocspresp \
  oidcalc  \
  p7content  \
--- a/security/nss/cmd/selfserv/selfserv.c
+++ b/security/nss/cmd/selfserv/selfserv.c
@@ -156,17 +156,17 @@ static void
 PrintUsageHeader(const char *progName)
 {
     fprintf(stderr,
             "Usage: %s -n rsa_nickname -p port [-BDENRbjlmrsuvx] [-w password]\n"
             "         [-t threads] [-i pid_file] [-c ciphers] [-Y] [-d dbdir] [-g numblocks]\n"
             "         [-f password_file] [-L [seconds]] [-M maxProcs] [-P dbprefix]\n"
             "         [-V [min-version]:[max-version]] [-a sni_name]\n"
             "         [ T <good|revoked|unknown|badsig|corrupted|none|ocsp>] [-A ca]\n"
-            "         [-C SSLCacheEntries] [-S dsa_nickname]"
+            "         [-C SSLCacheEntries] [-S dsa_nickname] -Q"
 #ifndef NSS_DISABLE_ECC
             " [-e ec_nickname]"
 #endif /* NSS_DISABLE_ECC */
             "\n"
             "         -U [0|1] -H [0|1|2] -W [0|1]\n",
             progName);
 }
 
@@ -219,17 +219,18 @@ PrintParameterUsage()
         "   ocsp: fetch from external OCSP server using AIA, or none\n"
         "-A <ca> Nickname of a CA used to sign a stapled cert status\n"
         "-U override default ECDHE ephemeral key reuse, 0: refresh, 1: reuse\n"
         "-H override default DHE server support, 0: disable, 1: enable, "
             " 2: require DH named groups\n"
         "-W override default DHE server weak parameters support, 0: disable, 1: enable\n"
         "-c Restrict ciphers\n"
         "-Y prints cipher values allowed for parameter -c and exits\n"
-        "-G enables the extended master secret extension [RFC7627]\n",
+        "-G enables the extended master secret extension [RFC7627]\n"
+        "-Q enables ALPN for HTTP/1.1 [RFC7301]\n",
         stderr);
 }
 
 static void
 Usage(const char *progName)
 {
     PrintUsageHeader(progName);
     PrintParameterUsage();
@@ -843,16 +844,17 @@ PRBool disableStepDown = PR_FALSE;
 PRBool bypassPKCS11 = PR_FALSE;
 PRBool disableLocking = PR_FALSE;
 PRBool testbypass = PR_FALSE;
 PRBool enableSessionTickets = PR_FALSE;
 PRBool enableCompression = PR_FALSE;
 PRBool failedToNegotiateName = PR_FALSE;
 PRBool enableExtendedMasterSecret = PR_FALSE;
 PRBool zeroRTT = PR_FALSE;
+PRBool enableALPN = PR_FALSE;
 
 static char *virtServerNameArray[MAX_VIRT_SERVER_NAME_ARRAY_INDEX];
 static int virtServerNameIndex = 1;
 
 static const char stopCmd[] = { "GET /stop " };
 static const char getCmd[] = { "GET " };
 static const char EOFmsg[] = { "EOF\r\n\r\n\r\n" };
 static const char outHeader[] = {
@@ -2007,16 +2009,30 @@ server_main(
             errExit("You tried enabling 0RTT without enabling TLS 1.3!");
         }
         rv = SSL_OptionSet(model_sock, SSL_ENABLE_0RTT_DATA, PR_TRUE);
         if (rv != SECSuccess) {
             errExit("error enabling 0RTT ");
         }
     }
 
+    if (enableALPN) {
+        PRUint8 alpnVal[] = {0x08,
+                             0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31};
+        rv = SSL_OptionSet(model_sock, SSL_ENABLE_ALPN, PR_TRUE);
+        if (rv != SECSuccess) {
+            errExit("error enabling ALPN");
+        }
+
+        rv = SSL_SetNextProtoNego(model_sock, alpnVal, sizeof(alpnVal));
+        if (rv != SECSuccess) {
+            errExit("error enabling ALPN");
+        }
+    }
+
     /* This cipher is not on by default. The Acceptance test
      * would like it to be. Turn this cipher on.
      */
 
     secStatus = SSL_CipherPrefSetDefault(TLS_RSA_WITH_NULL_MD5, PR_TRUE);
     if (secStatus != SECSuccess) {
         errExit("SSL_CipherPrefSetDefault:TLS_RSA_WITH_NULL_MD5");
     }
@@ -2259,17 +2275,17 @@ main(int argc, char **argv)
 
     PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
     SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions);
 
     /* please keep this list of options in ASCII collating sequence.
     ** numbers, then capital letters, then lower case, alphabetical.
     */
     optstate = PL_CreateOptState(argc, argv,
-                                 "2:A:BC:DEGH:L:M:NP:RS:T:U:V:W:YZa:bc:d:e:f:g:hi:jk:lmn:op:qrst:uvw:xyz");
+                                 "2:A:BC:DEGH:L:M:NP:QRS:T:U:V:W:YZa:bc:d:e:f:g:hi:jk:lmn:op:qrst:uvw:xyz");
     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
         ++optionsFound;
         switch (optstate->option) {
             case '2':
                 fileName = optstate->value;
                 break;
 
             case 'A':
@@ -2486,16 +2502,20 @@ main(int argc, char **argv)
             case 'z':
                 enableCompression = PR_TRUE;
                 break;
 
             case 'Z':
                 zeroRTT = PR_TRUE;
                 break;
 
+            case 'Q':
+                enableALPN = PR_TRUE;
+                break;
+
             default:
             case '?':
                 fprintf(stderr, "Unrecognized or bad option specified.\n");
                 fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
                 exit(4);
                 break;
         }
     }
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,8 +5,9 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
+
--- a/security/nss/external_tests/common/scoped_ptrs.h
+++ b/security/nss/external_tests/common/scoped_ptrs.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef scoped_ptrs_h__
 #define scoped_ptrs_h__
 
+#include <memory>
 #include "cert.h"
 #include "keyhi.h"
 #include "pk11pub.h"
 
 namespace nss_test {
 
 struct ScopedDelete {
   void operator()(CERTCertificate* cert) { CERT_DestroyCertificate(cert); }
--- a/security/nss/external_tests/pk11_gtest/manifest.mn
+++ b/security/nss/external_tests/pk11_gtest/manifest.mn
@@ -2,16 +2,17 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 CORE_DEPTH = ../..
 DEPTH      = ../..
 MODULE = nss
 
 CPPSRCS = \
+      pk11_aeskeywrap_unittest.cc \
       pk11_chacha20poly1305_unittest.cc \
       pk11_pbkdf2_unittest.cc \
       pk11_prf_unittest.cc \
       pk11_rsapss_unittest.cc \
       $(NULL)
 
 INCLUDES += -I$(CORE_DEPTH)/external_tests/google_test/gtest/include \
             -I$(CORE_DEPTH)/external_tests/common
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/pk11_gtest/pk11_aeskeywrap_unittest.cc
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nss.h"
+#include "pk11pub.h"
+#include <memory>
+
+#include "gtest/gtest.h"
+#include "scoped_ptrs.h"
+
+namespace nss_test {
+
+// Test vectors from https://tools.ietf.org/html/rfc3394#section-4.1 to 4.6
+unsigned char kKEK1[] = {
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+unsigned char kKD1[] = {
+  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+  0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
+};
+
+unsigned char kC1[] = {
+  0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47,
+  0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82,
+  0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5
+};
+
+unsigned char kKEK2[] = {
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
+};
+
+unsigned char kC2[] = {
+  0x96, 0x77, 0x8B, 0x25, 0xAE, 0x6C, 0xA4, 0x35,
+  0xF9, 0x2B, 0x5B, 0x97, 0xC0, 0x50, 0xAE, 0xD2,
+  0x46, 0x8A, 0xB8, 0xA1, 0x7A, 0xD8, 0x4E, 0x5D
+};
+
+unsigned char kKEK3[] = {
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+  0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
+};
+
+unsigned char kC3[] = {
+  0x64, 0xE8, 0xC3, 0xF9, 0xCE, 0x0F, 0x5B, 0xA2,
+  0x63, 0xE9, 0x77, 0x79, 0x05, 0x81, 0x8A, 0x2A,
+  0x93, 0xC8, 0x19, 0x1E, 0x7D, 0x6E, 0x8A, 0xE7
+};
+
+unsigned char kKD4[] = {
+  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+  0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+};
+
+unsigned char kC4[] = {
+  0x03, 0x1D, 0x33, 0x26, 0x4E, 0x15, 0xD3, 0x32,
+  0x68, 0xF2, 0x4E, 0xC2, 0x60, 0x74, 0x3E, 0xDC,
+  0xE1, 0xC6, 0xC7, 0xDD, 0xEE, 0x72, 0x5A, 0x93,
+  0x6B, 0xA8, 0x14, 0x91, 0x5C, 0x67, 0x62, 0xD2
+};
+
+unsigned char kC5[] = {
+  0xA8, 0xF9, 0xBC, 0x16, 0x12, 0xC6, 0x8B, 0x3F,
+  0xF6, 0xE6, 0xF4, 0xFB, 0xE3, 0x0E, 0x71, 0xE4,
+  0x76, 0x9C, 0x8B, 0x80, 0xA3, 0x2C, 0xB8, 0x95,
+  0x8C, 0xD5, 0xD1, 0x7D, 0x6B, 0x25, 0x4D, 0xA1
+};
+
+unsigned char kKD6[] = {
+  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+  0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+unsigned char kC6[] = {
+  0x28, 0xC9, 0xF4, 0x04, 0xC4, 0xB8, 0x10, 0xF4,
+  0xCB, 0xCC, 0xB3, 0x5C, 0xFB, 0x87, 0xF8, 0x26,
+  0x3F, 0x57, 0x86, 0xE2, 0xD8, 0x0E, 0xD3, 0x26,
+  0xCB, 0xC7, 0xF0, 0xE7, 0x1A, 0x99, 0xF4, 0x3B,
+  0xFB, 0x98, 0x8B, 0x9B, 0x7A, 0x02, 0xDD, 0x21
+};
+
+class Pkcs11AESKeyWrapTest : public ::testing::Test {
+ protected:
+  CK_MECHANISM_TYPE mechanism = CKM_NSS_AES_KEY_WRAP;
+
+  void
+  WrapUnwrap(unsigned char* kek, unsigned int kekLen, unsigned char* keyData,
+             unsigned int keyDataLen, unsigned char* expectedCiphertext)
+  {
+    unsigned char wrappedKey[40];
+    unsigned int wrappedKeyLen;
+    unsigned char unwrappedKey[40];
+    unsigned int unwrappedKeyLen = 0;
+    SECStatus rv;
+
+    ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
+    ASSERT_NE(nullptr, slot);
+
+    // Import encryption key.
+    SECItem keyItem = { siBuffer, kek, kekLen };
+    ScopedPK11SymKey encryptionKey(PK11_ImportSymKey(slot.get(), CKM_NSS_AES_KEY_WRAP,
+                                                     PK11_OriginUnwrap, CKA_ENCRYPT,
+                                                     &keyItem, nullptr));
+    EXPECT_TRUE(!!encryptionKey);
+
+    // Wrap key
+    rv = PK11_Encrypt(encryptionKey.get(), mechanism, nullptr /* param */,
+                      wrappedKey, &wrappedKeyLen, sizeof(wrappedKey),
+                      keyData, keyDataLen);
+    EXPECT_EQ(rv, SECSuccess) << "CKM_NSS_AES_KEY_WRAP encrypt failed";
+    EXPECT_TRUE(!memcmp(expectedCiphertext, wrappedKey, wrappedKeyLen));
+
+    // Unwrap key
+    rv = PK11_Decrypt(encryptionKey.get(), mechanism, nullptr /* param */,
+                      unwrappedKey, &unwrappedKeyLen, sizeof(unwrappedKey),
+                      wrappedKey, wrappedKeyLen);
+    EXPECT_EQ(rv, SECSuccess) << " CKM_NSS_AES_KEY_WRAP decrypt failed\n";
+    EXPECT_TRUE(!memcmp(keyData, unwrappedKey, unwrappedKeyLen));
+  }
+};
+
+TEST_F(Pkcs11AESKeyWrapTest, WrapUnwrepTest1) {
+  WrapUnwrap(kKEK1, sizeof(kKEK1), kKD1, sizeof(kKD1), kC1);
+}
+
+TEST_F(Pkcs11AESKeyWrapTest, WrapUnwrepTest2) {
+  WrapUnwrap(kKEK2, sizeof(kKEK2), kKD1, sizeof(kKD1), kC2);
+}
+
+TEST_F(Pkcs11AESKeyWrapTest, WrapUnwrepTest3) {
+  WrapUnwrap(kKEK3, sizeof(kKEK3), kKD1, sizeof(kKD1), kC3);
+}
+
+TEST_F(Pkcs11AESKeyWrapTest, WrapUnwrepTest4) {
+  WrapUnwrap(kKEK2, sizeof(kKEK2), kKD4, sizeof(kKD4), kC4);
+}
+
+TEST_F(Pkcs11AESKeyWrapTest, WrapUnwrepTest5) {
+  WrapUnwrap(kKEK3, sizeof(kKEK3), kKD4, sizeof(kKD4), kC5);
+}
+
+TEST_F(Pkcs11AESKeyWrapTest, WrapUnwrepTest6) {
+  WrapUnwrap(kKEK3, sizeof(kKEK3), kKD6, sizeof(kKD6), kC6);
+}
+
+} /* nss_test */
\ No newline at end of file
--- a/security/nss/external_tests/ssl_gtest/Makefile
+++ b/security/nss/external_tests/ssl_gtest/Makefile
@@ -42,8 +42,12 @@ include $(CORE_DEPTH)/coreconf/rules.mk
 #######################################################################
 # (6) Execute "component" rules. (OPTIONAL)                           #
 #######################################################################
 
 
 #######################################################################
 # (7) Execute "local" rules. (OPTIONAL).                              #
 #######################################################################
+
+ifndef NSS_ENABLE_TLS_1_3
+CPPSRCS := $(filter-out ssl_0rtt_unittest.cc, $(CPPSRCS))
+endif
--- a/security/nss/external_tests/ssl_gtest/manifest.mn
+++ b/security/nss/external_tests/ssl_gtest/manifest.mn
@@ -7,24 +7,31 @@ DEPTH      = ../..
 MODULE = nss
 
 # These sources have access to libssl internals
 CSRCS = \
       libssl_internals.c \
       $(NULL)
 
 CPPSRCS = \
+      ssl_0rtt_unittest.cc \
       ssl_agent_unittest.cc \
+      ssl_auth_unittest.cc \
       ssl_ciphersuite_unittest.cc \
       ssl_dhe_unittest.cc \
+      ssl_drop_unittest.cc \
+      ssl_ems_unittest.cc \
       ssl_extension_unittest.cc \
       ssl_gtest.cc \
       ssl_loopback_unittest.cc \
+      ssl_resumption_unittest.cc \
       ssl_skip_unittest.cc \
+      ssl_staticrsa_unittest.cc \
       ssl_v2_client_hello_unittest.cc \
+      ssl_version_unittest.cc \
       test_io.cc \
       tls_agent.cc \
       tls_connect.cc \
       tls_hkdf_unittest.cc \
       tls_filter.cc \
       tls_parser.cc \
       $(NULL)
 
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/ssl_0rtt_unittest.cc
@@ -0,0 +1,204 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secerr.h"
+#include "ssl.h"
+#include "sslerr.h"
+#include "sslproto.h"
+
+extern "C" {
+// This is not something that should make you happy.
+#include "libssl_internals.h"
+}
+
+#include "scoped_ptrs.h"
+#include "tls_parser.h"
+#include "tls_filter.h"
+#include "tls_connect.h"
+#include "gtest_utils.h"
+
+namespace nss_test {
+
+TEST_F(TlsConnectTest, DamageSecretHandleZeroRttClientFinished) {
+  SetupForZeroRtt();
+  client_->Set0RttEnabled(true);
+  server_->Set0RttEnabled(true);
+  client_->SetPacketFilter(new AfterRecordN(
+      client_,
+      server_,
+      0, // ClientHello.
+      [this]() {
+        SSLInt_DamageEarlyTrafficSecret(server_->ssl_fd());
+      }));
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
+  server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
+}
+
+TEST_F(TlsConnectTest, ZeroRttServerRejectByOption) {
+  SetupForZeroRtt();
+  client_->Set0RttEnabled(true);
+  ExpectResumption(RESUME_TICKET);
+  ZeroRttSendReceive(false);
+  Handshake();
+  CheckConnected();
+  SendReceive();
+}
+
+TEST_F(TlsConnectTest, ZeroRttServerForgetTicket) {
+  SetupForZeroRtt();
+  client_->Set0RttEnabled(true);
+  server_->Set0RttEnabled(true);
+  ClearServerCache();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  ExpectResumption(RESUME_NONE);
+  ZeroRttSendReceive(false);
+  Handshake();
+  CheckConnected();
+  SendReceive();
+}
+
+TEST_F(TlsConnectTest, ZeroRttServerOnly) {
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  ExpectResumption(RESUME_NONE);
+  server_->Set0RttEnabled(true);
+  client_->StartConnect();
+  server_->StartConnect();
+
+  // Client sends ordinary ClientHello.
+  client_->Handshake();
+
+  // Verify that the server doesn't get data.
+  uint8_t buf[100];
+  PRInt32 rv = PR_Read(server_->ssl_fd(), buf, sizeof(buf));
+  EXPECT_EQ(SECFailure, rv);
+  EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
+
+  // Now make sure that things complete.
+  Handshake();
+  CheckConnected();
+  SendReceive();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+}
+
+TEST_F(TlsConnectTest, ZeroRtt) {
+  SetupForZeroRtt();
+  client_->Set0RttEnabled(true);
+  server_->Set0RttEnabled(true);
+  ExpectResumption(RESUME_TICKET);
+  ZeroRttSendReceive(true);
+  Handshake();
+  ExpectEarlyDataAccepted(true);
+  CheckConnected();
+  SendReceive();
+}
+
+TEST_F(TlsConnectTest, TestTls13ZeroRttAlpn) {
+  EnableAlpn();
+  SetupForZeroRtt();
+  EnableAlpn();
+  client_->Set0RttEnabled(true);
+  server_->Set0RttEnabled(true);
+  ExpectResumption(RESUME_TICKET);
+  ExpectEarlyDataAccepted(true);
+  ZeroRttSendReceive(true, [this]() {
+      client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "a");
+      return true;
+    });
+  Handshake();
+  CheckConnected();
+  SendReceive();
+  CheckAlpn("a");
+}
+
+// Remove the old ALPN value and so the client will not offer ALPN.
+TEST_F(TlsConnectTest, TestTls13ZeroRttAlpnChangeBoth) {
+  EnableAlpn();
+  SetupForZeroRtt();
+  static const uint8_t alpn[] = { 0x01, 0x62 };  // "b"
+  EnableAlpn(alpn, sizeof(alpn));
+  client_->Set0RttEnabled(true);
+  server_->Set0RttEnabled(true);
+  ExpectResumption(RESUME_TICKET);
+  ZeroRttSendReceive(false, [this]() {
+      client_->CheckAlpn(SSL_NEXT_PROTO_NO_SUPPORT);
+      return false;
+    });
+  Handshake();
+  CheckConnected();
+  SendReceive();
+  CheckAlpn("b");
+}
+
+// Have the server negotiate a different ALPN value, and therefore
+// reject 0-RTT.
+TEST_F(TlsConnectTest, TestTls13ZeroRttAlpnChangeServer) {
+  EnableAlpn();
+  SetupForZeroRtt();
+  static const uint8_t client_alpn[] = { 0x01, 0x61, 0x01, 0x62 }; // "a", "b"
+  static const uint8_t server_alpn[] = { 0x01, 0x62 };  // "b"
+  client_->EnableAlpn(client_alpn, sizeof(client_alpn));
+  server_->EnableAlpn(server_alpn, sizeof(server_alpn));
+  client_->Set0RttEnabled(true);
+  server_->Set0RttEnabled(true);
+  ExpectResumption(RESUME_TICKET);
+  ZeroRttSendReceive(false, [this]() {
+      client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "a");
+      return true;
+    });
+  Handshake();
+  CheckConnected();
+  SendReceive();
+  CheckAlpn("b");
+}
+
+// Check that the client validates the ALPN selection of the server.
+// Stomp the ALPN on the client after sending the ClientHello so
+// that the server selection appears to be incorrect. The client
+// should then fail the connection.
+TEST_F(TlsConnectTest, TestTls13ZeroRttNoAlpnServer) {
+  EnableAlpn();
+  SetupForZeroRtt();
+  client_->Set0RttEnabled(true);
+  server_->Set0RttEnabled(true);
+  EnableAlpn();
+  ExpectResumption(RESUME_TICKET);
+  ZeroRttSendReceive(true, [this]() {
+      PRUint8 b[] = {'b'};
+      client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "a");
+      EXPECT_EQ(SECSuccess, SSLInt_Set0RttAlpn(client_->ssl_fd(), b,
+                                               sizeof(b)));
+      client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "b");
+      return true;
+    });
+  Handshake();
+  client_->CheckErrorCode(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
+  server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+}
+
+// Set up with no ALPN and then set the client so it thinks it has ALPN.
+// The server responds without the extension and the client returns an
+// error.
+TEST_F(TlsConnectTest, TestTls13ZeroRttNoAlpnClient) {
+  SetupForZeroRtt();
+  client_->Set0RttEnabled(true);
+  server_->Set0RttEnabled(true);
+  ExpectResumption(RESUME_TICKET);
+  ZeroRttSendReceive(true, [this]() {
+      PRUint8 b[] = {'b'};
+      EXPECT_EQ(SECSuccess, SSLInt_Set0RttAlpn(client_->ssl_fd(), b, 1));
+      client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "b");
+      return true;
+    });
+  Handshake();
+  client_->CheckErrorCode(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
+  server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+}
+
+} // namespace nss_test
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/ssl_auth_unittest.cc
@@ -0,0 +1,340 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secerr.h"
+#include "ssl.h"
+#include "sslerr.h"
+#include "sslproto.h"
+
+extern "C" {
+// This is not something that should make you happy.
+#include "libssl_internals.h"
+}
+
+#include "scoped_ptrs.h"
+#include "tls_parser.h"
+#include "tls_filter.h"
+#include "tls_connect.h"
+#include "gtest_utils.h"
+
+namespace nss_test {
+
+TEST_P(TlsConnectGeneric, ClientAuth) {
+  client_->SetupClientAuth();
+  server_->RequestClientAuth(true);
+  Connect();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+}
+
+// In TLS 1.3, the client sends its cert rejection on the
+// second flight, and since it has already received the
+// server's Finished, it transitions to complete and
+// then gets an alert from the server. The test harness
+// doesn't handle this right yet.
+TEST_P(TlsConnectStream, DISABLED_ClientAuthRequiredRejected) {
+  server_->RequestClientAuth(true);
+  ConnectExpectFail();
+}
+
+TEST_P(TlsConnectGeneric, ClientAuthRequestedRejected) {
+  server_->RequestClientAuth(false);
+  Connect();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+}
+
+
+TEST_P(TlsConnectGeneric, ClientAuthEcdsa) {
+  Reset(TlsAgent::kServerEcdsa);
+  client_->SetupClientAuth();
+  server_->RequestClientAuth(true);
+  Connect();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa);
+}
+
+static const SSLSignatureAndHashAlg SignatureEcdsaSha384[] = {
+  {ssl_hash_sha384, ssl_sign_ecdsa}
+};
+static const SSLSignatureAndHashAlg SignatureEcdsaSha256[] = {
+  {ssl_hash_sha256, ssl_sign_ecdsa}
+};
+static const SSLSignatureAndHashAlg SignatureRsaSha384[] = {
+  {ssl_hash_sha384, ssl_sign_rsa}
+};
+static const SSLSignatureAndHashAlg SignatureRsaSha256[] = {
+  {ssl_hash_sha256, ssl_sign_rsa}
+};
+
+// When signature algorithms match up, this should connect successfully; even
+// for TLS 1.1 and 1.0, where they should be ignored.
+TEST_P(TlsConnectGeneric, SignatureAlgorithmServerAuth) {
+  client_->SetSignatureAlgorithms(SignatureEcdsaSha384,
+                                  PR_ARRAY_SIZE(SignatureEcdsaSha384));
+  server_->SetSignatureAlgorithms(SignatureEcdsaSha384,
+                                  PR_ARRAY_SIZE(SignatureEcdsaSha384));
+  Reset(TlsAgent::kServerEcdsa);
+  Connect();
+}
+
+// Here the client picks a single option, which should work in all versions.
+// Defaults on the server include the first option.
+TEST_P(TlsConnectGeneric, SignatureAlgorithmClientOnly) {
+  const SSLSignatureAndHashAlg clientAlgorithms[] = {
+    {ssl_hash_sha384, ssl_sign_ecdsa},
+    {ssl_hash_sha384, ssl_sign_rsa}, // supported but unusable
+    {ssl_hash_md5, ssl_sign_ecdsa} // unsupported and ignored
+  };
+  client_->SetSignatureAlgorithms(clientAlgorithms,
+                                  PR_ARRAY_SIZE(clientAlgorithms));
+  Reset(TlsAgent::kServerEcdsa);
+  Connect();
+}
+
+// Here the server picks a single option, which should work in all versions.
+// Defaults on the client include the provided option.
+TEST_P(TlsConnectGeneric, SignatureAlgorithmServerOnly) {
+  server_->SetSignatureAlgorithms(SignatureEcdsaSha384,
+                                  PR_ARRAY_SIZE(SignatureEcdsaSha384));
+  Reset(TlsAgent::kServerEcdsa);
+  Connect();
+}
+
+// There is no need for overlap on signatures; since we don't actually use the
+// signatures for static RSA, this should still connect successfully.
+// This should also work in TLS 1.0 and 1.1 where the algorithms aren't used.
+TEST_P(TlsConnectGenericPre13, SignatureAlgorithmNoOverlapStaticRsa) {
+  client_->SetSignatureAlgorithms(SignatureRsaSha384,
+                                  PR_ARRAY_SIZE(SignatureRsaSha384));
+  server_->SetSignatureAlgorithms(SignatureRsaSha256,
+                                  PR_ARRAY_SIZE(SignatureRsaSha256));
+  EnableOnlyStaticRsaCiphers();
+  Connect();
+  CheckKeys(ssl_kea_rsa, ssl_auth_rsa_decrypt);
+}
+
+// TODO(ekr@rtfm.com): We need to enable this for 1.3 when we fix
+// bug 1287267.
+TEST_P(TlsConnectTls12, SignatureAlgorithmNoOverlapEcdsa) {
+  Reset(TlsAgent::kServerEcdsa);
+  client_->SetSignatureAlgorithms(SignatureEcdsaSha384,
+                                  PR_ARRAY_SIZE(SignatureEcdsaSha384));
+  server_->SetSignatureAlgorithms(SignatureEcdsaSha256,
+                                  PR_ARRAY_SIZE(SignatureEcdsaSha256));
+  ConnectExpectFail();
+}
+
+// Pre 1.2, a mismatch on signature algorithms shouldn't affect anything.
+TEST_P(TlsConnectPre12, SignatureAlgorithmNoOverlapEcdsa) {
+  Reset(TlsAgent::kServerEcdsa);
+  client_->SetSignatureAlgorithms(SignatureEcdsaSha384,
+                                  PR_ARRAY_SIZE(SignatureEcdsaSha384));
+  server_->SetSignatureAlgorithms(SignatureEcdsaSha256,
+                                  PR_ARRAY_SIZE(SignatureEcdsaSha256));
+  Connect();
+}
+
+TEST_P(TlsConnectTls12Plus, RequestClientAuthWithSha384) {
+  server_->SetSignatureAlgorithms(SignatureRsaSha384,
+                                  PR_ARRAY_SIZE(SignatureRsaSha384));
+  server_->RequestClientAuth(false);
+  Connect();
+}
+
+class BeforeFinished : public TlsRecordFilter {
+ private:
+  enum HandshakeState {
+    BEFORE_CCS,
+    AFTER_CCS,
+    DONE
+  };
+
+ public:
+  BeforeFinished(TlsAgent* client, TlsAgent* server,
+                 VoidFunction before_ccs, VoidFunction before_finished)
+      : client_(client),
+        server_(server),
+        before_ccs_(before_ccs),
+        before_finished_(before_finished),
+        state_(BEFORE_CCS) {}
+
+ protected:
+  virtual PacketFilter::Action FilterRecord(
+      const RecordHeader& header, const DataBuffer& body, DataBuffer* out) {
+    switch (state_) {
+      case BEFORE_CCS:
+        // Awaken when we see the CCS.
+        if (header.content_type() == kTlsChangeCipherSpecType) {
+          before_ccs_();
+
+          // Write the CCS out as a separate write, so that we can make
+          // progress. Ordinarily, libssl sends the CCS and Finished together,
+          // but that means that they both get processed together.
+          DataBuffer ccs;
+          header.Write(&ccs, 0, body);
+          server_->SendDirect(ccs);
+          client_->Handshake();
+          state_ = AFTER_CCS;
+          // Request that the original record be dropped by the filter.
+          return DROP;
+        }
+        break;
+
+      case AFTER_CCS:
+        EXPECT_EQ(kTlsHandshakeType, header.content_type());
+        // This could check that data contains a Finished message, but it's
+        // encrypted, so that's too much extra work.
+
+        before_finished_();
+        state_ = DONE;
+        break;
+
+      case DONE:
+        break;
+    }
+    return KEEP;
+  }
+
+ private:
+  TlsAgent* client_;
+  TlsAgent* server_;
+  VoidFunction before_ccs_;
+  VoidFunction before_finished_;
+  HandshakeState state_;
+};
+
+// Running code after the client has started processing the encrypted part of
+// the server's first flight, but before the Finished is processed is very hard
+// in TLS 1.3.  These encrypted messages are sent in a single encrypted blob.
+// The following test uses DTLS to make it possible to force the client to
+// process the handshake in pieces.
+//
+// The first encrypted message from the server is dropped, and the MTU is
+// reduced to just below the original message size so that the server sends two
+// messages.  The Finished message is then processed separately.
+class BeforeFinished13 : public PacketFilter {
+ private:
+  enum HandshakeState {
+    INIT,
+    BEFORE_FIRST_FRAGMENT,
+    BEFORE_SECOND_FRAGMENT,
+    DONE
+  };
+
+ public:
+  BeforeFinished13(TlsAgent* client, TlsAgent *server,
+                   VoidFunction before_finished)
+      : client_(client),
+        server_(server),
+        before_finished_(before_finished),
+        records_(0) {}
+
+ protected:
+  virtual PacketFilter::Action Filter(const DataBuffer& input,
+                                      DataBuffer* output) {
+    switch (++records_) {
+      case 1:
+        // Packet 1 is the server's entire first flight.  Drop it.
+        EXPECT_EQ(SECSuccess,
+                  SSLInt_SetMTU(server_->ssl_fd(), input.len() - 1));
+        return DROP;
+
+        // Packet 2 is the first part of the server's retransmitted first
+        // flight.  Keep that.
+
+      case 3:
+        // Packet 3 is the second part of the server's retransmitted first
+        // flight.  Before passing that on, make sure that the client processes
+        // packet 2, then call the before_finished_() callback.
+        client_->Handshake();
+        before_finished_();
+        break;
+
+      default:
+        break;
+    }
+    return KEEP;
+  }
+
+ private:
+  TlsAgent *client_;
+  TlsAgent *server_;
+  VoidFunction before_finished_;
+  size_t records_;
+};
+
+#ifdef NSS_ENABLE_TLS_1_3
+// This test uses an AuthCertificateCallback that blocks.  A filter is used to
+// split the server's first flight into two pieces.  Before the second piece is
+// processed by the client, SSL_AuthCertificateComplete() is called.
+TEST_F(TlsConnectDatagram13, AuthCompleteBeforeFinished) {
+  client_->SetAuthCertificateCallback(
+      [](TlsAgent&, PRBool, PRBool) -> SECStatus {
+        return SECWouldBlock;
+      });
+  server_->SetPacketFilter(new BeforeFinished13(client_, server_, [this]() {
+        EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
+      }));
+  Connect();
+}
+
+static void TriggerAuthComplete(PollTarget *target, Event event) {
+  std::cerr << "client: call SSL_AuthCertificateComplete" << std::endl;
+  EXPECT_EQ(TIMER_EVENT, event);
+  TlsAgent* client = static_cast<TlsAgent*>(target);
+  EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client->ssl_fd(), 0));
+}
+
+// This test uses a simple AuthCertificateCallback.  Due to the way that the
+// entire server flight is processed, the call to SSL_AuthCertificateComplete
+// will trigger after the Finished message is processed.
+TEST_F(TlsConnectDatagram13, AuthCompleteAfterFinished) {
+  client_->SetAuthCertificateCallback(
+      [this](TlsAgent&, PRBool, PRBool) -> SECStatus {
+        Poller::Timer *timer_handle;
+        // This is really just to unroll the stack.
+        Poller::Instance()->SetTimer(1U, client_, TriggerAuthComplete,
+                                     &timer_handle);
+        return SECWouldBlock;
+      });
+  Connect();
+}
+#endif
+
+TEST_P(TlsConnectGenericPre13, ClientWriteBetweenCCSAndFinishedWithFalseStart) {
+  client_->EnableFalseStart();
+  server_->SetPacketFilter(new BeforeFinished(client_, server_, [this]() {
+        EXPECT_TRUE(client_->can_falsestart_hook_called());
+      }, [this]() {
+        // Write something, which used to fail: bug 1235366.
+        client_->SendData(10);
+      }));
+
+  Connect();
+  server_->SendData(10);
+  Receive(10);
+}
+
+TEST_P(TlsConnectGenericPre13, AuthCompleteBeforeFinishedWithFalseStart) {
+  client_->EnableFalseStart();
+  client_->SetAuthCertificateCallback(
+      [](TlsAgent&, PRBool, PRBool) -> SECStatus {
+        return SECWouldBlock;
+      });
+  server_->SetPacketFilter(new BeforeFinished(client_, server_, []() {
+        // Do nothing before CCS
+      }, [this]() {
+        EXPECT_FALSE(client_->can_falsestart_hook_called());
+        // AuthComplete before Finished still enables false start.
+        EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
+        EXPECT_TRUE(client_->can_falsestart_hook_called());
+        client_->SendData(10);
+      }));
+
+  Connect();
+  server_->SendData(10);
+  Receive(10);
+}
+
+}
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/ssl_drop_unittest.cc
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secerr.h"
+#include "ssl.h"
+
+#include "scoped_ptrs.h"
+#include "tls_parser.h"
+#include "tls_filter.h"
+#include "tls_connect.h"
+#include "gtest_utils.h"
+
+namespace nss_test {
+
+// This class selectively drops complete writes.  This relies on the fact that
+// writes in libssl are on record boundaries.
+class SelectiveDropFilter : public PacketFilter, public PollTarget {
+ public:
+  SelectiveDropFilter(uint32_t pattern)
+      : pattern_(pattern),
+        counter_(0) {}
+
+ protected:
+  virtual Action Filter(const DataBuffer& input, DataBuffer* output) override {
+    if (counter_ >= 32) {
+      return KEEP;
+    }
+    return ((1 << counter_++) & pattern_) ? DROP : KEEP;
+  }
+
+ private:
+  const uint32_t pattern_;
+  uint8_t counter_;
+};
+
+TEST_P(TlsConnectDatagram, DropClientFirstFlightOnce) {
+  client_->SetPacketFilter(new SelectiveDropFilter(0x1));
+  Connect();
+  SendReceive();
+}
+
+TEST_P(TlsConnectDatagram, DropServerFirstFlightOnce) {
+  server_->SetPacketFilter(new SelectiveDropFilter(0x1));
+  Connect();
+  SendReceive();
+}
+
+// This drops the first transmission from both the client and server of all
+// flights that they send.  Note: In DTLS 1.3, the shorter handshake means that
+// this will also drop some application data, so we can't call SendReceive().
+TEST_P(TlsConnectDatagram, DropAllFirstTransmissions) {
+  client_->SetPacketFilter(new SelectiveDropFilter(0x15));
+  server_->SetPacketFilter(new SelectiveDropFilter(0x5));
+  Connect();
+}
+
+// This drops the server's first flight three times.
+TEST_P(TlsConnectDatagram, DropServerFirstFlightThrice) {
+  server_->SetPacketFilter(new SelectiveDropFilter(0x7));
+  Connect();
+}
+
+// This drops the client's second flight once
+TEST_P(TlsConnectDatagram, DropClientSecondFlightOnce) {
+  client_->SetPacketFilter(new SelectiveDropFilter(0x2));
+  Connect();
+}
+
+// This drops the client's second flight three times.
+TEST_P(TlsConnectDatagram, DropClientSecondFlightThrice) {
+  client_->SetPacketFilter(new SelectiveDropFilter(0xe));
+  Connect();
+}
+
+// This drops the server's second flight three times.
+TEST_P(TlsConnectDatagram, DropServerSecondFlightThrice) {
+  server_->SetPacketFilter(new SelectiveDropFilter(0xe));
+  Connect();
+}
+
+} // namespace nss_test
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/ssl_ems_unittest.cc
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secerr.h"
+#include "ssl.h"
+#include "sslerr.h"
+#include "sslproto.h"
+
+#include "scoped_ptrs.h"
+#include "tls_parser.h"
+#include "tls_filter.h"
+#include "tls_connect.h"
+#include "gtest_utils.h"
+
+namespace nss_test {
+
+TEST_P(TlsConnectGenericPre13, ConnectExtendedMasterSecret) {
+  EnableExtendedMasterSecret();
+  Connect();
+  Reset();
+  ExpectResumption(RESUME_SESSIONID);
+  EnableExtendedMasterSecret();
+  Connect();
+}
+
+TEST_P(TlsConnectTls12Plus, ConnectExtendedMasterSecretSha384) {
+  EnableExtendedMasterSecret();
+  server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
+  ConnectWithCipherSuite(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
+}
+
+TEST_P(TlsConnectGenericPre13, ConnectExtendedMasterSecretStaticRSA) {
+  EnableOnlyStaticRsaCiphers();
+  EnableExtendedMasterSecret();
+  Connect();
+}
+
+TEST_P(TlsConnectGenericPre13, ConnectExtendedMasterSecretECDHE) {
+  EnableExtendedMasterSecret();
+  Connect();
+
+  Reset();
+  EnableExtendedMasterSecret();
+  ExpectResumption(RESUME_SESSIONID);
+  Connect();
+}
+
+TEST_P(TlsConnectGenericPre13, ConnectExtendedMasterSecretTicket) {
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  EnableExtendedMasterSecret();
+  Connect();
+
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+
+  EnableExtendedMasterSecret();
+  ExpectResumption(RESUME_TICKET);
+  Connect();
+}
+
+TEST_P(TlsConnectGenericPre13,
+       ConnectExtendedMasterSecretClientOnly) {
+  client_->EnableExtendedMasterSecret();
+  ExpectExtendedMasterSecret(false);
+  Connect();
+}
+
+TEST_P(TlsConnectGenericPre13,
+       ConnectExtendedMasterSecretServerOnly) {
+  server_->EnableExtendedMasterSecret();
+  ExpectExtendedMasterSecret(false);
+  Connect();
+}
+
+TEST_P(TlsConnectGenericPre13,
+       ConnectExtendedMasterSecretResumeWithout) {
+  EnableExtendedMasterSecret();
+  Connect();
+
+  Reset();
+  server_->EnableExtendedMasterSecret();
+  auto alert_recorder = new TlsAlertRecorder();
+  server_->SetPacketFilter(alert_recorder);
+  ConnectExpectFail();
+  EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
+  EXPECT_EQ(kTlsAlertHandshakeFailure, alert_recorder->description());
+}
+
+TEST_P(TlsConnectGenericPre13,
+       ConnectNormalResumeWithExtendedMasterSecret) {
+  ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
+  ExpectExtendedMasterSecret(false);
+  Connect();
+
+  Reset();
+  EnableExtendedMasterSecret();
+  ExpectResumption(RESUME_NONE);
+  Connect();
+}
+
+} // namespace nss_test
--- a/security/nss/external_tests/ssl_gtest/ssl_extension_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_extension_unittest.cc
@@ -568,17 +568,21 @@ TEST_P(TlsExtensionTestPre13, SignedCert
   client_->StartConnect();
   ASSERT_EQ(SECSuccess,
     SSL_OptionSet(client_->ssl_fd(),
       SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, PR_TRUE));
 
   SignedCertificateTimestampsExtractor timestamps_extractor(*client_);
   Handshake();
   CheckConnected();
-  timestamps_extractor.assertTimestamps(timestamps);
+  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
+    timestamps_extractor.assertTimestamps(timestamps);
+  }
+  const SECItem* c_timestamps = SSL_PeerSignedCertTimestamps(client_->ssl_fd());
+  ASSERT_EQ(SECEqual, SECITEM_CompareItem(&si_timestamps, c_timestamps));
 }
 
 // Test SSL_PeerSignedCertTimestamps returning zero-length SECItem
 // when the client / the server / both have not enabled the feature.
 TEST_P(TlsExtensionTestPre13, SignedCertificateTimestampsInactiveClient) {
   uint8_t val[] = { 0x01, 0x23, 0x45, 0x67, 0x89 };
   const SECItem si_timestamps = { siBuffer, val, sizeof(val) };
 
--- a/security/nss/external_tests/ssl_gtest/ssl_loopback_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_loopback_unittest.cc
@@ -19,104 +19,16 @@ extern "C" {
 #include "scoped_ptrs.h"
 #include "tls_parser.h"
 #include "tls_filter.h"
 #include "tls_connect.h"
 #include "gtest_utils.h"
 
 namespace nss_test {
 
-uint8_t kBogusClientKeyExchange[] = {
-  0x01, 0x00,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-};
-
-typedef std::function<void(void)> VoidFunction;
-
-// When we see the ClientKeyExchange from |client|, increment the
-// ClientHelloVersion on |server|.
-class TlsInspectorClientHelloVersionChanger : public TlsHandshakeFilter {
- public:
-  TlsInspectorClientHelloVersionChanger(TlsAgent* server) : server_(server) {}
-
-  virtual PacketFilter::Action FilterHandshake(
-      const HandshakeHeader& header,
-      const DataBuffer& input, DataBuffer* output) {
-    if (header.handshake_type() == kTlsHandshakeClientKeyExchange) {
-      EXPECT_EQ(
-          SECSuccess,
-          SSLInt_IncrementClientHandshakeVersion(server_->ssl_fd()));
-    }
-    return KEEP;
-  }
-
- private:
-  TlsAgent* server_;
-};
-
-// Set the version number in the ClientHello.
-class TlsInspectorClientHelloVersionSetter : public TlsHandshakeFilter {
- public:
-  TlsInspectorClientHelloVersionSetter(uint16_t version) : version_(version) {}
-
-  virtual PacketFilter::Action FilterHandshake(
-      const HandshakeHeader& header,
-      const DataBuffer& input, DataBuffer* output) {
-    if (header.handshake_type() == kTlsHandshakeClientHello) {
-      *output = input;
-      output->Write(0, version_, 2);
-      return CHANGE;
-    }
-    return KEEP;
-  }
-
- private:
-  uint16_t version_;
-};
-
-class TlsServerKeyExchangeEcdhe {
- public:
-  bool Parse(const DataBuffer& buffer) {
-    TlsParser parser(buffer);
-
-    uint8_t curve_type;
-    if (!parser.Read(&curve_type)) {
-      return false;
-    }
-
-    if (curve_type != 3) {  // named_curve
-      return false;
-    }
-
-    uint32_t named_curve;
-    if (!parser.Read(&named_curve, 2)) {
-      return false;
-    }
-
-    return parser.ReadVariable(&public_key_, 1);
-  }
-
-  DataBuffer public_key_;
-};
-
 TEST_P(TlsConnectGeneric, SetupOnly) {}
 
 TEST_P(TlsConnectGeneric, Connect) {
   SetExpectedVersion(std::get<1>(GetParam()));
   Connect();
   CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
 }
 
@@ -147,342 +59,16 @@ TEST_P(TlsConnectGenericPre13, ConnectEc
 }
 
 TEST_P(TlsConnectGenericPre13, ConnectFalseStart) {
   client_->EnableFalseStart();
   Connect();
   SendReceive();
 }
 
-TEST_P(TlsConnectGenericPre13, ConnectResumed) {
-  ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
-  Connect();
-
-  Reset();
-  ExpectResumption(RESUME_SESSIONID);
-  Connect();
-}
-
-TEST_P(TlsConnectGeneric, ConnectClientCacheDisabled) {
-  ConfigureSessionCache(RESUME_NONE, RESUME_SESSIONID);
-  Connect();
-  SendReceive();
-
-  Reset();
-  ExpectResumption(RESUME_NONE);
-  Connect();
-  SendReceive();
-}
-
-TEST_P(TlsConnectGeneric, ConnectServerCacheDisabled) {
-  ConfigureSessionCache(RESUME_SESSIONID, RESUME_NONE);
-  Connect();
-  SendReceive();
-
-  Reset();
-  ExpectResumption(RESUME_NONE);
-  Connect();
-  SendReceive();
-}
-
-TEST_P(TlsConnectGeneric, ConnectSessionCacheDisabled) {
-  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
-  Connect();
-  SendReceive();
-
-  Reset();
-  ExpectResumption(RESUME_NONE);
-  Connect();
-  SendReceive();
-}
-
-TEST_P(TlsConnectGeneric, ConnectResumeSupportBoth) {
-  // This prefers tickets.
-  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
-  Connect();
-  SendReceive();
-
-  Reset();
-  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
-  ExpectResumption(RESUME_TICKET);
-  Connect();
-  SendReceive();
-}
-
-TEST_P(TlsConnectGeneric, ConnectResumeClientTicketServerBoth) {
-  // This causes no resumption because the client needs the
-  // session cache to resume even with tickets.
-  ConfigureSessionCache(RESUME_TICKET, RESUME_BOTH);
-  Connect();
-  SendReceive();
-
-  Reset();
-  ConfigureSessionCache(RESUME_TICKET, RESUME_BOTH);
-  ExpectResumption(RESUME_NONE);
-  Connect();
-  SendReceive();
-}
-
-TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicket) {
-  // This causes a ticket resumption.
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  Connect();
-  SendReceive();
-
-  Reset();
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  ExpectResumption(RESUME_TICKET);
-  Connect();
-  SendReceive();
-}
-
-TEST_P(TlsConnectGeneric, ConnectResumeClientServerTicketOnly) {
-  // This causes no resumption because the client needs the
-  // session cache to resume even with tickets.
-  ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
-  Connect();
-  SendReceive();
-
-  Reset();
-  ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
-  ExpectResumption(RESUME_NONE);
-  Connect();
-  SendReceive();
-}
-
-TEST_P(TlsConnectGeneric, ConnectResumeClientBothServerNone) {
-  ConfigureSessionCache(RESUME_BOTH, RESUME_NONE);
-  Connect();
-  SendReceive();
-
-  Reset();
-  ConfigureSessionCache(RESUME_BOTH, RESUME_NONE);
-  ExpectResumption(RESUME_NONE);
-  Connect();
-  SendReceive();
-}
-
-TEST_P(TlsConnectGeneric, ConnectResumeClientNoneServerBoth) {
-  ConfigureSessionCache(RESUME_NONE, RESUME_BOTH);
-  Connect();
-  SendReceive();
-
-  Reset();
-  ConfigureSessionCache(RESUME_NONE, RESUME_BOTH);
-  ExpectResumption(RESUME_NONE);
-  Connect();
-  SendReceive();
-}
-
-TEST_P(TlsConnectGenericPre13, ConnectResumeWithHigherVersion) {
-  EnsureTlsSetup();
-  SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_1);
-  ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_1);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_1);
-  Connect();
-
-  Reset();
-  EnsureTlsSetup();
-  SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_2);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_2);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_2);
-  ExpectResumption(RESUME_NONE);
-  Connect();
-}
-
-TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicketForget) {
-  // This causes a ticket resumption.
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  Connect();
-  SendReceive();
-
-  Reset();
-  ClearServerCache();
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  ExpectResumption(RESUME_NONE);
-  Connect();
-  SendReceive();
-}
-
-// This callback switches out the "server" cert used on the server with
-// the "client" certificate, which should be the same type.
-static int32_t SwitchCertificates(TlsAgent& agent, const SECItem *srvNameArr,
-                                  uint32_t srvNameArrSize) {
-  bool ok = agent.ConfigServerCert("client");
-  if (!ok) return SSL_SNI_SEND_ALERT;
-
-  return 0; // first config
-};
-
-TEST_P(TlsConnectGeneric, ServerSNICertSwitch) {
-  Connect();
-  ScopedCERTCertificate cert1(SSL_PeerCertificate(client_->ssl_fd()));
-
-  Reset();
-  EnsureTlsSetup();
-  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
-
-  server_->SetSniCallback(SwitchCertificates);
-
-  Connect();
-  ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd()));
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-  EXPECT_FALSE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
-}
-
-TEST_P(TlsConnectGeneric, ServerSNICertTypeSwitch) {
-  Reset(TlsAgent::kServerEcdsa);
-  Connect();
-  ScopedCERTCertificate cert1(SSL_PeerCertificate(client_->ssl_fd()));
-
-  Reset();
-  EnsureTlsSetup();
-  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
-
-  // Because we configure an RSA certificate here, it only adds a second, unused
-  // certificate, which has no effect on what the server uses.
-  server_->SetSniCallback(SwitchCertificates);
-
-  Connect();
-  ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd()));
-  CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa);
-  EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
-}
-
-TEST_P(TlsConnectGeneric, ClientAuth) {
-  client_->SetupClientAuth();
-  server_->RequestClientAuth(true);
-  Connect();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-}
-
-// In TLS 1.3, the client sends its cert rejection on the
-// second flight, and since it has already received the
-// server's Finished, it transitions to complete and
-// then gets an alert from the server. The test harness
-// doesn't handle this right yet.
-TEST_P(TlsConnectStream, DISABLED_ClientAuthRequiredRejected) {
-  server_->RequestClientAuth(true);
-  ConnectExpectFail();
-}
-
-TEST_P(TlsConnectGeneric, ClientAuthRequestedRejected) {
-  server_->RequestClientAuth(false);
-  Connect();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-}
-
-
-TEST_P(TlsConnectGeneric, ClientAuthEcdsa) {
-  Reset(TlsAgent::kServerEcdsa);
-  client_->SetupClientAuth();
-  server_->RequestClientAuth(true);
-  Connect();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa);
-}
-
-static const SSLSignatureAndHashAlg SignatureEcdsaSha384[] = {
-  {ssl_hash_sha384, ssl_sign_ecdsa}
-};
-static const SSLSignatureAndHashAlg SignatureEcdsaSha256[] = {
-  {ssl_hash_sha256, ssl_sign_ecdsa}
-};
-static const SSLSignatureAndHashAlg SignatureRsaSha384[] = {
-  {ssl_hash_sha384, ssl_sign_rsa}
-};
-static const SSLSignatureAndHashAlg SignatureRsaSha256[] = {
-  {ssl_hash_sha256, ssl_sign_rsa}
-};
-
-// When signature algorithms match up, this should connect successfully; even
-// for TLS 1.1 and 1.0, where they should be ignored.
-TEST_P(TlsConnectGeneric, SignatureAlgorithmServerAuth) {
-  client_->SetSignatureAlgorithms(SignatureEcdsaSha384,
-                                  PR_ARRAY_SIZE(SignatureEcdsaSha384));
-  server_->SetSignatureAlgorithms(SignatureEcdsaSha384,
-                                  PR_ARRAY_SIZE(SignatureEcdsaSha384));
-  Reset(TlsAgent::kServerEcdsa);
-  Connect();
-}
-
-// Here the client picks a single option, which should work in all versions.
-// Defaults on the server include the first option.
-TEST_P(TlsConnectGeneric, SignatureAlgorithmClientOnly) {
-  const SSLSignatureAndHashAlg clientAlgorithms[] = {
-    {ssl_hash_sha384, ssl_sign_ecdsa},
-    {ssl_hash_sha384, ssl_sign_rsa}, // supported but unusable
-    {ssl_hash_md5, ssl_sign_ecdsa} // unsupported and ignored
-  };
-  client_->SetSignatureAlgorithms(clientAlgorithms,
-                                  PR_ARRAY_SIZE(clientAlgorithms));
-  Reset(TlsAgent::kServerEcdsa);
-  Connect();
-}
-
-// Here the server picks a single option, which should work in all versions.
-// Defaults on the client include the provided option.
-TEST_P(TlsConnectGeneric, SignatureAlgorithmServerOnly) {
-  server_->SetSignatureAlgorithms(SignatureEcdsaSha384,
-                                  PR_ARRAY_SIZE(SignatureEcdsaSha384));
-  Reset(TlsAgent::kServerEcdsa);
-  Connect();
-}
-
-// There is no need for overlap on signatures; since we don't actually use the
-// signatures for static RSA, this should still connect successfully.
-// This should also work in TLS 1.0 and 1.1 where the algorithms aren't used.
-TEST_P(TlsConnectGenericPre13, SignatureAlgorithmNoOverlapStaticRsa) {
-  client_->SetSignatureAlgorithms(SignatureRsaSha384,
-                                  PR_ARRAY_SIZE(SignatureRsaSha384));
-  server_->SetSignatureAlgorithms(SignatureRsaSha256,
-                                  PR_ARRAY_SIZE(SignatureRsaSha256));
-  EnableOnlyStaticRsaCiphers();
-  Connect();
-  CheckKeys(ssl_kea_rsa, ssl_auth_rsa_decrypt);
-}
-
-TEST_P(TlsConnectGenericPre13, ConnectStaticRSA) {
-  EnableOnlyStaticRsaCiphers();
-  Connect();
-  CheckKeys(ssl_kea_rsa, ssl_auth_rsa_decrypt);
-}
-
-// Signature algorithms governs both verification and generation of signatures.
-// With ECDSA, we need to at least have a common signature algorithm configured.
-TEST_P(TlsConnectTls12, SignatureAlgorithmNoOverlapEcdsa) {
-  Reset(TlsAgent::kServerEcdsa);
-  client_->SetSignatureAlgorithms(SignatureEcdsaSha384,
-                                  PR_ARRAY_SIZE(SignatureEcdsaSha384));
-  server_->SetSignatureAlgorithms(SignatureEcdsaSha256,
-                                  PR_ARRAY_SIZE(SignatureEcdsaSha256));
-  ConnectExpectFail();
-}
-
-// Pre 1.2, a mismatch on signature algorithms shouldn't affect anything.
-TEST_P(TlsConnectPre12, SignatureAlgorithmNoOverlapEcdsa) {
-  Reset(TlsAgent::kServerEcdsa);
-  client_->SetSignatureAlgorithms(SignatureEcdsaSha384,
-                                  PR_ARRAY_SIZE(SignatureEcdsaSha384));
-  server_->SetSignatureAlgorithms(SignatureEcdsaSha256,
-                                  PR_ARRAY_SIZE(SignatureEcdsaSha256));
-  Connect();
-}
-
-TEST_P(TlsConnectTls12, RequestClientAuthWithSha384) {
-  server_->SetSignatureAlgorithms(SignatureRsaSha384,
-                                  PR_ARRAY_SIZE(SignatureRsaSha384));
-  server_->RequestClientAuth(false);
-  Connect();
-}
-
 TEST_P(TlsConnectGeneric, ConnectAlpn) {
   EnableAlpn();
   Connect();
   CheckAlpn("a");
 }
 
 TEST_P(TlsConnectGeneric, ConnectAlpnClone) {
   EnsureModelSockets();
@@ -492,82 +78,16 @@ TEST_P(TlsConnectGeneric, ConnectAlpnClo
 
 TEST_P(TlsConnectDatagram, ConnectSrtp) {
   EnableSrtp();
   Connect();
   CheckSrtp();
   SendReceive();
 }
 
-// This class selectively drops complete writes.  This relies on the fact that
-// writes in libssl are on record boundaries.
-class SelectiveDropFilter : public PacketFilter, public PollTarget {
- public:
-  SelectiveDropFilter(uint32_t pattern)
-      : pattern_(pattern),
-        counter_(0) {}
-
- protected:
-  virtual Action Filter(const DataBuffer& input, DataBuffer* output) override {
-    if (counter_ >= 32) {
-      return KEEP;
-    }
-    return ((1 << counter_++) & pattern_) ? DROP : KEEP;
-  }
-
- private:
-  const uint32_t pattern_;
-  uint8_t counter_;
-};
-
-TEST_P(TlsConnectDatagram, DropClientFirstFlightOnce) {
-  client_->SetPacketFilter(new SelectiveDropFilter(0x1));
-  Connect();
-  SendReceive();
-}
-
-TEST_P(TlsConnectDatagram, DropServerFirstFlightOnce) {
-  server_->SetPacketFilter(new SelectiveDropFilter(0x1));
-  Connect();
-  SendReceive();
-}
-
-// This drops the first transmission from both the client and server of all
-// flights that they send.  Note: In DTLS 1.3, the shorter handshake means that
-// this will also drop some application data, so we can't call SendReceive().
-TEST_P(TlsConnectDatagram, DropAllFirstTransmissions) {
-  client_->SetPacketFilter(new SelectiveDropFilter(0x15));
-  server_->SetPacketFilter(new SelectiveDropFilter(0x5));
-  Connect();
-}
-
-// This drops the server's first flight three times.
-TEST_P(TlsConnectDatagram, DropServerFirstFlightThrice) {
-  server_->SetPacketFilter(new SelectiveDropFilter(0x7));
-  Connect();
-}
-
-// This drops the client's second flight once
-TEST_P(TlsConnectDatagram, DropClientSecondFlightOnce) {
-  client_->SetPacketFilter(new SelectiveDropFilter(0x2));
-  Connect();
-}
-
-// This drops the client's second flight three times.
-TEST_P(TlsConnectDatagram, DropClientSecondFlightThrice) {
-  client_->SetPacketFilter(new SelectiveDropFilter(0xe));
-  Connect();
-}
-
-// This drops the server's second flight three times.
-TEST_P(TlsConnectDatagram, DropServerSecondFlightThrice) {
-  server_->SetPacketFilter(new SelectiveDropFilter(0xe));
-  Connect();
-}
-
 // 1.3 is disabled in the next few tests because we don't
 // presently support resumption in 1.3.
 TEST_P(TlsConnectStreamPre13, ConnectAndClientRenegotiate) {
   Connect();
   server_->PrepareForRenegotiate();
   client_->StartRenegotiate();
   Handshake();
   CheckConnected();
@@ -576,125 +96,21 @@ TEST_P(TlsConnectStreamPre13, ConnectAnd
 TEST_P(TlsConnectStreamPre13, ConnectAndServerRenegotiate) {
   Connect();
   client_->PrepareForRenegotiate();
   server_->StartRenegotiate();
   Handshake();
   CheckConnected();
 }
 
-// Test that a totally bogus EPMS is handled correctly.
-// This test is stream so we can catch the bad_record_mac alert.
-TEST_P(TlsConnectStreamPre13, ConnectStaticRSABogusCKE) {
-  EnableOnlyStaticRsaCiphers();
-  TlsInspectorReplaceHandshakeMessage* i1 =
-      new TlsInspectorReplaceHandshakeMessage(kTlsHandshakeClientKeyExchange,
-                                              DataBuffer(
-                                                  kBogusClientKeyExchange,
-                                                  sizeof(kBogusClientKeyExchange)));
-  client_->SetPacketFilter(i1);
-  auto alert_recorder = new TlsAlertRecorder();
-  server_->SetPacketFilter(alert_recorder);
-  ConnectExpectFail();
-  EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
-  EXPECT_EQ(kTlsAlertBadRecordMac, alert_recorder->description());
-}
-
-// Test that a PMS with a bogus version number is handled correctly.
-// This test is stream so we can catch the bad_record_mac alert.
-TEST_P(TlsConnectStreamPre13, ConnectStaticRSABogusPMSVersionDetect) {
-  EnableOnlyStaticRsaCiphers();
-  client_->SetPacketFilter(new TlsInspectorClientHelloVersionChanger(
-      server_));
-  auto alert_recorder = new TlsAlertRecorder();
-  server_->SetPacketFilter(alert_recorder);
-  ConnectExpectFail();
-  EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
-  EXPECT_EQ(kTlsAlertBadRecordMac, alert_recorder->description());
-}
-
-// Test that a PMS with a bogus version number is ignored when
-// rollback detection is disabled. This is a positive control for
-// ConnectStaticRSABogusPMSVersionDetect.
-TEST_P(TlsConnectGenericPre13, ConnectStaticRSABogusPMSVersionIgnore) {
-  EnableOnlyStaticRsaCiphers();
-  client_->SetPacketFilter(new TlsInspectorClientHelloVersionChanger(
-      server_));
-  server_->DisableRollbackDetection();
-  Connect();
-}
-
 TEST_P(TlsConnectGeneric, ConnectEcdhe) {
   Connect();
   CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
 }
 
-// Prior to TLS 1.3, we were not fully ephemeral; though 1.3 fixes that
-TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceReuseKey) {
-  TlsInspectorRecordHandshakeMessage* i1 =
-      new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange);
-  server_->SetPacketFilter(i1);
-  Connect();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-  TlsServerKeyExchangeEcdhe dhe1;
-  EXPECT_TRUE(dhe1.Parse(i1->buffer()));
-
-  // Restart
-  Reset();
-  TlsInspectorRecordHandshakeMessage* i2 =
-      new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange);
-  server_->SetPacketFilter(i2);
-  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
-  Connect();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-
-  TlsServerKeyExchangeEcdhe dhe2;
-  EXPECT_TRUE(dhe2.Parse(i2->buffer()));
-
-  // Make sure they are the same.
-  EXPECT_EQ(dhe1.public_key_.len(), dhe2.public_key_.len());
-  EXPECT_TRUE(!memcmp(dhe1.public_key_.data(), dhe2.public_key_.data(),
-                      dhe1.public_key_.len()));
-}
-
-// This test parses the ServerKeyExchange, which isn't in 1.3
-TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceNewKey) {
-  server_->EnsureTlsSetup();
-  SECStatus rv =
-      SSL_OptionSet(server_->ssl_fd(), SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE);
-  EXPECT_EQ(SECSuccess, rv);
-  TlsInspectorRecordHandshakeMessage* i1 =
-      new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange);
-  server_->SetPacketFilter(i1);
-  Connect();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-  TlsServerKeyExchangeEcdhe dhe1;
-  EXPECT_TRUE(dhe1.Parse(i1->buffer()));
-
-  // Restart
-  Reset();
-  server_->EnsureTlsSetup();
-  rv = SSL_OptionSet(server_->ssl_fd(), SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE);
-  EXPECT_EQ(SECSuccess, rv);
-  TlsInspectorRecordHandshakeMessage* i2 =
-      new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange);
-  server_->SetPacketFilter(i2);
-  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
-  Connect();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-
-  TlsServerKeyExchangeEcdhe dhe2;
-  EXPECT_TRUE(dhe2.Parse(i2->buffer()));
-
-  // Make sure they are different.
-  EXPECT_FALSE((dhe1.public_key_.len() == dhe2.public_key_.len()) &&
-               (!memcmp(dhe1.public_key_.data(), dhe2.public_key_.data(),
-                        dhe1.public_key_.len())));
-}
-
 TEST_P(TlsConnectGeneric, ConnectSendReceive) {
   Connect();
   SendReceive();
 }
 
 // The next two tests takes advantage of the fact that we
 // automatically read the first 1024 bytes, so if
 // we provide 1200 bytes, they overrun the read buffer
@@ -728,389 +144,28 @@ TEST_P(TlsConnectStream, ShortRead) {
   // Read the first tranche.
   WAIT_(client_->received_bytes() == 1024, 2000);
   ASSERT_EQ(1024U, client_->received_bytes());
   // The second tranche should now immediately be available.
   client_->ReadBytes();
   ASSERT_EQ(1200U, client_->received_bytes());
 }
 
-TEST_P(TlsConnectGenericPre13, ConnectExtendedMasterSecret) {
-  EnableExtendedMasterSecret();
-  Connect();
-  Reset();
-  ExpectResumption(RESUME_SESSIONID);
-  EnableExtendedMasterSecret();
-  Connect();
-}
-
-TEST_P(TlsConnectTls12Plus, ConnectExtendedMasterSecretSha384) {
-  EnableExtendedMasterSecret();
-  server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
-  ConnectWithCipherSuite(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
-}
-
-TEST_P(TlsConnectGenericPre13, ConnectExtendedMasterSecretStaticRSA) {
-  EnableOnlyStaticRsaCiphers();
-  EnableExtendedMasterSecret();
-  Connect();
-}
-
-// This test is stream so we can catch the bad_record_mac alert.
-TEST_P(TlsConnectStreamPre13, ConnectExtendedMasterSecretStaticRSABogusCKE) {
-  EnableOnlyStaticRsaCiphers();
-  EnableExtendedMasterSecret();
-  TlsInspectorReplaceHandshakeMessage* inspect =
-      new TlsInspectorReplaceHandshakeMessage(kTlsHandshakeClientKeyExchange,
-                                              DataBuffer(
-                                                  kBogusClientKeyExchange,
-                                                  sizeof(kBogusClientKeyExchange)));
-  client_->SetPacketFilter(inspect);
-  auto alert_recorder = new TlsAlertRecorder();
-  server_->SetPacketFilter(alert_recorder);
-  ConnectExpectFail();
-  EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
-  EXPECT_EQ(kTlsAlertBadRecordMac, alert_recorder->description());
-}
-
-// This test is stream so we can catch the bad_record_mac alert.
-TEST_P(TlsConnectStreamPre13, ConnectExtendedMasterSecretStaticRSABogusPMSVersionDetect) {
-  EnableOnlyStaticRsaCiphers();
-  EnableExtendedMasterSecret();
-  client_->SetPacketFilter(new TlsInspectorClientHelloVersionChanger(
-      server_));
-  auto alert_recorder = new TlsAlertRecorder();
-  server_->SetPacketFilter(alert_recorder);
-  ConnectExpectFail();
-  EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
-  EXPECT_EQ(kTlsAlertBadRecordMac, alert_recorder->description());
-}
-
-TEST_P(TlsConnectStreamPre13, ConnectExtendedMasterSecretStaticRSABogusPMSVersionIgnore) {
-  EnableOnlyStaticRsaCiphers();
-  EnableExtendedMasterSecret();
-  client_->SetPacketFilter(new TlsInspectorClientHelloVersionChanger(
-      server_));
-  server_->DisableRollbackDetection();
-  Connect();
-}
-
-TEST_P(TlsConnectGenericPre13, ConnectExtendedMasterSecretECDHE) {
-  EnableExtendedMasterSecret();
-  Connect();
-
-  Reset();
-  EnableExtendedMasterSecret();
-  ExpectResumption(RESUME_SESSIONID);
-  Connect();
-}
-
-TEST_P(TlsConnectGenericPre13, ConnectExtendedMasterSecretTicket) {
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  EnableExtendedMasterSecret();
-  Connect();
-
-  Reset();
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-
-  EnableExtendedMasterSecret();
-  ExpectResumption(RESUME_TICKET);
-  Connect();
-}
-
-TEST_P(TlsConnectGenericPre13,
-       ConnectExtendedMasterSecretClientOnly) {
-  client_->EnableExtendedMasterSecret();
-  ExpectExtendedMasterSecret(false);
-  Connect();
-}
-
-TEST_P(TlsConnectGenericPre13,
-       ConnectExtendedMasterSecretServerOnly) {
-  server_->EnableExtendedMasterSecret();
-  ExpectExtendedMasterSecret(false);
-  Connect();
-}
-
-TEST_P(TlsConnectGenericPre13,
-       ConnectExtendedMasterSecretResumeWithout) {
-  EnableExtendedMasterSecret();
-  Connect();
-
-  Reset();
-  server_->EnableExtendedMasterSecret();
-  auto alert_recorder = new TlsAlertRecorder();
-  server_->SetPacketFilter(alert_recorder);
-  ConnectExpectFail();
-  EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
-  EXPECT_EQ(kTlsAlertHandshakeFailure, alert_recorder->description());
-}
-
-TEST_P(TlsConnectGenericPre13,
-       ConnectNormalResumeWithExtendedMasterSecret) {
-  ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
-  ExpectExtendedMasterSecret(false);
-  Connect();
-
-  Reset();
-  EnableExtendedMasterSecret();
-  ExpectResumption(RESUME_NONE);
-  Connect();
-}
-
 TEST_P(TlsConnectGeneric, ConnectWithCompressionMaybe)
 {
   EnsureTlsSetup();
   client_->EnableCompression();
   server_->EnableCompression();
   Connect();
   EXPECT_EQ(client_->version() < SSL_LIBRARY_VERSION_TLS_1_3 &&
             mode_ != DGRAM, client_->is_compressed());
   SendReceive();
 }
 
-
-TEST_P(TlsConnectStream, ServerNegotiateTls10) {
-  uint16_t minver, maxver;
-  client_->GetVersionRange(&minver, &maxver);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
-                           maxver);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
-                           SSL_LIBRARY_VERSION_TLS_1_0);
-  Connect();
-}
-
-TEST_P(TlsConnectGeneric, ServerNegotiateTls11) {
-  if (version_ < SSL_LIBRARY_VERSION_TLS_1_1)
-    return;
-
-  uint16_t minver, maxver;
-  client_->GetVersionRange(&minver, &maxver);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           maxver);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_1);
-  Connect();
-}
-
-TEST_P(TlsConnectGeneric, ServerNegotiateTls12) {
-  if (version_ < SSL_LIBRARY_VERSION_TLS_1_2)
-    return;
-
-  uint16_t minver, maxver;
-  client_->GetVersionRange(&minver, &maxver);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
-                           maxver);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
-                           SSL_LIBRARY_VERSION_TLS_1_2);
-  Connect();
-}
-
-// Test the ServerRandom version hack from
-// [draft-ietf-tls-tls13-11 Section 6.3.1.1].
-// The first three tests test for active tampering. The next
-// two validate that we can also detect fallback using the
-// SSL_SetDowngradeCheckVersion() API.
-TEST_F(TlsConnectTest, TestDowngradeDetectionToTls11) {
-  client_->SetPacketFilter(new TlsInspectorClientHelloVersionSetter
-                           (SSL_LIBRARY_VERSION_TLS_1_1));
-  ConnectExpectFail();
-  ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
-}
-
-/* Attempt to negotiate the bogus DTLS 1.1 version. */
-TEST_F(DtlsConnectTest, TestDtlsVersion11) {
-  client_->SetPacketFilter(new TlsInspectorClientHelloVersionSetter(
-      ((~0x0101) & 0xffff)));
-  ConnectExpectFail();
-  // It's kind of surprising that SSL_ERROR_NO_CYPHER_OVERLAP is
-  // what is returned here, but this is deliberate in ssl3_HandleAlert().
-  EXPECT_EQ(SSL_ERROR_NO_CYPHER_OVERLAP, client_->error_code());
-  EXPECT_EQ(SSL_ERROR_UNSUPPORTED_VERSION, server_->error_code());
-}
-
 #ifdef NSS_ENABLE_TLS_1_3
-TEST_F(TlsConnectTest, TestDowngradeDetectionToTls12) {
-  EnsureTlsSetup();
-  client_->SetPacketFilter(new TlsInspectorClientHelloVersionSetter
-                           (SSL_LIBRARY_VERSION_TLS_1_2));
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  ConnectExpectFail();
-  ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
-}
-#endif
-
-// TLS 1.1 clients do not check the random values, so we should
-// instead get a handshake failure alert from the server.
-TEST_F(TlsConnectTest, TestDowngradeDetectionToTls10) {
-  client_->SetPacketFilter(new TlsInspectorClientHelloVersionSetter
-                          (SSL_LIBRARY_VERSION_TLS_1_0));
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
-                           SSL_LIBRARY_VERSION_TLS_1_1);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
-                           SSL_LIBRARY_VERSION_TLS_1_2);
-  ConnectExpectFail();
-  ASSERT_EQ(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE, server_->error_code());
-  ASSERT_EQ(SSL_ERROR_DECRYPT_ERROR_ALERT, client_->error_code());
-}
-
-TEST_F(TlsConnectTest, TestFallbackFromTls12) {
-  EnsureTlsSetup();
-  client_->SetDowngradeCheckVersion(SSL_LIBRARY_VERSION_TLS_1_2);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_1);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_2);
-  ConnectExpectFail();
-  ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
-}
-
-#ifdef NSS_ENABLE_TLS_1_3
-TEST_F(TlsConnectTest, TestFallbackFromTls13) {
-  EnsureTlsSetup();
-  client_->SetDowngradeCheckVersion(SSL_LIBRARY_VERSION_TLS_1_3);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
-                           SSL_LIBRARY_VERSION_TLS_1_2);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  ConnectExpectFail();
-  ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
-}
-
-// Test that two TLS resumptions work and produce the same ticket.
-// This will change after bug 1257047 is fixed.
-TEST_F(TlsConnectTest, TestTls13ResumptionTwice) {
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  Connect();
-  SendReceive(); // Need to read so that we absorb the session ticket.
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-  uint16_t original_suite;
-  EXPECT_TRUE(client_->cipher_suite(&original_suite));
-
-  Reset();
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  TlsExtensionCapture *c1 =
-      new TlsExtensionCapture(kTlsExtensionPreSharedKey);
-  client_->SetPacketFilter(c1);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  ExpectResumption(RESUME_TICKET);
-  Connect();
-  SendReceive();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-  // The filter will go away when we reset, so save the captured extension.
-  DataBuffer initialTicket(c1->extension());
-  ASSERT_LT(0U, initialTicket.len());
-
-  ScopedCERTCertificate cert1(SSL_PeerCertificate(client_->ssl_fd()));
-  ASSERT_TRUE(!!cert1.get());
-
-  Reset();
-  ClearStats();
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  TlsExtensionCapture *c2 =
-      new TlsExtensionCapture(kTlsExtensionPreSharedKey);
-  client_->SetPacketFilter(c2);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  ExpectResumption(RESUME_TICKET);
-  Connect();
-  SendReceive();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-  ASSERT_LT(0U, c2->extension().len());
-
-  ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd()));
-  ASSERT_TRUE(!!cert2.get());
-
-  // Check that the cipher suite is reported the same on both sides, though in
-  // TLS 1.3 resumption actually negotiates a different cipher suite.
-  uint16_t resumed_suite;
-  EXPECT_TRUE(server_->cipher_suite(&resumed_suite));
-  EXPECT_EQ(original_suite, resumed_suite);
-  EXPECT_TRUE(client_->cipher_suite(&resumed_suite));
-  EXPECT_EQ(original_suite, resumed_suite);
-
-  // TODO(ekr@rtfm.com): This will change when we fix bug 1257047.
-  ASSERT_EQ(initialTicket, c2->extension());
-}
-
-TEST_F(TlsConnectTest, DisableClientPSKAndFailToResume) {
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  Connect();
-  SendReceive(); // Need to read so that we absorb the session ticket.
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-
-  Reset();
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  TlsExtensionCapture *capture =
-      new TlsExtensionCapture(kTlsExtensionPreSharedKey);
-  client_->SetPacketFilter(capture);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  // We need to disable ALL PSK cipher suites with the same symmetric cipher and
-  // PRF hash.  Otherwise the server will just use a different key exchange.
-  client_->DisableAllCiphers();
-  client_->EnableCiphersByAuthType(ssl_auth_rsa_sign);
-  ExpectResumption(RESUME_NONE);
-  Connect();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-  EXPECT_EQ(0U, capture->extension().len());
-}
-
-TEST_F(TlsConnectTest, DisableServerPSKAndFailToResume) {
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  Connect();
-  SendReceive(); // Need to read so that we absorb the session ticket.
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-
-  Reset();
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  TlsExtensionCapture *clientCapture =
-      new TlsExtensionCapture(kTlsExtensionPreSharedKey);
-  client_->SetPacketFilter(clientCapture);
-  TlsExtensionCapture *serverCapture =
-      new TlsExtensionCapture(kTlsExtensionPreSharedKey);
-  server_->SetPacketFilter(serverCapture);
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  // We need to disable ALL PSK cipher suites with the same symmetric cipher and
-  // PRF hash.  Otherwise the server will just use a different key exchange.
-  server_->DisableAllCiphers();
-  server_->EnableCiphersByAuthType(ssl_auth_rsa_sign);
-  ExpectResumption(RESUME_NONE);
-  Connect();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-  // The client should have the extension, but the server should not.
-  EXPECT_LT(0U, clientCapture->extension().len());
-  EXPECT_EQ(0U, serverCapture->extension().len());
-}
-
 TEST_F(TlsConnectTest, DamageSecretHandleClientFinished) {
   client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->StartConnect();
   client_->StartConnect();
   client_->Handshake();
@@ -1121,357 +176,46 @@ TEST_F(TlsConnectTest, DamageSecretHandl
   server_->Handshake();
   // The client thinks it has connected.
   EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state());
   server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
   client_->Handshake();
   client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
 }
 
-// Read record N, process it, and then run the indicated function.
-// Records are numbered from 0.
-class AfterRecordN : public TlsRecordFilter {
- public:
-  AfterRecordN(TlsAgent *src, TlsAgent *dest, unsigned int record,
-               VoidFunction func) :
-      src_(src),
-      dest_(dest),
-      record_(record),
-      func_(func),
-      counter_(0) {}
-
-  virtual PacketFilter::Action FilterRecord(
-      const RecordHeader& header, const DataBuffer& body, DataBuffer* out) {
-    if (counter_++ == record_) {
-      DataBuffer buf;
-      header.Write(&buf, 0, body);
-      src_->SendDirect(buf);
-      dest_->Handshake();
-      func_();
-      return DROP;
-    }
-
-    return KEEP;
-  }
-
- private:
-  TlsAgent *src_;
-  TlsAgent *dest_;
-  unsigned int record_;
-  VoidFunction func_;
-  unsigned int counter_;
-};
-
 TEST_F(TlsConnectTest, DamageSecretHandleServerFinished) {
   client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->SetPacketFilter(new AfterRecordN(
       server_,
       client_,
       0, // ServerHello.
       [this]() {
         SSLInt_DamageHsTrafficSecret(client_->ssl_fd());
       }));
   ConnectExpectFail();
   client_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
   server_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
 }
-
-TEST_F(TlsConnectTest, DamageSecretHandleZeroRttClientFinished) {
-  SetupForZeroRtt();
-  client_->Set0RttEnabled(true);
-  server_->Set0RttEnabled(true);
-  client_->SetPacketFilter(new AfterRecordN(
-      client_,
-      server_,
-      0, // ClientHello.
-      [this]() {
-        SSLInt_DamageEarlyTrafficSecret(server_->ssl_fd());
-      }));
-  ConnectExpectFail();
-  client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
-  server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
-}
-
-TEST_F(TlsConnectTest, ZeroRttServerRejectByOption) {
-  SetupForZeroRtt();
-  client_->Set0RttEnabled(true);
-  ExpectResumption(RESUME_TICKET);
-  ZeroRttSendReceive(false);
-  Handshake();
-  CheckConnected();
-  SendReceive();
-}
-
-TEST_F(TlsConnectTest, ZeroRttServerForgetTicket) {
-  SetupForZeroRtt();
-  client_->Set0RttEnabled(true);
-  server_->Set0RttEnabled(true);
-  ClearServerCache();
-  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
-  ExpectResumption(RESUME_NONE);
-  ZeroRttSendReceive(false);
-  Handshake();
-  CheckConnected();
-  SendReceive();
-}
-
-TEST_F(TlsConnectTest, ZeroRttServerOnly) {
-  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
-                           SSL_LIBRARY_VERSION_TLS_1_3);
-  ExpectResumption(RESUME_NONE);
-  server_->Set0RttEnabled(true);
-  client_->StartConnect();
-  server_->StartConnect();
-
-  // Client sends ordinary ClientHello.
-  client_->Handshake();
-
-  // Verify that the server doesn't get data.
-  uint8_t buf[100];
-  PRInt32 rv = PR_Read(server_->ssl_fd(), buf, sizeof(buf));
-  EXPECT_EQ(SECFailure, rv);
-  EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
-
-  // Now make sure that things complete.
-  Handshake();
-  CheckConnected();
-  SendReceive();
-  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
-}
-
-TEST_F(TlsConnectTest, ZeroRtt) {
-  SetupForZeroRtt();
-  client_->Set0RttEnabled(true);
-  server_->Set0RttEnabled(true);
-  ExpectResumption(RESUME_TICKET);
-  ZeroRttSendReceive(true);
-  Handshake();
-  ExpectEarlyDataAccepted(true);
-  CheckConnected();
-  SendReceive();
-}
-
-TEST_F(TlsConnectTest, TestTls13ZeroRttAlpn) {
-  EnableAlpn();
-  SetupForZeroRtt();
-  EnableAlpn();
-  client_->Set0RttEnabled(true);
-  server_->Set0RttEnabled(true);
-  ExpectResumption(RESUME_TICKET);
-  ExpectEarlyDataAccepted(true);
-  ZeroRttSendReceive(true, [this]() {
-      client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "a");
-      return true;
-    });
-  Handshake();
-  CheckConnected();
-  SendReceive();
-  CheckAlpn("a");
-}
-
-// Remove the old ALPN value and so the client will not offer ALPN.
-TEST_F(TlsConnectTest, TestTls13ZeroRttAlpnChangeBoth) {
-  EnableAlpn();
-  SetupForZeroRtt();
-  static const uint8_t alpn[] = { 0x01, 0x62 };  // "b"
-  EnableAlpn(alpn, sizeof(alpn));
-  client_->Set0RttEnabled(true);
-  server_->Set0RttEnabled(true);
-  ExpectResumption(RESUME_TICKET);
-  ZeroRttSendReceive(false, [this]() {
-      client_->CheckAlpn(SSL_NEXT_PROTO_NO_SUPPORT);
-      return false;
-    });
-  Handshake();
-  CheckConnected();
-  SendReceive();
-  CheckAlpn("b");
-}
-
-// Have the server negotiate a different ALPN value, and therefore
-// reject 0-RTT.
-TEST_F(TlsConnectTest, TestTls13ZeroRttAlpnChangeServer) {
-  EnableAlpn();
-  SetupForZeroRtt();
-  static const uint8_t client_alpn[] = { 0x01, 0x61, 0x01, 0x62 }; // "a", "b"
-  static const uint8_t server_alpn[] = { 0x01, 0x62 };  // "b"
-  client_->EnableAlpn(client_alpn, sizeof(client_alpn));
-  server_->EnableAlpn(server_alpn, sizeof(server_alpn));
-  client_->Set0RttEnabled(true);
-  server_->Set0RttEnabled(true);
-  ExpectResumption(RESUME_TICKET);
-  ZeroRttSendReceive(false, [this]() {
-      client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "a");
-      return true;
-    });
-  Handshake();
-  CheckConnected();
-  SendReceive();
-  CheckAlpn("b");
-}
-
-// Check that the client validates the ALPN selection of the server.
-// Stomp the ALPN on the client after sending the ClientHello so
-// that the server selection appears to be incorrect. The client
-// should then fail the connection.
-TEST_F(TlsConnectTest, TestTls13ZeroRttNoAlpnServer) {
-  EnableAlpn();
-  SetupForZeroRtt();
-  client_->Set0RttEnabled(true);
-  server_->Set0RttEnabled(true);
-  EnableAlpn();
-  ExpectResumption(RESUME_TICKET);
-  ZeroRttSendReceive(true, [this]() {
-      PRUint8 b[] = {'b'};
-      client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "a");
-      EXPECT_EQ(SECSuccess, SSLInt_Set0RttAlpn(client_->ssl_fd(), b,
-                                               sizeof(b)));
-      client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "b");
-      return true;
-    });
-  Handshake();
-  client_->CheckErrorCode(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-  server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
-}
-
-// Set up with no ALPN and then set the client so it thinks it has ALPN.
-// The server responds without the extension and the client returns an
-// error.
-TEST_F(TlsConnectTest, TestTls13ZeroRttNoAlpnClient) {
-  SetupForZeroRtt();
-  client_->Set0RttEnabled(true);
-  server_->Set0RttEnabled(true);
-  ExpectResumption(RESUME_TICKET);
-  ZeroRttSendReceive(true, [this]() {
-      PRUint8 b[] = {'b'};
-      EXPECT_EQ(SECSuccess, SSLInt_Set0RttAlpn(client_->ssl_fd(), b, 1));
-      client_->CheckAlpn(SSL_NEXT_PROTO_EARLY_VALUE, "b");
-      return true;
-    });
-  Handshake();
-  client_->CheckErrorCode(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
-  server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
-}
+#endif
 
 TEST_P(TlsConnectDatagram, TestDtlsHolddownExpiry) {
   Connect();
   std::cerr << "Expiring holddown timer\n";
   SSLInt_ForceTimerExpiry(client_->ssl_fd());
   SSLInt_ForceTimerExpiry(server_->ssl_fd());
   SendReceive();
   if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
     // One for send, one for receive.
     EXPECT_EQ(2, SSLInt_CountTls13CipherSpecs(client_->ssl_fd()));
   }
 }
 
-#endif
-
-class BeforeFinished : public TlsRecordFilter {
- private:
-  enum HandshakeState {
-    BEFORE_CCS,
-    AFTER_CCS,
-    DONE
-  };
-
- public:
-  BeforeFinished(TlsAgent* client, TlsAgent* server,
-                 VoidFunction before_ccs, VoidFunction before_finished)
-      : client_(client),
-        server_(server),
-        before_ccs_(before_ccs),
-        before_finished_(before_finished),
-        state_(BEFORE_CCS) {}
-
- protected:
-  virtual PacketFilter::Action FilterRecord(
-      const RecordHeader& header, const DataBuffer& body, DataBuffer* out) {
-    switch (state_) {
-      case BEFORE_CCS:
-        // Awaken when we see the CCS.
-        if (header.content_type() == kTlsChangeCipherSpecType) {
-          before_ccs_();
-
-          // Write the CCS out as a separate write, so that we can make
-          // progress. Ordinarily, libssl sends the CCS and Finished together,
-          // but that means that they both get processed together.
-          DataBuffer ccs;
-          header.Write(&ccs, 0, body);
-          server_->SendDirect(ccs);
-          client_->Handshake();
-          state_ = AFTER_CCS;
-          // Request that the original record be dropped by the filter.
-          return DROP;
-        }
-        break;
-
-      case AFTER_CCS:
-        EXPECT_EQ(kTlsHandshakeType, header.content_type());
-        // This could check that data contains a Finished message, but it's
-        // encrypted, so that's too much extra work.
-
-        before_finished_();
-        state_ = DONE;
-        break;
-
-      case DONE:
-        break;
-    }
-    return KEEP;
-  }
-
- private:
-  TlsAgent* client_;
-  TlsAgent* server_;
-  VoidFunction before_ccs_;
-  VoidFunction before_finished_;
-  HandshakeState state_;
-};
-
-TEST_P(TlsConnectGenericPre13, ClientWriteBetweenCCSAndFinishedWithFalseStart) {
-  client_->EnableFalseStart();
-  server_->SetPacketFilter(new BeforeFinished(client_, server_, [this]() {
-        EXPECT_TRUE(client_->can_falsestart_hook_called());
-      }, [this]() {
-        // Write something, which used to fail: bug 1235366.
-        client_->SendData(10);
-      }));
-
-  Connect();
-  server_->SendData(10);
-  Receive(10);
-}
-
-TEST_P(TlsConnectGenericPre13, AuthCompleteBeforeFinishedWithFalseStart) {
-  client_->EnableFalseStart();
-  client_->SetAuthCertificateCallback(
-      [](TlsAgent&, PRBool, PRBool) -> SECStatus {
-        return SECWouldBlock;
-      });
-  server_->SetPacketFilter(new BeforeFinished(client_, server_, []() {
-        // Do nothing before CCS
-      }, [this]() {
-        EXPECT_FALSE(client_->can_falsestart_hook_called());
-        // AuthComplete before Finished still enables false start.
-        EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
-        EXPECT_TRUE(client_->can_falsestart_hook_called());
-        client_->SendData(10);
-      }));
-
-  Connect();
-  server_->SendData(10);
-  Receive(10);
-}
-
 // Replace the point in the client key exchange message with an empty one
 class ECCClientKEXFilter : public TlsHandshakeFilter {
 public:
   ECCClientKEXFilter() {}
 
 protected:
   virtual PacketFilter::Action FilterHandshake(const HandshakeHeader &header,
                                                const DataBuffer &input,
@@ -1520,130 +264,16 @@ TEST_P(TlsConnectGenericPre13, ConnectEC
 
 TEST_P(TlsConnectGenericPre13, ConnectECDHEmptyClientPoint) {
   // add packet filter
   client_->SetPacketFilter(new ECCClientKEXFilter());
   ConnectExpectFail();
   server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH);
 }
 
-#ifdef NSS_ENABLE_TLS_1_3
-// Running code after the client has started processing the encrypted part of
-// the server's first flight, but before the Finished is processed is very hard
-// in TLS 1.3.  These encrypted messages are sent in a single encrypted blob.
-// The following test uses DTLS to make it possible to force the client to
-// process the handshake in pieces.
-//
-// The first encrypted message from the server is dropped, and the MTU is
-// reduced to just below the original message size so that the server sends two
-// messages.  The Finished message is then processed separately.
-class BeforeFinished13 : public PacketFilter {
- private:
-  enum HandshakeState {
-    INIT,
-    BEFORE_FIRST_FRAGMENT,
-    BEFORE_SECOND_FRAGMENT,
-    DONE
-  };
-
- public:
-  BeforeFinished13(TlsAgent* client, TlsAgent *server,
-                   VoidFunction before_finished)
-      : client_(client),
-        server_(server),
-        before_finished_(before_finished),
-        records_(0) {}
-
- protected:
-  virtual PacketFilter::Action Filter(const DataBuffer& input,
-                                      DataBuffer* output) {
-    switch (++records_) {
-      case 1:
-        // Packet 1 is the server's entire first flight.  Drop it.
-        EXPECT_EQ(SECSuccess,
-                  SSLInt_SetMTU(server_->ssl_fd(), input.len() - 1));
-        return DROP;
-
-        // Packet 2 is the first part of the server's retransmitted first
-        // flight.  Keep that.
-
-      case 3:
-        // Packet 3 is the second part of the server's retransmitted first
-        // flight.  Before passing that on, make sure that the client processes
-        // packet 2, then call the before_finished_() callback.
-        client_->Handshake();
-        before_finished_();
-        break;
-
-      default:
-        break;
-    }
-    return KEEP;
-  }
-
- private:
-  TlsAgent *client_;
-  TlsAgent *server_;
-  VoidFunction before_finished_;
-  size_t records_;
-};
-
-// This test uses an AuthCertificateCallback that blocks.  A filter is used to
-// split the server's first flight into two pieces.  Before the second piece is
-// processed by the client, SSL_AuthCertificateComplete() is called.
-TEST_F(TlsConnectDatagram13, AuthCompleteBeforeFinished) {
-  client_->SetAuthCertificateCallback(
-      [](TlsAgent&, PRBool, PRBool) -> SECStatus {
-        return SECWouldBlock;
-      });
-  server_->SetPacketFilter(new BeforeFinished13(client_, server_, [this]() {
-        EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
-      }));
-  Connect();
-}
-
-static void TriggerAuthComplete(PollTarget *target, Event event) {
-  std::cerr << "client: call SSL_AuthCertificateComplete" << std::endl;
-  EXPECT_EQ(TIMER_EVENT, event);
-  TlsAgent* client = static_cast<TlsAgent*>(target);
-  EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client->ssl_fd(), 0));
-}
-
-// This test uses a simple AuthCertificateCallback.  Due to the way that the
-// entire server flight is processed, the call to SSL_AuthCertificateComplete
-// will trigger after the Finished message is processed.
-TEST_F(TlsConnectDatagram13, AuthCompleteAfterFinished) {
-  client_->SetAuthCertificateCallback(
-      [this](TlsAgent&, PRBool, PRBool) -> SECStatus {
-        Poller::Timer *timer_handle;
-        // This is really just to unroll the stack.
-        Poller::Instance()->SetTimer(1U, client_, TriggerAuthComplete,
-                                     &timer_handle);
-        return SECWouldBlock;
-      });
-  Connect();
-}
-
-// The TLS v1.3 spec section C.4 states that 'Implementations MUST NOT send or
-// accept any records with a version less than { 3, 0 }'. Thus we will not
-// allow version ranges including both SSL v3 and TLS v1.3.
-TEST_F(TlsConnectTest, DisallowSSLv3HelloWithTLSv13Enabled) {
-  SECStatus rv;
-  SSLVersionRange vrange = { SSL_LIBRARY_VERSION_3_0,
-                             SSL_LIBRARY_VERSION_TLS_1_3 };
-
-  EnsureTlsSetup();
-  rv = SSL_VersionRangeSet(client_->ssl_fd(), &vrange);
-  EXPECT_EQ(SECFailure, rv);
-
-  rv = SSL_VersionRangeSet(server_->ssl_fd(), &vrange);
-  EXPECT_EQ(SECFailure, rv);
-}
-#endif // NSS_ENABLE_TLS_1_3
-
 INSTANTIATE_TEST_CASE_P(GenericStream, TlsConnectGeneric,
                         ::testing::Combine(
                           TlsConnectTestBase::kTlsModesStream,
                           TlsConnectTestBase::kTlsVAll));
 INSTANTIATE_TEST_CASE_P(GenericDatagram, TlsConnectGeneric,
                         ::testing::Combine(
                           TlsConnectTestBase::kTlsModesDatagram,
                           TlsConnectTestBase::kTlsV11Plus));
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/ssl_resumption_unittest.cc
@@ -0,0 +1,445 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secerr.h"
+#include "ssl.h"
+#include "sslerr.h"
+#include "sslproto.h"
+#include <memory>
+#include <functional>
+
+extern "C" {
+// This is not something that should make you happy.
+#include "libssl_internals.h"
+}
+
+#include "scoped_ptrs.h"
+#include "tls_parser.h"
+#include "tls_filter.h"
+#include "tls_connect.h"
+#include "gtest_utils.h"
+
+namespace nss_test {
+
+class TlsServerKeyExchangeEcdhe {
+ public:
+  bool Parse(const DataBuffer& buffer) {
+    TlsParser parser(buffer);
+
+    uint8_t curve_type;
+    if (!parser.Read(&curve_type)) {
+      return false;
+    }
+
+    if (curve_type != 3) {  // named_curve
+      return false;
+    }
+
+    uint32_t named_curve;
+    if (!parser.Read(&named_curve, 2)) {
+      return false;
+    }
+
+    return parser.ReadVariable(&public_key_, 1);
+  }
+
+  DataBuffer public_key_;
+};
+
+TEST_P(TlsConnectGenericPre13, ConnectResumed) {
+  ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
+  Connect();
+
+  Reset();
+  ExpectResumption(RESUME_SESSIONID);
+  Connect();
+}
+
+TEST_P(TlsConnectGeneric, ConnectClientCacheDisabled) {
+  ConfigureSessionCache(RESUME_NONE, RESUME_SESSIONID);
+  Connect();
+  SendReceive();
+
+  Reset();
+  ExpectResumption(RESUME_NONE);
+  Connect();
+  SendReceive();
+}
+
+TEST_P(TlsConnectGeneric, ConnectServerCacheDisabled) {
+  ConfigureSessionCache(RESUME_SESSIONID, RESUME_NONE);
+  Connect();
+  SendReceive();
+
+  Reset();
+  ExpectResumption(RESUME_NONE);
+  Connect();
+  SendReceive();
+}
+
+TEST_P(TlsConnectGeneric, ConnectSessionCacheDisabled) {
+  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
+  Connect();
+  SendReceive();
+
+  Reset();
+  ExpectResumption(RESUME_NONE);
+  Connect();
+  SendReceive();
+}
+
+TEST_P(TlsConnectGeneric, ConnectResumeSupportBoth) {
+  // This prefers tickets.
+  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+  Connect();
+  SendReceive();
+
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+  ExpectResumption(RESUME_TICKET);
+  Connect();
+  SendReceive();
+}
+
+TEST_P(TlsConnectGeneric, ConnectResumeClientTicketServerBoth) {
+  // This causes no resumption because the client needs the
+  // session cache to resume even with tickets.
+  ConfigureSessionCache(RESUME_TICKET, RESUME_BOTH);
+  Connect();
+  SendReceive();
+
+  Reset();
+  ConfigureSessionCache(RESUME_TICKET, RESUME_BOTH);
+  ExpectResumption(RESUME_NONE);
+  Connect();
+  SendReceive();
+}
+
+TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicket) {
+  // This causes a ticket resumption.
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  Connect();
+  SendReceive();
+
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  ExpectResumption(RESUME_TICKET);
+  Connect();
+  SendReceive();
+}
+
+TEST_P(TlsConnectGeneric, ConnectResumeClientServerTicketOnly) {
+  // This causes no resumption because the client needs the
+  // session cache to resume even with tickets.
+  ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
+  Connect();
+  SendReceive();
+
+  Reset();
+  ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
+  ExpectResumption(RESUME_NONE);
+  Connect();
+  SendReceive();
+}
+
+TEST_P(TlsConnectGeneric, ConnectResumeClientBothServerNone) {
+  ConfigureSessionCache(RESUME_BOTH, RESUME_NONE);
+  Connect();
+  SendReceive();
+
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_NONE);
+  ExpectResumption(RESUME_NONE);
+  Connect();
+  SendReceive();
+}
+
+TEST_P(TlsConnectGeneric, ConnectResumeClientNoneServerBoth) {
+  ConfigureSessionCache(RESUME_NONE, RESUME_BOTH);
+  Connect();
+  SendReceive();
+
+  Reset();
+  ConfigureSessionCache(RESUME_NONE, RESUME_BOTH);
+  ExpectResumption(RESUME_NONE);
+  Connect();
+  SendReceive();
+}
+
+TEST_P(TlsConnectGenericPre13, ConnectResumeWithHigherVersion) {
+  EnsureTlsSetup();
+  SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_1);
+  ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_1);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_1);
+  Connect();
+
+  Reset();
+  EnsureTlsSetup();
+  SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_2);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_2);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_2);
+  ExpectResumption(RESUME_NONE);
+  Connect();
+}
+
+TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicketForget) {
+  // This causes a ticket resumption.
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  Connect();
+  SendReceive();
+
+  Reset();
+  ClearServerCache();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  ExpectResumption(RESUME_NONE);
+  Connect();
+  SendReceive();
+}
+
+// This callback switches out the "server" cert used on the server with
+// the "client" certificate, which should be the same type.
+static int32_t SwitchCertificates(TlsAgent& agent, const SECItem *srvNameArr,
+                                  uint32_t srvNameArrSize) {
+  bool ok = agent.ConfigServerCert("client");
+  if (!ok) return SSL_SNI_SEND_ALERT;
+
+  return 0; // first config
+};
+
+TEST_P(TlsConnectGeneric, ServerSNICertSwitch) {
+  Connect();
+  ScopedCERTCertificate cert1(SSL_PeerCertificate(client_->ssl_fd()));
+
+  Reset();
+  EnsureTlsSetup();
+  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
+
+  server_->SetSniCallback(SwitchCertificates);
+
+  Connect();
+  ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd()));
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+  EXPECT_FALSE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
+}
+
+TEST_P(TlsConnectGeneric, ServerSNICertTypeSwitch) {
+  Reset(TlsAgent::kServerEcdsa);
+  Connect();
+  ScopedCERTCertificate cert1(SSL_PeerCertificate(client_->ssl_fd()));
+
+  Reset();
+  EnsureTlsSetup();
+  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
+
+  // Because we configure an RSA certificate here, it only adds a second, unused
+  // certificate, which has no effect on what the server uses.
+  server_->SetSniCallback(SwitchCertificates);
+
+  Connect();
+  ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd()));
+  CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa);
+  EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
+}
+
+// Prior to TLS 1.3, we were not fully ephemeral; though 1.3 fixes that
+TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceReuseKey) {
+  TlsInspectorRecordHandshakeMessage* i1 =
+      new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange);
+  server_->SetPacketFilter(i1);
+  Connect();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+  TlsServerKeyExchangeEcdhe dhe1;
+  EXPECT_TRUE(dhe1.Parse(i1->buffer()));
+
+  // Restart
+  Reset();
+  TlsInspectorRecordHandshakeMessage* i2 =
+      new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange);
+  server_->SetPacketFilter(i2);
+  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
+  Connect();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+
+  TlsServerKeyExchangeEcdhe dhe2;
+  EXPECT_TRUE(dhe2.Parse(i2->buffer()));
+
+  // Make sure they are the same.
+  EXPECT_EQ(dhe1.public_key_.len(), dhe2.public_key_.len());
+  EXPECT_TRUE(!memcmp(dhe1.public_key_.data(), dhe2.public_key_.data(),
+                      dhe1.public_key_.len()));
+}
+
+// This test parses the ServerKeyExchange, which isn't in 1.3
+TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceNewKey) {
+  server_->EnsureTlsSetup();
+  SECStatus rv =
+      SSL_OptionSet(server_->ssl_fd(), SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE);
+  EXPECT_EQ(SECSuccess, rv);
+  TlsInspectorRecordHandshakeMessage* i1 =
+      new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange);
+  server_->SetPacketFilter(i1);
+  Connect();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+  TlsServerKeyExchangeEcdhe dhe1;
+  EXPECT_TRUE(dhe1.Parse(i1->buffer()));
+
+  // Restart
+  Reset();
+  server_->EnsureTlsSetup();
+  rv = SSL_OptionSet(server_->ssl_fd(), SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE);
+  EXPECT_EQ(SECSuccess, rv);
+  TlsInspectorRecordHandshakeMessage* i2 =
+      new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange);
+  server_->SetPacketFilter(i2);
+  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
+  Connect();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+
+  TlsServerKeyExchangeEcdhe dhe2;
+  EXPECT_TRUE(dhe2.Parse(i2->buffer()));
+
+  // Make sure they are different.
+  EXPECT_FALSE((dhe1.public_key_.len() == dhe2.public_key_.len()) &&
+               (!memcmp(dhe1.public_key_.data(), dhe2.public_key_.data(),
+                        dhe1.public_key_.len())));
+}
+
+#ifdef NSS_ENABLE_TLS_1_3
+// Test that two TLS resumptions work and produce the same ticket.
+// This will change after bug 1257047 is fixed.
+TEST_F(TlsConnectTest, TestTls13ResumptionTwice) {
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  Connect();
+  SendReceive(); // Need to read so that we absorb the session ticket.
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+  uint16_t original_suite;
+  EXPECT_TRUE(client_->cipher_suite(&original_suite));
+
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  TlsExtensionCapture *c1 =
+      new TlsExtensionCapture(kTlsExtensionPreSharedKey);
+  client_->SetPacketFilter(c1);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  ExpectResumption(RESUME_TICKET);
+  Connect();
+  SendReceive();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+  // The filter will go away when we reset, so save the captured extension.
+  DataBuffer initialTicket(c1->extension());
+  ASSERT_LT(0U, initialTicket.len());
+
+  ScopedCERTCertificate cert1(SSL_PeerCertificate(client_->ssl_fd()));
+  ASSERT_TRUE(!!cert1.get());
+
+  Reset();
+  ClearStats();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  TlsExtensionCapture *c2 =
+      new TlsExtensionCapture(kTlsExtensionPreSharedKey);
+  client_->SetPacketFilter(c2);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  ExpectResumption(RESUME_TICKET);
+  Connect();
+  SendReceive();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+  ASSERT_LT(0U, c2->extension().len());
+
+  ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd()));
+  ASSERT_TRUE(!!cert2.get());
+
+  // Check that the cipher suite is reported the same on both sides, though in
+  // TLS 1.3 resumption actually negotiates a different cipher suite.
+  uint16_t resumed_suite;
+  EXPECT_TRUE(server_->cipher_suite(&resumed_suite));
+  EXPECT_EQ(original_suite, resumed_suite);
+  EXPECT_TRUE(client_->cipher_suite(&resumed_suite));
+  EXPECT_EQ(original_suite, resumed_suite);
+
+  // TODO(ekr@rtfm.com): This will change when we fix bug 1257047.
+  ASSERT_EQ(initialTicket, c2->extension());
+}
+
+TEST_F(TlsConnectTest, DisableClientPSKAndFailToResume) {
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  Connect();
+  SendReceive(); // Need to read so that we absorb the session ticket.
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  TlsExtensionCapture *capture =
+      new TlsExtensionCapture(kTlsExtensionPreSharedKey);
+  client_->SetPacketFilter(capture);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  // We need to disable ALL PSK cipher suites with the same symmetric cipher and
+  // PRF hash.  Otherwise the server will just use a different key exchange.
+  client_->DisableAllCiphers();
+  client_->EnableCiphersByAuthType(ssl_auth_rsa_sign);
+  ExpectResumption(RESUME_NONE);
+  Connect();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+  EXPECT_EQ(0U, capture->extension().len());
+}
+
+TEST_F(TlsConnectTest, DisableServerPSKAndFailToResume) {
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  Connect();
+  SendReceive(); // Need to read so that we absorb the session ticket.
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+  TlsExtensionCapture *clientCapture =
+      new TlsExtensionCapture(kTlsExtensionPreSharedKey);
+  client_->SetPacketFilter(clientCapture);
+  TlsExtensionCapture *serverCapture =
+      new TlsExtensionCapture(kTlsExtensionPreSharedKey);
+  server_->SetPacketFilter(serverCapture);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  // We need to disable ALL PSK cipher suites with the same symmetric cipher and
+  // PRF hash.  Otherwise the server will just use a different key exchange.
+  server_->DisableAllCiphers();
+  server_->EnableCiphersByAuthType(ssl_auth_rsa_sign);
+  ExpectResumption(RESUME_NONE);
+  Connect();
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+  // The client should have the extension, but the server should not.
+  EXPECT_LT(0U, clientCapture->extension().len());
+  EXPECT_EQ(0U, serverCapture->extension().len());
+}
+#endif
+
+}  // namespace nss_test
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/ssl_staticrsa_unittest.cc
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secerr.h"
+#include "ssl.h"
+#include "sslerr.h"
+#include "sslproto.h"
+#include <memory>
+#include <functional>
+
+extern "C" {
+// This is not something that should make you happy.
+#include "libssl_internals.h"
+}
+
+#include "scoped_ptrs.h"
+#include "tls_parser.h"
+#include "tls_filter.h"
+#include "tls_connect.h"
+#include "gtest_utils.h"
+
+namespace nss_test {
+
+const uint8_t kBogusClientKeyExchange[] = {
+  0x01, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+TEST_P(TlsConnectGenericPre13, ConnectStaticRSA) {
+  EnableOnlyStaticRsaCiphers();
+  Connect();
+  CheckKeys(ssl_kea_rsa, ssl_auth_rsa_decrypt);
+}
+
+// Test that a totally bogus EPMS is handled correctly.
+// This test is stream so we can catch the bad_record_mac alert.
+TEST_P(TlsConnectStreamPre13, ConnectStaticRSABogusCKE) {
+  EnableOnlyStaticRsaCiphers();
+  TlsInspectorReplaceHandshakeMessage* i1 =
+      new TlsInspectorReplaceHandshakeMessage(kTlsHandshakeClientKeyExchange,
+                                              DataBuffer(
+                                                  kBogusClientKeyExchange,
+                                                  sizeof(kBogusClientKeyExchange)));
+  client_->SetPacketFilter(i1);
+  auto alert_recorder = new TlsAlertRecorder();
+  server_->SetPacketFilter(alert_recorder);
+  ConnectExpectFail();
+  EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
+  EXPECT_EQ(kTlsAlertBadRecordMac, alert_recorder->description());
+}
+
+// Test that a PMS with a bogus version number is handled correctly.
+// This test is stream so we can catch the bad_record_mac alert.
+TEST_P(TlsConnectStreamPre13, ConnectStaticRSABogusPMSVersionDetect) {
+  EnableOnlyStaticRsaCiphers();
+  client_->SetPacketFilter(new TlsInspectorClientHelloVersionChanger(
+      server_));
+  auto alert_recorder = new TlsAlertRecorder();
+  server_->SetPacketFilter(alert_recorder);
+  ConnectExpectFail();
+  EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
+  EXPECT_EQ(kTlsAlertBadRecordMac, alert_recorder->description());
+}
+
+// Test that a PMS with a bogus version number is ignored when
+// rollback detection is disabled. This is a positive control for
+// ConnectStaticRSABogusPMSVersionDetect.
+TEST_P(TlsConnectGenericPre13, ConnectStaticRSABogusPMSVersionIgnore) {
+  EnableOnlyStaticRsaCiphers();
+  client_->SetPacketFilter(new TlsInspectorClientHelloVersionChanger(
+      server_));
+  server_->DisableRollbackDetection();
+  Connect();
+}
+
+// This test is stream so we can catch the bad_record_mac alert.
+TEST_P(TlsConnectStreamPre13, ConnectExtendedMasterSecretStaticRSABogusCKE) {
+  EnableOnlyStaticRsaCiphers();
+  EnableExtendedMasterSecret();
+  TlsInspectorReplaceHandshakeMessage* inspect =
+      new TlsInspectorReplaceHandshakeMessage(kTlsHandshakeClientKeyExchange,
+                                              DataBuffer(
+                                                  kBogusClientKeyExchange,
+                                                  sizeof(kBogusClientKeyExchange)));
+  client_->SetPacketFilter(inspect);
+  auto alert_recorder = new TlsAlertRecorder();
+  server_->SetPacketFilter(alert_recorder);
+  ConnectExpectFail();
+  EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
+  EXPECT_EQ(kTlsAlertBadRecordMac, alert_recorder->description());
+}
+
+// This test is stream so we can catch the bad_record_mac alert.
+TEST_P(TlsConnectStreamPre13, ConnectExtendedMasterSecretStaticRSABogusPMSVersionDetect) {
+  EnableOnlyStaticRsaCiphers();
+  EnableExtendedMasterSecret();
+  client_->SetPacketFilter(new TlsInspectorClientHelloVersionChanger(
+      server_));
+  auto alert_recorder = new TlsAlertRecorder();
+  server_->SetPacketFilter(alert_recorder);
+  ConnectExpectFail();
+  EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
+  EXPECT_EQ(kTlsAlertBadRecordMac, alert_recorder->description());
+}
+
+TEST_P(TlsConnectStreamPre13, ConnectExtendedMasterSecretStaticRSABogusPMSVersionIgnore) {
+  EnableOnlyStaticRsaCiphers();
+  EnableExtendedMasterSecret();
+  client_->SetPacketFilter(new TlsInspectorClientHelloVersionChanger(
+      server_));
+  server_->DisableRollbackDetection();
+  Connect();
+}
+
+}  // namespace nspr_test
new file mode 100644
--- /dev/null
+++ b/security/nss/external_tests/ssl_gtest/ssl_version_unittest.cc
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secerr.h"
+#include "ssl.h"
+#include "sslerr.h"
+#include "sslproto.h"
+
+#include "scoped_ptrs.h"
+#include "tls_parser.h"
+#include "tls_filter.h"
+#include "tls_connect.h"
+#include "gtest_utils.h"
+
+namespace nss_test {
+
+// Set the version number in the ClientHello.
+class TlsInspectorClientHelloVersionSetter : public TlsHandshakeFilter {
+ public:
+  TlsInspectorClientHelloVersionSetter(uint16_t version) : version_(version) {}
+
+  virtual PacketFilter::Action FilterHandshake(
+      const HandshakeHeader& header,
+      const DataBuffer& input, DataBuffer* output) {
+    if (header.handshake_type() == kTlsHandshakeClientHello) {
+      *output = input;
+      output->Write(0, version_, 2);
+      return CHANGE;
+    }
+    return KEEP;
+  }
+
+ private:
+  uint16_t version_;
+};
+
+TEST_P(TlsConnectStream, ServerNegotiateTls10) {
+  uint16_t minver, maxver;
+  client_->GetVersionRange(&minver, &maxver);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
+                           maxver);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
+                           SSL_LIBRARY_VERSION_TLS_1_0);
+  Connect();
+}
+
+TEST_P(TlsConnectGeneric, ServerNegotiateTls11) {
+  if (version_ < SSL_LIBRARY_VERSION_TLS_1_1)
+    return;
+
+  uint16_t minver, maxver;
+  client_->GetVersionRange(&minver, &maxver);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           maxver);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_1);
+  Connect();
+}
+
+TEST_P(TlsConnectGeneric, ServerNegotiateTls12) {
+  if (version_ < SSL_LIBRARY_VERSION_TLS_1_2)
+    return;
+
+  uint16_t minver, maxver;
+  client_->GetVersionRange(&minver, &maxver);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+                           maxver);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+                           SSL_LIBRARY_VERSION_TLS_1_2);
+  Connect();
+}
+
+// Test the ServerRandom version hack from
+// [draft-ietf-tls-tls13-11 Section 6.3.1.1].
+// The first three tests test for active tampering. The next
+// two validate that we can also detect fallback using the
+// SSL_SetDowngradeCheckVersion() API.
+TEST_F(TlsConnectTest, TestDowngradeDetectionToTls11) {
+  client_->SetPacketFilter(new TlsInspectorClientHelloVersionSetter
+                           (SSL_LIBRARY_VERSION_TLS_1_1));
+  ConnectExpectFail();
+  ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
+}
+
+/* Attempt to negotiate the bogus DTLS 1.1 version. */
+TEST_F(DtlsConnectTest, TestDtlsVersion11) {
+  client_->SetPacketFilter(new TlsInspectorClientHelloVersionSetter(
+      ((~0x0101) & 0xffff)));
+  ConnectExpectFail();
+  // It's kind of surprising that SSL_ERROR_NO_CYPHER_OVERLAP is
+  // what is returned here, but this is deliberate in ssl3_HandleAlert().
+  EXPECT_EQ(SSL_ERROR_NO_CYPHER_OVERLAP, client_->error_code());
+  EXPECT_EQ(SSL_ERROR_UNSUPPORTED_VERSION, server_->error_code());
+}
+
+#ifdef NSS_ENABLE_TLS_1_3
+TEST_F(TlsConnectTest, TestDowngradeDetectionToTls12) {
+  EnsureTlsSetup();
+  client_->SetPacketFilter(new TlsInspectorClientHelloVersionSetter
+                           (SSL_LIBRARY_VERSION_TLS_1_2));
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  ConnectExpectFail();
+  ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
+}
+#endif
+
+// TLS 1.1 clients do not check the random values, so we should
+// instead get a handshake failure alert from the server.
+TEST_F(TlsConnectTest, TestDowngradeDetectionToTls10) {
+  client_->SetPacketFilter(new TlsInspectorClientHelloVersionSetter
+                          (SSL_LIBRARY_VERSION_TLS_1_0));
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
+                           SSL_LIBRARY_VERSION_TLS_1_1);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
+                           SSL_LIBRARY_VERSION_TLS_1_2);
+  ConnectExpectFail();
+  ASSERT_EQ(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE, server_->error_code());
+  ASSERT_EQ(SSL_ERROR_DECRYPT_ERROR_ALERT, client_->error_code());
+}
+
+TEST_F(TlsConnectTest, TestFallbackFromTls12) {
+  EnsureTlsSetup();
+  client_->SetDowngradeCheckVersion(SSL_LIBRARY_VERSION_TLS_1_2);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_1);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_2);
+  ConnectExpectFail();
+  ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
+}
+
+#ifdef NSS_ENABLE_TLS_1_3
+TEST_F(TlsConnectTest, TestFallbackFromTls13) {
+  EnsureTlsSetup();
+  client_->SetDowngradeCheckVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+                           SSL_LIBRARY_VERSION_TLS_1_2);
+  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
+                           SSL_LIBRARY_VERSION_TLS_1_3);
+  ConnectExpectFail();
+  ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
+}
+
+// The TLS v1.3 spec section C.4 states that 'Implementations MUST NOT send or
+// accept any records with a version less than { 3, 0 }'. Thus we will not
+// allow version ranges including both SSL v3 and TLS v1.3.
+TEST_F(TlsConnectTest, DisallowSSLv3HelloWithTLSv13Enabled) {
+  SECStatus rv;
+  SSLVersionRange vrange = { SSL_LIBRARY_VERSION_3_0,
+                             SSL_LIBRARY_VERSION_TLS_1_3 };
+
+  EnsureTlsSetup();
+  rv = SSL_VersionRangeSet(client_->ssl_fd(), &vrange);
+  EXPECT_EQ(SECFailure, rv);
+
+  rv = SSL_VersionRangeSet(server_->ssl_fd(), &vrange);
+  EXPECT_EQ(SECFailure, rv);
+}
+#endif // NSS_ENABLE_TLS_1_3
+
+} // namespace nss_test
--- a/security/nss/external_tests/ssl_gtest/tls_filter.cc
+++ b/security/nss/external_tests/ssl_gtest/tls_filter.cc
@@ -2,17 +2,23 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "tls_filter.h"
 #include "sslproto.h"
 
+extern "C" {
+// This is not something that should make you happy.
+#include "libssl_internals.h"
+}
+
 #include <iostream>
+#include "tls_agent.h"
 #include "gtest_utils.h"
 
 namespace nss_test {
 
 PacketFilter::Action TlsRecordFilter::Filter(const DataBuffer& input, DataBuffer* output) {
   bool changed = false;
   size_t offset = 0U;
   output->Allocate(input.len());
@@ -405,9 +411,34 @@ PacketFilter::Action TlsExtensionFilter:
 PacketFilter::Action TlsExtensionCapture::FilterExtension(
     uint16_t extension_type, const DataBuffer& input, DataBuffer* output) {
   if (extension_type == extension_) {
     data_.Assign(input);
   }
   return KEEP;
 }
 
+PacketFilter::Action AfterRecordN::FilterRecord(
+      const RecordHeader& header, const DataBuffer& body, DataBuffer* out) {
+  if (counter_++ == record_) {
+    DataBuffer buf;
+    header.Write(&buf, 0, body);
+    src_->SendDirect(buf);
+    dest_->Handshake();
+    func_();
+    return DROP;
+  }
+
+  return KEEP;
+}
+
+PacketFilter::Action TlsInspectorClientHelloVersionChanger::FilterHandshake(
+    const HandshakeHeader& header,
+    const DataBuffer& input, DataBuffer* output) {
+  if (header.handshake_type() == kTlsHandshakeClientKeyExchange) {
+    EXPECT_EQ(
+        SECSuccess,
+        SSLInt_IncrementClientHandshakeVersion(server_->ssl_fd()));
+  }
+  return KEEP;
+}
+
 }  // namespace nss_test
--- a/security/nss/external_tests/ssl_gtest/tls_filter.h
+++ b/security/nss/external_tests/ssl_gtest/tls_filter.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef tls_filter_h_
 #define tls_filter_h_
 
+#include <functional>
 #include <memory>
 #include <vector>
 
 #include "test_io.h"
 #include "tls_parser.h"
 
 namespace nss_test {
 
@@ -211,11 +212,49 @@ class TlsExtensionCapture : public TlsEx
       uint16_t extension_type, const DataBuffer& input, DataBuffer* output);
   const DataBuffer& extension() const { return data_; }
 
  private:
   const uint16_t extension_;
   DataBuffer data_;
 };
 
+class TlsAgent;
+typedef std::function<void(void)> VoidFunction;
+
+class AfterRecordN : public TlsRecordFilter {
+ public:
+  AfterRecordN(TlsAgent *src, TlsAgent *dest, unsigned int record,
+               VoidFunction func) :
+      src_(src),
+      dest_(dest),
+      record_(record),
+      func_(func),
+      counter_(0) {}
+
+  virtual PacketFilter::Action FilterRecord(
+      const RecordHeader& header, const DataBuffer& body, DataBuffer* out);
+
+ private:
+  TlsAgent *src_;
+  TlsAgent *dest_;
+  unsigned int record_;
+  VoidFunction func_;
+  unsigned int counter_;
+};
+
+// When we see the ClientKeyExchange from |client|, increment the
+// ClientHelloVersion on |server|.
+class TlsInspectorClientHelloVersionChanger : public TlsHandshakeFilter {
+ public:
+  TlsInspectorClientHelloVersionChanger(TlsAgent* server) : server_(server) {}
+
+  virtual PacketFilter::Action FilterHandshake(
+      const HandshakeHeader& header,
+      const DataBuffer& input, DataBuffer* output);
+
+ private:
+  TlsAgent* server_;
+};
+
 }  // namespace nss_test
 
 #endif
--- a/security/nss/external_tests/ssl_gtest/tls_hkdf_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/tls_hkdf_unittest.cc
@@ -105,26 +105,36 @@ void DumpKey(const std::string& label, S
   ASSERT_EQ(SECSuccess, rv);
 
   SECItem *key_data = PK11_GetKeyData(key.get());
   ASSERT_NE(nullptr, key_data);
 
   DumpData(label, key_data->data, key_data->len);
 }
 
+extern "C" {
+  extern char ssl_trace;
+  extern FILE* ssl_trace_iob;
+}
+
 class TlsHkdfTest
   : public ::testing::Test,
     public ::testing::WithParamInterface<SSLHashType> {
  public:
   TlsHkdfTest()
     : k1_(),
       k2_(),
       hash_type_(GetParam()),
       slot_(PK11_GetInternalSlot()) {
     EXPECT_NE(nullptr, slot_);
+    char *ev = getenv("SSLTRACE");
+    if (ev && ev[0]) {
+      ssl_trace = atoi(ev);
+      ssl_trace_iob = stderr;
+    }
   }
 
   void SetUp() {
     ImportKey(&k1_, kKey1, slot_.get());
     ImportKey(&k2_, kKey2, slot_.get());
   }
 
   void VerifyKey(const ScopedPK11SymKey& key, const DataBuffer& expected) {
--- a/security/nss/lib/freebl/aeskeywrap.c
+++ b/security/nss/lib/freebl/aeskeywrap.c
@@ -131,39 +131,41 @@ increment_and_xor(unsigned char *A, unsi
     A[3] ^= T[3];
     A[4] ^= T[4];
     A[5] ^= T[5];
     A[6] ^= T[6];
     A[7] ^= T[7];
 }
 
 /* A and T point to two 64-bit values stored most signficant byte first
-** (big endian).  This function XORs T with A, giving a new A, then 
+** (big endian).  This function XORs T with A, giving a new A, then
 ** decrements the 64-bit value T.
-*/ 
+*/
 static void
-xor_and_decrement(unsigned char *A, unsigned char *T)
+xor_and_decrement(PRUint64 *A, PRUint64 *T)
 {
-    A[0] ^= T[0];
-    A[1] ^= T[1];
-    A[2] ^= T[2];
-    A[3] ^= T[3];
-    A[4] ^= T[4];
-    A[5] ^= T[5];
-    A[6] ^= T[6];
-    A[7] ^= T[7];
+    unsigned char* TP = (unsigned char*)T;
+    const PRUint64 mask = 0xFF;
+    *A = ((*A & mask << 56) ^ (*T & mask << 56)) |
+         ((*A & mask << 48) ^ (*T & mask << 48)) |
+         ((*A & mask << 40) ^ (*T & mask << 40)) |
+         ((*A & mask << 32) ^ (*T & mask << 32)) |
+         ((*A & mask << 24) ^ (*T & mask << 23)) |
+         ((*A & mask << 16) ^ (*T & mask << 16)) |
+         ((*A & mask << 8) ^ (*T & mask << 8)) |
+         ((*A & mask) ^ (*T & mask));
 
-    if (!T[7]--)
-        if (!T[6]--)
-	    if (!T[5]--)
-		if (!T[4]--)
-		    if (!T[3]--)
-			if (!T[2]--)
-			    if (!T[1]--)
-				 T[0]--;
+    if (!TP[7]--)
+        if (!TP[6]--)
+	    if (!TP[5]--)
+		if (!TP[4]--)
+		    if (!TP[3]--)
+			if (!TP[2]--)
+			    if (!TP[1]--)
+				 TP[0]--;
 
 }
 
 /* Given an unsigned long t (in host byte order), store this value as a
 ** 64-bit big-endian value (MSB first) in *pt.
 */
 static void
 set_t(unsigned char *pt, unsigned long t)
@@ -297,20 +299,18 @@ AESKeyWrap_Decrypt(AESKeyWrapContext *cx
     unsigned int   i, j;
     unsigned int   aesLen     = AES_BLOCK_SIZE;
     unsigned int   outLen;
     SECStatus      s          = SECFailure;
     /* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
     PRUint64       t;
     PRUint64       B[2];
 
-#define A B[0]
-
     /* Check args */
-    if (inputLen < 3 * AES_KEY_WRAP_BLOCK_SIZE || 
+    if (inputLen < 3 * AES_KEY_WRAP_BLOCK_SIZE ||
         0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
 	PORT_SetError(SEC_ERROR_INPUT_LEN);
 	return s;
     }
     outLen = inputLen - AES_KEY_WRAP_BLOCK_SIZE;
 #ifdef maybe
     if (!output && pOutputLen) {	/* caller is asking for output size */
     	*pOutputLen = outLen;
@@ -325,58 +325,58 @@ AESKeyWrap_Decrypt(AESKeyWrapContext *cx
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	return s;
     }
     nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
     R = PORT_NewArray(PRUint64, nBlocks);
     if (!R)
     	return s;	/* error is already set. */
     nBlocks--;
-    /* 
+    /*
     ** 1) Initialize variables.
     */
     memcpy(&R[0], input, inputLen);
-    A = R[0];
+    B[0] = R[0];
 #if BIG_ENDIAN_WITH_64_BIT_REGISTERS
     t = 6UL * nBlocks;
 #else
     set_t((unsigned char *)&t, 6UL * nBlocks);
 #endif
-    /* 
+    /*
     ** 2) Calculate intermediate values.
     */
     for (j = 0; j < 6; ++j) {
     	for (i = nBlocks; i; --i) {
 	    /* here, XOR A with t (in big endian order) and decrement t; */
 #if BIG_ENDIAN_WITH_64_BIT_REGISTERS
-   	    A ^= t--; 
+   	    B[0] ^= t--;
 #else
-	    xor_and_decrement((unsigned char *)&A, (unsigned char *)&t);
+	    xor_and_decrement(&B[0], &t);
 #endif
 	    B[1] = R[i];
-	    s = AES_Decrypt(&cx->aescx, (unsigned char *)B, &aesLen, 
+	    s = AES_Decrypt(&cx->aescx, (unsigned char *)B, &aesLen,
 	                    sizeof B,  (unsigned char *)B, sizeof B);
-	    if (s != SECSuccess) 
+	    if (s != SECSuccess)
 	        break;
 	    R[i] = B[1];
 	}
     }
-    /* 
+    /*
     ** 3) Output the results.
     */
     if (s == SECSuccess) {
-	int bad = memcmp(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
+	int bad = memcmp(&B[0], cx->iv, AES_KEY_WRAP_IV_BYTES);
 	if (!bad) {
 	    memcpy(output, &R[1], outLen);
 	    if (pOutputLen)
 		*pOutputLen = outLen;
 	} else {
 	    s = SECFailure;
 	    PORT_SetError(SEC_ERROR_BAD_DATA);
-	    if (pOutputLen) 
+	    if (pOutputLen)
 		*pOutputLen = 0;
     	}
     } else if (pOutputLen) {
     	*pOutputLen = 0;
     }
     PORT_ZFree(R, inputLen);
     return s;
 }
--- a/security/nss/lib/freebl/dsa.c
+++ b/security/nss/lib/freebl/dsa.c
@@ -312,22 +312,23 @@ DSA_NewKeyFromSeed(const PQGParams *para
 
 static SECStatus 
 dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
                const unsigned char *kb)
 {
     mp_int p, q, g;  /* PQG parameters */
     mp_int x, k;     /* private key & pseudo-random integer */
     mp_int r, s;     /* tuple (r, s) is signature) */
+    mp_int t;        /* holding tmp values */
     mp_err err   = MP_OKAY;
     SECStatus rv = SECSuccess;
     unsigned int dsa_subprime_len, dsa_signature_len, offset;
     SECItem localDigest;
     unsigned char localDigestData[DSA_MAX_SUBPRIME_LEN];
-    
+    SECItem t2 = { siBuffer, NULL, 0 };
 
     /* FIPS-compliance dictates that digest is a SHA hash. */
     /* Check args. */
     if (!key || !signature || !digest) {
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	return SECFailure;
     }
 
@@ -355,23 +356,25 @@ dsa_SignDigest(DSAPrivateKey *key, SECIt
     /* Initialize MPI integers. */
     MP_DIGITS(&p) = 0;
     MP_DIGITS(&q) = 0;
     MP_DIGITS(&g) = 0;
     MP_DIGITS(&x) = 0;
     MP_DIGITS(&k) = 0;
     MP_DIGITS(&r) = 0;
     MP_DIGITS(&s) = 0;
+    MP_DIGITS(&t) = 0;
     CHECK_MPI_OK( mp_init(&p) );
     CHECK_MPI_OK( mp_init(&q) );
     CHECK_MPI_OK( mp_init(&g) );
     CHECK_MPI_OK( mp_init(&x) );
     CHECK_MPI_OK( mp_init(&k) );
     CHECK_MPI_OK( mp_init(&r) );
     CHECK_MPI_OK( mp_init(&s) );
+    CHECK_MPI_OK( mp_init(&t) );
     /*
     ** Convert stored PQG and private key into MPI integers.
     */
     SECITEM_TO_MPINT(key->params.prime,    &p);
     SECITEM_TO_MPINT(key->params.subPrime, &q);
     SECITEM_TO_MPINT(key->params.base,     &g);
     SECITEM_TO_MPINT(key->privateValue,    &x);
     OCTETS_TO_MPINT(kb, &k, dsa_subprime_len);
@@ -382,18 +385,26 @@ dsa_SignDigest(DSAPrivateKey *key, SECIt
     */
     CHECK_MPI_OK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */
     CHECK_MPI_OK(     mp_mod(&r, &q, &r) );     /* r = r mod q    */
     /*                                  
     ** FIPS 186-1, Section 5, Step 2
     **
     ** s = (k**-1 * (HASH(M) + x*r)) mod q
     */
+    if (DSA_NewRandom(NULL, &key->params.subPrime, &t2) != SECSuccess) {
+        PORT_SetError(SEC_ERROR_NEED_RANDOM);
+        rv = SECFailure;
+        goto cleanup;
+    }
+    SECITEM_TO_MPINT(t2, &t); /* t <-$ Zq */
+    CHECK_MPI_OK( mp_mulmod(&k, &t, &q, &k) );  /* k = k * t mod q */
+    CHECK_MPI_OK( mp_invmod(&k, &q, &k) );      /* k = k**-1 mod q */
+    CHECK_MPI_OK( mp_mulmod(&k, &t, &q, &k) );  /* k = k * t mod q */
     SECITEM_TO_MPINT(localDigest, &s);          /* s = HASH(M)     */
-    CHECK_MPI_OK( mp_invmod(&k, &q, &k) );      /* k = k**-1 mod q */
     CHECK_MPI_OK( mp_mulmod(&x, &r, &q, &x) );  /* x = x * r mod q */
     CHECK_MPI_OK( mp_addmod(&s, &x, &q, &s) );  /* s = s + x mod q */
     CHECK_MPI_OK( mp_mulmod(&s, &k, &q, &s) );  /* s = s * k mod q */
     /*
     ** verify r != 0 and s != 0
     ** mentioned as optional in FIPS 186-1.
     */
     if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) {
@@ -417,16 +428,18 @@ cleanup:
     PORT_Memset(localDigestData, 0, DSA_MAX_SUBPRIME_LEN);
     mp_clear(&p);
     mp_clear(&q);
     mp_clear(&g);
     mp_clear(&x);
     mp_clear(&k);
     mp_clear(&r);
     mp_clear(&s);
+    mp_clear(&t);
+    SECITEM_FreeItem(&t2, PR_FALSE);
     if (err) {
 	translate_mpi_error(err);
 	rv = SECFailure;
     }
     return rv;
 }
 
 /* signature is caller-supplied buffer of at least 40 bytes.
--- a/security/nss/lib/freebl/ec.c
+++ b/security/nss/lib/freebl/ec.c
@@ -591,36 +591,39 @@ SECStatus
 ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, 
     const SECItem *digest, const unsigned char *kb, const int kblen)
 {
     SECStatus rv = SECFailure;
 #ifndef NSS_DISABLE_ECC
     mp_int x1;
     mp_int d, k;     /* private key, random integer */
     mp_int r, s;     /* tuple (r, s) is the signature */
+    mp_int t;        /* holding tmp values */
     mp_int n;
     mp_err err = MP_OKAY;
     ECParams *ecParams = NULL;
     SECItem kGpoint = { siBuffer, NULL, 0};
     int flen = 0;    /* length in bytes of the field size */
     unsigned olen;   /* length in bytes of the base point order */
     unsigned obits;  /* length in bits  of the base point order */
+    unsigned char *t2 = NULL;
 
 #if EC_DEBUG
     char mpstr[256];
 #endif
 
     /* Initialize MPI integers. */
     /* must happen before the first potential call to cleanup */
     MP_DIGITS(&x1) = 0;
     MP_DIGITS(&d) = 0;
     MP_DIGITS(&k) = 0;
     MP_DIGITS(&r) = 0;
     MP_DIGITS(&s) = 0;
     MP_DIGITS(&n) = 0;
+    MP_DIGITS(&t) = 0;
 
     /* Check args */
     if (!key || !signature || !digest || !kb || (kblen < 0)) {
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	goto cleanup;
     }
 
     ecParams = &(key->ecParams);
@@ -637,16 +640,17 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *k
 
 
     CHECK_MPI_OK( mp_init(&x1) );
     CHECK_MPI_OK( mp_init(&d) );
     CHECK_MPI_OK( mp_init(&k) );
     CHECK_MPI_OK( mp_init(&r) );
     CHECK_MPI_OK( mp_init(&s) );
     CHECK_MPI_OK( mp_init(&n) );
+    CHECK_MPI_OK( mp_init(&t) );
 
     SECITEM_TO_MPINT( ecParams->order, &n );
     SECITEM_TO_MPINT( key->privateValue, &d );
 
     CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
     /* Make sure k is in the interval [1, n-1] */
     if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
 #if EC_DEBUG
@@ -743,20 +747,32 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *k
     mp_todecimal(&s, mpstr);
     printf("digest: %s (decimal)\n", mpstr);
     mp_todecimal(&r, mpstr);
     printf("r : %s (dec)\n", mpstr);
     mp_tohex(&r, mpstr);
     printf("r : %s\n", mpstr);
 #endif
 
-    CHECK_MPI_OK( mp_invmod(&k, &n, &k) );      /* k = k**-1 mod n */
-    CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) );  /* d = d * r mod n */
-    CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) );  /* s = s + d mod n */
-    CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) );  /* s = s * k mod n */
+    if ((t2 = PORT_Alloc(2*ecParams->order.len)) == NULL) {
+        rv = SECFailure;
+        goto cleanup;
+    }
+    if (RNG_GenerateGlobalRandomBytes(t2, 2*ecParams->order.len) != SECSuccess) {
+        PORT_SetError(SEC_ERROR_NEED_RANDOM);
+        rv = SECFailure;
+        goto cleanup;
+    }
+    CHECK_MPI_OK( mp_read_unsigned_octets(&t, t2, 2*ecParams->order.len) ); /* t <-$ Zn */
+    CHECK_MPI_OK( mp_mulmod(&k, &t, &n, &k) ); /* k = k * t mod n */
+    CHECK_MPI_OK( mp_invmod(&k, &n, &k) );     /* k = k**-1 mod n */
+    CHECK_MPI_OK( mp_mulmod(&k, &t, &n, &k) ); /* k = k * t mod n */
+    CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) ); /* d = d * r mod n */
+    CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) ); /* s = s + d mod n */
+    CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) ); /* s = s * k mod n */
 
 #if EC_DEBUG
     mp_todecimal(&s, mpstr);
     printf("s : %s (dec)\n", mpstr);
     mp_tohex(&s, mpstr);
     printf("s : %s\n", mpstr);
 #endif
 
@@ -783,16 +799,21 @@ finish:
     err = MP_OKAY;
 cleanup:
     mp_clear(&x1);
     mp_clear(&d);
     mp_clear(&k);
     mp_clear(&r);
     mp_clear(&s);
     mp_clear(&n);
+    mp_clear(&t);
+
+    if (t2) {
+        PORT_Free(t2);
+    }
 
     if (kGpoint.data) {
 	PORT_ZFree(kGpoint.data, 2*flen + 1);
     }
 
     if (err) {
 	MP_TO_SEC_ERROR(err);
 	rv = SECFailure;
--- a/security/nss/lib/nss/config.mk
+++ b/security/nss/lib/nss/config.mk
@@ -100,8 +100,15 @@ endif
 ifeq (,$(filter-out WINNT WIN95,$(OS_TARGET)))
 ifndef NS_USE_GCC
 # Export 'mktemp' to be backward compatible with NSS 3.2.x and 3.3.x
 # but do not put it in the import library.  See bug 142575.
 DEFINES += -DWIN32_NSS3_DLL_COMPAT
 DLLFLAGS += -EXPORT:mktemp=nss_mktemp,PRIVATE
 endif
 endif
+
+ifdef POLICY_FILE
+ifndef POLICY_PATH
+$(error You must define POLICY_PATH if you set POLICY_FILE)
+endif
+DEFINES += -DPOLICY_FILE=\"$(POLICY_FILE)\" -DPOLICY_PATH=\"$(POLICY_PATH)\"
+endif
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -17,22 +17,22 @@
 
 /*
  * NSS's major version, minor version, patch level, build number, and whether
  * this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define NSS_VERSION  "3.26" _NSS_CUSTOMIZED " Beta"
+#define NSS_VERSION  "3.26" _NSS_CUSTOMIZED
 #define NSS_VMAJOR   3
-#define NSS_VMINOR   25
+#define NSS_VMINOR   26
 #define NSS_VPATCH   0
 #define NSS_VBUILD   0
-#define NSS_BETA     PR_TRUE
+#define NSS_BETA     PR_FALSE
 
 #ifndef RC_INVOKED
 
 #include "seccomon.h"
 
 typedef struct NSSInitParametersStr NSSInitParameters;
 
 /*
--- a/security/nss/lib/nss/nssinit.c
+++ b/security/nss/lib/nss/nssinit.c
@@ -333,47 +333,47 @@ nss_FindExternalRoot(const char *dbpath,
 
 /*
  * see nss_Init for definitions of the various options.
  *
  * this function builds a moduleSpec string from the options and previously
  * set statics (from PKCS11_Configure, for instance), and uses it to kick off
  * the loading of the various PKCS #11 modules.
  */
-static SECStatus
+static SECMODModule *
 nss_InitModules(const char *configdir, const char *certPrefix, 
 		const char *keyPrefix, const char *secmodName, 
 		const char *updateDir, const char *updCertPrefix, 
 		const char *updKeyPrefix, const char *updateID, 
 		const char *updateName, char *configName, char *configStrings,
 		PRBool pwRequired, PRBool readOnly, PRBool noCertDB,
 		PRBool noModDB, PRBool forceOpen, PRBool optimizeSpace,
 		PRBool isContextInit)
 {
-    SECStatus rv = SECFailure;
+    SECMODModule *module = NULL;
     char *moduleSpec = NULL;
     char *flags = NULL;
     char *lconfigdir = NULL;
     char *lcertPrefix = NULL;
     char *lkeyPrefix = NULL;
     char *lsecmodName = NULL;
     char *lupdateDir = NULL;
     char *lupdCertPrefix = NULL;
     char *lupdKeyPrefix = NULL;
     char *lupdateID = NULL;
     char *lupdateName = NULL;
 
     if (NSS_InitializePRErrorTable() != SECSuccess) {
 	PORT_SetError(SEC_ERROR_NO_MEMORY);
-	return rv;
+	return NULL;
     }
 
     flags = nss_makeFlags(readOnly,noCertDB,noModDB,forceOpen,
 					pwRequired, optimizeSpace);
-    if (flags == NULL) return rv;
+    if (flags == NULL) return NULL;
 
     /*
      * configdir is double nested, and Windows uses the same character
      * for file seps as we use for escapes! (sigh).
      */
     lconfigdir = NSSUTIL_DoubleEscape(configdir, '\'', '\"');
     if (lconfigdir == NULL) {
 	goto loser;
@@ -430,24 +430,24 @@ loser:
     if (lsecmodName) PORT_Free(lsecmodName);
     if (lupdateDir) PORT_Free(lupdateDir);
     if (lupdCertPrefix) PORT_Free(lupdCertPrefix);
     if (lupdKeyPrefix) PORT_Free(lupdKeyPrefix);
     if (lupdateID) PORT_Free(lupdateID);
     if (lupdateName) PORT_Free(lupdateName);
 
     if (moduleSpec) {
-	SECMODModule *module = SECMOD_LoadModule(moduleSpec,NULL,PR_TRUE);
+	module = SECMOD_LoadModule(moduleSpec, NULL, PR_TRUE);
 	PR_smprintf_free(moduleSpec);
-	if (module) {
-	    if (module->loaded) rv=SECSuccess;
+	if (module && !module->loaded) {
 	    SECMOD_DestroyModule(module);
+	    return NULL;
 	}
     }
-    return rv;
+    return module;
 }
 
 /*
  * OK there are now lots of options here, lets go through them all:
  *
  * configdir - base directory where all the cert, key, and module datbases live.
  * certPrefix - prefix added to the beginning of the cert database example: "
  * 			"https-server1-"
@@ -515,43 +515,46 @@ nss_doLockInit(void)
 	return PR_FAILURE;
     }
     return PR_SUCCESS;
 }
 
 
 static SECStatus
 nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix,
-		 const char *secmodName, const char *updateDir, 
+		 const char *secmodName, const char *updateDir,
 		 const char *updCertPrefix, const char *updKeyPrefix,
 		 const char *updateID, const char *updateName,
 		 NSSInitContext ** initContextPtr,
 		 NSSInitParameters *initParams,
-		 PRBool readOnly, PRBool noCertDB, 
+		 PRBool readOnly, PRBool noCertDB,
 		 PRBool noModDB, PRBool forceOpen, PRBool noRootInit,
 		 PRBool optimizeSpace, PRBool noSingleThreadedModules,
 		 PRBool allowAlreadyInitializedModules,
 		 PRBool dontFinalizeModules)
 {
-    SECStatus rv = SECFailure;
+    SECMODModule *parent = NULL;
 #ifndef NSS_DISABLE_LIBPKIX
     PKIX_UInt32 actualMinorVersion = 0;
     PKIX_Error *pkixError = NULL;
 #endif /* NSS_DISABLE_LIBPKIX */
     PRBool isReallyInitted;
     char *configStrings = NULL;
     char *configName = NULL;
     PRBool passwordRequired = PR_FALSE;
+#ifdef POLICY_FILE
+    char *ignoreVar;
+#endif
 
     /* if we are trying to init with a traditional NSS_Init call, maintain
      * the traditional idempotent behavior. */
     if (!initContextPtr && nssIsInitted) {
 	return SECSuccess;
     }
-  
+
     /* make sure our lock and condition variable are initialized one and only
      * one time */ 
     if (PR_CallOnce(&nssInitOnce, nss_doLockInit) != PR_SUCCESS) {
 	return SECFailure;
     }
 
     /*
      * if we haven't done basic initialization, single thread the 
@@ -638,23 +641,23 @@ nss_Init(const char *configdir, const ch
 	configStrings = pk11_config_strings;
 	configName = pk11_config_name;
 	passwordRequired = pk11_password_required;
     }
 
     /* Skip the module init if we are already initted and we are trying
      * to init with noCertDB and noModDB */
     if (!(isReallyInitted && noCertDB && noModDB)) {
-	rv = nss_InitModules(configdir, certPrefix, keyPrefix, secmodName, 
-		updateDir, updCertPrefix, updKeyPrefix, updateID, 
+	parent = nss_InitModules(configdir, certPrefix, keyPrefix, secmodName,
+		updateDir, updCertPrefix, updKeyPrefix, updateID,
 		updateName, configName, configStrings, passwordRequired,
-		readOnly, noCertDB, noModDB, forceOpen, optimizeSpace, 
+		readOnly, noCertDB, noModDB, forceOpen, optimizeSpace,
 		(initContextPtr != NULL));
 
-	if (rv != SECSuccess) {
+	if (parent == NULL) {
 	    goto loser;
 	}
     }
 
 
     /* finish up initialization */
     if (!isReallyInitted) {
 	if (SECOID_Init() != SECSuccess) {
@@ -683,17 +686,40 @@ nss_Init(const char *configdir, const ch
 		     * path. Skip it */
 		    dbpath = NULL;
 		}
 		if (dbpath) {
 		    nss_FindExternalRoot(dbpath, secmodName);
 		}
 	    }
 	}
-
+#ifdef POLICY_FILE
+	/* Load the system crypto policy file if it exists,
+	 * unless the NSS_IGNORE_SYSTEM_POLICY environment
+	 * variable has been set to 1. */
+	ignoreVar = PR_GetEnvSecure("NSS_IGNORE_SYSTEM_POLICY");
+	if (ignoreVar == NULL || strncmp(ignoreVar, "1", sizeof("1")) != 0) {
+	    if (PR_Access(POLICY_PATH "/" POLICY_FILE, PR_ACCESS_READ_OK) == PR_SUCCESS) {
+	    SECMODModule *module = SECMOD_LoadModule(
+		"name=\"Policy File\" "
+		"parameters=\"configdir='sql:" POLICY_PATH "' "
+		"secmod='" POLICY_FILE "' "
+		"flags=readOnly,noCertDB,forceSecmodChoice,forceOpen\" "
+		"NSS=\"flags=internal,moduleDB,skipFirst,moduleDBOnly,critical\"",
+		parent, PR_TRUE);
+	    if (module) {
+		PRBool isLoaded = module->loaded;
+		SECMOD_DestroyModule(module);
+		if (!isLoaded) {
+		    goto loser;
+		}
+	    }
+	}
+    }
+#endif
 	pk11sdr_Init();
 	cert_CreateSubjectKeyIDHashTable();
 
 #ifndef NSS_DISABLE_LIBPKIX
 	pkixError = PKIX_Initialize
 	    (PKIX_FALSE, PKIX_MAJOR_VERSION, PKIX_MINOR_VERSION,
 	    PKIX_MINOR_VERSION, &actualMinorVersion, &plContext);
 
@@ -724,32 +750,38 @@ nss_Init(const char *configdir, const ch
     nssIsInInit--;
     /* now that we are inited, all waiters can move forward */
     PZ_NotifyAllCondVar(nssInitCondition);
     PZ_Unlock(nssInitLock);
 
     if (initContextPtr && configStrings) {
 	PR_smprintf_free(configStrings);
     }
+    if (parent) {
+	SECMOD_DestroyModule(parent);
+    }
 
     return SECSuccess;
 
 loser:
     if (initContextPtr && *initContextPtr) {
 	PORT_Free(*initContextPtr);
 	*initContextPtr = NULL;
 	if (configStrings) {
 	   PR_smprintf_free(configStrings);
 	}
     }
     PZ_Lock(nssInitLock);
     nssIsInInit--;
     /* We failed to init, allow one to move forward */
     PZ_NotifyCondVar(nssInitCondition);
     PZ_Unlock(nssInitLock);
+    if (parent) {
+	SECMOD_DestroyModule(parent);
+    }
     return SECFailure;
 }
 
 
 SECStatus
 NSS_Init(const char *configdir)
 {
     return nss_Init(configdir, "", "", SECMOD_DB, "", "", "", "", "", NULL,
--- a/security/nss/lib/pki/pki3hack.c
+++ b/security/nss/lib/pki/pki3hack.c
@@ -1313,32 +1313,34 @@ DeleteCertTrustMatchingSlot(PK11SlotInfo
     nssPKIObject_Unlock(tObject);
     nssPKIObject_Destroy(tObject);
 
     return failureCount == 0 ? PR_SUCCESS : PR_FAILURE;
 }
 
 /*
 ** Delete trust objects matching the slot of the given certificate.
-** Returns an error if any device fails to delete. 
+** Returns an error if any device fails to delete.
 */
 NSS_EXTERN PRStatus
 STAN_DeleteCertTrustMatchingSlot(NSSCertificate *c)
 {
     PRStatus nssrv = PR_SUCCESS;
 
+    unsigned int i;
+    nssPKIObject *tobject = NULL;
+    nssPKIObject *cobject = &c->object;
+
     NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
     NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c);
     if (!nssTrust) {
         return PR_FAILURE;
     }
 
-    nssPKIObject *tobject = &nssTrust->object;
-    nssPKIObject *cobject = &c->object;
-    unsigned int i;
+    tobject = &nssTrust->object;
 
     /* Iterate through the cert and trust object instances looking for
      * those with matching pk11 slots to delete. Even if some device
      * can't delete we keep going. Keeping a status variable for the
      * loop so that once it's failed the other gets set.
      */
     NSSRWLock_LockRead(td->tokensLock);
     nssPKIObject_AddRef(cobject);
--- a/security/nss/lib/softoken/softkver.h
+++ b/security/nss/lib/softoken/softkver.h
@@ -20,16 +20,16 @@
 
 /*
  * Softoken's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define SOFTOKEN_VERSION  "3.26" SOFTOKEN_ECC_STRING " Beta"
+#define SOFTOKEN_VERSION  "3.26" SOFTOKEN_ECC_STRING
 #define SOFTOKEN_VMAJOR   3
-#define SOFTOKEN_VMINOR   25
+#define SOFTOKEN_VMINOR   26
 #define SOFTOKEN_VPATCH   0
 #define SOFTOKEN_VBUILD   0
-#define SOFTOKEN_BETA     PR_TRUE
+#define SOFTOKEN_BETA     PR_FALSE
 
 #endif /* _SOFTKVER_H_ */
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -9966,20 +9966,16 @@ ssl3_SendServerHello(sslSocket *ss)
     rv = ssl3_SetupPendingCipherSpec(ss);
     if (rv != SECSuccess) {
         return rv; /* err set by ssl3_SetupPendingCipherSpec */
     }
 
     return SECSuccess;
 }
 
-static SECStatus
-ssl3_PickSignatureHashAlgorithm(sslSocket *ss,
-                                SSLSignatureAndHashAlg *out);
-
 SECStatus
 ssl_CreateDHEKeyPair(const namedGroupDef *groupDef,
                      const ssl3DHParams *params,
                      sslEphemeralKeyPair **keyPair)
 {
     SECKEYDHParams dhParam;
     SECKEYPublicKey *pubKey = NULL;   /* Ephemeral DH key */
     SECKEYPrivateKey *privKey = NULL; /* Ephemeral DH key */
@@ -10132,17 +10128,17 @@ loser:
     return SECFailure;
 }
 
 /* ssl3_PickSignatureHashAlgorithm selects a hash algorithm to use when signing
  * elements of the handshake. (The negotiated cipher suite determines the
  * signature algorithm.) Prior to TLS 1.2, the MD5/SHA1 combination is always
  * used. With TLS 1.2, a client may advertise its support for signature and
  * hash combinations. */
-static SECStatus
+SECStatus
 ssl3_PickSignatureHashAlgorithm(sslSocket *ss,
                                 SSLSignatureAndHashAlg *out)
 {
     PRUint32 policy;
     unsigned int i, j;
 
     out->sigAlg = ss->ssl3.hs.kea_def->signKeyType;
 
--- a/security/nss/lib/ssl/sslimpl.h
+++ b/security/nss/lib/ssl/sslimpl.h
@@ -2027,16 +2027,18 @@ PRBool ssl3_ClientExtensionAdvertised(ss
 SECStatus ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid);
 const ssl3CipherSuiteDef *ssl_LookupCipherSuiteDef(ssl3CipherSuite suite);
 SECStatus ssl3_SelectServerCert(sslSocket *ss);
 SECStatus ssl3_TLSSignatureAlgorithmForKeyType(KeyType keyType,
                                                SSLSignType *out);
 
 SECStatus ssl3_SetCipherSuite(sslSocket *ss, ssl3CipherSuite chosenSuite,
                               PRBool initHashes);
+SECStatus ssl3_PickSignatureHashAlgorithm(sslSocket *ss,
+                                          SSLSignatureAndHashAlg *out);
 
 /* Pull in TLS 1.3 functions */
 #include "tls13con.h"
 
 /********************** misc calls *********************/
 
 #ifdef DEBUG
 extern void ssl3_CheckCipherSuiteOrderConsistency();
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -72,18 +72,18 @@ static sslOptions ssl_defaults = {
     PR_FALSE,              /* noLocks            */
     PR_FALSE,              /* enableSessionTickets */
     PR_FALSE,              /* enableDeflate      */
     2,                     /* enableRenegotiation (default: requires extension) */
     PR_FALSE,              /* requireSafeNegotiation */
     PR_FALSE,              /* enableFalseStart   */
     PR_TRUE,               /* cbcRandomIV        */
     PR_FALSE,              /* enableOCSPStapling */
-    PR_TRUE,               /* enableNPN          */
-    PR_FALSE,              /* enableALPN         */
+    PR_FALSE,              /* enableNPN          */
+    PR_TRUE,               /* enableALPN         */
     PR_TRUE,               /* reuseServerECDHEKey */
     PR_FALSE,              /* enableFallbackSCSV */
     PR_TRUE,               /* enableServerDhe */
     PR_FALSE,              /* enableExtendedMS    */
     PR_FALSE,              /* enableSignedCertTimestamps */
     PR_FALSE               /* requireDHENamedGroups */
 };
 
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -2432,17 +2432,16 @@ tls13_SendEncryptedExtensions(sslSocket 
     return SECSuccess;
 }
 
 SECStatus
 tls13_SendCertificateVerify(sslSocket *ss, SECKEYPrivateKey *privKey)
 {
     SECStatus rv = SECFailure;
     SECItem buf = { siBuffer, NULL, 0 };
-    KeyType keyType;
     unsigned int len;
     SSLSignatureAndHashAlg sigAndHash;
     TLS13CombinedHash hash;
     SSL3Hashes tbsHash; /* The hash "to be signed". */
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
@@ -2450,23 +2449,40 @@ tls13_SendCertificateVerify(sslSocket *s
                 SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_single);
     rv = tls13_ComputeHandshakeHashes(ss, &hash);
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
-    rv = tls13_AddContextToHashes(ss, &hash, tls13_GetHash(ss), PR_TRUE,
+    if (ss->sec.isServer) {
+        rv = ssl3_PickSignatureHashAlgorithm(ss, &sigAndHash);
+        if (rv != SECSuccess) {
+            return SECFailure;
+        }
+    } else {
+        PORT_Assert(ss->ssl3.hs.tls12CertVerifyHash != ssl_hash_none);
+        if (ss->ssl3.hs.tls12CertVerifyHash == ssl_hash_none) {
+            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+            return SECFailure;
+        }
+        sigAndHash.hashAlg = ss->ssl3.hs.tls12CertVerifyHash;
+        rv = ssl3_TLSSignatureAlgorithmForKeyType(privKey->keyType,
+                                                  &sigAndHash.sigAlg);
+        if (rv != SECSuccess) {
+            return SECFailure;
+        }
+    }
+    rv = tls13_AddContextToHashes(ss, &hash, sigAndHash.hashAlg, PR_TRUE,
                                   &tbsHash);
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
-    keyType = privKey->keyType;
     rv = ssl3_SignHashes(&tbsHash, privKey, &buf, PR_TRUE);
     if (rv == SECSuccess && !ss->sec.isServer) {
         /* Remember the info about the slot that did the signing.
          * Later, when doing an SSL restart handshake, verify this.
          * These calls are mere accessors, and can't fail.
          */
         PK11SlotInfo *slot;
         sslSessionID *sid = ss->sec.ci.sid;
@@ -2483,23 +2499,17 @@ tls13_SendCertificateVerify(sslSocket *s
     }
 
     len = buf.len + 2 + 2;
 
     rv = ssl3_AppendHandshakeHeader(ss, certificate_verify, len);
     if (rv != SECSuccess) {
         goto done; /* error code set by AppendHandshake */
     }
-    rv = ssl3_TLSSignatureAlgorithmForKeyType(keyType,
-                                              &sigAndHash.sigAlg);
-    if (rv != SECSuccess) {
-        goto done;
-    }
-
-    sigAndHash.hashAlg = tbsHash.hashAlg;
+
     rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
     if (rv != SECSuccess) {
         goto done; /* err set by AppendHandshake. */
     }
 
     rv = ssl3_AppendHandshakeVariable(ss, buf.data, buf.len, 2);
     if (rv != SECSuccess) {
         goto done; /* error code set by AppendHandshake */
@@ -2533,47 +2543,34 @@ tls13_HandleCertificateVerify(sslSocket 
 
     rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY,
                               wait_cert_verify);
     if (rv != SECSuccess) {
         return SECFailure;
     }
     PORT_Assert(hashes);
 
-    /* We only support CertificateVerify messages that use the handshake
-     * hash.
-     * TODO(ekr@rtfm.com): This should be easy to relax in TLS 1.3 by
-     * reading the client's hash algorithm first, but there may
-     * be subtleties so retain the restriction for now.
-     */
-    rv = tls13_AddContextToHashes(ss, hashes, tls13_GetHash(ss), PR_FALSE,
-                                  &tbsHash);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SSL_ERROR_DIGEST_FAILURE, internal_error);
-        return SECFailure;
-    }
-
     rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
                                                &sigAndHash);
     if (rv != SECSuccess) {
         PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_VERIFY);
         return SECFailure;
     }
 
     rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
         ss, &sigAndHash, ss->sec.peerCert);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_VERIFY, decrypt_error);
         return SECFailure;
     }
 
-    /* We only support CertificateVerify messages that use the handshake
-     * hash. TODO(ekr@rtfm.com): bug 1179338. */
-    if (sigAndHash.hashAlg != tls13_GetHash(ss)) {
-        FATAL_ERROR(ss, SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM, decrypt_error);
+    rv = tls13_AddContextToHashes(ss, hashes, sigAndHash.hashAlg, PR_FALSE,
+                                  &tbsHash);
+    if (rv != SECSuccess) {
+        FATAL_ERROR(ss, SSL_ERROR_DIGEST_FAILURE, internal_error);
         return SECFailure;
     }
 
     rv = ssl3_ConsumeHandshakeVariable(ss, &signed_hash, 2, &b, &length);
     if (rv != SECSuccess) {
         PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_VERIFY);
         return SECFailure;
     }
@@ -3192,16 +3189,17 @@ static const struct {
     { ssl_padding_xtn, ExtensionNotUsed },
     { ssl_extended_master_secret_xtn, ExtensionNotUsed },
     { ssl_session_ticket_xtn, ExtensionClientOnly },
     { ssl_tls13_key_share_xtn, ExtensionSendClear },
     { ssl_tls13_pre_shared_key_xtn, ExtensionSendClear },
     { ssl_tls13_early_data_xtn, ExtensionSendClear },
     { ssl_next_proto_nego_xtn, ExtensionNotUsed },
     { ssl_renegotiation_info_xtn, ExtensionNotUsed },
+    { ssl_signed_cert_timestamp_xtn, ExtensionSendEncrypted },
     { ssl_tls13_draft_version_xtn, ExtensionClientOnly }
 };
 
 PRBool
 tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message)
 {
     unsigned int i;
 
--- a/security/nss/lib/ssl/tls13hkdf.c
+++ b/security/nss/lib/ssl/tls13hkdf.c
@@ -79,24 +79,25 @@ tls13_HkdfExtract(PK11SymKey *ikm1, PK11
     paramsi.len = sizeof(params);
 
     PORT_Assert(kTlsHkdfInfo[baseHash].pkcs11Mech);
     PORT_Assert(kTlsHkdfInfo[baseHash].hashSize);
     PORT_Assert(kTlsHkdfInfo[baseHash].hash == baseHash);
 
     /* A zero ikm2 is a key of hash-length 0s. */
     if (!ikm2in) {
-        slot = PK11_GetInternalSlot();
         SECItem zeroItem = {
             siBuffer,
             (unsigned char *)zeroKeyBuf,
             kTlsHkdfInfo[baseHash].hashSize
         };
-        if (!slot)
+        slot = PK11_GetInternalSlot();
+        if (!slot) {
             return SECFailure;
+        }
         zeroKey = PK11_ImportSymKey(slot,
                                     kTlsHkdfInfo[baseHash].pkcs11Mech,
                                     PK11_OriginUnwrap,
                                     CKA_DERIVE, &zeroItem, NULL);
         if (!zeroKey)
             return SECFailure;
         ikm2 = zeroKey;
     } else {
--- a/security/nss/lib/util/nssutil.h
+++ b/security/nss/lib/util/nssutil.h
@@ -16,20 +16,20 @@
  * NSS utilities's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
  */
 #define NSSUTIL_VERSION  "3.26"
 #define NSSUTIL_VMAJOR   3
-#define NSSUTIL_VMINOR   25
+#define NSSUTIL_VMINOR   26
 #define NSSUTIL_VPATCH   0
 #define NSSUTIL_VBUILD   0
-#define NSSUTIL_BETA     PR_TRUE
+#define NSSUTIL_BETA     PR_FALSE
 
 SEC_BEGIN_PROTOS
 
 /*
  * Returns a const string of the UTIL library version.
  */
 extern const char *NSSUTIL_GetVersion(void);
 
--- a/security/nss/lib/util/utilpars.c
+++ b/security/nss/lib/util/utilpars.c
@@ -1145,18 +1145,19 @@ char *
 	noModDB = PR_TRUE;
 	*dbType = NSS_DB_TYPE_SQL;
 	PORT_Free(*filename);
 	*filename = NULL;
         *rw = PR_FALSE;
    }
 
    /* only use the renamed secmod for legacy databases */
-   if ((*dbType != NSS_DB_TYPE_LEGACY) && 
-	(*dbType != NSS_DB_TYPE_MULTIACCESS)) {
+   if ((*dbType != NSS_DB_TYPE_LEGACY) &&
+	(*dbType != NSS_DB_TYPE_MULTIACCESS) &&
+	  !NSSUTIL_ArgHasFlag("flags", "forceSecmodChoice", save_params)) {
 	secmodName="pkcs11.txt";
    }
 
    if (noModDB) {
 	value = NULL;
    } else if (lconfigdir && lconfigdir[0] != '\0') {
 	value = PR_smprintf("%s" NSSUTIL_PATH_SEPARATOR "%s",
 			lconfigdir,secmodName);
--- a/security/nss/tests/ec/ec.sh
+++ b/security/nss/tests/ec/ec.sh
@@ -28,10 +28,10 @@ run_ec_tests()
         SCRIPTNAME=${ECTEST}.sh
         echo "Running ec tests for ${ECTEST}"
         echo "TIMESTAMP ${ECTEST} BEGIN: `date`"
         (cd ${QADIR}/ec; . ./${SCRIPTNAME} 2>&1)
         echo "TIMESTAMP ${ECTEST} END: `date`"
     done
 }
 
-ECTESTS="ecperf"
-run_ec_tests
\ No newline at end of file
+ECTESTS="ecperf ectest"
+run_ec_tests
new file mode 100644
--- /dev/null
+++ b/security/nss/tests/ec/ectest.sh
@@ -0,0 +1,52 @@
+#! /bin/bash
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+########################################################################
+#
+# tests/ec/ectest.sh
+#
+# needs to work on all Unix and Windows platforms
+#
+# special strings
+# ---------------
+#   FIXME ... known problems, search for this string
+#   NOTE .... unexpected behavior
+#
+########################################################################
+
+############################## ectest_init #############################
+# local shell function to initialize this script
+########################################################################
+
+ectest_init()
+{
+  SCRIPTNAME="ectest.sh"
+  if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ] ; then
+      cd ../common
+      . ./init.sh
+  fi
+  SCRIPTNAME="ectest.sh"
+  html_head "ectest test"
+}
+
+ectest_cleanup()
+{
+  html "</TABLE><BR>"
+  cd ${QADIR}
+  chmod a+rw $RONLY_DIR
+  . common/cleanup.sh
+}
+
+ectest_init
+ECTEST_OUT=`ectest`
+ECTEST_OUT=`echo $ECTEST_OUT | grep -i "not okay"`
+# TODO: expose individual tests and failures instead of overall
+if [ -n "$ECTEST_OUT" ] ; then
+  html_failed "ec(test) test"
+else
+  html_passed "ec(test) test"
+fi
+ectest_cleanup
--- a/security/sandbox/linux/SandboxFilter.cpp
+++ b/security/sandbox/linux/SandboxFilter.cpp
@@ -642,16 +642,17 @@ public:
     case __NR_rt_tgsigqueueinfo: {
       Arg<pid_t> tgid(0);
       return If(tgid == getpid(), Allow())
         .Else(InvalidSyscall());
     }
 #endif
 
     case __NR_mlock:
+    case __NR_munlock:
       return Allow();
 
       // We can't usefully allow fork+exec, even on a temporary basis;
       // the child would inherit the seccomp-bpf policy and almost
       // certainly die from an unexpected SIGSYS.  We also can't have
       // fork() crash, currently, because there are too many system
       // libraries/plugins that try to run commands.  But they can
       // usually do something reasonable on error.
--- a/testing/web-platform/meta/fetch/nosniff/image.html.ini
+++ b/testing/web-platform/meta/fetch/nosniff/image.html.ini
@@ -1,103 +0,0 @@
-[image.html]
-  type: testharness
-  [URL query: ]
-    expected:
-      if not debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "mac") and (version == "OS X 10.8") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and (os == "mac") and (version == "OS X 10.6.8") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and (os == "mac") and (version == "OS X 10.6.8") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "mac") and (version == "OS X 10.8"): FAIL
-      if not debug and not e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-
-  [URL query: ?type=]
-    expected:
-      if not debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "mac") and (version == "OS X 10.8") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and (os == "mac") and (version == "OS X 10.6.8") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and (os == "mac") and (version == "OS X 10.6.8") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "mac") and (version == "OS X 10.8"): FAIL
-      if not debug and not e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-
-  [URL query: ?type=x]
-    expected:
-      if not debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "mac") and (version == "OS X 10.8") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and (os == "mac") and (version == "OS X 10.6.8") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and (os == "mac") and (version == "OS X 10.6.8") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "mac") and (version == "OS X 10.8"): FAIL
-      if not debug and not e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-
-  [URL query: ?type=x/x]
-    expected:
-      if not debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "mac") and (version == "OS X 10.8") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and (os == "mac") and (version == "OS X 10.6.8") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "linux") and (version == "Ubuntu 12.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and (os == "mac") and (version == "OS X 10.6.8") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "mac") and (version == "OS X 10.10.2") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "mac") and (version == "OS X 10.8"): FAIL
-      if not debug and not e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-
-  [URL query: ?type=image/gif]
-    expected:
-      if not debug and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
-      if debug and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if debug and (os == "win") and (version == "10.0.10240") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "win") and (version == "10.0.10240") and (processor == "x86_64") and (bits == 64): FAIL
-
-  [URL query: ?type=image/png]
-    expected:
-      if not debug and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
-      if debug and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if debug and (os == "win") and (version == "10.0.10240") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "win") and (version == "10.0.10240") and (processor == "x86_64") and (bits == 64): FAIL
-
-  [URL query: ?type=image/png;blah]
-    expected:
-      if not debug and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if debug and (os == "win") and (version == "5.1.2600") and (processor == "x86") and (bits == 32): FAIL
-      if debug and (os == "win") and (version == "6.2.9200") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if debug and (os == "win") and (version == "10.0.10240") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and (os == "win") and (version == "10.0.10240") and (processor == "x86_64") and (bits == 64): FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/nosniff/importscripts.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[importscripts.html]
-  type: testharness
-  [Test importScripts()]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/nosniff/parsing-nosniff.html.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[parsing-nosniff.html]
-  type: testharness
-  [URL query: first]
-    expected: FAIL
-
-  [URL query: uppercase]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/nosniff/script.html.ini
+++ /dev/null
@@ -1,14 +0,0 @@
-[script.html]
-  type: testharness
-  [URL query: ]
-    expected: FAIL
-
-  [URL query: ?type=]
-    expected: FAIL
-
-  [URL query: ?type=x]
-    expected: FAIL
-
-  [URL query: ?type=x/x]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/fetch/nosniff/stylesheet.html.ini
+++ /dev/null
@@ -1,17 +0,0 @@
-[stylesheet.html]
-  type: testharness
-  [URL query: ]
-    expected: FAIL
-
-  [URL query: ?type=]
-    expected: FAIL
-
-  [URL query: ?type=x]
-    expected: FAIL
-
-  [URL query: ?type=x/x]
-    expected: FAIL
-
-  [URL query: ?type=text/css;blah]
-    expected: FAIL
-
--- a/testing/web-platform/meta/fetch/nosniff/worker.html.ini
+++ b/testing/web-platform/meta/fetch/nosniff/worker.html.ini
@@ -1,14 +1,3 @@
 [worker.html]
   type: testharness
-  [URL query: ]
-    expected: FAIL
-
-  [URL query: ?type=]
-    expected: FAIL
-
-  [URL query: ?type=x]
-    expected: FAIL
-
-  [URL query: ?type=x/x]
-    expected: FAIL
-
+  expected: ERROR
--- a/testing/web-platform/tests/fetch/nosniff/resources/image.py
+++ b/testing/web-platform/tests/fetch/nosniff/resources/image.py
@@ -1,14 +1,14 @@
 import os.path
 
 def main(request, response):
     type = request.GET.first("type", None)
 
-    body = open(os.path.join(os.path.dirname(__file__), "../../../images/blue96x96.png")).read()
+    body = open(os.path.join(os.path.dirname(__file__), "../../../images/blue96x96.png"), "rb").read()
 
     response.add_required_headers = False
     response.writer.write_status(200)
     response.writer.write_header("x-content-type-options", "nosniff")
     response.writer.write_header("content-length", len(body))
     if(type != None):
       response.writer.write_header("content-type", type)
     response.writer.end_headers()
--- a/testing/web-platform/tests/fetch/nosniff/stylesheet.html
+++ b/testing/web-platform/tests/fetch/nosniff/stylesheet.html
@@ -17,18 +17,14 @@
     }, "URL query: " + urlpart)
   })
 
   passes.forEach(function(urlpart) {
     async_test(function(t) {
       var link = document.createElement("link")
       link.rel = "stylesheet"
       link.onerror = t.unreached_func("Unexpected error event")
-      link.onload = t.step_func_done(function(){
-        if(passes[passes.length-1] == urlpart) {
-          assert_equals(document.styleSheets.length, passes.length)
-        }
-      })
+      link.onload = t.step_func_done(function(){})
       link.href = "resources/css.py" + urlpart
       document.body.appendChild(link)
     }, "URL query: " + urlpart)
   })
 </script>
deleted file mode 100644
--- a/toolkit/xre/MacQuirks.h
+++ /dev/null
@@ -1,256 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-#ifndef MacQuirks_h__
-#define MacQuirks_h__
-
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#include "CoreFoundation/CoreFoundation.h"
-#include "CoreServices/CoreServices.h"
-#include "Carbon/Carbon.h"
-
-// This file is a copy and paste from existing methods from
-// libxul. This is intentional because this interpose
-// library does not link with libxul.
-
-struct VersionPart {
-  int32_t     numA;
-
-  const char *strB;    // NOT null-terminated, can be a null pointer
-  uint32_t    strBlen;
-
-  int32_t     numC;
-
-  char       *extraD;  // null-terminated
-};
-
-/**
- * Parse a version part into a number and "extra text".
- *
- * @returns A pointer to the next versionpart, or null if none.
- */
-static char*
-ParseVP(char *part, VersionPart &result)
-{
-  char *dot;
-
-  result.numA = 0;
-  result.strB = nullptr;
-  result.strBlen = 0;
-  result.numC = 0;
-  result.extraD = nullptr;
-
-  if (!part)
-    return part;
-
-  dot = strchr(part, '.');
-  if (dot)
-    *dot = '\0';
-
-  if (part[0] == '*' && part[1] == '\0') {
-    result.numA = INT32_MAX;
-    result.strB = "";
-  }
-  else {
-    result.numA = strtol(part, const_cast<char**>(&result.strB), 10);
-  }
-
-  if (!*result.strB) {
-    result.strB = nullptr;
-    result.strBlen = 0;
-  }
-  else {
-    if (result.strB[0] == '+') {
-      static const char kPre[] = "pre";
-
-      ++result.numA;
-      result.strB = kPre;
-      result.strBlen = sizeof(kPre) - 1;
-    }
-    else {
-      const char *numstart = strpbrk(result.strB, "0123456789+-");
-      if (!numstart) {
-  result.strBlen = strlen(result.strB);
-      }
-      else {
-  result.strBlen = numstart - result.strB;
-
-  result.numC = strtol(numstart, &result.extraD, 10);
-  if (!*result.extraD)
-    result.extraD = nullptr;
-      }
-    }
-  }
-
-  if (dot) {
-    ++dot;
-
-    if (!*dot)
-      dot = nullptr;
-  }
-
-  return dot;
-}
-
-
-// compare two null-terminated strings, which may be null pointers
-static int32_t
-ns_strcmp(const char *str1, const char *str2)
-{
-  // any string is *before* no string
-  if (!str1)
-    return str2 != 0;
-
-  if (!str2)
-    return -1;
-
-  return strcmp(str1, str2);
-}
-
-// compare two length-specified string, which may be null pointers
-static int32_t
-ns_strnncmp(const char *str1, uint32_t len1, const char *str2, uint32_t len2)
-{
-  // any string is *before* no string
-  if (!str1)
-    return str2 != 0;
-
-  if (!str2)
-    return -1;
-
-  for (; len1 && len2; --len1, --len2, ++str1, ++str2) {
-    if (*str1 < *str2)
-      return -1;
-
-    if (*str1 > *str2)
-      return 1;
-  }
-
-  if (len1 == 0)
-    return len2 == 0 ? 0 : -1;
-
-  return 1;
-}
-
-// compare two int32_t
-static int32_t
-ns_cmp(int32_t n1, int32_t n2)
-{
-  if (n1 < n2)
-    return -1;
-
-  return n1 != n2;
-}
-
-/**
- * Compares two VersionParts
- */
-static int32_t
-CompareVP(VersionPart &v1, VersionPart &v2)
-{
-  int32_t r = ns_cmp(v1.numA, v2.numA);
-  if (r)
-    return r;
-
-  r = ns_strnncmp(v1.strB, v1.strBlen, v2.strB, v2.strBlen);
-  if (r)
-    return r;
-
-  r = ns_cmp(v1.numC, v2.numC);
-  if (r)
-    return r;
-
-  return ns_strcmp(v1.extraD, v2.extraD);
-}
-
-/* this is intentionally not static so that we don't end up making copies
- * anywhere */
-int32_t
-NS_CompareVersions(const char *A, const char *B)
-{
-  char *A2 = strdup(A);
-  if (!A2)
-    return 1;
-
-  char *B2 = strdup(B);
-  if (!B2) {
-    free(A2);
-    return 1;
-  }
-
-  int32_t result;
-  char *a = A2, *b = B2;
-
-  do {
-    VersionPart va, vb;
-
-    a = ParseVP(a, va);
-    b = ParseVP(b, vb);
-
-    result = CompareVP(va, vb);
-    if (result)
-      break;
-
-  } while (a || b);
-
-  free(A2);
-  free(B2);
-
-  return result;
-}
-
-
-static void
-TriggerQuirks()
-{
-  int mib[2];
-
-  mib[0] = CTL_KERN;
-  mib[1] = KERN_OSRELEASE;
-  // we won't support versions greater than 10.7.99
-  char release[sizeof("10.7.99")];
-  size_t len = sizeof(release);
-  // sysctl will return ENOMEM if the release string is longer than sizeof(release)
-  int ret = sysctl(mib, 2, release, &len, nullptr, 0);
-  // we only want to trigger this on OS X 10.6, on versions 10.6.8 or newer
-  // Darwin version 10 corresponds to OS X version 10.6, version 11 is 10.7
-  // http://en.wikipedia.org/wiki/Darwin_(operating_system)#Release_history
-  if (ret == 0 && NS_CompareVersions(release, "10.8.0") >= 0 && NS_CompareVersions(release, "11") < 0) {
-    CFBundleRef mainBundle = CFBundleGetMainBundle();
-    if (mainBundle) {
-      CFRetain(mainBundle);
-
-      CFStringRef bundleID = CFBundleGetIdentifier(mainBundle);
-      if (bundleID) {
-        CFRetain(bundleID);
-
-        CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFBundleGetInfoDictionary(mainBundle);
-        CFDictionarySetValue(dict, CFSTR("CFBundleIdentifier"), CFSTR("org.mozilla.firefox"));
-
-        // Trigger a load of the quirks table for org.mozilla.firefox.
-        // We use different function on 32/64bit because of how the APIs
-        // behave to force a call to GetBugsForOurBundleIDFromCoreservicesd.
-#ifdef __i386__
-        ProcessSerialNumber psn;
-        ::GetCurrentProcess(&psn);
-#else
-        SInt32 major;
-        ::Gestalt(gestaltSystemVersionMajor, &major);
-#endif
-
-        // restore the original id
-        dict = (CFMutableDictionaryRef)CFBundleGetInfoDictionary(mainBundle);
-        CFDictionarySetValue(dict, CFSTR("CFBundleIdentifier"), bundleID);
-
-        CFRelease(bundleID);
-      }
-      CFRelease(mainBundle);
-    }
-  }
-}
-
-#endif //MacQuirks_h__
--- a/toolkit/xre/moz.build
+++ b/toolkit/xre/moz.build
@@ -25,17 +25,16 @@ EXPORTS += ['nsAppRunner.h']
 if CONFIG['MOZ_INSTRUMENT_EVENT_LOOP']:
     EXPORTS += ['EventTracer.h']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     UNIFIED_SOURCES += [
         'nsNativeAppSupportWin.cpp',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-    EXPORTS += ['MacQuirks.h']
     UNIFIED_SOURCES += [
         'MacApplicationDelegate.mm',
         'MacAutoreleasePool.mm',
         'MacLaunchHelper.mm',
         'nsCommandLineServiceMac.cpp',
         'nsNativeAppSupportCocoa.mm',
         'updaterfileutils_osx.mm',
     ]