author | Carsten "Tomcat" Book <cbook@mozilla.com> |
Wed, 20 Jul 2016 16:55:12 +0200 | |
changeset 305851 | d224fc999cb6accb208af0a105f14433375e2e77 |
parent 305850 | 03269dd72a7259f582977714559f0f4ef19988aa (current diff) |
parent 305820 | da701570fa3f6147f56b4d83c190da120470f560 (diff) |
child 305852 | f90a9f8af37c202842f5d9c5b2928004124ab5e1 |
child 306038 | a71e7db89da62e577f8995c886cc74272997a1bb |
child 306067 | 63a62a6c3cddfefae733a428c24def6063d320d1 |
push id | 79681 |
push user | cbook@mozilla.com |
push date | Wed, 20 Jul 2016 14:56:17 +0000 |
treeherder | mozilla-inbound@f90a9f8af37c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 50.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
50.0a1
/
20160721030216
/
pushlog to previous
nightly linux64
50.0a1
/
20160721030216
/
pushlog to previous
nightly mac
50.0a1
/
20160721030203
/
pushlog to previous
nightly win32
50.0a1
/
20160721030216
/
pushlog to previous
nightly win64
50.0a1
/
20160721030216
/
pushlog to previous
|
dom/plugins/ipc/interpose/plugin_child_quirks.mm | file | annotate | diff | comparison | revisions | |
security/nss/.travis.yml | file | annotate | diff | comparison | revisions | |
security/nss/circle.yml | file | annotate | diff | comparison | revisions | |
testing/web-platform/meta/fetch/nosniff/importscripts.html.ini | file | annotate | diff | comparison | revisions | |
testing/web-platform/meta/fetch/nosniff/parsing-nosniff.html.ini | file | annotate | diff | comparison | revisions | |
testing/web-platform/meta/fetch/nosniff/script.html.ini | file | annotate | diff | comparison | revisions | |
testing/web-platform/meta/fetch/nosniff/stylesheet.html.ini | file | annotate | diff | comparison | revisions | |
toolkit/xre/MacQuirks.h | file | annotate | diff | comparison | revisions |
--- 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', ]