Merge inbound to mozilla-central r=merge a=merge
authorGurzau Raul <rgurzau@mozilla.com>
Wed, 10 Jan 2018 11:58:20 +0200
changeset 398525 d5f42a23909eb181274731b07e4984bfbd18557d
parent 398524 78bb2af7c912124443ee144e967a301a68680211 (current diff)
parent 398441 ce14f861f1a8139c7e94b7aa171ec6b0d3808cbf (diff)
child 398526 24bc6a0ee0843bdd8474a81c013d5b8c2268e80b
child 398618 7f1a490e8af146f19fcb3f52afccba015cc6a45b
child 398635 2438a090b77a56b38547f7250bb499cb2e1ffcce
push id98764
push userncsoregi@mozilla.com
push dateWed, 10 Jan 2018 10:16:20 +0000
treeherdermozilla-inbound@24bc6a0ee084 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone59.0a1
first release with
nightly linux32
d5f42a23909e / 59.0a1 / 20180110100224 / files
nightly linux64
d5f42a23909e / 59.0a1 / 20180110100224 / files
nightly mac
d5f42a23909e / 59.0a1 / 20180110100224 / files
nightly win32
d5f42a23909e / 59.0a1 / 20180110100224 / files
nightly win64
d5f42a23909e / 59.0a1 / 20180110100224 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central r=merge a=merge
security/manager/ssl/security-prefs.js
security/manager/ssl/tests/unit/test_signed_apps/cose_multiple_signed.zip
security/manager/ssl/tests/unit/test_signed_apps/cose_signed.zip
testing/web-platform/meta/html/semantics/scripting-1/the-script-element/script-type-and-language-with-params.html.ini
third_party/rust/cose/src/cbor/decoder.rs
third_party/rust/cose/src/cbor/mod.rs
third_party/rust/cose/src/cbor/serializer.rs
third_party/rust/cose/src/cbor/test_decoder.rs
third_party/rust/cose/src/cbor/test_serializer.rs
third_party/rust/cose/src/nss.rs
third_party/rust/cose/src/test_nss.rs
third_party/rust/cose/src/util_test.rs
toolkit/components/contextualidentity/tests/unit/test_migration2to3.js
toolkit/components/extensions/test/mochitest/test_ext_jsversion.html
--- a/browser/base/content/test/general/file_trackingUI_6.html
+++ b/browser/base/content/test/general/file_trackingUI_6.html
@@ -1,16 +1,16 @@
 <!DOCTYPE html>
 <html>
 <head>
   <meta charset="UTF-8">
   <title>Testing the shield from fetch and XHR</title>
 </head>
 <body>
   <p>Hello there!</p>
-  <script type="application/javascript; version=1.8">
+  <script type="application/javascript">
     function test_fetch() {
       let url = "http://trackertest.org/browser/browser/base/content/test/general/file_trackingUI_6.js";
       return fetch(url);
     }
   </script>
 </body>
 </html>
--- a/devtools/client/debugger/new/README.mozilla
+++ b/devtools/client/debugger/new/README.mozilla
@@ -1,13 +1,13 @@
 This is the debugger.html project output.
 See https://github.com/devtools-html/debugger.html
 
-Version 5.0
-Comparison - https://github.com/devtools-html/debugger.html/compare/release-4...release-5
-Commit: https://github.com/devtools-html/debugger.html/commit/5ecfc84198524399ae75748bd1a28d2df2b45733
+Version 6.0
+Comparison - https://github.com/devtools-html/debugger.html/compare/release-5...release-6
+Commit: https://github.com/devtools-html/debugger.html/commit/bdfae442a439b5d97767070af5b5f8b3fd00c2fc
 
 Packages:
 - babel-plugin-transform-es2015-modules-commonjs @6.26.0
 - babel-preset-react @6.24.1
 - react @15.6.2
 - react-dom @15.6.2
 - webpack @3.8.1
--- a/devtools/client/debugger/new/debugger.js
+++ b/devtools/client/debugger/new/debugger.js
@@ -40723,26 +40723,28 @@ var _selectors = __webpack_require__(135
 var _breakpoint = __webpack_require__(1364);
 
 var _utils = __webpack_require__(1366);
 
 var _source = __webpack_require__(1356);
 
 var _pause = __webpack_require__(1400);
 
-var _devtoolsContextmenu = __webpack_require__(1413);
-
 var _Close = __webpack_require__(1374);
 
 var _Close2 = _interopRequireDefault(_Close);
 
 __webpack_require__(1334);
 
 var _lodash = __webpack_require__(2);
 
+var _BreakpointsContextMenu = __webpack_require__(1805);
+
+var _BreakpointsContextMenu2 = _interopRequireDefault(_BreakpointsContextMenu);
+
 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 function isCurrentlyPausedAtBreakpoint(frame, why, breakpoint) {
   if (!(0, _pause.isInterrupted)(why)) {
     return false;
   }
@@ -40786,191 +40788,16 @@ class Breakpoints extends _react.PureCom
 
     if (breakpoint.disabled) {
       this.props.enableBreakpoint(breakpoint.location);
     } else {
       this.props.disableBreakpoint(breakpoint.location);
     }
   }
 
-  showContextMenu(e, breakpoint) {
-    const {
-      removeBreakpoint,
-      removeBreakpoints,
-      removeAllBreakpoints,
-      toggleBreakpoints,
-      toggleAllBreakpoints,
-      toggleDisabledBreakpoint,
-      setBreakpointCondition,
-      openConditionalPanel,
-      breakpoints
-    } = this.props;
-
-    e.preventDefault();
-
-    const deleteSelfLabel = L10N.getStr("breakpointMenuItem.deleteSelf2.label");
-    const deleteAllLabel = L10N.getStr("breakpointMenuItem.deleteAll2.label");
-    const deleteOthersLabel = L10N.getStr("breakpointMenuItem.deleteOthers2.label");
-    const enableSelfLabel = L10N.getStr("breakpointMenuItem.enableSelf2.label");
-    const enableAllLabel = L10N.getStr("breakpointMenuItem.enableAll2.label");
-    const enableOthersLabel = L10N.getStr("breakpointMenuItem.enableOthers2.label");
-    const disableSelfLabel = L10N.getStr("breakpointMenuItem.disableSelf2.label");
-    const disableAllLabel = L10N.getStr("breakpointMenuItem.disableAll2.label");
-    const disableOthersLabel = L10N.getStr("breakpointMenuItem.disableOthers2.label");
-    const removeConditionLabel = L10N.getStr("breakpointMenuItem.removeCondition2.label");
-    const addConditionLabel = L10N.getStr("breakpointMenuItem.addCondition2.label");
-    const editConditionLabel = L10N.getStr("breakpointMenuItem.editCondition2.label");
-
-    const deleteSelfKey = L10N.getStr("breakpointMenuItem.deleteSelf2.accesskey");
-    const deleteAllKey = L10N.getStr("breakpointMenuItem.deleteAll2.accesskey");
-    const deleteOthersKey = L10N.getStr("breakpointMenuItem.deleteOthers2.accesskey");
-    const enableSelfKey = L10N.getStr("breakpointMenuItem.enableSelf2.accesskey");
-    const enableAllKey = L10N.getStr("breakpointMenuItem.enableAll2.accesskey");
-    const enableOthersKey = L10N.getStr("breakpointMenuItem.enableOthers2.accesskey");
-    const disableSelfKey = L10N.getStr("breakpointMenuItem.disableSelf2.accesskey");
-    const disableAllKey = L10N.getStr("breakpointMenuItem.disableAll2.accesskey");
-    const disableOthersKey = L10N.getStr("breakpointMenuItem.disableOthers2.accesskey");
-    const removeConditionKey = L10N.getStr("breakpointMenuItem.removeCondition2.accesskey");
-    const editConditionKey = L10N.getStr("breakpointMenuItem.editCondition2.accesskey");
-    const addConditionKey = L10N.getStr("breakpointMenuItem.addCondition2.accesskey");
-
-    const otherBreakpoints = breakpoints.filter(b => b !== breakpoint);
-    const enabledBreakpoints = breakpoints.filter(b => !b.disabled);
-    const disabledBreakpoints = breakpoints.filter(b => b.disabled);
-    const otherEnabledBreakpoints = breakpoints.filter(b => !b.disabled && b !== breakpoint);
-    const otherDisabledBreakpoints = breakpoints.filter(b => b.disabled && b !== breakpoint);
-
-    const deleteSelf = {
-      id: "node-menu-delete-self",
-      label: deleteSelfLabel,
-      accesskey: deleteSelfKey,
-      disabled: false,
-      click: () => removeBreakpoint(breakpoint.location)
-    };
-
-    const deleteAll = {
-      id: "node-menu-delete-all",
-      label: deleteAllLabel,
-      accesskey: deleteAllKey,
-      disabled: false,
-      click: () => removeAllBreakpoints()
-    };
-
-    const deleteOthers = {
-      id: "node-menu-delete-other",
-      label: deleteOthersLabel,
-      accesskey: deleteOthersKey,
-      disabled: false,
-      click: () => removeBreakpoints(otherBreakpoints)
-    };
-
-    const enableSelf = {
-      id: "node-menu-enable-self",
-      label: enableSelfLabel,
-      accesskey: enableSelfKey,
-      disabled: false,
-      click: () => toggleDisabledBreakpoint(breakpoint.location.line)
-    };
-
-    const enableAll = {
-      id: "node-menu-enable-all",
-      label: enableAllLabel,
-      accesskey: enableAllKey,
-      disabled: false,
-      click: () => toggleAllBreakpoints(false)
-    };
-
-    const enableOthers = {
-      id: "node-menu-enable-others",
-      label: enableOthersLabel,
-      accesskey: enableOthersKey,
-      disabled: false,
-      click: () => toggleBreakpoints(false, otherDisabledBreakpoints)
-    };
-
-    const disableSelf = {
-      id: "node-menu-disable-self",
-      label: disableSelfLabel,
-      accesskey: disableSelfKey,
-      disabled: false,
-      click: () => toggleDisabledBreakpoint(breakpoint.location.line)
-    };
-
-    const disableAll = {
-      id: "node-menu-disable-all",
-      label: disableAllLabel,
-      accesskey: disableAllKey,
-      disabled: false,
-      click: () => toggleAllBreakpoints(true)
-    };
-
-    const disableOthers = {
-      id: "node-menu-disable-others",
-      label: disableOthersLabel,
-      accesskey: disableOthersKey,
-      click: () => toggleBreakpoints(true, otherEnabledBreakpoints)
-    };
-
-    const removeCondition = {
-      id: "node-menu-remove-condition",
-      label: removeConditionLabel,
-      accesskey: removeConditionKey,
-      disabled: false,
-      click: () => setBreakpointCondition(breakpoint.location)
-    };
-
-    const addCondition = {
-      id: "node-menu-add-condition",
-      label: addConditionLabel,
-      accesskey: addConditionKey,
-      click: () => {
-        this.selectBreakpoint(breakpoint);
-        openConditionalPanel(breakpoint.location.line);
-      }
-    };
-
-    const editCondition = {
-      id: "node-menu-edit-condition",
-      label: editConditionLabel,
-      accesskey: editConditionKey,
-      click: () => {
-        this.selectBreakpoint(breakpoint);
-        openConditionalPanel(breakpoint.location.line);
-      }
-    };
-
-    const hideEnableSelf = !breakpoint.disabled;
-    const hideEnableAll = disabledBreakpoints.size === 0;
-    const hideEnableOthers = otherDisabledBreakpoints.size === 0;
-    const hideDisableAll = enabledBreakpoints.size === 0;
-    const hideDisableOthers = otherEnabledBreakpoints.size === 0;
-    const hideDisableSelf = breakpoint.disabled;
-
-    const items = [{ item: enableSelf, hidden: () => hideEnableSelf }, { item: enableAll, hidden: () => hideEnableAll }, { item: enableOthers, hidden: () => hideEnableOthers }, {
-      item: { type: "separator" },
-      hidden: () => hideEnableSelf && hideEnableAll && hideEnableOthers
-    }, { item: deleteSelf }, { item: deleteAll }, { item: deleteOthers, hidden: () => breakpoints.size === 1 }, {
-      item: { type: "separator" },
-      hidden: () => hideDisableSelf && hideDisableAll && hideDisableOthers
-    }, { item: disableSelf, hidden: () => hideDisableSelf }, { item: disableAll, hidden: () => hideDisableAll }, { item: disableOthers, hidden: () => hideDisableOthers }, {
-      item: { type: "separator" }
-    }, {
-      item: addCondition,
-      hidden: () => breakpoint.condition
-    }, {
-      item: editCondition,
-      hidden: () => !breakpoint.condition
-    }, {
-      item: removeCondition,
-      hidden: () => !breakpoint.condition
-    }];
-
-    (0, _devtoolsContextmenu.showMenu)(e, (0, _devtoolsContextmenu.buildMenu)(items));
-  }
-
   selectBreakpoint(breakpoint) {
     this.props.selectLocation(breakpoint.location);
   }
 
   removeBreakpoint(event, breakpoint) {
     event.stopPropagation();
     this.props.removeBreakpoint(breakpoint.location);
   }
@@ -40995,17 +40822,17 @@ class Breakpoints extends _react.PureCom
         className: (0, _classnames2.default)({
           breakpoint,
           paused: isCurrentlyPaused,
           disabled: isDisabled,
           "is-conditional": isConditional
         }),
         key: locationId,
         onClick: () => this.selectBreakpoint(breakpoint),
-        onContextMenu: e => this.showContextMenu(e, breakpoint)
+        onContextMenu: e => (0, _BreakpointsContextMenu2.default)(_extends({}, this.props, { breakpoint, contextMenuEvent: e }))
       },
       _react2.default.createElement("input", {
         type: "checkbox",
         className: "breakpoint-checkbox",
         checked: !isDisabled,
         onChange: () => this.handleCheckbox(breakpoint),
         onClick: ev => ev.stopPropagation()
       }),
@@ -44167,18 +43994,16 @@ var _extends = Object.assign || function
                                                                                                                                                                                                                                                                    * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 var _react = __webpack_require__(0);
 
 var _react2 = _interopRequireDefault(_react);
 
 var _reactRedux = __webpack_require__(1189);
 
-var _redux = __webpack_require__(3);
-
 var _fuzzaldrinPlus = __webpack_require__(161);
 
 var _actions = __webpack_require__(1354);
 
 var _actions2 = _interopRequireDefault(_actions);
 
 var _selectors = __webpack_require__(1352);
 
@@ -44206,18 +44031,17 @@ class QuickOpenModal extends _react.Comp
 
     this.closeModal = () => {
       this.props.closeQuickOpen();
     };
 
     this.searchSources = query => {
       if (query == "") {
         const results = this.props.sources;
-        this.setState({ results });
-        return;
+        return this.setState({ results });
       }
 
       if (this.isGotoSourceQuery()) {
         const [baseQuery] = query.split(":");
         const results = (0, _fuzzaldrinPlus.filter)(this.props.sources, baseQuery, { key: "value" });
         this.setState({ results });
       } else {
         const results = (0, _fuzzaldrinPlus.filter)(this.props.sources, query, { key: "value" });
@@ -44228,18 +44052,17 @@ class QuickOpenModal extends _react.Comp
     this.searchSymbols = query => {
       const { symbols: { functions, variables } } = this.props;
 
       let results = functions;
       if (this.isVariableQuery()) {
         results = variables;
       }
       if (query === "@" || query === "#") {
-        this.setState({ results });
-        return;
+        return this.setState({ results });
       }
 
       results = (0, _fuzzaldrinPlus.filter)(results, query.slice(1), {
         key: "value"
       });
 
       this.setState({ results });
     };
@@ -44263,120 +44086,128 @@ class QuickOpenModal extends _react.Comp
         this.props.setQuickOpenQuery(item.id);
       }
     };
 
     this.selectResultItem = (e, item) => {
       if (item == null) {
         return;
       }
-      const { selectLocation, selectedSource, query } = this.props;
+
       if (this.isShortcutQuery()) {
-        this.setModifier(item);
-        return;
-      } else if (this.isGotoSourceQuery()) {
-        const location = (0, _quickOpen.parseLineColumn)(query);
-        if (location != null) {
-          selectLocation(_extends({}, location, { sourceId: item.id }));
-        }
-      } else if (this.isSymbolSearch()) {
-        if (selectedSource == null) {
-          return;
-        }
-        const line = item.location && item.location.start ? item.location.start.line : 0;
-        selectLocation({ sourceId: selectedSource.get("id"), line });
-      } else {
-        selectLocation({ sourceId: item.id, line: 0 });
-      }
-
-      this.closeModal();
+        return this.setModifier(item);
+      }
+
+      if (this.isGotoSourceQuery()) {
+        const location = (0, _quickOpen.parseLineColumn)(this.props.query);
+        return this.gotoLocation(_extends({}, location, { sourceId: item.id }));
+      }
+
+      if (this.isSymbolSearch()) {
+        return this.gotoLocation({
+          line: item.location && item.location.start ? item.location.start.line : 0
+        });
+      }
+
+      this.gotoLocation({ sourceId: item.id, line: 0 });
     };
 
     this.onSelectResultItem = item => {
       const { selectLocation, selectedSource, highlightLineRange } = this.props;
       if (!this.isSymbolSearch() || selectedSource == null) {
         return;
       }
 
       if (this.isVariableQuery()) {
         const line = item.location && item.location.start ? item.location.start.line : 0;
-        selectLocation({ sourceId: selectedSource.get("id"), line });
+        return selectLocation({
+          sourceId: selectedSource.get("id"),
+          line,
+          column: null
+        });
       }
 
       if (this.isFunctionQuery()) {
-        highlightLineRange(_extends({}, item.location != null ? { start: item.location.start.line, end: item.location.end.line } : {}, {
+        return highlightLineRange(_extends({}, item.location != null ? { start: item.location.start.line, end: item.location.end.line } : {}, {
           sourceId: selectedSource.get("id")
         }));
       }
     };
 
-    this.traverseResults = direction => {
+    this.traverseResults = e => {
+      const direction = e.key === "ArrowUp" ? -1 : 1;
       const { selectedIndex, results } = this.state;
-      const resultCount = this.resultCount();
+      const resultCount = this.getResultCount();
       const index = selectedIndex + direction;
       const nextIndex = (index + resultCount) % resultCount;
 
       this.setState({ selectedIndex: nextIndex });
 
       if (results != null) {
         this.onSelectResultItem(results[nextIndex]);
       }
     };
 
+    this.gotoLocation = location => {
+      const { selectLocation, selectedSource } = this.props;
+      const selectedSourceId = selectedSource ? selectedSource.get("id") : "";
+      if (location != null) {
+        const sourceId = location.sourceId ? location.sourceId : selectedSourceId;
+        selectLocation({
+          sourceId,
+          line: location.line,
+          column: location.column || null
+        });
+        this.closeModal();
+      }
+    };
+
     this.onChange = e => {
       const { selectedSource, setQuickOpenQuery } = this.props;
       setQuickOpenQuery(e.target.value);
       const noSource = !selectedSource || !selectedSource.get("text");
       if (this.isSymbolSearch() && noSource) {
         return;
       }
       this.updateResults(e.target.value);
     };
 
     this.onKeyDown = e => {
-      const { selectLocation, selectedSource, enabled, query } = this.props;
+      const { enabled, query } = this.props;
       const { results, selectedIndex } = this.state;
 
       if (!enabled || !results) {
         return;
       }
 
-      const canTraverse = !this.isGotoQuery();
-      if (e.key === "ArrowUp" && canTraverse) {
-        return this.traverseResults(-1);
-      } else if (e.key === "ArrowDown" && canTraverse) {
-        return this.traverseResults(1);
-      } else if (e.key === "Enter") {
+      if (e.key === "Enter") {
         if (this.isGotoQuery()) {
-          if (!selectedSource) {
-            return;
-          }
           const location = (0, _quickOpen.parseLineColumn)(query);
-          if (location != null) {
-            selectLocation(_extends({}, location, { sourceId: selectedSource.get("id") }));
-          }
-        } else if (this.isShortcutQuery()) {
-          this.setModifier(results[selectedIndex]);
-          return;
-        } else {
-          this.selectResultItem(e, results[selectedIndex]);
-        }
+          return this.gotoLocation(location);
+        }
+
+        if (this.isShortcutQuery()) {
+          return this.setModifier(results[selectedIndex]);
+        }
+
+        return this.selectResultItem(e, results[selectedIndex]);
+      }
+
+      if (e.key === "Tab") {
         return this.closeModal();
-      } else if (e.key === "Tab") {
-        return this.closeModal();
-      }
-    };
-
-    this.resultCount = () => {
+      }
+
+      if (["ArrowUp", "ArrowDown"].includes(e.key)) {
+        return this.traverseResults(e);
+      }
+    };
+
+    this.getResultCount = () => {
       const results = this.state.results;
-
-      if (results && results.length) {
-        return results.length;
-      }
-      return 0;
+      return results && results.length ? results.length : 0;
     };
 
     this.isFunctionQuery = () => this.props.searchType === "functions";
 
     this.isVariableQuery = () => this.props.searchType === "variables";
 
     this.isSymbolSearch = () => this.isFunctionQuery() || this.isVariableQuery();
 
@@ -44403,86 +44234,74 @@ class QuickOpenModal extends _react.Comp
 
     const nowEnabled = !prevProps.enabled && this.props.enabled;
     const queryChanged = prevProps.query !== this.props.query;
     if (nowEnabled || queryChanged) {
       this.updateResults(this.props.query);
     }
   }
 
-  renderResults() {
-    const { enabled, searchType } = this.props;
+  // Query helpers
+
+
+  render() {
+    const { enabled, query, searchType } = this.props;
     const { selectedIndex, results } = this.state;
-    if (!enabled || !results) {
+
+    if (!enabled) {
       return null;
     }
 
-    return _react2.default.createElement(_ResultList2.default, _extends({
-      key: "results",
-      items: results,
-      selected: selectedIndex,
-      selectItem: this.selectResultItem,
-      ref: "resultList"
-    }, searchType === "sources" || searchType === "gotoSource" ? { size: "big" } : {}));
-  }
-
-  renderInput() {
-    const { query, searchType } = this.props;
-    const summaryMsg = L10N.getFormatStr("sourceSearch.resultsSummary1", this.resultCount());
+    const summaryMsg = L10N.getFormatStr("sourceSearch.resultsSummary1", this.getResultCount());
 
     const showSummary = searchType === "sources" || searchType === "functions" || searchType === "variables" || searchType === "shortcuts";
 
     return _react2.default.createElement(
-      "div",
-      { key: "input", className: "input-wrapper" },
+      _Modal2.default,
+      { "in": enabled, handleClose: this.closeModal },
       _react2.default.createElement(_SearchInput2.default, _extends({
         query: query,
-        count: this.resultCount(),
+        count: this.getResultCount(),
         placeholder: L10N.getStr("sourceSearch.search")
       }, showSummary === true ? { summaryMsg } : {}, {
         onChange: this.onChange,
         onKeyDown: this.onKeyDown,
         handleClose: this.closeModal
-      }))
-    );
-  }
-  render() {
-    const { enabled } = this.props;
-
-    if (!enabled) {
-      return null;
-    }
-
-    return _react2.default.createElement(
-      _Modal2.default,
-      { "in": enabled, handleClose: this.closeModal },
-      this.renderInput(),
-      this.renderResults()
-    );
-  }
-}
-
-exports.QuickOpenModal = QuickOpenModal;
+      })),
+      results && _react2.default.createElement(_ResultList2.default, _extends({
+        key: "results",
+        items: results,
+        selected: selectedIndex,
+        selectItem: this.selectResultItem,
+        ref: "resultList"
+      }, searchType === "sources" || searchType === "gotoSource" ? { size: "big" } : {}))
+    );
+  }
+}
+
+exports.QuickOpenModal = QuickOpenModal; /* istanbul ignore next: ignoring testing of redux connection stuff */
+
 function mapStateToProps(state) {
   const selectedSource = (0, _selectors.getSelectedSource)(state);
   let symbols = null;
   if (selectedSource != null) {
     symbols = (0, _selectors.getSymbols)(state, selectedSource.toJS());
   }
   return {
     enabled: (0, _selectors.getQuickOpenEnabled)(state),
     sources: (0, _quickOpen.formatSources)((0, _selectors.getSources)(state)),
     selectedSource,
     symbols: (0, _quickOpen.formatSymbols)(symbols),
     query: (0, _selectors.getQuickOpenQuery)(state),
     searchType: (0, _selectors.getQuickOpenType)(state)
   };
 }
 
-exports.default = (0, _reactRedux.connect)(mapStateToProps, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(QuickOpenModal);
+/* istanbul ignore next: ignoring testing of redux connection stuff */
+exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(QuickOpenModal);
 
 /***/ }),
 /* 1653 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
@@ -49654,11 +49473,203 @@ function mapFrames() {
 
     dispatch({
       type: "MAP_FRAMES",
       frames: mappedFrames
     });
   };
 }
 
+/***/ }),
+/* 1805 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = showContextMenu;
+
+var _devtoolsContextmenu = __webpack_require__(1413);
+
+function showContextMenu(props) {
+  const {
+    removeBreakpoint,
+    removeBreakpoints,
+    removeAllBreakpoints,
+    toggleBreakpoints,
+    toggleAllBreakpoints,
+    toggleDisabledBreakpoint,
+    selectLocation,
+    setBreakpointCondition,
+    openConditionalPanel,
+    breakpoints,
+    breakpoint,
+    contextMenuEvent
+  } = props;
+
+  contextMenuEvent.preventDefault();
+
+  const deleteSelfLabel = L10N.getStr("breakpointMenuItem.deleteSelf2.label");
+  const deleteAllLabel = L10N.getStr("breakpointMenuItem.deleteAll2.label");
+  const deleteOthersLabel = L10N.getStr("breakpointMenuItem.deleteOthers2.label");
+  const enableSelfLabel = L10N.getStr("breakpointMenuItem.enableSelf2.label");
+  const enableAllLabel = L10N.getStr("breakpointMenuItem.enableAll2.label");
+  const enableOthersLabel = L10N.getStr("breakpointMenuItem.enableOthers2.label");
+  const disableSelfLabel = L10N.getStr("breakpointMenuItem.disableSelf2.label");
+  const disableAllLabel = L10N.getStr("breakpointMenuItem.disableAll2.label");
+  const disableOthersLabel = L10N.getStr("breakpointMenuItem.disableOthers2.label");
+  const removeConditionLabel = L10N.getStr("breakpointMenuItem.removeCondition2.label");
+  const addConditionLabel = L10N.getStr("breakpointMenuItem.addCondition2.label");
+  const editConditionLabel = L10N.getStr("breakpointMenuItem.editCondition2.label");
+
+  const deleteSelfKey = L10N.getStr("breakpointMenuItem.deleteSelf2.accesskey");
+  const deleteAllKey = L10N.getStr("breakpointMenuItem.deleteAll2.accesskey");
+  const deleteOthersKey = L10N.getStr("breakpointMenuItem.deleteOthers2.accesskey");
+  const enableSelfKey = L10N.getStr("breakpointMenuItem.enableSelf2.accesskey");
+  const enableAllKey = L10N.getStr("breakpointMenuItem.enableAll2.accesskey");
+  const enableOthersKey = L10N.getStr("breakpointMenuItem.enableOthers2.accesskey");
+  const disableSelfKey = L10N.getStr("breakpointMenuItem.disableSelf2.accesskey");
+  const disableAllKey = L10N.getStr("breakpointMenuItem.disableAll2.accesskey");
+  const disableOthersKey = L10N.getStr("breakpointMenuItem.disableOthers2.accesskey");
+  const removeConditionKey = L10N.getStr("breakpointMenuItem.removeCondition2.accesskey");
+  const editConditionKey = L10N.getStr("breakpointMenuItem.editCondition2.accesskey");
+  const addConditionKey = L10N.getStr("breakpointMenuItem.addCondition2.accesskey");
+
+  const otherBreakpoints = breakpoints.filter(b => b !== breakpoint);
+  const enabledBreakpoints = breakpoints.filter(b => !b.disabled);
+  const disabledBreakpoints = breakpoints.filter(b => b.disabled);
+  const otherEnabledBreakpoints = breakpoints.filter(b => !b.disabled && b !== breakpoint);
+  const otherDisabledBreakpoints = breakpoints.filter(b => b.disabled && b !== breakpoint);
+
+  const deleteSelf = {
+    id: "node-menu-delete-self",
+    label: deleteSelfLabel,
+    accesskey: deleteSelfKey,
+    disabled: false,
+    click: () => removeBreakpoint(breakpoint.location)
+  };
+
+  const deleteAll = {
+    id: "node-menu-delete-all",
+    label: deleteAllLabel,
+    accesskey: deleteAllKey,
+    disabled: false,
+    click: () => removeAllBreakpoints()
+  };
+
+  const deleteOthers = {
+    id: "node-menu-delete-other",
+    label: deleteOthersLabel,
+    accesskey: deleteOthersKey,
+    disabled: false,
+    click: () => removeBreakpoints(otherBreakpoints)
+  };
+
+  const enableSelf = {
+    id: "node-menu-enable-self",
+    label: enableSelfLabel,
+    accesskey: enableSelfKey,
+    disabled: false,
+    click: () => toggleDisabledBreakpoint(breakpoint.location.line)
+  };
+
+  const enableAll = {
+    id: "node-menu-enable-all",
+    label: enableAllLabel,
+    accesskey: enableAllKey,
+    disabled: false,
+    click: () => toggleAllBreakpoints(false)
+  };
+
+  const enableOthers = {
+    id: "node-menu-enable-others",
+    label: enableOthersLabel,
+    accesskey: enableOthersKey,
+    disabled: false,
+    click: () => toggleBreakpoints(false, otherDisabledBreakpoints)
+  };
+
+  const disableSelf = {
+    id: "node-menu-disable-self",
+    label: disableSelfLabel,
+    accesskey: disableSelfKey,
+    disabled: false,
+    click: () => toggleDisabledBreakpoint(breakpoint.location.line)
+  };
+
+  const disableAll = {
+    id: "node-menu-disable-all",
+    label: disableAllLabel,
+    accesskey: disableAllKey,
+    disabled: false,
+    click: () => toggleAllBreakpoints(true)
+  };
+
+  const disableOthers = {
+    id: "node-menu-disable-others",
+    label: disableOthersLabel,
+    accesskey: disableOthersKey,
+    click: () => toggleBreakpoints(true, otherEnabledBreakpoints)
+  };
+
+  const removeCondition = {
+    id: "node-menu-remove-condition",
+    label: removeConditionLabel,
+    accesskey: removeConditionKey,
+    disabled: false,
+    click: () => setBreakpointCondition(breakpoint.location)
+  };
+
+  const addCondition = {
+    id: "node-menu-add-condition",
+    label: addConditionLabel,
+    accesskey: addConditionKey,
+    click: () => {
+      selectLocation(breakpoint.location);
+      openConditionalPanel(breakpoint.location.line);
+    }
+  };
+
+  const editCondition = {
+    id: "node-menu-edit-condition",
+    label: editConditionLabel,
+    accesskey: editConditionKey,
+    click: () => {
+      selectLocation(breakpoint.location);
+      openConditionalPanel(breakpoint.location.line);
+    }
+  };
+
+  const hideEnableSelf = !breakpoint.disabled;
+  const hideEnableAll = disabledBreakpoints.size === 0;
+  const hideEnableOthers = otherDisabledBreakpoints.size === 0;
+  const hideDisableAll = enabledBreakpoints.size === 0;
+  const hideDisableOthers = otherEnabledBreakpoints.size === 0;
+  const hideDisableSelf = breakpoint.disabled;
+
+  const items = [{ item: enableSelf, hidden: () => hideEnableSelf }, { item: enableAll, hidden: () => hideEnableAll }, { item: enableOthers, hidden: () => hideEnableOthers }, {
+    item: { type: "separator" },
+    hidden: () => hideEnableSelf && hideEnableAll && hideEnableOthers
+  }, { item: deleteSelf }, { item: deleteAll }, { item: deleteOthers, hidden: () => breakpoints.size === 1 }, {
+    item: { type: "separator" },
+    hidden: () => hideDisableSelf && hideDisableAll && hideDisableOthers
+  }, { item: disableSelf, hidden: () => hideDisableSelf }, { item: disableAll, hidden: () => hideDisableAll }, { item: disableOthers, hidden: () => hideDisableOthers }, {
+    item: { type: "separator" }
+  }, {
+    item: addCondition,
+    hidden: () => breakpoint.condition
+  }, {
+    item: editCondition,
+    hidden: () => !breakpoint.condition
+  }, {
+    item: removeCondition,
+    hidden: () => !breakpoint.condition
+  }];
+
+  (0, _devtoolsContextmenu.showMenu)(contextMenuEvent, (0, _devtoolsContextmenu.buildMenu)(items));
+}
+
 /***/ })
 /******/ ]);
 });
\ No newline at end of file
--- a/devtools/client/debugger/new/test/mochitest/browser.ini
+++ b/devtools/client/debugger/new/test/mochitest/browser.ini
@@ -99,18 +99,19 @@ skip-if = os == "linux" # bug 1351952
 [browser_dbg-pause-ux.js]
 skip-if = os == "win"
 [browser_dbg-navigation.js]
 [browser_dbg-minified.js]
 [browser_dbg-pretty-print.js]
 [browser_dbg-pretty-print-console.js]
 [browser_dbg-pretty-print-paused.js]
 [browser_dbg-preview.js]
-skip-if = true # regular failures during release in Bug 1415300
+skip-if = os == "win"
 [browser_dbg-preview-source-maps.js]
+skip-if = os == "win"
 [browser_dbg-returnvalues.js]
 [browser_dbg-scopes-mutations.js]
 [browser_dbg-search-file.js]
 skip-if = os == "win" # Bug 1393121
 [browser_dbg-quick-open.js]
 skip-if = true # regular failures during release in Bug 1415300
 [browser_dbg-search-project.js]
 [browser_dbg-sourcemaps.js]
--- a/devtools/client/shared/components/test/mochitest/test_HSplitBox_01.html
+++ b/devtools/client/shared/components/test/mochitest/test_HSplitBox_01.html
@@ -5,17 +5,17 @@
 <html>
 <!--
 Basic tests for the HSplitBox component.
 -->
 <head>
   <meta charset="utf-8">
   <title>Tree component test</title>
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript "src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
   <link rel="stylesheet" href="resource://devtools/client/themes/splitters.css" type="text/css"/>
   <link rel="stylesheet" href="chrome://devtools/skin/components-h-split-box.css" type="text/css"/>
   <style>
     html {
       --theme-splitter-color: black;
     }
   </style>
--- a/devtools/client/storage/test/storage-cookies-samesite.html
+++ b/devtools/client/storage/test/storage-cookies-samesite.html
@@ -1,16 +1,16 @@
 <!DOCTYPE HTML>
 <html>
   <head>
     <meta charset="utf-8">
     <title>Storage inspector cookie samesite test</title>
   </head>
   <body>
-    <script type="application/javascript;version=1.7">
+    <script type="application/javascript">
     "use strict";
     let expiresIn24Hours = new Date(Date.now() + 60 * 60 * 24 * 1000).toUTCString();
 
     document.cookie = "test1=value1;expires=" + expiresIn24Hours + ";";
     document.cookie = "test2=value2;expires=" + expiresIn24Hours + ";SameSite=lax";
     document.cookie = "test3=value3;expires=" + expiresIn24Hours + ";SameSite=strict";
     </script>
   </body>
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -248,17 +248,17 @@ FindExceptionStackForConsoleReport(nsPID
   if (win && win->InnerObjectsFreed()) {
     // Pretend like we have no stack, so we don't end up keeping the global
     // alive via the stack.
     return nullptr;
   }
 
   JS::RootingContext* rcx = RootingCx();
   JS::RootedObject exceptionObject(rcx, &exceptionValue.toObject());
-  JSObject* stackObject = ExceptionStackOrNull(exceptionObject);
+  JSObject* stackObject = JS::ExceptionStackOrNull(exceptionObject);
   if (stackObject) {
     return stackObject;
   }
 
   // It is not a JS Exception, try DOM Exception.
   RefPtr<Exception> exception;
   UNWRAP_OBJECT(DOMException, exceptionObject, exception);
   if (!exception) {
--- a/dom/browser-element/mochitest/test_browserElement_inproc_ExposableURI.html
+++ b/dom/browser-element/mochitest/test_browserElement_inproc_ExposableURI.html
@@ -7,13 +7,13 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 795317</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="browserElementTestHelpers.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795317">Mozilla Bug 795317</a>
 
-<script type="application/javascript;version1.7" src="browserElement_ExposableURI.js"></script>
+<script type="application/javascript" src="browserElement_ExposableURI.js"></script>
 
 </body>
 </html>
 
--- a/dom/browser-element/mochitest/test_browserElement_inproc_LoadEvents.html
+++ b/dom/browser-element/mochitest/test_browserElement_inproc_LoadEvents.html
@@ -7,12 +7,12 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 710231</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="browserElementTestHelpers.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=710231">Mozilla Bug 710231</a>
 
-<script type="application/javascript;version1.7" src="browserElement_LoadEvents.js"></script>
+<script type="application/javascript" src="browserElement_LoadEvents.js"></script>
 
 </body>
 </html>
--- a/dom/browser-element/mochitest/test_browserElement_oop_ExposableURI.html
+++ b/dom/browser-element/mochitest/test_browserElement_oop_ExposableURI.html
@@ -7,13 +7,13 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 795317</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="browserElementTestHelpers.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795317">Mozilla Bug 795317</a>
 
-<script type="application/javascript;version1.7" src="browserElement_ExposableURI.js"></script>
+<script type="application/javascript" src="browserElement_ExposableURI.js"></script>
 
 </body>
 </html>
 
--- a/dom/browser-element/mochitest/test_browserElement_oop_LoadEvents.html
+++ b/dom/browser-element/mochitest/test_browserElement_oop_LoadEvents.html
@@ -7,13 +7,13 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 710231</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="browserElementTestHelpers.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=710231">Mozilla Bug 710231</a>
 
-<script type="application/javascript;version1.7" src="browserElement_LoadEvents.js"></script>
+<script type="application/javascript" src="browserElement_LoadEvents.js"></script>
 
 </body>
 </html>
 
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -507,16 +507,18 @@ WebGLContext::DrawArrays_check(const cha
 void
 WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei vertCount,
                                   GLsizei instanceCount, const char* const funcName)
 {
     AUTO_PROFILER_LABEL("WebGLContext::DrawArraysInstanced", GRAPHICS);
     if (IsContextLost())
         return;
 
+    const gl::GLContext::TlsScope inTls(gl);
+
     Maybe<uint32_t> lastVert;
     if (!DrawArrays_check(funcName, first, vertCount, instanceCount, &lastVert))
         return;
 
     bool error = false;
     const ScopedDrawHelper scopedHelper(this, funcName, mode, lastVert, instanceCount,
                                         &error);
     if (error)
@@ -663,16 +665,18 @@ void
 WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei indexCount, GLenum type,
                                     WebGLintptr byteOffset, GLsizei instanceCount,
                                     const char* const funcName)
 {
     AUTO_PROFILER_LABEL("WebGLContext::DrawElementsInstanced", GRAPHICS);
     if (IsContextLost())
         return;
 
+    const gl::GLContext::TlsScope inTls(gl);
+
     Maybe<uint32_t> lastVert;
     if (!DrawElements_check(funcName, indexCount, type, byteOffset, instanceCount,
                             &lastVert))
     {
         return;
     }
 
     bool error = false;
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -574,16 +574,17 @@ HTMLFormElement::DoSubmitOrReset(WidgetE
 
   MOZ_ASSERT(false);
   return NS_OK;
 }
 
 nsresult
 HTMLFormElement::DoReset()
 {
+  mEverTriedInvalidSubmit = false;
   // JBK walk the elements[] array instead of form frame controls - bug 34297
   uint32_t numElements = GetElementCount();
   for (uint32_t elementX = 0; elementX < numElements; ++elementX) {
     // Hold strong ref in case the reset does something weird
     nsCOMPtr<nsIFormControl> controlNode = GetElementAt(elementX);
     if (controlNode) {
       controlNode->Reset();
     }
--- a/dom/html/HTMLScriptElement.cpp
+++ b/dom/html/HTMLScriptElement.cpp
@@ -166,19 +166,30 @@ HTMLScriptElement::SetText(const nsAStri
 {
   aRv = nsContentUtils::SetNodeTextContent(this, aValue, true);
 }
 
 // variation of this code in nsSVGScriptElement - check if changes
 // need to be transfered when modifying
 
 bool
-HTMLScriptElement::GetScriptType(nsAString& type)
+HTMLScriptElement::GetScriptType(nsAString& aType)
 {
-  return GetAttr(kNameSpaceID_None, nsGkAtoms::type, type);
+  nsAutoString type;
+  if (!GetAttr(kNameSpaceID_None, nsGkAtoms::type, type)) {
+    return false;
+  }
+
+  // ASCII whitespace https://infra.spec.whatwg.org/#ascii-whitespace:
+  // U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or U+0020 SPACE.
+  static const char kASCIIWhitespace[] = "\t\n\f\r ";
+  type.Trim(kASCIIWhitespace);
+
+  aType.Assign(type);
+  return true;
 }
 
 void
 HTMLScriptElement::GetScriptText(nsAString& text)
 {
   IgnoredErrorResult rv;
   GetText(text, rv);
 }
--- a/dom/html/test/forms/test_required_attribute.html
+++ b/dom/html/test/forms/test_required_attribute.html
@@ -114,16 +114,23 @@ function checkTextareaRequiredValidity()
 
   element.focus();
   element.required = true;
   SpecialPowers.wrap(element).value = 'foobar';
   element.blur();
   element.form.reset();
   checkSufferingFromBeingMissing(element, false);
 
+  SpecialPowers.wrap(element).value = '';
+  element.form.reportValidity();
+  checkSufferingFromBeingMissing(element, true);
+
+  element.form.reset();
+  checkSufferingFromBeingMissing(element, false);
+
   // TODO: for the moment, a textarea outside of a document is mutable.
   SpecialPowers.wrap(element).value = ''; // To make -moz-ui-valid apply.
   element.required = false;
   document.forms[0].removeChild(element);
   checkNotSufferingFromBeingMissing(element);
 }
 
 function checkInputRequiredNotApply(type, isBarred)
@@ -186,16 +193,23 @@ function checkInputRequiredValidity(type
 
   element.focus();
   element.required = true;
   SpecialPowers.wrap(element).value = 'foobar';
   element.blur();
   element.form.reset();
   checkSufferingFromBeingMissing(element, false);
 
+  SpecialPowers.wrap(element).value = '';
+  element.form.reportValidity();
+  checkSufferingFromBeingMissing(element, true);
+
+  element.form.reset();
+  checkSufferingFromBeingMissing(element, false);
+
   element.required = true;
   SpecialPowers.wrap(element).value = ''; // To make :-moz-ui-valid apply.
   checkSufferingFromBeingMissing(element, true);
   document.forms[0].removeChild(element);
   // Removing the child changes nothing about whether it's valid
   checkSufferingFromBeingMissing(element, true);
 }
 
@@ -225,16 +239,24 @@ function checkInputRequiredValidityForCh
   element.required = true;
   element.checked = true;
   element.blur();
   element.form.reset();
   checkSufferingFromBeingMissing(element, false);
 
   element.required = true;
   element.checked = false;
+  element.form.reportValidity();
+  checkSufferingFromBeingMissing(element, true);
+
+  element.form.reset();
+  checkSufferingFromBeingMissing(element, false);
+
+  element.required = true;
+  element.checked = false;
   document.forms[0].removeChild(element);
   checkSufferingFromBeingMissing(element, true);
 }
 
 function checkInputRequiredValidityForRadio()
 {
   var element = document.createElement('input');
   element.type = 'radio';
@@ -301,16 +323,24 @@ function checkInputRequiredValidityForRa
   element2.required = true;
   element2.checked = true;
   element2.blur();
   element2.form.reset();
   checkSufferingFromBeingMissing(element2, false);
 
   element2.required = true;
   element2.checked = false;
+  element2.form.reportValidity();
+  checkSufferingFromBeingMissing(element2, true);
+
+  element2.form.reset();
+  checkSufferingFromBeingMissing(element2, false);
+
+  element2.required = true;
+  element2.checked = false;
   document.forms[0].removeChild(element2);
   checkSufferingFromBeingMissing(element2, true);
 }
 
 function checkInputRequiredValidityForFile()
 {
   var element = document.createElement('input');
   element.type = 'file'
@@ -338,16 +368,24 @@ function checkInputRequiredValidityForFi
   SpecialPowers.wrap(element).mozSetFileArray([file]);
   element.required = true;
   element.blur();
   element.form.reset();
   checkSufferingFromBeingMissing(element, false);
 
   element.required = true;
   SpecialPowers.wrap(element).value = '';
+  element.form.reportValidity();
+  checkSufferingFromBeingMissing(element, true);
+
+  element.form.reset();
+  checkSufferingFromBeingMissing(element, false);
+
+  element.required = true;
+  SpecialPowers.wrap(element).value = '';
   document.forms[0].removeChild(element);
   checkSufferingFromBeingMissing(element, true);
 }
 
 checkTextareaRequiredValidity();
 
 // The require attribute behavior depend of the input type.
 // First of all, checks for types that make the element barred from
--- a/dom/html/test/test_checked.html
+++ b/dom/html/test/test_checked.html
@@ -21,17 +21,17 @@ and
   <form id="f2">
   </form>
   <menu id="m1">
   </menu>
   <menu id="m2">
   </menu>
 </div>
 <pre id="test">
-<script class="testbody" type="text/javascript; version=1.7">
+<script class="testbody" type="text/javascript">
 
 /** Test for Bug 418756 and 617528 **/
 var group1;
 var group2;
 var group3;
 
 var tags = ["input", "menuitem"];
 for (let tag of tags) {
--- a/dom/script/ModuleLoadRequest.cpp
+++ b/dom/script/ModuleLoadRequest.cpp
@@ -24,43 +24,40 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(Modul
                                    mModuleScript,
                                    mImports)
 
 NS_IMPL_ADDREF_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
 NS_IMPL_RELEASE_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
 
 ModuleLoadRequest::ModuleLoadRequest(nsIURI* aURI,
                                      nsIScriptElement* aElement,
-                                     ValidJSVersion aValidJSVersion,
                                      CORSMode aCORSMode,
                                      const SRIMetadata& aIntegrity,
                                      nsIURI* aReferrer,
                                      mozilla::net::ReferrerPolicy aReferrerPolicy,
                                      ScriptLoader* aLoader)
   : ScriptLoadRequest(ScriptKind::eModule,
                       aURI,
                       aElement,
-                      aValidJSVersion,
                       aCORSMode,
                       aIntegrity,
                       aReferrer,
                       aReferrerPolicy),
     mIsTopLevel(true),
     mLoader(aLoader),
     mVisitedSet(new VisitedURLSet())
 {
   mVisitedSet->PutEntry(aURI);
 }
 
 ModuleLoadRequest::ModuleLoadRequest(nsIURI* aURI,
                                      ModuleLoadRequest* aParent)
   : ScriptLoadRequest(ScriptKind::eModule,
                       aURI,
                       aParent->mElement,
-                      aParent->mValidJSVersion,
                       aParent->mCORSMode,
                       SRIMetadata(),
                       aParent->mURI,
                       aParent->mReferrerPolicy),
     mIsTopLevel(false),
     mLoader(aParent->mLoader),
     mVisitedSet(aParent->mVisitedSet)
 {
--- a/dom/script/ModuleLoadRequest.h
+++ b/dom/script/ModuleLoadRequest.h
@@ -40,17 +40,16 @@ class ModuleLoadRequest final : public S
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
 
   // Create a top-level module load request.
   ModuleLoadRequest(nsIURI* aURI,
                     nsIScriptElement* aElement,
-                    ValidJSVersion aValidJSVersion,
                     CORSMode aCORSMode,
                     const SRIMetadata& aIntegrity,
                     nsIURI* aReferrer,
                     mozilla::net::ReferrerPolicy,
                     ScriptLoader* aLoader);
 
   // Create a module load request for an imported module.
   ModuleLoadRequest(nsIURI* aURI,
--- a/dom/script/ScriptLoadRequest.cpp
+++ b/dom/script/ScriptLoadRequest.cpp
@@ -36,17 +36,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ScriptLoadRequest)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScript)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 ScriptLoadRequest::ScriptLoadRequest(ScriptKind aKind,
                                      nsIURI* aURI,
                                      nsIScriptElement* aElement,
-                                     ValidJSVersion aValidJSVersion,
                                      mozilla::CORSMode aCORSMode,
                                      const SRIMetadata& aIntegrity,
                                      nsIURI* aReferrer,
                                      mozilla::net::ReferrerPolicy aReferrerPolicy)
   : mKind(aKind)
   , mElement(aElement)
   , mScriptFromHead(false)
   , mProgress(Progress::eLoading)
@@ -60,17 +59,16 @@ ScriptLoadRequest::ScriptLoadRequest(Scr
   , mIsXSLT(false)
   , mIsCanceled(false)
   , mWasCompiledOMT(false)
   , mIsTracking(false)
   , mOffThreadToken(nullptr)
   , mScriptText()
   , mScriptBytecode()
   , mBytecodeOffset(0)
-  , mValidJSVersion(aValidJSVersion)
   , mURI(aURI)
   , mLineNo(1)
   , mCORSMode(aCORSMode)
   , mIntegrity(aIntegrity)
   , mReferrer(aReferrer)
   , mReferrerPolicy(aReferrerPolicy)
 {
 }
--- a/dom/script/ScriptLoadRequest.h
+++ b/dom/script/ScriptLoadRequest.h
@@ -24,21 +24,16 @@ namespace dom {
 class ModuleLoadRequest;
 class ScriptLoadRequestList;
 
 enum class ScriptKind {
   eClassic,
   eModule
 };
 
-enum class ValidJSVersion : bool {
-  eInvalid,
-  eValid
-};
-
 /*
  * A class that handles loading and evaluation of <script> elements.
  */
 
 class ScriptLoadRequest : public nsISupports,
                           private mozilla::LinkedListElement<ScriptLoadRequest>
 {
   typedef LinkedListElement<ScriptLoadRequest> super;
@@ -49,17 +44,16 @@ class ScriptLoadRequest : public nsISupp
 
 protected:
   virtual ~ScriptLoadRequest();
 
 public:
   ScriptLoadRequest(ScriptKind aKind,
                     nsIURI* aURI,
                     nsIScriptElement* aElement,
-                    ValidJSVersion aValidJSVersion,
                     mozilla::CORSMode aCORSMode,
                     const SRIMetadata &aIntegrity,
                     nsIURI* aReferrer,
                     mozilla::net::ReferrerPolicy aReferrerPolicy);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ScriptLoadRequest)
 
@@ -212,17 +206,16 @@ public:
   // ownership to jsapi.
   mozilla::Vector<char16_t> mScriptText;
 
   // Holds the SRI serialized hash and the script bytecode for non-inline
   // scripts.
   mozilla::Vector<uint8_t> mScriptBytecode;
   uint32_t mBytecodeOffset; // Offset of the bytecode in mScriptBytecode
 
-  ValidJSVersion mValidJSVersion;
   const nsCOMPtr<nsIURI> mURI;
   nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
   nsCOMPtr<nsIPrincipal> mOriginPrincipal;
   nsAutoCString mURL;     // Keep the URI's filename alive during off thread parsing.
   int32_t mLineNo;
   const mozilla::CORSMode mCORSMode;
   const SRIMetadata mIntegrity;
   const nsCOMPtr<nsIURI> mReferrer;
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -1054,22 +1054,21 @@ ScriptLoader::StartLoad(ScriptLoadReques
       contentPolicyType,
       loadGroup,
       prompter,
       nsIRequest::LOAD_NORMAL |
       nsIChannel::LOAD_CLASSIFY_URI);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // To avoid decoding issues, the JSVersion is explicitly guarded here, and the
-  // build-id is part of the JSBytecodeMimeType constant.
+  // To avoid decoding issues, the build-id is part of the JSBytecodeMimeType
+  // constant.
   aRequest->mCacheInfo = nullptr;
   nsCOMPtr<nsICacheInfoChannel> cic(do_QueryInterface(channel));
-  if (cic && nsContentUtils::IsBytecodeCacheEnabled() &&
-      aRequest->mValidJSVersion == ValidJSVersion::eValid) {
+  if (cic && nsContentUtils::IsBytecodeCacheEnabled()) {
     if (!aRequest->IsLoadingSource()) {
       // Inform the HTTP cache that we prefer to have information coming from the
       // bytecode cache instead of the sources, if such entry is already registered.
       LOG(("ScriptLoadRequest (%p): Maybe request bytecode", aRequest));
       cic->PreferAlternativeDataType(nsContentUtils::JSBytecodeMimeType());
     } else {
       // If we are explicitly loading from the sources, such as after a
       // restarted request, we might still want to save the bytecode after.
@@ -1169,73 +1168,16 @@ bool
 ScriptLoader::PreloadURIComparator::Equals(const PreloadInfo& aPi,
                                            nsIURI* const& aURI) const
 {
   bool same;
   return NS_SUCCEEDED(aPi.mRequest->mURI->Equals(aURI, &same)) &&
          same;
 }
 
-/**
- * Returns ValidJSVersion::eValid if aVersionStr is a string of the form '1.n',
- * n = 0, ..., 8, and ValidJSVersion::eInvalid for other strings.
- */
-static ValidJSVersion
-ParseJavascriptVersion(const nsAString& aVersionStr)
-{
-  if (aVersionStr.Length() != 3 || aVersionStr[0] != '1' ||
-      aVersionStr[1] != '.') {
-    return ValidJSVersion::eInvalid;
-  }
-  if ('0' <= aVersionStr[2] && aVersionStr[2] <= '8') {
-    return ValidJSVersion::eValid;
-  }
-  return ValidJSVersion::eInvalid;
-}
-
-static inline bool
-ParseTypeAttribute(const nsAString& aType, ValidJSVersion* aVersion)
-{
-  MOZ_ASSERT(!aType.IsEmpty());
-  MOZ_ASSERT(aVersion);
-  MOZ_ASSERT(*aVersion == ValidJSVersion::eValid);
-
-  nsContentTypeParser parser(aType);
-
-  nsAutoString mimeType;
-  nsresult rv = parser.GetType(mimeType);
-  NS_ENSURE_SUCCESS(rv, false);
-
-  if (!nsContentUtils::IsJavascriptMIMEType(mimeType)) {
-    return false;
-  }
-
-  // Get the version string, and ensure the language supports it.
-  nsAutoString versionName;
-  rv = parser.GetParameter("version", versionName);
-
-  if (rv == NS_ERROR_INVALID_ARG) {
-    Telemetry::Accumulate(Telemetry::SCRIPT_LOADED_WITH_VERSION, false);
-    // Argument not set.
-    return true;
-  }
-
-  if (NS_FAILED(rv)) {
-    return false;
-  }
-
-  *aVersion = ParseJavascriptVersion(versionName);
-  if (*aVersion == ValidJSVersion::eValid) {
-    Telemetry::Accumulate(Telemetry::SCRIPT_LOADED_WITH_VERSION, true);
-    return true;
-  }
-
-  return true;
-}
-
 static bool
 CSPAllowsInlineScript(nsIScriptElement* aElement, nsIDocument* aDocument)
 {
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   // Note: For imports NodePrincipal and the principal of the master are
   // the same.
   nsresult rv = aDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp));
   NS_ENSURE_SUCCESS(rv, false);
@@ -1258,35 +1200,34 @@ CSPAllowsInlineScript(nsIScriptElement* 
                             &allowInlineScript);
   return allowInlineScript;
 }
 
 ScriptLoadRequest*
 ScriptLoader::CreateLoadRequest(ScriptKind aKind,
                                 nsIURI* aURI,
                                 nsIScriptElement* aElement,
-                                ValidJSVersion aValidJSVersion,
                                 CORSMode aCORSMode,
                                 const SRIMetadata& aIntegrity,
                                 mozilla::net::ReferrerPolicy aReferrerPolicy)
 {
   nsIURI* referrer = mDocument->GetDocumentURI();
 
   if (aKind == ScriptKind::eClassic) {
     ScriptLoadRequest* slr = new ScriptLoadRequest(aKind, aURI, aElement,
-                                                   aValidJSVersion, aCORSMode, aIntegrity,
+                                                   aCORSMode, aIntegrity,
                                                    referrer, aReferrerPolicy);
 
     LOG(("ScriptLoader %p creates ScriptLoadRequest %p", this, slr));
     return slr;
   }
 
   MOZ_ASSERT(aKind == ScriptKind::eModule);
-  return new ModuleLoadRequest(aURI, aElement, aValidJSVersion, aCORSMode,
-                               aIntegrity, referrer, aReferrerPolicy, this);
+  return new ModuleLoadRequest(aURI, aElement, aCORSMode, aIntegrity, referrer,
+                               aReferrerPolicy, this);
 }
 
 bool
 ScriptLoader::ProcessScriptElement(nsIScriptElement* aElement)
 {
   // We need a document to evaluate scripts.
   NS_ENSURE_TRUE(mDocument, false);
 
@@ -1305,23 +1246,21 @@ ScriptLoader::ProcessScriptElement(nsISc
   ScriptKind scriptKind =
     aElement->GetScriptIsModule() ? ScriptKind::eModule : ScriptKind::eClassic;
 
   // Step 13. Check that the script is not an eventhandler
   if (IsScriptEventHandler(scriptKind, scriptContent)) {
     return false;
   }
 
-  ValidJSVersion validJSVersion = ValidJSVersion::eValid;
-
   // For classic scripts, check the type attribute to determine language and
   // version. If type exists, it trumps the deprecated 'language='
   if (scriptKind == ScriptKind::eClassic) {
     if (!type.IsEmpty()) {
-      NS_ENSURE_TRUE(ParseTypeAttribute(type, &validJSVersion), false);
+      NS_ENSURE_TRUE(nsContentUtils::IsJavascriptMIMEType(type), false);
     } else if (!hasType) {
       // no 'type=' element
       // "language" is a deprecated attribute of HTML, so we check it only for
       // HTML script elements.
       if (scriptContent->IsHTMLElement()) {
         nsAutoString language;
         scriptContent->AsElement()->GetAttr(kNameSpaceID_None,
                                             nsGkAtoms::language,
@@ -1424,19 +1363,18 @@ ScriptLoader::ProcessScriptElement(nsISc
         }
       }
 
       nsCOMPtr<nsIPrincipal> principal = aElement->GetScriptURITriggeringPrincipal();
       if (!principal) {
         principal = scriptContent->NodePrincipal();
       }
 
-      request = CreateLoadRequest(scriptKind, scriptURI, aElement,
-                                  validJSVersion, ourCORSMode, sriMetadata,
-                                  ourRefPolicy);
+      request = CreateLoadRequest(scriptKind, scriptURI, aElement, ourCORSMode,
+                                  sriMetadata, ourRefPolicy);
       request->mTriggeringPrincipal = Move(principal);
       request->mIsInline = false;
       request->SetScriptMode(aElement->GetScriptDeferred(),
                              aElement->GetScriptAsync());
       // keep request->mScriptFromHead to false so we don't treat non preloaded
       // scripts as blockers for full page load. See bug 792438.
 
       rv = StartLoad(request);
@@ -1451,18 +1389,16 @@ ScriptLoader::ProcessScriptElement(nsISc
         return false;
       }
     }
 
     // Should still be in loading stage of script.
     NS_ASSERTION(!request->InCompilingStage(),
                  "Request should not yet be in compiling stage.");
 
-    request->mValidJSVersion = validJSVersion;
-
     if (request->IsAsyncScript()) {
       AddAsyncRequest(request);
       if (request->IsReadyToRun()) {
         // The script is available already. Run it ASAP when the event
         // loop gets a chance to spin.
 
         // KVKV TODO: Instead of processing immediately, try off-thread-parsing
         // it and only schedule a pending ProcessRequest if that fails.
@@ -1555,20 +1491,19 @@ ScriptLoader::ProcessScriptElement(nsISc
 
   // Inline classic scripts ignore their CORS mode and are always CORS_NONE.
   CORSMode corsMode = CORS_NONE;
   if (scriptKind == ScriptKind::eModule) {
     corsMode = aElement->GetCORSMode();
   }
 
   request = CreateLoadRequest(scriptKind, mDocument->GetDocumentURI(), aElement,
-                              validJSVersion, corsMode,
+                              corsMode,
                               SRIMetadata(), // SRI doesn't apply
                               ourRefPolicy);
-  request->mValidJSVersion = validJSVersion;
   request->mIsInline = true;
   request->mTriggeringPrincipal = mDocument->NodePrincipal();
   request->mLineNo = aElement->GetScriptLineNumber();
   request->mProgress = ScriptLoadRequest::Progress::eLoading_Source;
   request->mDataType = ScriptLoadRequest::DataType::eSource;
   TRACE_FOR_TEST_BOOL(request->mElement, "scriptloader_load_source");
   CollectScriptTelemetry(nullptr, request);
 
@@ -2187,20 +2122,16 @@ ScriptLoader::EvaluateScript(ScriptLoadR
   // Make sure context is a strong reference since we access it after
   // we've executed a script, which may cause all other references to
   // the context to go away.
   nsCOMPtr<nsIScriptContext> context = globalObject->GetScriptContext();
   if (!context) {
     return NS_ERROR_FAILURE;
   }
 
-  if (aRequest->mValidJSVersion == ValidJSVersion::eInvalid) {
-    return NS_OK;
-  }
-
   // New script entry point required, due to the "Create a script" sub-step of
   // http://www.whatwg.org/specs/web-apps/current-work/#execute-the-script-block
   nsAutoMicroTask mt;
   AutoEntryScript aes(globalObject, "<script> element", true);
   JSContext* cx = aes.cx();
   JS::Rooted<JSObject*> global(cx, globalObject->GetGlobalJSObject());
 
   bool oldProcessingScriptTag = context->GetProcessingScriptTag();
@@ -3205,17 +3136,17 @@ ScriptLoader::PreloadURI(nsIURI* aURI, c
     nsAutoCString sourceUri;
     if (mDocument->GetDocumentURI()) {
       mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
     }
     SRICheck::IntegrityMetadata(aIntegrity, sourceUri, mReporter, &sriMetadata);
   }
 
   RefPtr<ScriptLoadRequest> request =
-    CreateLoadRequest(ScriptKind::eClassic, aURI, nullptr, ValidJSVersion::eValid,
+    CreateLoadRequest(ScriptKind::eClassic, aURI, nullptr,
                       Element::StringToCORSMode(aCrossOrigin), sriMetadata,
                       aReferrerPolicy);
   request->mTriggeringPrincipal = mDocument->NodePrincipal();
   request->mIsInline = false;
   request->mScriptFromHead = aScriptFromHead;
   request->SetScriptMode(aDefer, aAsync);
 
   nsresult rv = StartLoad(request);
--- a/dom/script/ScriptLoader.h
+++ b/dom/script/ScriptLoader.h
@@ -337,17 +337,16 @@ public:
   }
 
 private:
   virtual ~ScriptLoader();
 
   ScriptLoadRequest* CreateLoadRequest(ScriptKind aKind,
                                        nsIURI* aURI,
                                        nsIScriptElement* aElement,
-                                       ValidJSVersion aValidJSVersion,
                                        mozilla::CORSMode aCORSMode,
                                        const SRIMetadata& aIntegrity,
                                        mozilla::net::ReferrerPolicy aReferrerPolicy);
 
   /**
    * Unblocks the creator parser of the parser-blocking scripts.
    */
   void UnblockParser(ScriptLoadRequest* aParserBlockingRequest);
--- a/dom/tests/mochitest/bugs/test_bug1171215.html
+++ b/dom/tests/mochitest/bugs/test_bug1171215.html
@@ -5,17 +5,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 -->
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 1022869</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <iframe src="about:blank"></iframe>
-  <script type="text/javascript; version=1.8">
+  <script type="text/javascript">
 
   var f = document.getElementsByTagName("iframe")[0];
 
   SimpleTest.waitForExplicitFinish();
 
   /** Test for Bug 1022869 **/
   function startTest() {
     // Initialize our cookie.
--- a/dom/tests/mochitest/bugs/test_no_find_showDialog.html
+++ b/dom/tests/mochitest/bugs/test_no_find_showDialog.html
@@ -2,17 +2,17 @@
 <html>
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 1348409</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <iframe src="about:blank"></iframe>
-  <script type="text/javascript; version=1.8">
+  <script type="text/javascript">
 
   function checkForFindDialog() {
     let chromeScript = SpecialPowers.loadChromeScript(_ => {
       addMessageListener("test:check", () => {
         const { utils: Cu } = Components;
 
         Cu.import("resource://gre/modules/Services.jsm");
 
@@ -84,9 +84,9 @@
 </p>
 
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 </pre>
 </body>
-</html>
\ No newline at end of file
+</html>
--- a/dom/tests/mochitest/script/mochitest.ini
+++ b/dom/tests/mochitest/script/mochitest.ini
@@ -1,6 +1,7 @@
 [DEFAULT]
 support-files =
   file_blocked_script.sjs
 
 [test_bug1053321.html]
 skip-if = os == 'android' # bug 1386644
+[test_whitespace.html]
--- a/dom/tests/mochitest/script/test_bug1053321.html
+++ b/dom/tests/mochitest/script/test_bug1053321.html
@@ -18,23 +18,24 @@ are unexpectedly blocked.
   <!-- this script is not loaded until file_blocked_script.sjs?unblock&async request is made,
        when this script is executed, it sets window.script_executed_async to true
    -->
   <script async src="file_blocked_script.sjs?blocked&async"></script>
 </head>
 
 <body>
   <script>
-    // No need for an async test, we make it all before window.onload.
-    //
+    SimpleTest.waitForExplicitFinish();
+
     // We can't test whether the two scripts have not been executed here, since
     // preloads of the two images below (that unblock the two tested <head>
     // scripts) may happen sooner than this script executes.
     document.addEventListener("DOMContentLoaded", function() {
       ok(window.script_executed_defer, "Deferred script executed before DOMContentLoaded");
     });
     window.addEventListener("load", function() {
       ok(window.script_executed_async, "Async script executed before onload");
+      SimpleTest.finish();
     }, true);
   </script>
   <img src="file_blocked_script.sjs?unblock&defer"/>
   <img src="file_blocked_script.sjs?unblock&async"/>
 </body>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/script/test_whitespace.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for ScriptLoader and type with whitespaces</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<script type="application/javascript">
+let passed = false;
+
+let tests = [
+  [ " application/javascript", true ],
+  [ "\tapplication/javascript\n\r \t", true ],
+];
+
+for (let i = 0; i < tests.length; ++i) {
+  passed = false;
+
+  let script = document.createElement('script');
+  script.setAttribute('type', tests[i][0]);
+  script.innerText = "passed = true;";
+  document.body.appendChild(script);
+
+  ok (passed, tests[i][1], "Test " + tests[i][0] + " passed");
+}
+</script>
+
+</body>
+</html>
--- a/dom/workers/ServiceWorkerEvents.h
+++ b/dom/workers/ServiceWorkerEvents.h
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=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 mozilla_dom_workers_serviceworkerevents_h__
 #define mozilla_dom_workers_serviceworkerevents_h__
 
+#include "mozilla/dom/DOMPrefs.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/ExtendableEventBinding.h"
 #include "mozilla/dom/ExtendableMessageEventBinding.h"
 #include "mozilla/dom/FetchEventBinding.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/Response.h"
 #include "mozilla/dom/workers/bindings/ServiceWorker.h"
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -2342,30 +2342,32 @@ ServiceWorkerManager::RemoveScopeAndRegi
   if (auto entry = data->mUpdateTimers.Lookup(aRegistration->mScope)) {
     entry.Data()->Cancel();
     entry.Remove();
   }
 
   // Verify there are no controlled clients for the purged registration.
   for (auto iter = swm->mControlledClients.Iter(); !iter.Done(); iter.Next()) {
     auto& reg = iter.UserData()->mRegistrationInfo;
-    if (reg->mScope.Equals(aRegistration->mScope)) {
+    if (reg->mScope.Equals(aRegistration->mScope) &&
+        reg->mPrincipal->Equals(aRegistration->mPrincipal)) {
       MOZ_DIAGNOSTIC_ASSERT(false,
                             "controlled client when removing registration");
       iter.Remove();
       break;
     }
   }
 
   // Registration lifecycle is managed via mControlledClients now.  Do not
   // assert on on mControlledDocuments as races may cause this to still be
   // set when the registration is destroyed.
   for (auto iter = swm->mControlledDocuments.Iter(); !iter.Done(); iter.Next()) {
     ServiceWorkerRegistrationInfo* reg = iter.UserData();
-    if (reg->mScope.Equals(aRegistration->mScope)) {
+    if (reg->mScope.Equals(aRegistration->mScope) &&
+        reg->mPrincipal->Equals(aRegistration->mPrincipal)) {
       iter.Remove();
       break;
     }
   }
 
   RefPtr<ServiceWorkerRegistrationInfo> info;
   data->mInfos.Remove(aRegistration->mScope, getter_AddRefs(info));
   data->mOrderedScopes.RemoveElement(aRegistration->mScope);
@@ -3228,18 +3230,18 @@ ServiceWorkerManager::UpdateInternal(nsI
 
   queue->ScheduleJob(job);
 }
 
 already_AddRefed<GenericPromise>
 ServiceWorkerManager::MaybeClaimClient(nsIDocument* aDocument,
                                        ServiceWorkerRegistrationInfo* aWorkerRegistration)
 {
-  MOZ_ASSERT(aWorkerRegistration);
-  MOZ_ASSERT(aWorkerRegistration->GetActive());
+  MOZ_DIAGNOSTIC_ASSERT(aWorkerRegistration);
+  MOZ_DIAGNOSTIC_ASSERT(aWorkerRegistration->GetActive());
 
   RefPtr<GenericPromise> ref;
 
   // Same origin check
   if (!aWorkerRegistration->mPrincipal->Equals(aDocument->NodePrincipal())) {
     ref = GenericPromise::CreateAndReject(NS_ERROR_DOM_SECURITY_ERR, __func__);
     return ref.forget();
   }
@@ -3281,17 +3283,23 @@ ServiceWorkerManager::MaybeClaimClient(n
     PrincipalInfoToPrincipal(aServiceWorker.PrincipalInfo());
   if (!principal) {
     ref = GenericPromise::CreateAndResolve(false, __func__);
     return ref.forget();
   }
 
   RefPtr<ServiceWorkerRegistrationInfo> registration =
     GetRegistration(principal, aServiceWorker.Scope());
-  if (!registration) {
+
+  // While ServiceWorkerManager is distributed across child processes its
+  // possible for us to sometimes get a claim for a new worker that has
+  // not propagated to this process yet.  For now, simply note that we
+  // are done.  The fix for this is to move the SWM to the parent process
+  // so there are no consistency errors.
+  if (NS_WARN_IF(!registration) || NS_WARN_IF(!registration->GetActive())) {
     ref = GenericPromise::CreateAndResolve(false, __func__);
     return ref.forget();
   }
 
   ref = MaybeClaimClient(aDoc, registration);
   return ref.forget();
 }
 
--- a/dom/workers/test/serviceworkers/browser.ini
+++ b/dom/workers/test/serviceworkers/browser.ini
@@ -13,10 +13,11 @@ support-files =
   server_multie10s_update.sjs
 
 [browser_devtools_serviceworker_interception.js]
 [browser_force_refresh.js]
 [browser_download.js]
 [browser_multie10s_update.js]
 skip-if = !e10s || os != "win" # Bug 1404914
 [browser_storage_permission.js]
+[browser_unregister_with_containers.js]
 [browser_userContextId_openWindow.js]
 skip-if = !e10s
--- a/dom/workers/test/serviceworkers/browser_storage_permission.js
+++ b/dom/workers/test/serviceworkers/browser_storage_permission.js
@@ -5,16 +5,19 @@ const { interfaces: Ci } = Components;
 const BASE_URI = "http://mochi.test:8888/browser/dom/workers/test/serviceworkers/";
 const PAGE_URI = BASE_URI + "empty.html";
 const SCOPE = PAGE_URI + "?storage_permission";
 const SW_SCRIPT = BASE_URI + "empty.js";
 
 
 add_task(async function setup() {
   await SpecialPowers.pushPrefEnv({"set": [
+    // Until the e10s refactor is complete, use a single process to avoid
+    // service worker propagation race.
+    ["dom.ipc.processCount", 1],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
   ]});
 
   let tab = BrowserTestUtils.addTab(gBrowser, PAGE_URI);
   let browser = gBrowser.getBrowserForTab(tab);
   await BrowserTestUtils.browserLoaded(browser);
 
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/browser_unregister_with_containers.js
@@ -0,0 +1,138 @@
+"use strict";
+
+const { interfaces: Ci } = Components;
+
+const BASE_URI = "http://mochi.test:8888/browser/dom/workers/test/serviceworkers/";
+const PAGE_URI = BASE_URI + "empty.html";
+const SCOPE = PAGE_URI + "?unregister_with_containers";
+const SW_SCRIPT = BASE_URI + "empty.js";
+
+function doRegister(browser) {
+  return ContentTask.spawn(browser, { script: SW_SCRIPT, scope: SCOPE },
+    async function(opts) {
+      let reg = await content.navigator.serviceWorker.register(opts.script,
+                                                               { scope: opts.scope });
+      let worker = reg.installing || reg.waiting || reg.active;
+      await new Promise(resolve => {
+        if (worker.state === "activated") {
+          resolve();
+          return;
+        }
+        worker.addEventListener("statechange", function onStateChange() {
+          if (worker.state === "activated") {
+            worker.removeEventListener("statechange", onStateChange);
+            resolve();
+          }
+        });
+      });
+    }
+  );
+}
+
+function doUnregister(browser) {
+  return ContentTask.spawn(browser, SCOPE, async function(uri) {
+    let reg = await content.navigator.serviceWorker.getRegistration(uri);
+    let worker = reg.active;
+    await reg.unregister();
+    await new Promise(resolve => {
+      if (worker.state === "redundant") {
+        resolve();
+        return;
+      }
+      worker.addEventListener("statechange", function onStateChange() {
+        if (worker.state === "redundant") {
+          worker.removeEventListener("statechange", onStateChange);
+          resolve();
+        }
+      });
+    });
+  });
+}
+
+function isControlled(browser) {
+  return ContentTask.spawn(browser, null, function() {
+    return !!content.navigator.serviceWorker.controller;
+  });
+}
+
+async function checkControlled(browser) {
+  let controlled = await isControlled(browser);
+  ok(controlled, "window should be controlled");
+}
+
+async function checkUncontrolled(browser) {
+  let controlled = await isControlled(browser);
+  ok(!controlled, "window should not be controlled");
+}
+
+add_task(async function test() {
+  await SpecialPowers.pushPrefEnv({"set": [
+    // Avoid service worker propagation races by disabling multi-e10s for now.
+    // This can be removed after the e10s refactor is complete.
+    ["dom.ipc.processCount", 1],
+    ["dom.serviceWorkers.enabled", true],
+    ["dom.serviceWorkers.testing.enabled", true],
+  ]});
+
+  // Setup service workers in two different contexts with the same scope.
+  let containerTab1 = BrowserTestUtils.addTab(gBrowser, PAGE_URI, { userContextId: 1 });
+  let containerBrowser1 = gBrowser.getBrowserForTab(containerTab1);
+  await BrowserTestUtils.browserLoaded(containerBrowser1);
+
+  let containerTab2 = BrowserTestUtils.addTab(gBrowser, PAGE_URI, { userContextId: 2 });
+  let containerBrowser2 = gBrowser.getBrowserForTab(containerTab2);
+  await BrowserTestUtils.browserLoaded(containerBrowser2);
+
+  await doRegister(containerBrowser1);
+  await doRegister(containerBrowser2);
+
+  await checkUncontrolled(containerBrowser1);
+  await checkUncontrolled(containerBrowser2);
+
+  // Close the tabs we used to register the service workers.  These are not
+  // controlled.
+  await BrowserTestUtils.removeTab(containerTab1);
+  await BrowserTestUtils.removeTab(containerTab2);
+
+  // Open a controlled tab in each container.
+  containerTab1 = BrowserTestUtils.addTab(gBrowser, SCOPE, { userContextId: 1 });
+  containerBrowser1 = gBrowser.getBrowserForTab(containerTab1);
+  await BrowserTestUtils.browserLoaded(containerBrowser1);
+
+  containerTab2 = BrowserTestUtils.addTab(gBrowser, SCOPE, { userContextId: 2 });
+  containerBrowser2 = gBrowser.getBrowserForTab(containerTab2);
+  await BrowserTestUtils.browserLoaded(containerBrowser2);
+
+  await checkControlled(containerBrowser1);
+  await checkControlled(containerBrowser2);
+
+  // Remove the first container's controlled tab
+  await BrowserTestUtils.removeTab(containerTab1);
+
+  // Create a new uncontrolled tab for the first container and use it to
+  // unregister the service worker.
+  containerTab1 = BrowserTestUtils.addTab(gBrowser, PAGE_URI, { userContextId: 1 });
+  containerBrowser1 = gBrowser.getBrowserForTab(containerTab1);
+  await BrowserTestUtils.browserLoaded(containerBrowser1);
+  await doUnregister(containerBrowser1);
+
+  await checkUncontrolled(containerBrowser1);
+  await checkControlled(containerBrowser2);
+
+  // Remove the second container's controlled tab
+  await BrowserTestUtils.removeTab(containerTab2);
+
+  // Create a new uncontrolled tab for the second container and use it to
+  // unregister the service worker.
+  containerTab2 = BrowserTestUtils.addTab(gBrowser, PAGE_URI, { userContextId: 2 });
+  containerBrowser2 = gBrowser.getBrowserForTab(containerTab2);
+  await BrowserTestUtils.browserLoaded(containerBrowser2);
+  await doUnregister(containerBrowser2);
+
+  await checkUncontrolled(containerBrowser1);
+  await checkUncontrolled(containerBrowser2);
+
+  // Close the two tabs we used to unregister the service worker.
+  await BrowserTestUtils.removeTab(containerTab1);
+  await BrowserTestUtils.removeTab(containerTab2);
+});
--- a/dom/xbl/test/test_bug389322.xhtml
+++ b/dom/xbl/test/test_bug389322.xhtml
@@ -100,27 +100,19 @@ addLoadEvent(function() {
 });
 addLoadEvent(SimpleTest.finish);
 
 function report(testName, success) {
   is(success, true, "JS 1.7 should work in " + testName);
 }
 ]]>
 </script>
-<script type="text/javascript; version=1.7"><![CDATA[
-  try {
-    eval("let x = 1;");
-    var success = true;
-  }
-  catch (e) { success = false; }
-  report("HTML script tags with explicit version", success)
-]]></script>
 <script type="text/javascript"><![CDATA[
   try {
     eval("let x = 1;");
     var success = true;
   }
   catch (e) { success = false; }
-  is(success, true, "let should work in versionless HTML script tags");
+  is(success, true, "let should work in HTML script tags");
 ]]></script>
 </pre>
 </body>
 </html>
--- a/gfx/cairo/cairo/src/cairo-ft-font.c
+++ b/gfx/cairo/cairo/src/cairo-ft-font.c
@@ -2700,31 +2700,33 @@ static void
      *   font_face ------> unscaled
      *        <-....weak....../
      *
      * To:
      *
      *    font_face <------- unscaled
      */
 
-    if (font_face->unscaled &&
-	font_face->unscaled->from_face &&
-	font_face->next == NULL &&
-	font_face->unscaled->faces == font_face &&
-	CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1)
+    if (font_face->unscaled)
     {
-	cairo_font_face_reference (&font_face->base);
-
-	_cairo_unscaled_font_destroy (&font_face->unscaled->base);
-	font_face->unscaled = NULL;
-
-	return;
-    }
-
-    if (font_face->unscaled) {
+	CAIRO_MUTEX_LOCK (font_face->unscaled->mutex);
+
+	if (font_face->unscaled->from_face &&
+	    font_face->next == NULL &&
+	    font_face->unscaled->faces == font_face &&
+	    CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1)
+	{
+	    cairo_font_face_reference (&font_face->base);
+
+	    CAIRO_MUTEX_UNLOCK (font_face->unscaled->mutex);
+	    _cairo_unscaled_font_destroy (&font_face->unscaled->base);
+	    font_face->unscaled = NULL;
+	    return;
+	}
+
 	cairo_ft_font_face_t *tmp_face = NULL;
 	cairo_ft_font_face_t *last_face = NULL;
 
 	/* Remove face from linked list */
 	for (tmp_face = font_face->unscaled->faces;
 	     tmp_face;
 	     tmp_face = tmp_face->next)
 	{
@@ -2733,16 +2735,17 @@ static void
 		    last_face->next = tmp_face->next;
 		else
 		    font_face->unscaled->faces = tmp_face->next;
 	    }
 
 	    last_face = tmp_face;
 	}
 
+	CAIRO_MUTEX_UNLOCK (font_face->unscaled->mutex);
 	_cairo_unscaled_font_destroy (&font_face->unscaled->base);
 	font_face->unscaled = NULL;
     }
 
 #if CAIRO_HAS_FC_FONT
     if (font_face->pattern) {
 	FcPatternDestroy (font_face->pattern);
 	cairo_font_face_destroy (font_face->resolved_font_face);
@@ -2850,16 +2853,18 @@ static cairo_status_t
 #endif
 
 static cairo_font_face_t *
 _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
 			    cairo_ft_options_t	     *ft_options)
 {
     cairo_ft_font_face_t *font_face, **prev_font_face;
 
+    CAIRO_MUTEX_LOCK (unscaled->mutex);
+
     /* Looked for an existing matching font face */
     for (font_face = unscaled->faces, prev_font_face = &unscaled->faces;
 	 font_face;
 	 prev_font_face = &font_face->next, font_face = font_face->next)
     {
 	if (font_face->ft_options.load_flags == ft_options->load_flags &&
 	    font_face->ft_options.extra_flags == ft_options->extra_flags &&
 	    cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
@@ -2871,25 +2876,29 @@ static cairo_font_face_t *
 	    }
 
 	    if (font_face->unscaled == NULL) {
 		/* Resurrect this "zombie" font_face (from
 		 * _cairo_ft_font_face_destroy), switching its unscaled_font
 		 * from owner to ownee. */
 		font_face->unscaled = unscaled;
 		_cairo_unscaled_font_reference (&unscaled->base);
-		return &font_face->base;
-	    } else
-		return cairo_font_face_reference (&font_face->base);
+	    } else {
+		cairo_font_face_reference (&font_face->base);
+	    }
+
+	    CAIRO_MUTEX_UNLOCK (unscaled->mutex);
+	    return &font_face->base;
 	}
     }
 
     /* No match found, create a new one */
     font_face = malloc (sizeof (cairo_ft_font_face_t));
     if (unlikely (!font_face)) {
+	CAIRO_MUTEX_UNLOCK (unscaled->mutex);
 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 	return (cairo_font_face_t *)&_cairo_font_face_nil;
     }
 
     font_face->unscaled = unscaled;
     _cairo_unscaled_font_reference (&unscaled->base);
 
     font_face->ft_options = *ft_options;
@@ -2906,16 +2915,17 @@ static cairo_font_face_t *
     unscaled->faces = font_face;
 
 #if CAIRO_HAS_FC_FONT
     font_face->pattern = NULL;
 #endif
 
     _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
 
+    CAIRO_MUTEX_UNLOCK (unscaled->mutex);
     return &font_face->base;
 }
 
 /* implement the platform-specific interface */
 
 #if CAIRO_HAS_FC_FONT
 static cairo_status_t
 _cairo_ft_font_options_substitute (const cairo_font_options_t *options,
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -259,19 +259,19 @@ ChooseDebugFlags(CreateContextFlags crea
 #endif
 
     return debugFlags;
 }
 
 GLContext::GLContext(CreateContextFlags flags, const SurfaceCaps& caps,
                      GLContext* sharedContext, bool isOffscreen, bool useTLSIsCurrent)
   : mImplicitMakeCurrent(false),
+    mUseTLSIsCurrent(ShouldUseTLSIsCurrent(useTLSIsCurrent)),
     mIsOffscreen(isOffscreen),
     mContextLost(false),
-    mUseTLSIsCurrent(ShouldUseTLSIsCurrent(useTLSIsCurrent)),
     mVersion(0),
     mProfile(ContextProfile::Unknown),
     mShadingLanguageVersion(0),
     mVendor(GLVendor::Other),
     mRenderer(GLRenderer::Other),
     mTopError(LOCAL_GL_NO_ERROR),
     mDebugFlags(ChooseDebugFlags(flags)),
     mSharedContext(sharedContext),
@@ -3069,19 +3069,17 @@ GLContext::MakeCurrent(bool aForce) cons
             MOZ_ASSERT(IsCurrentImpl());
             return true;
         }
     }
 
     if (!MakeCurrentImpl())
         return false;
 
-    if (mUseTLSIsCurrent) {
-        sCurrentContext.set(reinterpret_cast<uintptr_t>(this));
-    }
+    sCurrentContext.set(reinterpret_cast<uintptr_t>(this));
     return true;
 }
 
 void
 GLContext::ResetSyncCallCount(const char* resetReason) const
 {
     if (ShouldSpew()) {
         printf_stderr("On %s, mSyncGLCallCount = %" PRIu64 "\n",
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -194,16 +194,33 @@ class GLContext
     , public GenericAtomicRefCounted
     , public SupportsWeakPtr<GLContext>
 {
 public:
     MOZ_DECLARE_WEAKREFERENCE_TYPENAME(GLContext)
     static MOZ_THREAD_LOCAL(uintptr_t) sCurrentContext;
 
     bool mImplicitMakeCurrent;
+    bool mUseTLSIsCurrent;
+
+    class TlsScope final {
+        GLContext* const mGL;
+        const bool mWasTlsOk;
+    public:
+        explicit TlsScope(GLContext* const gl)
+            : mGL(gl)
+            , mWasTlsOk(gl->mUseTLSIsCurrent)
+        {
+            mGL->mUseTLSIsCurrent = true;
+        }
+
+        ~TlsScope() {
+            mGL->mUseTLSIsCurrent = mWasTlsOk;
+        }
+    };
 
 // -----------------------------------------------------------------------------
 // basic getters
 public:
 
     /**
      * Returns true if the context is using ANGLE. This should only be overridden
      * for an ANGLE implementation.
@@ -315,17 +332,16 @@ public:
      */
     virtual GLuint GetDefaultFramebuffer() {
         return 0;
     }
 
 protected:
     bool mIsOffscreen;
     mutable bool mContextLost;
-    const bool mUseTLSIsCurrent;
 
     /**
      * mVersion store the OpenGL's version, multiplied by 100. For example, if
      * the context is an OpenGL 2.1 context, mVersion value will be 210.
      */
     uint32_t mVersion;
     ContextProfile mProfile;
 
--- a/gfx/webrender_bindings/RenderD3D11TextureHostOGL.cpp
+++ b/gfx/webrender_bindings/RenderD3D11TextureHostOGL.cpp
@@ -204,17 +204,17 @@ RenderDXGITextureHostOGL::DeleteTextureH
   }
 
   const auto& egl = &gl::sEGLLibrary;
   if (mSurface) {
     egl->fDestroySurface(egl->Display(), mSurface);
     mSurface = 0;
   }
   if (mStream) {
-    egl->fStreamConsumerReleaseKHR(egl->Display(), mStream);
+    egl->fDestroyStreamKHR(egl->Display(), mStream);
     mStream = 0;
   }
 
   mTexture = nullptr;
   mKeyedMutex = nullptr;
 }
 
 GLuint
@@ -412,16 +412,16 @@ RenderDXGIYCbCrTextureHostOGL::DeleteTex
     mKeyedMutexs[i] = nullptr;
 
     const auto& egl = &gl::sEGLLibrary;
     if (mSurfaces[i]) {
       egl->fDestroySurface(egl->Display(), mSurfaces[i]);
       mSurfaces[i] = 0;
     }
     if (mStreams[i]) {
-      egl->fStreamConsumerReleaseKHR(egl->Display(), mStreams[i]);
+      egl->fDestroyStreamKHR(egl->Display(), mStreams[i]);
       mStreams[i] = 0;
     }
   }
 }
 
 } // namespace wr
 } // namespace mozilla
--- a/js/rust/build.rs
+++ b/js/rust/build.rs
@@ -251,17 +251,17 @@ const WHITELIST_VARS: &'static [&'static
     "JS::NullHandleValue",
     "JS::TrueHandleValue",
     "JS::UndefinedHandleValue",
 ];
 
 /// Functions we want to generate bindings to.
 const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
     "INTERNED_STRING_TO_JSID",
-    "ExceptionStackOrNull",
+    "JS::ExceptionStackOrNull",
     "JS_AddExtraGCRootsTracer",
     "JS_AddInterruptCallback",
     "JS::AddPromiseReactions",
     "js::AddRawValueRoot",
     "JS_AlreadyHasOwnPropertyById",
     "JS_AtomizeAndPinString",
     "js::AssertSameCompartment",
     "JS::BuildStackString",
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -555,24 +555,29 @@ typedef bool
 typedef JSObject*
 (* JSGetIncumbentGlobalCallback)(JSContext* cx);
 
 typedef bool
 (* JSEnqueuePromiseJobCallback)(JSContext* cx, JS::HandleObject job,
                                 JS::HandleObject allocationSite, JS::HandleObject incumbentGlobal,
                                 void* data);
 
+namespace JS {
+
 enum class PromiseRejectionHandlingState {
     Unhandled,
     Handled
 };
 
+} /* namespace JS */
+
 typedef void
 (* JSPromiseRejectionTrackerCallback)(JSContext* cx, JS::HandleObject promise,
-                                      PromiseRejectionHandlingState state, void* data);
+                                      JS::PromiseRejectionHandlingState state,
+                                      void* data);
 
 typedef void
 (* JSProcessPromiseCallback)(JSContext* cx, JS::HandleObject promise);
 
 /**
  * Possible exception types. These types are part of a JSErrorFormatString
  * structure. They define which error to throw in case of a runtime error.
  *
@@ -5801,26 +5806,29 @@ JS_DropExceptionState(JSContext* cx, JSE
  * able to lazily create) an error report struct, and this function will return
  * the address of that struct.  Otherwise, it returns nullptr. The lifetime
  * of the error report struct that might be returned is the same as the
  * lifetime of the exception object.
  */
 extern JS_PUBLIC_API(JSErrorReport*)
 JS_ErrorFromException(JSContext* cx, JS::HandleObject obj);
 
+namespace JS {
 /**
  * If the given object is an exception object (or an unwrappable
  * cross-compartment wrapper for one), return the stack for that exception, if
  * any.  Will return null if the given object is not an exception object
  * (including if it's null or a security wrapper that can't be unwrapped) or if
  * the exception has no stack.
  */
 extern JS_PUBLIC_API(JSObject*)
 ExceptionStackOrNull(JS::HandleObject obj);
 
+} /* namespace JS */
+
 /**
  * A JS context always has an "owner thread". The owner thread is set when the
  * context is created (to the current thread) and practically all entry points
  * into the JS engine check that a context (or anything contained in the
  * context: runtime, compartment, object, etc) is only touched by its owner
  * thread. Embeddings may check this invariant outside the JS engine by calling
  * JS_AbortIfWrongThread (which will abort if not on the owner thread, even for
  * non-debug builds).
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -418,17 +418,17 @@ js::ErrorFromException(JSContext* cx, Ha
         MOZ_ASSERT(cx->isThrowingOutOfMemory());
         cx->recoverFromOutOfMemory();
     }
 
     return report;
 }
 
 JS_PUBLIC_API(JSObject*)
-ExceptionStackOrNull(HandleObject objArg)
+JS::ExceptionStackOrNull(HandleObject objArg)
 {
     JSObject* obj = CheckedUnwrap(objArg);
     if (!obj || !obj->is<ErrorObject>()) {
       return nullptr;
     }
 
     return obj->as<ErrorObject>().stack();
 }
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -843,17 +843,18 @@ DrainJobQueue(JSContext* cx, unsigned ar
         return false;
 
     args.rval().setUndefined();
     return true;
 }
 
 static void
 ForwardingPromiseRejectionTrackerCallback(JSContext* cx, JS::HandleObject promise,
-                                          PromiseRejectionHandlingState state, void* data)
+                                          JS::PromiseRejectionHandlingState state,
+                                          void* data)
 {
     RootedValue callback(cx, GetShellContext(cx)->promiseRejectionTrackerCallback);
     if (callback.isNull()) {
         return;
     }
 
     AutoCompartment ac(cx, &callback.toObject());
 
--- a/js/src/vm/List-inl.h
+++ b/js/src/vm/List-inl.h
@@ -28,17 +28,17 @@ inline MOZ_MUST_USE bool
 AppendToList(JSContext* cx, HandleNativeObject list, HandleValue value)
 {
     uint32_t length = list->getDenseInitializedLength();
 
     if (!list->ensureElements(cx, length + 1))
         return false;
 
     list->ensureDenseInitializedLength(cx, length, 1);
-    list->setDenseElement(length, value);
+    list->setDenseElementWithType(cx, length, value);
 
     return true;
 }
 
 template<class T>
 inline MOZ_MUST_USE T*
 PeekList(NativeObject* list)
 {
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -748,29 +748,29 @@ void
 JSRuntime::addUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise)
 {
     MOZ_ASSERT(promise->is<PromiseObject>());
     if (!cx->promiseRejectionTrackerCallback)
         return;
 
     void* data = cx->promiseRejectionTrackerCallbackData;
     cx->promiseRejectionTrackerCallback(cx, promise,
-                                        PromiseRejectionHandlingState::Unhandled, data);
+                                        JS::PromiseRejectionHandlingState::Unhandled, data);
 }
 
 void
 JSRuntime::removeUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise)
 {
     MOZ_ASSERT(promise->is<PromiseObject>());
     if (!cx->promiseRejectionTrackerCallback)
         return;
 
     void* data = cx->promiseRejectionTrackerCallbackData;
     cx->promiseRejectionTrackerCallback(cx, promise,
-                                        PromiseRejectionHandlingState::Handled, data);
+                                        JS::PromiseRejectionHandlingState::Handled, data);
 }
 
 mozilla::non_crypto::XorShift128PlusRNG&
 JSRuntime::randomKeyGenerator()
 {
     MOZ_ASSERT(CurrentThreadCanAccessRuntime(this));
     if (randomKeyGenerator_.isNothing()) {
         mozilla::Array<uint64_t, 2> seed;
--- a/layout/style/test/bug453896_iframe.html
+++ b/layout/style/test/bug453896_iframe.html
@@ -1,16 +1,16 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
 <html lang="en-US">
 <head>
   <title>Bug 453896 Test middle frame</title>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <meta http-equiv="Content-Style-Type" content="text/css">
-  <script type="application/javascript; version=1.7">
+  <script type="application/javascript">
 
 function run(test_window)
 {
   var subdoc = document.getElementById("subdoc").contentDocument;
   var subwin = document.getElementById("subdoc").contentWindow;
   var style = subdoc.getElementById("style");
   var iframe_style = document.getElementById("subdoc").style;
   var body_cs = subdoc.defaultView.getComputedStyle(subdoc.body);
--- a/layout/style/test/chrome/test_moz_document_rules.html
+++ b/layout/style/test/chrome/test_moz_document_rules.html
@@ -5,17 +5,17 @@
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
 </head>
 <body onload="run()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=398962">Mozilla Bug 398962</a>
 <iframe id="iframe" src="http://mochi.test:8888/tests/layout/style/test/chrome/moz_document_helper.html"></iframe>
 <pre id="test">
-<script type="application/javascript; version=1.8">
+<script type="application/javascript">
 
 var [gStyleSheetService, gIOService] = (function() {
     return [
             Components.classes["@mozilla.org/content/style-sheet-service;1"]
                 .getService(Components.interfaces.nsIStyleSheetService),
             Components.classes["@mozilla.org/network/io-service;1"]
                 .getService(Components.interfaces.nsIIOService)
            ];
--- a/layout/style/test/test_addSheet.html
+++ b/layout/style/test/test_addSheet.html
@@ -7,17 +7,17 @@
 </head>
 <body onload="run()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1024707">Mozilla Bug 1024707</a>
 
 <iframe id="iframe1" src="additional_sheets_helper.html"></iframe>
 <iframe id="iframe2" src="additional_sheets_helper.html"></iframe>
 
 <pre id="test">
-<script type="application/javascript; version=1.8">
+<script type="application/javascript">
 
 let gIOService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
   .getService(SpecialPowers.Ci.nsIIOService);
 
 let gSSService = SpecialPowers.Cc["@mozilla.org/content/style-sheet-service;1"]
   .getService(SpecialPowers.Ci.nsIStyleSheetService);
 
 function test(win, sheet) {
--- a/layout/style/test/test_additional_sheets.html
+++ b/layout/style/test/test_additional_sheets.html
@@ -4,17 +4,17 @@
   <title>Test for additional sheets</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body onload="run()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=737003">Mozilla Bug 737003</a>
 <iframe id="iframe" src="additional_sheets_helper.html"></iframe>
 <pre id="test">
-<script type="application/javascript; version=1.8">
+<script type="application/javascript">
 
 var gIOService = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
   .getService(SpecialPowers.Ci.nsIIOService)
 
 var gSSService = SpecialPowers.Cc["@mozilla.org/content/style-sheet-service;1"]
   .getService(SpecialPowers.Ci.nsIStyleSheetService);
 
 function getUri(style)
--- a/layout/style/test/test_computed_style_prefs.html
+++ b/layout/style/test/test_computed_style_prefs.html
@@ -7,17 +7,17 @@
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=919594">Mozilla Bug 919594</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
-<script type="application/javascript; version=1.7">
+<script type="application/javascript">
 
 /** Test that preffed off properties do not appear in computed style **/
 
 function testWithAllPrefsDisabled() {
   let exposedProperties = Object.keys(gCS).map(i => gCS[i]);
 
   // Store the number of properties for later tests to use.
   gLengthWithAllPrefsDisabled = gCS.length;
--- a/layout/style/test/test_media_queries_dynamic.html
+++ b/layout/style/test/test_media_queries_dynamic.html
@@ -10,17 +10,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 </head>
 <body onload="run()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=473400">Mozilla Bug 473400</a>
 <iframe id="subdoc" src="about:blank"></iframe>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
-<script class="testbody" type="application/javascript; version=1.7">
+<script class="testbody" type="application/javascript">
 
 /** Test for Bug 473400 **/
 
 SimpleTest.waitForExplicitFinish();
 
 function run() {
   var subdoc = document.getElementById("subdoc").contentDocument;
   var subwin = document.getElementById("subdoc").contentWindow;
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1274,16 +1274,19 @@ var BrowserApp = {
               UITelemetry.addEvent("undo.1", "toast", null, "closetab");
               ss.undoCloseTab(window, closedTabData);
             }
           }
         });
       }
     }
 
+    // Retrieve updated tabIndex again for the removal because the index could
+    // be changed if a new tab is added by the event listener.
+    tabIndex = this._tabs.indexOf(aTab);
     aTab.destroy();
     this._tabs.splice(tabIndex, 1);
   },
 
   _handleTabMove(fromTabId, fromPosition, toTabId, toPosition) {
     let movedTab = this._tabs[fromPosition];
     if (movedTab.id != fromTabId || this._tabs[toPosition].id != toTabId) {
       // The gecko and/or java Tabs tabs lists changed sometime between when the Tabs list was
--- a/mobile/android/tests/browser/chrome/head.js
+++ b/mobile/android/tests/browser/chrome/head.js
@@ -1,26 +1,30 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function fuzzyEquals(a, b) {
   return (Math.abs(a - b) < 1e-6);
 }
 
-function promiseBrowserEvent(browser, eventType) {
+function promiseBrowserEvent(browser, eventType, options) {
   return new Promise((resolve) => {
     function handle(event) {
       // Since we'll be redirecting, don't make assumptions about the given URL and the loaded URL
       if (event.target != browser.contentDocument || event.target.location.href == "about:blank") {
         info("Skipping spurious '" + eventType + "' event" + " for " + event.target.location.href);
         return;
       }
       info("Received event " + eventType + " from browser");
       browser.removeEventListener(eventType, handle, true);
-      resolve(event);
+      if (options && options.resolveAtNextTick) {
+        setTimeout(() => resolve(event), 0);
+      } else {
+        resolve(event);
+      }
     }
 
     browser.addEventListener(eventType, handle, true);
     info("Now waiting for " + eventType + " event from browser");
   });
 }
 
 function promiseTabEvent(container, eventType) {
--- a/mobile/android/tests/browser/chrome/test_session_form_data.html
+++ b/mobile/android/tests/browser/chrome/test_session_form_data.html
@@ -91,17 +91,17 @@ add_task(function* test_formdata() {
 
   // Creates a tab, loads a page with some form fields,
   // modifies their values and closes the tab.
   function createAndRemoveTab() {
     return Task.spawn(function* () {
       // Create a new tab.
       let tab = gBrowserApp.addTab(URL);
       let browser = tab.browser;
-      yield promiseBrowserEvent(browser, "load");
+      yield promiseBrowserEvent(browser, "load", { resolveAtNextTick: true });
 
       // Modify form data.
       setInputValue(browser, {id: "txt", value: OUTER_VALUE});
       setInputValue(browser, {id: "txt", value: INNER_VALUE, frame: 0});
 
       // Remove the tab.
       gBrowserApp.closeTab(tab);
       yield promiseTabEvent(browser, "SSTabCloseProcessed");
@@ -146,17 +146,17 @@ add_task(function* test_formdata2() {
 
   // Creates a tab, loads a page with some form fields,
   // modifies their values and closes the tab.
   function createAndRemoveTab() {
     return Task.spawn(function* () {
       // Create a new tab.
       let tab = gBrowserApp.addTab(URL);
       let browser = tab.browser;
-      yield promiseBrowserEvent(browser, "load");
+      yield promiseBrowserEvent(browser, "load", { resolveAtNextTick: true });
 
       // Modify form data.
       setInputValue(browser, {id: "txt", value: OUTER_VALUE});
       setInputValue(browser, {id: "txt", value: INNER_VALUE, frame: 0});
 
       // Remove the tab.
       gBrowserApp.closeTab(tab);
       yield promiseTabEvent(browser, "SSTabCloseProcessed");
@@ -167,17 +167,17 @@ add_task(function* test_formdata2() {
   let state = ss.getClosedTabs(gChromeWin);
   let [{formdata}] = state;
   is(formdata.id.txt, OUTER_VALUE, "outer value is correct");
   is(formdata.children[0].id.txt, INNER_VALUE, "inner value is correct");
 
   // Restore the closed tab.
   let closedTabData = ss.getClosedTabs(gChromeWin)[0];
   let browser = ss.undoCloseTab(gChromeWin, closedTabData);
-  yield promiseBrowserEvent(browser, "load");
+  yield promiseBrowserEvent(browser, "load", { resolveAtNextTick: true });
 
   // Check the form data.
   is(getInputValue(browser, {id: "txt"}), OUTER_VALUE, "outer value restored correctly");
   is(getInputValue(browser, {id: "txt", frame: 0}), INNER_VALUE, "inner value restored correctly");
 
   // Remove the tab.
   gBrowserApp.closeTab(gBrowserApp.getTabForBrowser(browser));
 });
@@ -206,17 +206,17 @@ add_task(function* test_formdata_navigat
 
   // Creates a tab, loads a page with some form fields, modifies their values,
   // navigates to a different page and back again and closes the tab.
   function createNavigateAndRemoveTab() {
     return Task.spawn(function* () {
       // Create a new tab.
       let tab = gBrowserApp.addTab(URL);
       let browser = tab.browser;
-      yield promiseBrowserEvent(browser, "load");
+      yield promiseBrowserEvent(browser, "load", { resolveAtNextTick: true });
 
       // Modify form data.
       setInputValue(browser, {id: "txt", value: OUTER_VALUE});
       setInputValue(browser, {id: "txt", value: INNER_VALUE, frame: 0});
 
       // Visit a different page.
       gBrowserApp.loadURI(otherURL, browser);
       yield promiseBrowserEvent(browser, "DOMContentLoaded");
@@ -246,17 +246,17 @@ add_task(function* test_formdata_navigat
   let state = ss.getClosedTabs(gChromeWin);
   let [{formdata}] = state;
   is(formdata.id.txt, OUTER_VALUE, "outer value is correct");
   is(formdata.children[0].id.txt, INNER_VALUE, "inner value is correct");
 
   // Restore the closed tab.
   let closedTabData = ss.getClosedTabs(gChromeWin)[0];
   let browser = ss.undoCloseTab(gChromeWin, closedTabData);
-  yield promiseBrowserEvent(browser, "load");
+  yield promiseBrowserEvent(browser, "load", { resolveAtNextTick: true });
 
   // Check the form data.
   is(getInputValue(browser, {id: "txt"}), OUTER_VALUE, "outer value restored correctly");
   is(getInputValue(browser, {id: "txt", frame: 0}), INNER_VALUE, "inner value restored correctly");
 
   // Remove the tab.
   gBrowserApp.closeTab(gBrowserApp.getTabForBrowser(browser));
 });
--- a/security/apps/AppSignatureVerification.cpp
+++ b/security/apps/AppSignatureVerification.cpp
@@ -8,16 +8,17 @@
 
 #include "AppTrustDomain.h"
 #include "CryptoTask.h"
 #include "NSSCertDBTrustDomain.h"
 #include "ScopedNSSTypes.h"
 #include "SharedCertVerifier.h"
 #include "certdb.h"
 #include "cms.h"
+#include "cosec.h"
 #include "mozilla/Base64.h"
 #include "mozilla/Casting.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Unused.h"
 #include "nsCOMPtr.h"
@@ -338,18 +339,20 @@ ReadLine(/*in/out*/ const char* & nextLi
     }
 
     ++nextLineStart; // skip space and keep appending
   }
 }
 
 // The header strings are defined in the JAR specification.
 #define JAR_MF_SEARCH_STRING "(M|/M)ETA-INF/(M|m)(ANIFEST|anifest).(MF|mf)$"
+#define JAR_COSE_MF_SEARCH_STRING "(M|/M)ETA-INF/cose.manifest$"
 #define JAR_SF_SEARCH_STRING "(M|/M)ETA-INF/*.(SF|sf)$"
 #define JAR_RSA_SEARCH_STRING "(M|/M)ETA-INF/*.(RSA|rsa)$"
+#define JAR_COSE_SEARCH_STRING "(M|/M)ETA-INF/cose.sig$"
 #define JAR_META_DIR "META-INF"
 #define JAR_MF_HEADER "Manifest-Version: 1.0"
 #define JAR_SF_HEADER "Signature-Version: 1.0"
 
 nsresult
 ParseAttribute(const nsAutoCString & curLine,
                /*out*/ nsAutoCString & attrName,
                /*out*/ nsAutoCString & attrValue)
@@ -835,27 +838,476 @@ VerifySignature(AppTrustedRoot trustedRo
     return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
   }
 
   return MapSECStatus(
     NSS_CMSSignerInfo_Verify(signerInfo, const_cast<SECItem*>(detachedDigest),
                              &pkcs7DataOid));
 }
 
+class CoseVerificationContext
+{
+public:
+  explicit CoseVerificationContext(AppTrustedRoot aTrustedRoot)
+    : mTrustedRoot(aTrustedRoot)
+    , mCertDER(nullptr)
+    , mCertDERLen(0)
+  {
+  }
+  ~CoseVerificationContext() {}
+
+  AppTrustedRoot GetTrustedRoot() { return mTrustedRoot; }
+  nsresult SetCert(SECItem* aCertDER)
+  {
+    mCertDERLen = aCertDER->len;
+    mCertDER = MakeUnique<uint8_t[]>(mCertDERLen);
+    if (!mCertDER) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+    memcpy(mCertDER.get(), aCertDER->data, mCertDERLen);
+    return NS_OK;
+  }
+  uint8_t* GetCert() { return mCertDER.get(); }
+  unsigned int GetCertLen() { return mCertDERLen; }
+
+private:
+  AppTrustedRoot mTrustedRoot;
+  UniquePtr<uint8_t[]> mCertDER;
+  unsigned int mCertDERLen;
+};
+
+// Verification function called from cose-rust.
+// Returns true if everything goes well and the signature and certificate chain
+// are good, false in any other case.
+bool
+CoseVerificationCallback(const uint8_t* aPayload,
+                         size_t aPayloadLen,
+                         const uint8_t** aCertChain,
+                         size_t aCertChainLen,
+                         const size_t* aCertsLen,
+                         const uint8_t* aEECert,
+                         size_t aEECertLen,
+                         const uint8_t* aSignature,
+                         size_t aSignatureLen,
+                         uint8_t aSignatureAlgorithm,
+                         void* ctx)
+{
+  if (!ctx || !aPayload || !aEECert || !aSignature) {
+    return false;
+  }
+  // The ctx here is a pointer to a CoseVerificationContext object
+  CoseVerificationContext* context = static_cast<CoseVerificationContext*>(ctx);
+  AppTrustedRoot aTrustedRoot = context->GetTrustedRoot();
+
+  CK_MECHANISM_TYPE mechanism;
+  SECOidTag oid;
+  uint32_t hash_length;
+  SECItem param = { siBuffer, nullptr, 0 };
+  switch (aSignatureAlgorithm) {
+    case ES256:
+      mechanism = CKM_ECDSA;
+      oid = SEC_OID_SHA256;
+      hash_length = SHA256_LENGTH;
+      break;
+    case ES384:
+      mechanism = CKM_ECDSA;
+      oid = SEC_OID_SHA384;
+      hash_length = SHA384_LENGTH;
+      break;
+    case ES512:
+      mechanism = CKM_ECDSA;
+      oid = SEC_OID_SHA512;
+      hash_length = SHA512_LENGTH;
+      break;
+    default:
+      return false;
+  }
+
+  uint8_t hashBuf[HASH_LENGTH_MAX];
+  SECStatus rv = PK11_HashBuf(oid, hashBuf, aPayload, aPayloadLen);
+  if (rv != SECSuccess) {
+    return false;
+  }
+  SECItem hashItem = { siBuffer, hashBuf, hash_length };
+  CERTCertDBHandle* dbHandle = CERT_GetDefaultCertDB();
+  if (!dbHandle) {
+    return false;
+  }
+  SECItem derCert = { siBuffer,
+                      const_cast<uint8_t*>(aEECert),
+                      static_cast<unsigned int>(aEECertLen) };
+  UniqueCERTCertificate cert(
+    CERT_NewTempCertificate(dbHandle, &derCert, nullptr, false, true));
+  if (!cert) {
+    return false;
+  }
+  UniqueSECKEYPublicKey key(CERT_ExtractPublicKey(cert.get()));
+  if (!key) {
+    return false;
+  }
+  SECItem signatureItem = { siBuffer,
+                             const_cast<uint8_t*>(aSignature),
+                             static_cast<unsigned int>(aSignatureLen) };
+  rv = PK11_VerifyWithMechanism(
+    key.get(), mechanism, &param, &signatureItem, &hashItem, nullptr);
+  if (rv != SECSuccess) {
+    return false;
+  }
+
+  // Load intermediate certs into NSS so we can verify the cert chain.
+  UniqueCERTCertList tempCerts(CERT_NewCertList());
+  for (size_t i = 0; i < aCertChainLen; ++i) {
+    SECItem derCert = { siBuffer,
+                        const_cast<uint8_t*>(aCertChain[i]),
+                        static_cast<unsigned int>(aCertsLen[i]) };
+    UniqueCERTCertificate tempCert(
+      CERT_NewTempCertificate(dbHandle, &derCert, nullptr, false, true));
+    // Skip certs that we can't parse. If it was one we needed, the verification
+    // will fail later.
+    if (!tempCert) {
+      continue;
+    }
+    if (CERT_AddCertToListTail(tempCerts.get(), tempCert.get()) != SECSuccess) {
+      return false;
+    }
+    Unused << tempCert.release();
+  }
+
+  UniqueCERTCertList builtChain;
+  nsresult nrv = VerifyCertificate(cert.get(), aTrustedRoot, builtChain);
+  bool result = true;
+  if (NS_FAILED(nrv)) {
+    result = false;
+  }
+
+  // Passing back the signing certificate in form of the DER cert.
+  nrv = context->SetCert(&cert->derCert);
+  if (NS_FAILED(nrv)) {
+    result = false;
+  }
+
+  return result;
+}
+
+nsresult
+VerifyAppManifest(SECOidTag aDigestToUse, nsCOMPtr<nsIZipReader> aZip,
+                  nsTHashtable<nsCStringHashKey>& aIgnoredFiles,
+                  const SECItem& aManifestBuffer)
+{
+  // Allocate the I/O buffer only once per JAR, instead of once per entry, in
+  // order to minimize malloc/free calls and in order to avoid fragmenting
+  // memory.
+  ScopedAutoSECItem buf(128 * 1024);
+
+  nsTHashtable<nsCStringHashKey> items;
+
+  nsresult rv = ParseMF(BitwiseCast<char*, unsigned char*>(aManifestBuffer.data),
+    aZip, aDigestToUse, items, buf);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  // Verify every entry in the file.
+  nsCOMPtr<nsIUTF8StringEnumerator> entries;
+  rv = aZip->FindEntries(EmptyCString(), getter_AddRefs(entries));
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  if (!entries) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  for (;;) {
+    bool hasMore;
+    rv = entries->HasMore(&hasMore);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (!hasMore) {
+      break;
+    }
+
+    nsAutoCString entryFilename;
+    rv = entries->GetNext(entryFilename);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    MOZ_LOG(gPIPNSSLog,
+            LogLevel::Debug,
+            ("Verifying digests for %s", entryFilename.get()));
+
+    if (entryFilename.Length() == 0) {
+      return NS_ERROR_SIGNED_JAR_ENTRY_INVALID;
+    }
+
+    // The files that comprise the signature mechanism are not covered by the
+    // signature. Ignore these files.
+    if (aIgnoredFiles.Contains(entryFilename)) {
+      continue;
+    }
+
+    // Entries with names that end in "/" are directory entries, which are not
+    // signed.
+    //
+    // Since bug 1415991 we don't support unpacked JARs. The "/" entries are
+    // therefore harmless.
+    if (entryFilename.Last() == '/') {
+      continue;
+    }
+
+    nsCStringHashKey* item = items.GetEntry(entryFilename);
+    if (!item) {
+      return NS_ERROR_SIGNED_JAR_UNSIGNED_ENTRY;
+    }
+
+    // Remove the item so we can check for leftover items later
+    items.RemoveEntry(item);
+  }
+
+  // We verified that every entry that we require to be signed is signed. But,
+  // were there any missing entries--that is, entries that are mentioned in the
+  // manifest but missing from the archive?
+  if (items.Count() != 0) {
+    return NS_ERROR_SIGNED_JAR_ENTRY_MISSING;
+  }
+
+  return NS_OK;
+}
+
 // This corresponds to the preference "security.signed_app_signatures.policy".
-enum class SignaturePolicy {
-  PKCS7WithSHA1OrSHA256 = 0,
-  PKCS7WithSHA256 = 1,
+// The lowest order bit determines which PKCS#7 algorithms are accepted.
+// xxx_0_: SHA-1 and/or SHA-256 PKCS#7 allowed
+// xxx_1_: SHA-256 PKCS#7 allowed
+// The next two bits determine whether COSE is required and PKCS#7 is allowed
+// x_00_x: COSE disabled, ignore files, PKCS#7 must verify
+// x_01_x: COSE is verified if present, PKCS#7 must verify
+// x_10_x: COSE is required, PKCS#7 must verify if present
+// x_11_x: COSE is required, PKCS#7 disabled (fail when present)
+class SignaturePolicy
+{
+public:
+  explicit SignaturePolicy(int32_t preference)
+    : mProcessCose(true)
+    , mCoseRequired(false)
+    , mProcessPK7(true)
+    , mPK7Required(true)
+    , mSHA1Allowed(true)
+    , mSHA256Allowed(true)
+  {
+    mCoseRequired = (preference & 0b100) != 0;
+    mProcessCose = (preference & 0b110) != 0;
+    mPK7Required = (preference & 0b100) == 0;
+    mProcessPK7 = (preference & 0b110) != 0b110;
+    if ((preference & 0b1) == 0) {
+      mSHA1Allowed = true;
+      mSHA256Allowed = true;
+    } else {
+      mSHA1Allowed = false;
+      mSHA256Allowed = true;
+    }
+  }
+  ~SignaturePolicy()
+  {
+  }
+  bool ProcessCOSE() { return mProcessCose; }
+  bool COSERequired() { return mCoseRequired; }
+  bool PK7Required() { return mPK7Required; }
+  bool ProcessPK7() { return mProcessPK7; }
+  bool IsPK7HashAllowed(SECOidTag aHashAlg)
+  {
+    if (aHashAlg == SEC_OID_SHA256 && mSHA256Allowed) {
+      return true;
+    }
+    if (aHashAlg == SEC_OID_SHA1 && mSHA1Allowed) {
+      return true;
+    }
+    return false;
+  }
+
+private:
+  bool mProcessCose;
+  bool mCoseRequired;
+  bool mProcessPK7;
+  bool mPK7Required;
+  bool mSHA1Allowed;
+  bool mSHA256Allowed;
 };
 
 nsresult
-OpenSignedAppFile(AppTrustedRoot aTrustedRoot, nsIFile* aJarFile,
+VerifyCOSESignature(AppTrustedRoot aTrustedRoot, nsIZipReader* aZip,
+                    SignaturePolicy& aPolicy,
+                    nsTHashtable<nsCStringHashKey>& aIgnoredFiles,
+                    /* out */ bool& aVerified,
+                    /* out */ UniqueSECItem* aCoseCertItem)
+{
+  NS_ENSURE_ARG_POINTER(aZip);
+  NS_ENSURE_ARG_POINTER(aCoseCertItem);
+  bool required = aPolicy.COSERequired();
+  aVerified = false;
+
+  // Read COSE signature file.
+  nsAutoCString coseFilename;
+  ScopedAutoSECItem coseBuffer;
+  nsresult rv = FindAndLoadOneEntry(
+    aZip, NS_LITERAL_CSTRING(JAR_COSE_SEARCH_STRING), coseFilename, coseBuffer);
+  if (NS_FAILED(rv)) {
+    return required ? NS_ERROR_SIGNED_JAR_WRONG_SIGNATURE : NS_OK;
+  }
+
+  // Verify COSE signature.
+  nsAutoCString mfFilename;
+  ScopedAutoSECItem manifestBuffer;
+  rv = FindAndLoadOneEntry(aZip,
+                           NS_LITERAL_CSTRING(JAR_COSE_MF_SEARCH_STRING),
+                           mfFilename,
+                           manifestBuffer);
+  if (NS_FAILED(rv)) {
+    return required ? NS_ERROR_SIGNED_JAR_WRONG_SIGNATURE : rv;
+  }
+  MOZ_ASSERT(manifestBuffer.len >= 1);
+  MOZ_ASSERT(coseBuffer.len >= 1);
+  CoseVerificationContext context(aTrustedRoot);
+  bool coseVerification = verify_cose_signature_ffi(manifestBuffer.data,
+                                                    manifestBuffer.len - 1,
+                                                    coseBuffer.data,
+                                                    coseBuffer.len - 1,
+                                                    &context,
+                                                    CoseVerificationCallback);
+  if (!coseVerification) {
+    return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID;
+  }
+  // CoseVerificationCallback sets the context certificate to the first cert
+  // it encounters.
+  const SECItem derCert = { siBuffer, context.GetCert(), context.GetCertLen() };
+  aCoseCertItem->reset(SECITEM_DupItem(&derCert));
+  if (!aCoseCertItem) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // aIgnoredFiles contains the PKCS#7 manifest and signature files iff the
+  // PKCS#7 verification was successful.
+  aIgnoredFiles.PutEntry(mfFilename);
+  aIgnoredFiles.PutEntry(coseFilename);
+  rv = VerifyAppManifest(SEC_OID_SHA256, aZip, aIgnoredFiles, manifestBuffer);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  aVerified = true;
+  return NS_OK;
+}
+
+nsresult
+VerifyPK7Signature(AppTrustedRoot aTrustedRoot, nsIZipReader* aZip,
+                   SignaturePolicy& aPolicy,
+                   /* out */ nsTHashtable<nsCStringHashKey>& aIgnoredFiles,
+                   /* out */ bool& aVerified,
+                   /* out */ UniqueCERTCertList& aBuiltChain)
+{
+  NS_ENSURE_ARG_POINTER(aZip);
+  bool required = aPolicy.PK7Required();
+  aVerified = false;
+
+  // Signature (RSA) file
+  nsAutoCString sigFilename;
+  ScopedAutoSECItem sigBuffer;
+  nsresult rv = FindAndLoadOneEntry(
+    aZip, nsLiteralCString(JAR_RSA_SEARCH_STRING), sigFilename, sigBuffer);
+  if (NS_FAILED(rv)) {
+    return required ? NS_ERROR_SIGNED_JAR_NOT_SIGNED : NS_OK;
+  }
+
+  // Signature (SF) file
+  nsAutoCString sfFilename;
+  ScopedAutoSECItem sfBuffer;
+  rv = FindAndLoadOneEntry(
+    aZip, NS_LITERAL_CSTRING(JAR_SF_SEARCH_STRING), sfFilename, sfBuffer);
+  if (NS_FAILED(rv)) {
+    return required ? NS_ERROR_SIGNED_JAR_MANIFEST_INVALID : NS_OK;
+  }
+
+  // Calculate both the SHA-1 and SHA-256 hashes of the signature file - we
+  // don't know what algorithm the PKCS#7 signature used.
+  Digest sfCalculatedSHA1Digest;
+  rv = sfCalculatedSHA1Digest.DigestBuf(
+    SEC_OID_SHA1, sfBuffer.data, sfBuffer.len - 1);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  Digest sfCalculatedSHA256Digest;
+  rv = sfCalculatedSHA256Digest.DigestBuf(
+    SEC_OID_SHA256, sfBuffer.data, sfBuffer.len - 1);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  // Verify PKCS#7 signature.
+  // If we get here, the signature has to verify even if PKCS#7 is not required.
+  sigBuffer.type = siBuffer;
+  SECOidTag digestToUse;
+  rv = VerifySignature(aTrustedRoot,
+                       sigBuffer,
+                       sfCalculatedSHA1Digest.get(),
+                       sfCalculatedSHA256Digest.get(),
+                       digestToUse,
+                       aBuiltChain);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  // Check the digest used for the signature against the policy.
+  if (!aPolicy.IsPK7HashAllowed(digestToUse)) {
+    return NS_ERROR_SIGNED_JAR_WRONG_SIGNATURE;
+  }
+
+  nsAutoCString mfDigest;
+  rv = ParseSF(
+    BitwiseCast<char*, unsigned char*>(sfBuffer.data), digestToUse, mfDigest);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  // Read PK7 manifest (MF) file.
+  ScopedAutoSECItem manifestBuffer;
+  Digest mfCalculatedDigest;
+  nsAutoCString mfFilename;
+  rv = FindAndLoadOneEntry(aZip,
+                           NS_LITERAL_CSTRING(JAR_MF_SEARCH_STRING),
+                           mfFilename,
+                           manifestBuffer,
+                           digestToUse,
+                           &mfCalculatedDigest);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  nsDependentCSubstring calculatedDigest(
+    DigestToDependentString(mfCalculatedDigest));
+  if (!mfDigest.Equals(calculatedDigest)) {
+    return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID;
+  }
+
+  // Verify PKCS7 manifest file hashes.
+  aIgnoredFiles.PutEntry(sfFilename);
+  aIgnoredFiles.PutEntry(sigFilename);
+  aIgnoredFiles.PutEntry(mfFilename);
+  rv = VerifyAppManifest(digestToUse, aZip, aIgnoredFiles, manifestBuffer);
+  if (NS_FAILED(rv)) {
+    aIgnoredFiles.Clear();
+    return rv;
+  }
+
+  aVerified = true;
+  return NS_OK;
+}
+
+nsresult
+OpenSignedAppFile(AppTrustedRoot aTrustedRoot,
+                  nsIFile* aJarFile,
                   SignaturePolicy aPolicy,
-                  /*out, optional */ nsIZipReader** aZipReader,
-                  /*out, optional */ nsIX509Cert** aSignerCert)
+                  /* out, optional */ nsIZipReader** aZipReader,
+                  /* out, optional */ nsIX509Cert** aSignerCert)
 {
   NS_ENSURE_ARG_POINTER(aJarFile);
 
   if (aZipReader) {
     *aZipReader = nullptr;
   }
 
   if (aSignerCert) {
@@ -866,191 +1318,86 @@ OpenSignedAppFile(AppTrustedRoot aTruste
 
   static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
   nsCOMPtr<nsIZipReader> zip = do_CreateInstance(kZipReaderCID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = zip->Open(aJarFile);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Signature (RSA) file
-  nsAutoCString sigFilename;
-  ScopedAutoSECItem sigBuffer;
-  rv = FindAndLoadOneEntry(zip, nsLiteralCString(JAR_RSA_SEARCH_STRING),
-                           sigFilename, sigBuffer);
-  if (NS_FAILED(rv)) {
-    return NS_ERROR_SIGNED_JAR_NOT_SIGNED;
-  }
-
-  // Signature (SF) file
-  nsAutoCString sfFilename;
-  ScopedAutoSECItem sfBuffer;
-  rv = FindAndLoadOneEntry(zip, NS_LITERAL_CSTRING(JAR_SF_SEARCH_STRING),
-                           sfFilename, sfBuffer);
-  if (NS_FAILED(rv)) {
-    return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID;
-  }
-
-  // Calculate both the SHA-1 and SHA-256 hashes of the signature file - we
-  // don't know what algorithm the PKCS#7 signature used.
-  Digest sfCalculatedSHA1Digest;
-  rv = sfCalculatedSHA1Digest.DigestBuf(SEC_OID_SHA1, sfBuffer.data,
-                                        sfBuffer.len - 1);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  Digest sfCalculatedSHA256Digest;
-  rv = sfCalculatedSHA256Digest.DigestBuf(SEC_OID_SHA256, sfBuffer.data,
-                                          sfBuffer.len - 1);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
+  bool pk7Verified = false;
+  bool coseVerified = false;
+  nsTHashtable<nsCStringHashKey> ignoredFiles;
+  UniqueCERTCertList pk7BuiltChain;
+  UniqueSECItem coseCertItem;
 
-  sigBuffer.type = siBuffer;
-  UniqueCERTCertList builtChain;
-  SECOidTag digestToUse;
-  rv = VerifySignature(aTrustedRoot, sigBuffer, sfCalculatedSHA1Digest.get(),
-                       sfCalculatedSHA256Digest.get(), digestToUse, builtChain);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
-  switch (aPolicy) {
-    case SignaturePolicy::PKCS7WithSHA256:
-      if (digestToUse != SEC_OID_SHA256) {
-        return NS_ERROR_SIGNED_JAR_WRONG_SIGNATURE;
-      }
-      break;
-    case SignaturePolicy::PKCS7WithSHA1OrSHA256:
-      break;
-  }
-
-  nsAutoCString mfDigest;
-  rv = ParseSF(BitwiseCast<char*, unsigned char*>(sfBuffer.data), digestToUse,
-               mfDigest);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
-  // Manifest (MF) file
-  nsAutoCString mfFilename;
-  ScopedAutoSECItem manifestBuffer;
-  Digest mfCalculatedDigest;
-  rv = FindAndLoadOneEntry(zip, NS_LITERAL_CSTRING(JAR_MF_SEARCH_STRING),
-                           mfFilename, manifestBuffer, digestToUse,
-                           &mfCalculatedDigest);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
-  nsDependentCSubstring calculatedDigest(
-    DigestToDependentString(mfCalculatedDigest));
-  if (!mfDigest.Equals(calculatedDigest)) {
-    return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID;
+  // First we have to verify the PKCS#7 signature if there is one.
+  // This signature covers all files (except for the signature files itself),
+  // including the COSE signature files. Only when this verification is
+  // successful the respective files will be ignored in the subsequent COSE
+  // signature verification.
+  if (aPolicy.ProcessPK7()) {
+    rv = VerifyPK7Signature(
+      aTrustedRoot, zip, aPolicy, ignoredFiles, pk7Verified, pk7BuiltChain);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
   }
 
-  // Allocate the I/O buffer only once per JAR, instead of once per entry, in
-  // order to minimize malloc/free calls and in order to avoid fragmenting
-  // memory.
-  ScopedAutoSECItem buf(128 * 1024);
-
-  nsTHashtable<nsCStringHashKey> items;
-
-  rv = ParseMF(BitwiseCast<char*, unsigned char*>(manifestBuffer.data), zip,
-               digestToUse, items, buf);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
-  // Verify every entry in the file.
-  nsCOMPtr<nsIUTF8StringEnumerator> entries;
-  rv = zip->FindEntries(EmptyCString(), getter_AddRefs(entries));
-  if (NS_SUCCEEDED(rv) && !entries) {
-    rv = NS_ERROR_UNEXPECTED;
-  }
-  if (NS_FAILED(rv)) {
-    return rv;
+  if (aPolicy.ProcessCOSE()) {
+    rv = VerifyCOSESignature(
+      aTrustedRoot, zip, aPolicy, ignoredFiles, coseVerified, &coseCertItem);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
   }
 
-  for (;;) {
-    bool hasMore;
-    rv = entries->HasMore(&hasMore);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (!hasMore) {
-      break;
-    }
-
-    nsAutoCString entryFilename;
-    rv = entries->GetNext(entryFilename);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Verifying digests for %s",
-           entryFilename.get()));
-
-    // The files that comprise the signature mechanism are not covered by the
-    // signature.
-    //
-    // XXX: This is OK for a single signature, but doesn't work for
-    // multiple signatures, because the metadata for the other signatures
-    // is not signed either.
-    if (entryFilename == mfFilename ||
-        entryFilename == sfFilename ||
-        entryFilename == sigFilename) {
-      continue;
-    }
-
-    if (entryFilename.Length() == 0) {
-      return NS_ERROR_SIGNED_JAR_ENTRY_INVALID;
-    }
-
-    // Entries with names that end in "/" are directory entries, which are not
-    // signed.
-    //
-    // XXX: As long as we don't unpack the JAR into the filesystem, the "/"
-    // entries are harmless. But, it is not clear what the security
-    // implications of directory entries are if/when we were to unpackage the
-    // JAR into the filesystem.
-    if (entryFilename[entryFilename.Length() - 1] == '/') {
-      continue;
-    }
-
-    nsCStringHashKey * item = items.GetEntry(entryFilename);
-    if (!item) {
-      return NS_ERROR_SIGNED_JAR_UNSIGNED_ENTRY;
-    }
-
-    // Remove the item so we can check for leftover items later
-    items.RemoveEntry(item);
-  }
-
-  // We verified that every entry that we require to be signed is signed. But,
-  // were there any missing entries--that is, entries that are mentioned in the
-  // manifest but missing from the archive?
-  if (items.Count() != 0) {
-    return NS_ERROR_SIGNED_JAR_ENTRY_MISSING;
+  if ((aPolicy.PK7Required() && !pk7Verified) ||
+      (aPolicy.COSERequired() && !coseVerified)) {
+    return NS_ERROR_SIGNED_JAR_WRONG_SIGNATURE;
   }
 
   // Return the reader to the caller if they want it
   if (aZipReader) {
     zip.forget(aZipReader);
   }
 
   // Return the signer's certificate to the reader if they want it.
   // XXX: We should return an nsIX509CertList with the whole validated chain.
   if (aSignerCert) {
-    CERTCertListNode* signerCertNode = CERT_LIST_HEAD(builtChain);
-    if (!signerCertNode || CERT_LIST_END(signerCertNode, builtChain) ||
-        !signerCertNode->cert) {
-      return NS_ERROR_FAILURE;
+    // The COSE certificate is authoritative.
+    if (aPolicy.COSERequired() || (coseCertItem && coseCertItem->len != 0)) {
+      if (!coseCertItem || coseCertItem->len == 0) {
+        return NS_ERROR_FAILURE;
+      }
+      CERTCertDBHandle* dbHandle = CERT_GetDefaultCertDB();
+      if (!dbHandle) {
+        return NS_ERROR_FAILURE;
+      }
+      UniqueCERTCertificate cert(CERT_NewTempCertificate(
+        dbHandle, coseCertItem.get(), nullptr, false, true));
+      if (!cert) {
+        return NS_ERROR_FAILURE;
+      }
+      nsCOMPtr<nsIX509Cert> signerCert = nsNSSCertificate::Create(cert.get());
+      if (!signerCert) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+      signerCert.forget(aSignerCert);
+    } else {
+      CERTCertListNode* signerCertNode = CERT_LIST_HEAD(pk7BuiltChain);
+      if (!signerCertNode || CERT_LIST_END(signerCertNode, pk7BuiltChain) ||
+          !signerCertNode->cert) {
+        return NS_ERROR_FAILURE;
+      }
+      nsCOMPtr<nsIX509Cert> signerCert =
+        nsNSSCertificate::Create(signerCertNode->cert);
+      NS_ENSURE_TRUE(signerCert, NS_ERROR_OUT_OF_MEMORY);
+      signerCert.forget(aSignerCert);
     }
-    nsCOMPtr<nsIX509Cert> signerCert =
-      nsNSSCertificate::Create(signerCertNode->cert);
-    NS_ENSURE_TRUE(signerCert, NS_ERROR_OUT_OF_MEMORY);
-    signerCert.forget(aSignerCert);
   }
 
   return NS_OK;
 }
 
 class OpenSignedAppFileTask final : public CryptoTask
 {
 public:
@@ -1085,44 +1432,34 @@ private:
   const AppTrustedRoot mTrustedRoot;
   const nsCOMPtr<nsIFile> mJarFile;
   const SignaturePolicy mPolicy;
   nsMainThreadPtrHandle<nsIOpenSignedAppFileCallback> mCallback;
   nsCOMPtr<nsIZipReader> mZipReader; // out
   nsCOMPtr<nsIX509Cert> mSignerCert; // out
 };
 
-static const SignaturePolicy sDefaultSignaturePolicy =
-  SignaturePolicy::PKCS7WithSHA1OrSHA256;
+static const int32_t sDefaultSignaturePolicy = 0b10;
 
 } // unnamed namespace
 
 NS_IMETHODIMP
 nsNSSCertificateDB::OpenSignedAppFileAsync(
   AppTrustedRoot aTrustedRoot, nsIFile* aJarFile,
   nsIOpenSignedAppFileCallback* aCallback)
 {
   NS_ENSURE_ARG_POINTER(aJarFile);
   NS_ENSURE_ARG_POINTER(aCallback);
   if (!NS_IsMainThread()) {
     return NS_ERROR_NOT_SAME_THREAD;
   }
-  SignaturePolicy policy =
-    static_cast<SignaturePolicy>(
-      Preferences::GetInt("security.signed_app_signatures.policy",
-                          static_cast<int32_t>(sDefaultSignaturePolicy)));
-  switch (policy) {
-    case SignaturePolicy::PKCS7WithSHA1OrSHA256:
-      break;
-    case SignaturePolicy::PKCS7WithSHA256:
-      break;
-    default:
-      policy = sDefaultSignaturePolicy;
-      break;
-  }
+  int32_t policyInt =
+    Preferences::GetInt("security.signed_app_signatures.policy",
+                        static_cast<int32_t>(sDefaultSignaturePolicy));
+  SignaturePolicy policy(policyInt);
   RefPtr<OpenSignedAppFileTask> task(new OpenSignedAppFileTask(aTrustedRoot,
                                                                aJarFile,
                                                                policy,
                                                                aCallback));
   return task->Dispatch("SignedJAR");
 }
 
 NS_IMETHODIMP
--- a/security/apps/moz.build
+++ b/security/apps/moz.build
@@ -13,16 +13,17 @@ UNIFIED_SOURCES += [
 ]
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/security/certverifier',
     '/security/manager/ssl',
     '/security/pkix/include',
+    '/third_party/rust/cose-c/include',
 ]
 
 DEFINES['NSS_ENABLE_ECC'] = 'True'
 for var in ('DLL_PREFIX', 'DLL_SUFFIX'):
     DEFINES[var] = '"%s"' % CONFIG[var]
 
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += [
--- a/security/manager/ssl/security-prefs.js
+++ b/security/manager/ssl/security-prefs.js
@@ -63,20 +63,27 @@ pref("security.OCSP.timeoutMilliseconds.
 
 pref("security.pki.cert_short_lifetime_in_days", 10);
 // NB: Changes to this pref affect CERT_CHAIN_SHA1_POLICY_STATUS telemetry.
 // See the comment in CertVerifier.cpp.
 // 3 = only allow SHA-1 for certificates issued by an imported root.
 pref("security.pki.sha1_enforcement_level", 3);
 
 // This preference controls what signature algorithms are accepted for signed
-// apps (i.e. add-ons).
-// 0: SHA-1 and/or SHA-256 PKCS#7 allowed
-// 1: SHA-256 PKCS#7 allowed
-pref("security.signed_app_signatures.policy", 0);
+// apps (i.e. add-ons). The number is interpreted as a bit mask with the
+// following semantic:
+// The lowest order bit determines which PKCS#7 algorithms are accepted.
+// xxx_0_: SHA-1 and/or SHA-256 PKCS#7 allowed
+// xxx_1_: SHA-256 PKCS#7 allowed
+// The next two bits determine whether COSE is required and PKCS#7 is allowed
+// x_00_x: COSE disabled, ignore files, PKCS#7 must verify
+// x_01_x: COSE is verified if present, PKCS#7 must verify
+// x_10_x: COSE is required, PKCS#7 must verify if present
+// x_11_x: COSE is required, PKCS#7 disabled (fail when present)
+pref("security.signed_app_signatures.policy", 2);
 
 // security.pki.name_matching_mode controls how the platform matches hostnames
 // to name information in TLS certificates. The possible values are:
 // 0: always fall back to the subject common name if necessary (as in, if the
 //    subject alternative name extension is either not present or does not
 //    contain any DNS names or IP addresses)
 // 1: fall back to the subject common name for certificates valid before 23
 //    August 2016 if necessary
--- a/security/manager/ssl/tests/gtest/CoseTest.cpp
+++ b/security/manager/ssl/tests/gtest/CoseTest.cpp
@@ -103,22 +103,22 @@ const uint8_t SIGNATURE[] = {
   0xc4, 0x11, 0x9d, 0x07, 0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7,
   0x99, 0x1b, 0x7b, 0x2d, 0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0x30,
   0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48,
   0x00, 0x30, 0x45, 0x02, 0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50, 0xcd,
   0x5d, 0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2, 0x73, 0x75,
   0x5f, 0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02, 0x21,
   0x00, 0xff, 0x81, 0xbe, 0xa8, 0x0d, 0x03, 0x36, 0x6b, 0x75, 0xe2, 0x70, 0x6a,
   0xac, 0x07, 0x2e, 0x4c, 0xdc, 0xf9, 0xc5, 0x89, 0xc1, 0xcf, 0x88, 0xc2, 0xc8,
-  0x2a, 0x32, 0xf5, 0x42, 0x0c, 0xfa, 0x0b, 0xa0, 0x58, 0x40, 0xb7, 0x50, 0xae,
-  0x12, 0x41, 0xb2, 0x62, 0x28, 0x80, 0x0b, 0xaa, 0x99, 0xec, 0x5f, 0x1c, 0x91,
-  0x2f, 0xd8, 0x65, 0xd0, 0x1c, 0x38, 0x7c, 0x37, 0x63, 0x6d, 0xfa, 0x67, 0x9d,
-  0x21, 0xff, 0x54, 0x98, 0xf8, 0x97, 0x63, 0xc2, 0x2e, 0x3c, 0xfa, 0x25, 0x28,
-  0xec, 0x2c, 0x96, 0x8c, 0xca, 0xfc, 0x94, 0xd0, 0xc2, 0x19, 0x28, 0x28, 0x43,
-  0xe6, 0x64, 0xd4, 0x09, 0x2b, 0x0f, 0x01, 0xc3, 0x6e
+  0x2a, 0x32, 0xf5, 0x42, 0x0c, 0xfa, 0x0b, 0xa0, 0x58, 0x40, 0x1e, 0x6e, 0x08,
+  0xdf, 0x8f, 0x4f, 0xd6, 0xab, 0x23, 0xae, 0x84, 0xaa, 0xf3, 0x43, 0x35, 0x9a,
+  0x53, 0xb9, 0x8b, 0xf9, 0x81, 0xa1, 0xbc, 0x1e, 0x5c, 0x57, 0x5c, 0x0a, 0x20,
+  0x37, 0xf4, 0x3d, 0x11, 0x08, 0xa0, 0x97, 0x4b, 0x68, 0xa4, 0x0f, 0x80, 0xe9,
+  0x96, 0x30, 0x04, 0x24, 0x0e, 0x81, 0x3d, 0x2a, 0x8a, 0x64, 0x40, 0x61, 0x5a,
+  0x19, 0x00, 0xff, 0x74, 0x40, 0x71, 0x82, 0x65, 0xe9
 };
 
 // This is a COSE signature generated with the cose rust library (see
 // third-party/rust/cose). The payload is signed twice; with the P256 and the
 // RSA key from pykey.py.
 const uint8_t SIGNATURE_ES256_PS256[] = {
   0xd8, 0x62, 0x84, 0x59, 0x08, 0x52, 0xa1, 0x04, 0x84, 0x59, 0x01, 0x4e, 0x30,
   0x82, 0x01, 0x4a, 0x30, 0x81, 0xf1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14,
@@ -303,22 +303,22 @@ const uint8_t SIGNATURE_ES256_PS256[] = 
   0x11, 0x9d, 0x07, 0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99,
   0x1b, 0x7b, 0x2d, 0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0x30, 0x0a,
   0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00,
   0x30, 0x45, 0x02, 0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50, 0xcd, 0x5d,
   0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2, 0x73, 0x75, 0x5f,
   0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02, 0x21, 0x00,
   0xff, 0x81, 0xbe, 0xa8, 0x0d, 0x03, 0x36, 0x6b, 0x75, 0xe2, 0x70, 0x6a, 0xac,
   0x07, 0x2e, 0x4c, 0xdc, 0xf9, 0xc5, 0x89, 0xc1, 0xcf, 0x88, 0xc2, 0xc8, 0x2a,
-  0x32, 0xf5, 0x42, 0x0c, 0xfa, 0x0b, 0xa0, 0x58, 0x40, 0xfa, 0xc6, 0xb7, 0xae,
-  0xec, 0x0b, 0x0b, 0xe2, 0xef, 0xae, 0xf7, 0x9d, 0x64, 0xe5, 0xaf, 0xbb, 0x2c,
-  0x4b, 0xe8, 0x7c, 0x61, 0xa9, 0x1e, 0xb9, 0x6d, 0x9c, 0xfa, 0xe3, 0x11, 0x77,
-  0xaf, 0x44, 0x9d, 0xc3, 0xa8, 0xa9, 0xbc, 0x58, 0xed, 0xc5, 0xe5, 0xa1, 0x92,
-  0x3b, 0x89, 0xa3, 0x3b, 0x1e, 0xbf, 0x6e, 0x33, 0x64, 0x21, 0x0b, 0x97, 0xee,
-  0xb7, 0xae, 0x84, 0x17, 0x5c, 0xff, 0x27, 0xa0, 0x83, 0x59, 0x02, 0xbb, 0xa2,
+  0x32, 0xf5, 0x42, 0x0c, 0xfa, 0x0b, 0xa0, 0x58, 0x40, 0xa3, 0xfb, 0x49, 0xe6,
+  0x45, 0x29, 0x64, 0x76, 0xeb, 0x9d, 0xbd, 0xf5, 0x38, 0x56, 0xbe, 0x6e, 0x31,
+  0x57, 0x73, 0xc1, 0x2d, 0x3e, 0xac, 0xee, 0xba, 0x55, 0x8e, 0x37, 0xd4, 0xea,
+  0x80, 0x25, 0x31, 0x99, 0x9f, 0x4a, 0xb0, 0xf9, 0xd8, 0xb0, 0xed, 0x74, 0xfc,
+  0x8c, 0x02, 0xf0, 0x9f, 0x95, 0xf1, 0xaa, 0x71, 0xcc, 0xd2, 0xe7, 0x1a, 0x6d,
+  0xd4, 0xed, 0xff, 0xf2, 0x78, 0x09, 0x83, 0x7e, 0x83, 0x59, 0x02, 0xbb, 0xa2,
   0x01, 0x38, 0x24, 0x04, 0x59, 0x02, 0xb3, 0x30, 0x82, 0x02, 0xaf, 0x30, 0x82,
   0x01, 0x99, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x07, 0x1c, 0x3b, 0x71,
   0x08, 0xbe, 0xd7, 0x9f, 0xfd, 0xaf, 0x26, 0xb6, 0x08, 0xa3, 0x99, 0x06, 0x77,
   0x69, 0x32, 0x7e, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
   0x01, 0x01, 0x0b, 0x30, 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04,
   0x03, 0x0c, 0x07, 0x69, 0x6e, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x22, 0x18,
   0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30,
   0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33, 0x31,
@@ -363,36 +363,36 @@ const uint8_t SIGNATURE_ES256_PS256[] = 
   0xd0, 0x67, 0xd2, 0x6b, 0x06, 0xfe, 0x60, 0x13, 0x42, 0x3d, 0xb7, 0xca, 0xcb,
   0xab, 0x7b, 0x5f, 0x5d, 0x01, 0x56, 0xd3, 0x99, 0x80, 0x0f, 0xde, 0x7f, 0x3a,
   0x61, 0x9c, 0xd3, 0x6b, 0x5e, 0xfe, 0xb5, 0xfc, 0x39, 0x8b, 0x8e, 0xf0, 0x8c,
   0x8b, 0x65, 0x46, 0x45, 0xff, 0x47, 0x8f, 0xd4, 0xdd, 0xae, 0xc9, 0x72, 0xc7,
   0x7f, 0x28, 0x86, 0xf1, 0xf7, 0x6e, 0xcb, 0x86, 0x03, 0xeb, 0x0c, 0x46, 0xe5,
   0xa0, 0x6b, 0xef, 0xd4, 0x5e, 0xa4, 0x0f, 0x53, 0xe1, 0xbc, 0xb4, 0xc9, 0x37,
   0x0e, 0x75, 0xdd, 0x93, 0xe8, 0x0f, 0x18, 0x0a, 0x02, 0x83, 0x17, 0x74, 0xbb,
   0x1a, 0x42, 0x5b, 0x63, 0x2c, 0x80, 0x80, 0xa6, 0x84, 0xa0, 0x59, 0x01, 0x00,
-  0x67, 0xbe, 0xe4, 0x81, 0xed, 0x1e, 0xce, 0x7d, 0x18, 0xf5, 0x85, 0xa2, 0xcb,
-  0x1d, 0x75, 0x6f, 0x8a, 0x34, 0xaa, 0x6b, 0x58, 0x91, 0xd2, 0xa4, 0x58, 0x4f,
-  0xe1, 0x8b, 0x6a, 0x36, 0xe1, 0x67, 0x23, 0x2c, 0x5d, 0x7e, 0x05, 0xe2, 0xa0,
-  0x18, 0xa8, 0x78, 0x7d, 0x85, 0xda, 0x07, 0x60, 0xc6, 0x8e, 0x44, 0x14, 0xad,
-  0xbc, 0x35, 0x2f, 0xf3, 0xd8, 0xda, 0x34, 0x65, 0x12, 0x45, 0x6a, 0xbe, 0x46,
-  0x53, 0x09, 0xc8, 0xcc, 0x96, 0x6b, 0x07, 0xd4, 0xc3, 0x4f, 0xd2, 0x7b, 0x88,
-  0xad, 0x10, 0x3b, 0x93, 0x3c, 0x9a, 0xc4, 0x1a, 0x98, 0x12, 0x2f, 0xf9, 0xc9,
-  0xb9, 0xd2, 0xda, 0x40, 0xe9, 0x9e, 0xd8, 0x74, 0x2f, 0x02, 0xf1, 0xf0, 0x9a,
-  0x31, 0x99, 0xb4, 0x82, 0xe1, 0x25, 0xee, 0x3f, 0xf9, 0xd5, 0xbb, 0x10, 0x8b,
-  0xff, 0x03, 0x0f, 0xcb, 0x96, 0x8f, 0x29, 0x51, 0x71, 0xfc, 0xe2, 0x0e, 0x9c,
-  0xf7, 0x3d, 0xc0, 0x95, 0xc6, 0x70, 0xfd, 0x8c, 0xb7, 0xf6, 0xa7, 0xfa, 0x7d,
-  0xd6, 0x44, 0x0b, 0xa3, 0xd3, 0x97, 0xf5, 0xcd, 0x6d, 0xc9, 0x17, 0xc6, 0xcb,
-  0xd5, 0x82, 0x01, 0x0e, 0xef, 0xb3, 0xbd, 0x33, 0x6e, 0x49, 0x57, 0xb1, 0x38,
-  0x57, 0x27, 0x91, 0x22, 0x5a, 0xeb, 0x02, 0x97, 0x53, 0xeb, 0x56, 0x01, 0xdc,
-  0xf9, 0xe9, 0x6c, 0x38, 0x7c, 0x0b, 0x1c, 0x7e, 0x19, 0xc7, 0x4b, 0x9d, 0x30,
-  0xad, 0x14, 0x2a, 0xb2, 0x07, 0x99, 0x80, 0x40, 0x42, 0x82, 0x49, 0x4e, 0xb5,
-  0x1a, 0x49, 0xa3, 0x31, 0x7f, 0xd9, 0x78, 0xd1, 0x08, 0x39, 0xaf, 0x0d, 0xeb,
-  0x8a, 0x93, 0x43, 0xab, 0x3d, 0x3f, 0x9b, 0xe3, 0x25, 0x3b, 0x09, 0xa9, 0x00,
-  0xfc, 0x98, 0xb9, 0xdc, 0x73, 0x91, 0x87, 0x58, 0x53, 0xd4, 0xc1, 0x8b, 0x05,
-  0xe6, 0x85, 0xc8, 0x48, 0xb8, 0x7e, 0x23, 0xcf, 0x12
+  0x51, 0xf4, 0xe6, 0x1c, 0x18, 0x7b, 0x28, 0xa0, 0x1f, 0x63, 0xbf, 0xa5, 0xbd,
+  0x89, 0x9f, 0xd9, 0x30, 0x46, 0x4b, 0x34, 0x9b, 0x9d, 0x0f, 0xb0, 0x33, 0x11,
+  0xf8, 0xaa, 0x84, 0x4e, 0xb2, 0xca, 0x29, 0x83, 0x54, 0x28, 0x99, 0x2a, 0x43,
+  0x7f, 0xe0, 0xe6, 0xd8, 0xdc, 0xd7, 0xf4, 0xb3, 0xd7, 0xf7, 0x39, 0xd5, 0xdc,
+  0xde, 0xdc, 0x23, 0x78, 0xd7, 0x90, 0xc0, 0x52, 0xf5, 0xd2, 0x14, 0x6f, 0xf9,
+  0x24, 0x48, 0xc8, 0x75, 0x4a, 0x9a, 0x4c, 0x61, 0x2f, 0x96, 0x4e, 0xc8, 0x02,
+  0x95, 0x72, 0xef, 0xbc, 0x91, 0xae, 0xf8, 0x23, 0xfb, 0xba, 0x9f, 0xfd, 0xe0,
+  0x1a, 0x8e, 0xa9, 0x03, 0x16, 0x76, 0xf4, 0xdb, 0x81, 0x5a, 0x69, 0xeb, 0xf5,
+  0x55, 0xd7, 0x68, 0x28, 0xe4, 0xce, 0xde, 0x1b, 0xb4, 0x90, 0xac, 0x97, 0x07,
+  0x15, 0xe0, 0xce, 0x5f, 0x3f, 0x89, 0xaf, 0xc1, 0xb8, 0x46, 0x5e, 0x87, 0xa1,
+  0x8d, 0xa7, 0x44, 0x09, 0x02, 0x4e, 0xbe, 0x6b, 0xfb, 0xab, 0xeb, 0x19, 0x62,
+  0x9e, 0xb0, 0xef, 0x0a, 0x6b, 0xcf, 0xe0, 0x00, 0xa9, 0x68, 0x2a, 0x8e, 0xfe,
+  0x8a, 0xb9, 0x57, 0x52, 0xb3, 0x08, 0x80, 0x5e, 0xa6, 0x88, 0x5f, 0x31, 0xd1,
+  0xe9, 0x6d, 0xf7, 0x54, 0x4e, 0xf8, 0x17, 0xb0, 0x1c, 0xca, 0xa6, 0xa6, 0x80,
+  0xf8, 0xd8, 0xf5, 0x94, 0xa4, 0xb2, 0xd0, 0x7e, 0xbb, 0x4f, 0xdb, 0x3a, 0x91,
+  0x5f, 0xb3, 0xc1, 0xfa, 0x60, 0xe4, 0xce, 0xe3, 0xe5, 0x14, 0x1f, 0x9c, 0x01,
+  0x60, 0xff, 0xe2, 0x09, 0xe6, 0x1a, 0x82, 0x69, 0xb6, 0xeb, 0x52, 0x1e, 0x3d,
+  0xc7, 0xfd, 0x69, 0x9d, 0x2a, 0xa5, 0xdb, 0xc1, 0x6a, 0x5a, 0x7d, 0x23, 0x2a,
+  0x00, 0xe4, 0x53, 0x16, 0x8e, 0xc1, 0x56, 0xf5, 0x5a, 0x8d, 0x59, 0x1f, 0x7f,
+  0xff, 0x77, 0x6f, 0x92, 0xea, 0x5d, 0x31, 0xe9, 0x18
 };
 
 // The RSA intermediate certificate that issued the EE cert used in the
 // signature above. The certificate was generated with pycert.py
 const uint8_t RSA_INT[] = {
   0x30, 0x82, 0x02, 0xd0, 0x30, 0x82, 0x01, 0xba, 0xa0, 0x03, 0x02, 0x01, 0x02,
   0x02, 0x14, 0x07, 0x10, 0xaf, 0xc4, 0x1a, 0x3a, 0x56, 0x4f, 0xd8, 0xc2, 0xcc,
   0x46, 0xd7, 0x5b, 0xdf, 0x1c, 0x4e, 0x2f, 0x49, 0x3a, 0x30, 0x0b, 0x06, 0x09,
@@ -625,17 +625,18 @@ verify_callback(const uint8_t* payload,
                 size_t payload_len,
                 const uint8_t** cert_chain,
                 size_t cert_chain_len,
                 const size_t* certs_len,
                 const uint8_t* ee_cert,
                 size_t ee_cert_len,
                 const uint8_t* signature,
                 size_t signature_len,
-                uint8_t signature_algorithm)
+                uint8_t signature_algorithm,
+                void* ctx)
 {
   UniquePK11SlotInfo slot(PK11_GetInternalSlot());
   if (!slot) {
     return false;
   }
 
   CK_MECHANISM_TYPE mechanism;
   SECOidTag oid;
@@ -698,41 +699,47 @@ verify_callback(const uint8_t* payload,
 class psm_COSE : public ::testing::Test
 {
 };
 
 TEST_F(psm_COSE, CoseTestingSingleSignature)
 {
   SECStatus rv = NSS_NoDB_Init(nullptr);
   ASSERT_EQ(SECSuccess, rv);
-  bool result = verify_cose_signature_ffi(
-    PAYLOAD, sizeof(PAYLOAD), SIGNATURE, sizeof(SIGNATURE), verify_callback);
+  bool result = verify_cose_signature_ffi(PAYLOAD,
+                                          sizeof(PAYLOAD),
+                                          SIGNATURE,
+                                          sizeof(SIGNATURE),
+                                          nullptr,
+                                          verify_callback);
   ASSERT_TRUE(result);
 }
 
 TEST_F(psm_COSE, CoseTestingTwoSignatures)
 {
   SECStatus rv = NSS_NoDB_Init(nullptr);
   ASSERT_EQ(SECSuccess, rv);
   bool result = verify_cose_signature_ffi(PAYLOAD,
                                           sizeof(PAYLOAD),
                                           SIGNATURE_ES256_PS256,
                                           sizeof(SIGNATURE_ES256_PS256),
+                                          nullptr,
                                           verify_callback);
   ASSERT_TRUE(result);
 }
 
 TEST_F(psm_COSE, CoseTestingAlteredPayload)
 {
   SECStatus rv = NSS_NoDB_Init(nullptr);
   ASSERT_EQ(SECSuccess, rv);
   uint8_t altered_payload[20] = { 84,  104, 105, 115, 32,  104, 115,
                                   32,  116, 104, 101, 32,  99,  111,
                                   110, 116, 101, 110, 116, 46 };
   bool result = verify_cose_signature_ffi(altered_payload,
                                           sizeof(altered_payload),
                                           SIGNATURE_ES256_PS256,
                                           sizeof(SIGNATURE_ES256_PS256),
+                                          nullptr,
                                           verify_callback);
   ASSERT_FALSE(result);
 }
 
 } // namespace mozilla
--- a/security/manager/ssl/tests/unit/sign_app.py
+++ b/security/manager/ssl/tests/unit/sign_app.py
@@ -116,16 +116,36 @@ def addManifestEntry(filename, hashes, c
     pairs to use, the contents of the file, and the current list
     of manifest entries."""
     entry = 'Name: %s\n' % filename
     for (hashFunc, name) in hashes:
         base64hash = b64encode(hashFunc(contents).digest())
         entry += '%s-Digest: %s\n' % (name, base64hash)
     entries.append(entry)
 
+def getCert(subject, keyName, issuerName, ee, issuerKey=""):
+    """Helper function to create an X509 cert from a specification.
+    Takes the subject, the subject key name to use, the issuer name,
+    a bool whether this is an EE cert or not, and optionally an issuer key
+    name."""
+    certSpecification = 'issuer:%s\n' % issuerName + \
+        'subject:' + subject + '\n' + \
+        'subjectKey:%s\n' % keyName
+    if ee:
+        certSpecification += 'extension:keyUsage:digitalSignature'
+    else:
+        certSpecification += 'extension:basicConstraints:cA,\n' + \
+            'extension:keyUsage:cRLSign,keyCertSign'
+    if issuerKey:
+        certSpecification += '\nissuerKey:%s' % issuerKey
+    certSpecificationStream = StringIO.StringIO()
+    print >>certSpecificationStream, certSpecification
+    certSpecificationStream.seek(0)
+    return pycert.Certificate(certSpecificationStream)
+
 def coseAlgorithmToSignatureParams(coseAlgorithm, issuerName):
     """Given a COSE algorithm ('ES256', 'ES384', 'ES512') and an issuer
     name, returns a (algorithm id, pykey.ECCKey, encoded certificate)
     triplet for use with coseSig.
     """
     if coseAlgorithm == 'ES256':
         keyName = 'secp256r1'
         algId = ES256
@@ -133,89 +153,87 @@ def coseAlgorithmToSignatureParams(coseA
         keyName = 'secp384r1'
         algId = ES384
     elif coseAlgorithm == 'ES512':
         keyName = 'secp521r1' # COSE uses the hash algorithm; this is the curve
         algId = ES512
     else:
         raise UnknownCOSEAlgorithmError(coseAlgorithm)
     key = pykey.ECCKey(keyName)
-    certSpecification = 'issuer:%s\n' % issuerName + \
-        'subject: xpcshell signed app test signer\n' + \
-        'subjectKey:%s\n' % keyName + \
-        'extension:keyUsage:digitalSignature'
-    certSpecificationStream = StringIO.StringIO()
-    print >>certSpecificationStream, certSpecification
-    certSpecificationStream.seek(0)
-    cert = pycert.Certificate(certSpecificationStream)
-    return (algId, key, cert.toDER())
+    # The subject must differ to avoid errors when importing into NSS later.
+    ee = getCert('xpcshell signed app test signer ' + keyName, keyName, issuerName, True, 'default')
+    return (algId, key, ee.toDER())
 
-def signZip(appDirectory, outputFile, issuerName, manifestHashes,
-            signatureHashes, pkcs7Hashes, doSign, coseAlgorithms):
+def signZip(appDirectory, outputFile, issuerName, rootName, manifestHashes,
+            signatureHashes, pkcs7Hashes, coseAlgorithms, emptySignerInfos):
     """Given a directory containing the files to package up,
     an output filename to write to, the name of the issuer of
-    the signing certificate, a list of hash algorithms to use in
-    the manifest file, a similar list for the signature file,
-    a similar list for the pkcs#7 signature, whether or not to
-    actually sign the resulting package, and a list of COSE
-    signature algorithms to include, packages up the files in the
-    directory and creates the output as appropriate."""
+    the signing certificate, the name of trust anchor, a list of hash algorithms
+    to use in the manifest file, a similar list for the signature file,
+    a similar list for the pkcs#7 signature, a list of COSE signature algorithms
+    to include, and whether the pkcs#7 signer info should be kept empty,
+    packages up the files in the directory and creates the output
+    as appropriate."""
     # This ensures each manifest file starts with the magic string and
     # then a blank line.
     mfEntries = ['Manifest-Version: 1.0', '']
 
     with zipfile.ZipFile(outputFile, 'w') as outZip:
         for (fullPath, internalPath) in walkDirectory(appDirectory):
             with open(fullPath) as inputFile:
                 contents = inputFile.read()
             outZip.writestr(internalPath, contents)
 
             # Add the entry to the manifest we're building
             addManifestEntry(internalPath, manifestHashes, contents, mfEntries)
 
-        # Just exit early if we're not actually signing.
-        if not doSign:
-            return
-
         if len(coseAlgorithms) > 0:
             coseManifest = '\n'.join(mfEntries)
             outZip.writestr('META-INF/cose.manifest', coseManifest)
             addManifestEntry('META-INF/cose.manifest', manifestHashes,
                              coseManifest, mfEntries)
+            intermediates = []
+            coseIssuerName = issuerName
+            if rootName:
+                coseIssuerName = 'xpcshell signed app test issuer'
+                intermediate = getCert(coseIssuerName, 'default', rootName, False)
+                intermediate = intermediate.toDER()
+                intermediates.append(intermediate)
             signatures = map(lambda coseAlgorithm:
-                coseAlgorithmToSignatureParams(coseAlgorithm, issuerName),
+                coseAlgorithmToSignatureParams(coseAlgorithm, coseIssuerName),
                 coseAlgorithms)
-            coseSignatureBytes = coseSig(coseManifest, [], signatures)
+            coseSignatureBytes = coseSig(coseManifest, intermediates, signatures)
             outZip.writestr('META-INF/cose.sig', coseSignatureBytes)
             addManifestEntry('META-INF/cose.sig', manifestHashes,
                              coseSignatureBytes, mfEntries)
 
-        mfContents = '\n'.join(mfEntries)
-        sfContents = 'Signature-Version: 1.0\n'
-        for (hashFunc, name) in signatureHashes:
-            base64hash = b64encode(hashFunc(mfContents).digest())
-            sfContents += '%s-Digest-Manifest: %s\n' % (name, base64hash)
+        if len(pkcs7Hashes) != 0 or emptySignerInfos:
+            mfContents = '\n'.join(mfEntries)
+            sfContents = 'Signature-Version: 1.0\n'
+            for (hashFunc, name) in signatureHashes:
+                base64hash = b64encode(hashFunc(mfContents).digest())
+                sfContents += '%s-Digest-Manifest: %s\n' % (name, base64hash)
 
-        cmsSpecification = ''
-        for name in pkcs7Hashes:
-            hashFunc, _ = hashNameToFunctionAndIdentifier(name)
-            cmsSpecification += '%s:%s\n' % (name,
-                                             hashFunc(sfContents).hexdigest())
-        cmsSpecification += 'signer:\n' + \
-            'issuer:%s\n' % issuerName + \
-            'subject:xpcshell signed app test signer\n' + \
-            'extension:keyUsage:digitalSignature'
-        cmsSpecificationStream = StringIO.StringIO()
-        print >>cmsSpecificationStream, cmsSpecification
-        cmsSpecificationStream.seek(0)
-        cms = pycms.CMS(cmsSpecificationStream)
-        p7 = cms.toDER()
-        outZip.writestr('META-INF/A.RSA', p7)
-        outZip.writestr('META-INF/A.SF', sfContents)
-        outZip.writestr('META-INF/MANIFEST.MF', mfContents)
+            cmsSpecification = ''
+            for name in pkcs7Hashes:
+                hashFunc, _ = hashNameToFunctionAndIdentifier(name)
+                cmsSpecification += '%s:%s\n' % (name,
+                                                 hashFunc(sfContents).hexdigest())
+            cmsSpecification += 'signer:\n' + \
+                'issuer:%s\n' % issuerName + \
+                'subject:xpcshell signed app test signer\n' + \
+                'extension:keyUsage:digitalSignature'
+            cmsSpecificationStream = StringIO.StringIO()
+            print >>cmsSpecificationStream, cmsSpecification
+            cmsSpecificationStream.seek(0)
+            cms = pycms.CMS(cmsSpecificationStream)
+            p7 = cms.toDER()
+            outZip.writestr('META-INF/A.RSA', p7)
+            outZip.writestr('META-INF/A.SF', sfContents)
+            outZip.writestr('META-INF/MANIFEST.MF', mfContents)
 
 class Error(Exception):
     """Base class for exceptions in this module."""
     pass
 
 
 class UnknownHashAlgorithmError(Error):
     """Helper exception type to handle unknown hash algorithms."""
@@ -247,20 +265,20 @@ def hashNameToFunctionAndIdentifier(name
     raise UnknownHashAlgorithmError(name)
 
 def main(outputFile, appPath, *args):
     """Main entrypoint. Given an already-opened file-like
     object, a path to the app directory to sign, and some
     optional arguments, signs the contents of the directory and
     writes the resulting package to the 'file'."""
     parser = argparse.ArgumentParser(description='Sign an app.')
-    parser.add_argument('-n', '--no-sign', action='store_true',
-                        help='Don\'t actually sign - only create zip')
     parser.add_argument('-i', '--issuer', action='store', help='Issuer name',
                         default='xpcshell signed apps test root')
+    parser.add_argument('-r', '--root', action='store', help='Root name',
+                        default='')
     parser.add_argument('-m', '--manifest-hash', action='append',
                         help='Hash algorithms to use in manifest',
                         default=[])
     parser.add_argument('-s', '--signature-hash', action='append',
                         help='Hash algorithms to use in signature file',
                         default=[])
     parser.add_argument('-c', '--cose-sign', action='append',
                         help='Append a COSE signature with the given ' +
@@ -272,14 +290,12 @@ def main(outputFile, appPath, *args):
                        default=[])
     group.add_argument('-e', '--empty-signerInfos', action='store_true',
                        help='Emit pkcs#7 SignedData with empty signerInfos')
     parsed = parser.parse_args(args)
     if len(parsed.manifest_hash) == 0:
         parsed.manifest_hash.append('sha256')
     if len(parsed.signature_hash) == 0:
         parsed.signature_hash.append('sha256')
-    if len(parsed.pkcs7_hash) == 0 and not parsed.empty_signerInfos:
-        parsed.pkcs7_hash.append('sha256')
-    signZip(appPath, outputFile, parsed.issuer,
+    signZip(appPath, outputFile, parsed.issuer, parsed.root,
             map(hashNameToFunctionAndIdentifier, parsed.manifest_hash),
             map(hashNameToFunctionAndIdentifier, parsed.signature_hash),
-            parsed.pkcs7_hash, not parsed.no_sign, parsed.cose_sign)
+            parsed.pkcs7_hash, parsed.cose_sign, parsed.empty_signerInfos)
--- a/security/manager/ssl/tests/unit/test_signed_apps.js
+++ b/security/manager/ssl/tests/unit/test_signed_apps.js
@@ -185,18 +185,24 @@ var hashTestcases = [
     expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID },
   { name: "app_mf-256_sf-1_p7-1",
     expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID },
   { name: "app_mf-256_sf-256_p7-1",
     expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID },
 ];
 
 // Policy values for the preference "security.signed_app_signatures.policy"
-const PKCS7WithSHA1OrSHA256 = 0;
-const PKCS7WithSHA256 = 1;
+const PKCS7WithSHA1OrSHA256 = 0b0;
+const PKCS7WithSHA256 = 0b1;
+const COSEAndPKCS7WithSHA1OrSHA256 = 0b10;
+const COSEAndPKCS7WithSHA256 = 0b11;
+const COSERequiredAndPKCS7WithSHA1OrSHA256 = 0b100;
+const COSERequiredAndPKCS7WithSHA256 = 0b101;
+const COSEOnly = 0b110;
+const COSEOnlyAgain = 0b111;
 
 function add_signature_test(policy, test) {
   // First queue up a test to set the desired policy:
   add_test(function () {
     Services.prefs.setIntPref("security.signed_app_signatures.policy", policy);
     run_next_test();
   });
   // Then queue up the test itself:
@@ -228,16 +234,106 @@ add_signature_test(PKCS7WithSHA1OrSHA256
 
 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
   certdb.openSignedAppFileAsync(
     Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("unknown_issuer_app"),
     check_open_result("unknown_issuer",
                       getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER)));
 });
 
+add_signature_test(COSEAndPKCS7WithSHA1OrSHA256, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("cose_signed_with_pkcs7"),
+    check_open_result("cose_signed_with_pkcs7", Cr.NS_OK));
+});
+
+add_signature_test(COSEAndPKCS7WithSHA256, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("app_mf-256_sf-256_p7-256"),
+    check_open_result("no COSE but correct PK#7", Cr.NS_OK));
+});
+
+add_signature_test(COSEAndPKCS7WithSHA256, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("app_mf-1_sf-256_p7-256"),
+    check_open_result("no COSE and wrong PK#7 hash", Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID));
+});
+
+add_signature_test(COSERequiredAndPKCS7WithSHA1OrSHA256, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("app_mf-256_sf-256_p7-256"),
+    check_open_result("COSE signature missing (SHA1 or 256)", Cr.NS_ERROR_SIGNED_JAR_WRONG_SIGNATURE));
+});
+
+add_signature_test(COSERequiredAndPKCS7WithSHA256, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("app_mf-256_sf-256_p7-256"),
+    check_open_result("COSE signature missing (SHA256)", Cr.NS_ERROR_SIGNED_JAR_WRONG_SIGNATURE));
+});
+
+add_signature_test(COSERequiredAndPKCS7WithSHA256, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("only_cose_signed"),
+    check_open_result("COSE signature only (PK#7 allowed, not present)", Cr.NS_OK));
+});
+
+add_signature_test(COSERequiredAndPKCS7WithSHA1OrSHA256, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("only_cose_signed"),
+    check_open_result("COSE signature only (PK#7 allowed, not present)", Cr.NS_OK));
+});
+
+add_signature_test(COSEAndPKCS7WithSHA1OrSHA256, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("cose_multiple_signed_with_pkcs7"),
+    check_open_result("cose_multiple_signed_with_pkcs7", Cr.NS_OK));
+});
+
+add_signature_test(COSEAndPKCS7WithSHA1OrSHA256, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("cose_int_signed_with_pkcs7"),
+    check_open_result("COSE signed with an intermediate", Cr.NS_OK));
+});
+
+add_signature_test(COSEAndPKCS7WithSHA1OrSHA256, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("only_cose_signed"),
+    check_open_result("PK7 signature missing", Cr.NS_ERROR_SIGNED_JAR_NOT_SIGNED));
+});
+
+add_signature_test(COSEOnly, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("cose_multiple_signed_with_pkcs7"),
+    check_open_result("Expected only COSE signature", Cr.NS_ERROR_SIGNED_JAR_UNSIGNED_ENTRY));
+});
+
+add_signature_test(COSEOnly, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("only_cose_multiple_signed"),
+    check_open_result("only Multiple COSE signatures", Cr.NS_OK));
+});
+
+add_signature_test(COSEOnly, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("only_cose_signed"),
+    check_open_result("only_cose_signed", Cr.NS_OK));
+});
+
+add_signature_test(COSEOnlyAgain, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("only_cose_signed"),
+    check_open_result("only_cose_signed (again)", Cr.NS_OK));
+});
+
+add_signature_test(COSEOnly, function () {
+  certdb.openSignedAppFileAsync(
+    Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("cose_signed_with_pkcs7"),
+    check_open_result("COSE only expected but also PK#7 signed", Cr.NS_ERROR_SIGNED_JAR_UNSIGNED_ENTRY));
+});
+
 // Sanity check to ensure a no-op tampering gives a valid result
 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
   let tampered = tampered_app_path("identity_tampering");
   tamper(original_app_path("app_mf-1_sf-1_p7-1"), tampered, { }, []);
   certdb.openSignedAppFileAsync(
     Ci.nsIX509CertDB.AppXPCShellRoot, original_app_path("app_mf-1_sf-1_p7-1"),
     check_open_result("identity_tampering", Cr.NS_OK));
 });
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..da5a487b168a537b8d681bfd7a943dcfa2cbf884
GIT binary patch
literal 5002
zc%1E6X;c%*7EUK2NLZqvpb#-4C_CLDAgdTiVjw1jogk<I0)&JRlCa6J7+erg5oT~0
zP*KMX5dl#Yoxxq)MsY<DMMl(zvgoL|0k4B1lF@UVfA5_$oxZ25ZuR}Dy6S#6b&JhF
zp(i60mt2;^&<{1OWx-{IXu=Z574f5ZQkiwEG+va3B@m28HA|9s5-C4kWaLC3S}Gbu
z+&CUwG4h8S3DguBPc+gz(l++45oirsLq^ziEPGtXuj!Db1zc7L1{Pl`nZl&{$MB^D
z_?E@+2ofGQGLA=xikFO3Wr}Wiqup35!IjD#RdtaFghI4nT_jh=wc*Ecqj}b1QS=%%
zYk?+KAFKFCPdddHeikcaf}&>^AfXe10NOn%WdD@1o<C~T5a7hq)oq#oxuOkZCv08Z
z)>}B-KfmnX`~UXNH(V+<TJ}3$=a|A@JgF>7mHSfpcn|7U|9J-rKp+&N3+rHKBwKm1
zXf_e?Ql9lF3z(mtR)HTq+=&2LgIFvJ=7JMp9C@&QbTZM--ipGHhE+}kcYl$G*dMYZ
zv55A*A#o1jF_9FKZBTF|D2ufVkG7AGVnU9rg`S`{)pZo`BPo=T!a1POF(qMv7so@K
zz~Om;4EqEUB`ClrArXvYxzm^=I*At-6U+CC{){x956XyCcC3IElAOwQ47LzU5*G?n
z7Ff{89t)Efc#s@|14w?3@gd%1P#75K<ElhF=XrG9QWXS3A(Q?#ZBl-8OZW;7N@FW}
zIR}LS<tQX52fE8qNC1hPJVP|CcnN)0r0b?14%Bbl6BhjztOPYNYUZoxs|GXyKwSj^
znn80w6AUT<jnXho5l2X4ctRloh86K530$#Q`Y|p@;^SqY(Nr7}gzO-Q=m3sfAtMS0
zkO<m+Qh?@=DLDHh+>EcleMI9+rHMQVJW!)AM+2xJP;vl=fc03U8~_jvIX=57>vV6C
z2StZ+F!mE&U3BhrKeY3zd-f_ONNAjP;+)Cuj+Pm})s$gMMf$5=2s-zNBno096DBO%
z5weTAdH{dZxD1(b+2eyD|EdGQtY|Ocl;^{?BMVOogjzjQ<hbV<`}q1b*O5+n=H%X8
z;trhV+QBGwi)!P-U(=7|a8nCvf(l%(IiKk`OrNoP?)4mxzB#%r0rgQK6&c6^8>h61
zSs3F>c;Uu<#oR^poyFS66QS)I8`|qG41Cx(-Q>Dj-w{2nT`><1q}dq7^Z%^N{fRrh
zclIrlO?x*?VA)^98>1~7b@Obxp06*_gAN}U@|^Wf;&U3hiK=X!inZ%mi-f5HY@ZGq
zfEw_OPS-)JfG7YM2Gtcc92yNTGDc}RQHpt6Q8GPn^_IRH!+MKvymh{vwfa4|ZvR16
z(r){cXAGKN_rIF6x*z8RElsjCyjWPf%QK{Yb3^@kd3(0=4G)bd*TUoPA|LkR)f3ni
z^WWWTjfk~D<hE98JW5Y~@dh+*pP9@yw!GgmAf&nn)w@7{ZDCe!W<!X8Uo<R`5x44A
z%(zO{-|{~1!v<u18!mEPV^z5SX1$_3dhX4PYjYVzRk!cl&DK`$FYS_ARGBoKeb?!m
zsGZewNo$J_{Zif)!=4ZUcjqQ|!}gop8!q>T8xQ|*u5ZfBn{N!O<8T$v&tqD4ii2)n
z*IA|gn;QQ8OhePqlk>JT|JYYZuc-6LPPaJUrT(J)_3~^E(rp_s8_hvFfN~@Wb}9TP
zPN?Vjw+<U)ZdDgJXRTD3dFdIVs!^E}|HO&EhZH1;2!bE+%)W^?QkM{<ya+KIIwTOt
z0d+8{@UZ@Hh1Yq)NC5??qTCT^@5ZA?xgBrb*6hS`Dp#XBpQ)(3&vO~DE_Ac>PGwL-
z&H2}CsY3hHlQyYhI<$J4nu`i<ml&j3scuJimwW9zz8wc@e&I!`Szq&_U5A+3>2Z&a
z)Cvryy0g1Vs_A*eBjzWIny0bcMRH+l-OGD_hFe01!=_O2LwyIMG!`9%_K>`3J40d&
zU6u%JuNeQ_&nSH^xvDewE=|Y+p1K{}dOE)IUB*#C{_7iRIVZHpy0$^h>^tSJPe16*
ztt(p975;-2dkv<m-jNxEKUr98+dJ5HcGomNU$;4|d6s5dOjb_4sH@4TD(_M0x!pGq
z(bahWY^h#~C}OUERndb*sk2O6p4O*?IzD@)@p!92Eh+L4iSa8v2?EnHXOZ6)?mwzq
z-je%f4sM%)zFT9@gK6GRHFS4(Z*1sk^~z?vII_(;yZ=!-e&v-av4LGjPI>VB&_tgt
zI+NI!!*cHtwjaZQ8-{D8iA$i!XM-2rv#{bvq)gfRcGG;P3lKNJ7Qb=0B7;(sXA@Sv
zQKN(^p@*c7kL0axsfJI{2!ukkzKrB#YhOPyC`Uj3ya=kuayhyMR^31X0HhA8VN@)%
zP)L2)H`T{p0?OscH?VuZgx&k@C-)|2{Vvn5iD6T~qHA?0s$$Kjiyi(KLjFhZ{x{@*
zSIGY!dU^`;Ss^>kel=ZFNXcwlaAtPcl<c3+);X=g`IP-7$$YBYv`nYy>iwbn>BlAl
z_n=oig6muc*Fw~B*VE9*L;9f9%wMmx`CjEbY-B`LcTi{)Ver<RtDOT)!|RhW=Nt|&
z(Qgx$oxkOy_S4>XYnukAI3_=;I%XD^F|ZJ2e8jzaPw<<!=7Z6)b)2CY;k3bJy{=uY
z`z#~6AMmSBF%5Ex=T{DITf8@^vz*?zzuhs~DY5pT;7Q4yq1;#8CVXs*SUZ8anRveR
z5OnTR{xt3+H?Q(NEh<@^^b-`kUY6ayeGUHC%4+<>4*n?X*>Pcc1!^(Asdm!@X`?~9
z&t==}S{@ma1NE@m9DoS|lK+8Af14spSJ43;3XO!FvYY`<{XFGrDCkSlfi`0;Xvhdn
zz^@auZ_XEZx)k3TVm?V;<U4GU^E^Oi<_wsSfz4-+enD9PK+6Hd$~&DTtEc*zXEd#s
zpP5H7@84l@<6^JCRx7;T+3Gd*P2S=#+;eG(sqg-uitn}Iyw_{a$~^VD|4C0mi1DQ0
zMANN_!>VZ)(8S|1LBW{@hWtU9@8!zVhB51gro~&;yp_M~VNWbvd2UAGfxTH}-NEbE
z+pd3NsACTpyv!+Dv<GvuKcYF-3p(AI;j#N%tMkpa`*KfW6%a_Hp6g4yUJzH<d^j8a
z)8(&>x|Kd;b})GH+*rp<KZ7f$K17)k4YN8nNv{5)_x!g%C7EkDFZ2C2t?*$syvvCZ
zY^zS6v?13NVe>H1F?k(>me3rTUOG7Mv4cteD$aXiPQ@;HY;42*C+XwEBE5-d7Ydg{
zKV`^YghfA^AH0NIS)znDJ|7sjy|x<78Jq|XG9Q75zkP&bh))pP#?G4&6_^~C7(<d!
zneN_^VzxlWbo5x}z!W)>l=s=MwwA1}g;NuSO#X5hOft)pM)mWzX43vmPDT;Gp1dg|
zdpi&rQJf?SO)3<`dU(iK0tpyTVsgZ^=-_3sF%n{UGCwuN!685t@eO2{!pfl09Gk$1
zIL~mJFe!>1on*nV@QR?*{Hc6<Ur97W$`LUc)Iees1(GH!))+ueMt%D@X7tJe5Xy%$
z%BIQ(Dr2UppO06RZIn+<#%!AYc7~#CtDG;7*<w-O%AS=ml#|CX3^MvFsid;G@{VQ9
uTpg>te^ItoruCSu5l)HZ%BIRx95da6`#Le%43&{3nE?MD!&YlYKK8$n7cBJv
rename from security/manager/ssl/tests/unit/test_signed_apps/cose_multiple_signed.zip
rename to security/manager/ssl/tests/unit/test_signed_apps/cose_multiple_signed_with_pkcs7.zip
index 33a7740e46c3d7d398e64cd2590c1998c485ace1..56111b5ce5e0f38ffab0098bc0c5a186f4350126
GIT binary patch
literal 4929
zc%1E6X;c%*7EUK2K#)x~MUWUlcIbqFfTD&ZKv=>SmLRAB0trhJl7K7&LU0suL=;5@
z)ZhlFARvl3xTE5N<Dde9A~K2&ih_=^IKXRgK{9&YydUqJ_s*H_zNf2i_5G^4>-*}|
zEiX3&QXMvNh(%d$+QCNEG^jjbijc)Jxts`=P-GD$<Z)Bb7!3BaXJrCQAms44SbGfK
zY@&k8jAcO&SUOaRp(Kh}+{x<6x~X@upap1w!=h8sUeg+W?}9Tkg~}6#g3O0PBzsWk
zY>p5ET_QFMBVaMZV_BF8o?!A(G|>#}b2AoFaD`$!Sxq<$HepJTFPtf2T5@8Ukt_>7
zH*$j)%~=txjh^^Ostef%y5~=r+(gTZfw*oM40uQ-6X}UXeYdLQVW3JwWyhM|f0+qn
z#ucyVc(rxBe_7E#*Z=MH)7({jZ1PzhwfYIZP$@KWh2tvmbO!Y*>^z77V6X|(gnSSg
ziRM(AlVuoB$g=pX0*_C3bN`PFx5wZtKs1^LX~7;dO+08{7b4!;#+=NFgk1I*M>?0p
zr{k;%G`x*ZP^@hzJDg0g3J44bMN!tFkv6;t51bv%oeFwV96ken6ooWWC<BbKON?`N
zWsvxB43;bCW)nvs2l#o%#e=alM<)-03xO5Oj^emRenFb92Wdo#S5!1DXmt|PF3^-O
zh<A@kbT)M&lH6B2lL)qfegt1TUXUjdjPdvPc90U@kH)D49~nr$kg5LVw+T6sZJ}#P
z#mIEYdvPWMzGNS;0Lg$a1jTSGPz=nGAm9KTu5LN5n%sNENQ;x-P`oVP@^~S#*d0_v
z$(yWmSvRN%017fN&=_Y38lVt<NW_e}iTp4jn-vp-f$+Jka14{r7k-=|1U#My#LiO2
zgE(s(4sQ!i9zl~1TM!Rge{z5X93BKe!Wn-9?jzddvj8Jxh4G=^CBT6UPz@yu_3D-b
z96-rU77&0e!V!k_Jood@%&wu~szYeT(e=pgmof^DOBN4WY+Y*RndC+ZHsLf|QDSTw
zRCmjwx|I4Ff6dEn-8Co0Ty{UQSK@l;{C;In5mbOWq^pcXBH*&=Qs0jd0{|=%P1|v;
zJ0xjup?e#y$Ro>ab!(8jhJJSIK$4Cx|4B;T%AS`%9X<rFGuME6Ww*^vnIEi37ni12
z%5A+9yJ5MHf9cGuUthRnd!JlyrqZ0>9x%gjTWdl?f3somq7qoh+2yc0oyOU%7^Z1t
z+oR<{$6b_0=ifg~d~Z5)N5rw+<mbh=EA%+qnY%-78Wo=3-jh{mrFTd$=2NV05-3sb
zuUeUv^P<Fqy7YtD8`~lnxGi&W<dazSY_`EQnaX)@-KsYukpO=|&%6s)RsAB83%c90
z0v+KA&h@BPjIR1)r+X=|LCYMHTJmtc)dq?zO}i!FjDE^+9Pi1BJ+xXPuZSuMToxSf
zy;n`ut0^SA6SKb_1#TIy7RIl{g})rV;h2u*_XLW2>Jv8^sUHAH+iGiulbsz3UZ_MD
z-L!j$DtczHdL=}{;C+BC7GfbCVxbqrLfcO)l-;#DICkLb*`eDuvwk<_VN9s$n*U=g
zw6Y~YEKC4ZrdTLrnt_C25uq?-F<U^gF%3?cwc%}&hLc9|)ulC?UaeaKH`eG_m1AK3
zq*l$m^w!SjIA2;+(F_Io#umHs=Xli9(-{O|vEF{LE2Q)qmy|hXxZa^G4sq5f>z96b
zf6$<|-ou-jqQl&>TYrn998Zlm84aBssoGh$3hbA&7oJvK+@C$NsD*wYTi;a4SulV6
zTJ!ecGVF<%El*<@#z?LA=X$t9^N%RPwgN+`A)*1r%#3DgcWy?(GDFFqFBk)6k(<dK
zN9C%?$Di}lN3zcC4cNCguiG=%?q0_I0=`Pj#+>-H^z1*<Jo^(ia&s+$7oKS-DT~XM
zElgJtZO97fIrzY|TBh!p+{x(Qy5dWd<IP47_?C3sttr?F8~!lE5_^75t??Efa!^rY
zC}f%AWlZt$j?1~dvOi!<9dba9N%i{JLR)_4kA#eZ4m=*yk4*3}ZiyYS?Zd6r@3=m2
zrL!{tq1&qP^NLxG53t4iC4sB@P=-s2+4l6BHf@q<txNvmo+W29v=A>_9R&UR=qSeB
zmlUVx{?Ash{A%;c24QdinA<c@(w;egXP>YXA6P}XbfLD}<%%-z#fJ!*NGlj`bW38z
z;R_<1j_A(Ny{%_FeFElht15nhguy0E>FWuYXyM~a1jWc_Uj|7QE)gT!AlF?u0N@lr
zd5Anp2)H)HYlW$o0Erkr1WDr$NE#15NrRYvR-|3U_9BCM%{3P)qD*x8w*O^mnBa`S
z1s~z`{*5%Cj$*&=4KT??Wf<f~!zW02I?KD1oTJ%79Oa(OLfNP|ELOYU`^4I{=H)wf
zK#YFMg{uaoU2S@2s)|sBT<vvlqPvd;#Yabl$H^rh3@V|lAJn<0Uj$EUBK<j+bK4eU
zoOc9siTb3Y&i!I^j8dP5Sa~3=oTFWJ2X4R7g!rn2-=(a$X*5E?v{HZTfz-MzW>Rid
zK(0gcqRU;UT=Ys8-pL}pHq>nMtBnXcoCeRev`<k<N9o_xiP=$}&s<*Hoj>z@JZ}Gt
zEe~t15B^!MYj8*Yb)A+{3H$N!6iY0R^IJ{!cBbyD1uX`<k8F{n+1$|4N1C0}+-Ui9
zVDm05+^OSZ)cGR<?*`mG#L@OyXzRXBaA;8j{4M!XV}7Cq9Wp*(v|%fGO^5U41tA)l
zJFnE(Z&3CwdMjA-LbEYhE${ZDu}7)(DnKXh9Sh^I(2Z%z?Rr3+izNvk7aG&G3V-c9
zx&$2_R?!;}9Dx~aF}&S9*f_p9VU6J_KLhQKn4)Vf-tyazjBIKg)v#OLQ&Ddmn>Of<
z(64i>EDIbOHW`f+<uJzdLY+pFUpYK&FE<P8eaxx6<S{2Jf7#LTeJhS6bW2>$9eZdO
zX&+yGBKrBR`(xSfn2kD7ZTy*W9((ZD3Qyv$-u!7cQ+27Uq^wOQz1!siSw}0~y1e`}
zy}7809&%!vsPEwQjKhc(I*rx4<%H+vq<S}5WmdC@I5AKQ(dIZL5RmvEQ2P54S+&ju
zU?Grjh?EjHaMqV!E|0){EjrM0ss@R}A~CTQ7+ty2c6B?^82@*h<ztLaZqvoQN4{@5
zPRh@tkWYOjSpYza0ob~V56+agWdnybs}7bi3>)sx-}452#&OqSv#K5bUiDhS*SF=}
zPmXtQqt)z7B^Wi;0)rh3U&<`~VRmPH!3Z-^=>Cd4z}fdSU@3p3T{Sdi{n}PPk1eTh
zC4Dz;#UBY0wa?HnUsP#q!MoCwmUm$9o{GUvr?jC}n{xVz1HmhE4I)lne<p)%qCScM
zWLC_!G{Jl3kA<j?2udQ+kAL&4rw0dK&rBz<w-6s39-4n*PHHYed}_(T2J5od)$+3C
zb>d1j)OMX$-3PS{%OqAx!^<08`_=rfDGsZ9Y0133d%w(Qu8AjmPqtUD|Mn7{rUKVc
zn{od?P1AsG`i@?ep-Qdk(;^Cg=|(VA4*rzbel;!nI{89F$P~p3SkssB(^kdipO^af
zm;kB=7(fe4B-8waVfZ+@j}_hDMd0km!n>LJhB+tr;~3$jI1b5!U@N^mzH)uZ(P}88
zm@xIPyWv5kQJpBhbPErse{zb?h~Lh+q>(*s@oo`}1hSJbCOV2l649asAdld|;5$VI
zCP%Ra_|Vmyq(oa=KW^A}kRb_6gNmX9qwM@#eaUg*o<t(ZCfc!`d@SQd5m7j+gt!D3
zA3q%EOrhYzq9Z597=WuIzQ2p|`A7#~(t9e>q0;*xQ=v&;c15IPq&GXJVjBOl^&uTA
zo#sx(q7mOqdZjU>bG|7IBJvv<pmezOie)PNqP+C_MLJem)>E<fm83*29V#uwsnAu*
W-xj8qo6O{p$U)~bD2hD!vHt@3{sedc
rename from security/manager/ssl/tests/unit/test_signed_apps/cose_signed.zip
rename to security/manager/ssl/tests/unit/test_signed_apps/cose_signed_with_pkcs7.zip
index 918c715aded14f600b7a2e615f388bfc5dcef31b..4542e8a2337e689f5db78f7e1f3b8a6f55693d26
GIT binary patch
literal 4222
zc%1E5X;@O*8fF8cVrmYV$27^*a!B_^919Zx1rZb{z_da|KoJmdK9x~Vsi&+=Z4k@m
z(Mq#yuz9jhb<1vMvw1z$(QG)Uvbt$^qnSzd+<SlAANP6AW`ECK`&;{a*V=2n@8<g=
z87Q<RLVKuHMGTvS$@MI_tu<rVGWb$)sz9moNK?wB1y~%;VaPKpTcA*iWm1O#9Nt~q
zA?0TX;2Vb+xD!XsRSBd6-2;8Y&pLn}pa<lDor8@WG4NX&<n9KywT6K$ib|p|sWBq4
z5(l3ukpQO<@KZ7bxKx>9;8vv_MldvthYnno+F#!ai9l%01ooxyReVoz245)fkV}Qd
zk*rW-tPNKCl5`p+3cglq%|JWyG$6ABfdKB)DWsTOP0!UjLj*Yb?7qA6e*c>}upo28
z%)8IaKD`Xm{B{1{o=e8hmOJDhx3y@}@`X-iQT7DSR*z&*m(l7iC;)-bnicGW$w-<)
zXN7ns%aj6-Ar&w`U#G+kGCTkWd4O0f3)VsaZiINS(KHg?+h+<zEQDPFxZoHmSsnv<
z6IghksQ3)OBvA^5;KkvlfT}d_B%zNil?nN?!s%cHl{f@AC<<MqBpxX7&&>=C<B{c=
zJV6-9@W~`lII--^EHHx=9Ks~f2!aeznmA1O1!<%nbP=hMY3Z!^oIJii*G;a-3YX-D
zx`mL);W?pXf*&`Q5bZCEk061PxHvXZM|jTVoYG~m=(J|`&9W)Q!nUM^<PGS;nz!>8
z@Q{HU0cSK1=?kinUZ5HnSA#+VNTj9bC$s#n^OMJlE6;8Ss`T7nh29Vj8e<Gy7tt2=
z8Uuil9s+cMCV@^ER4f`bYJ9FdSt$}oBsdsfDoDZc<#OfV2SOo}sXzy7Q#=THLlE8%
z95~_!9DX1k^#1Gs2@oCx2jN`412>2^aIe5A1<7)FxfBq{11&K6@T{&9kpRYEpn(GP
zQNajw#EGLv`R(uC*KNh}b}vSEJkv7@4xHBOQ8wK@B9B2$a22<BQ6)ZS&8qb=?Iu0V
z*H<pTwPsww6#Y%;u9~o|CpVdb#-I^AAv;qv8imv^)OmlD8UPSNENj)pj>Nq6RpD)r
zhFRpEb1Oc4jAO~IS9!M4^3H;lvmQSK4&xK?w&R`X=c|2I>;3FSK0Uo~pF!D;jN%zl
zaof#{u6NT)*asK8k8Y{F!x=TH{8skamo1YLrfx$d9-o0YY}@?PEgauX*!FNn{C=8A
z-^ANTNN?TDSEcT)raawnZI8XUf?u6@d2-dsipND&UiMoR{ZSh%UAZ-;FY9I%m3D7q
z(x?B^{SQA40xVxJP1u=XSt4?}sJCyzpN#rtXfz;qemvpS1+&=H{Iwl-inzhZ?9e96
zEu5X@qmY{gh+fZ9vPJ&;Ca+?uKFg++bIh^eeWt8)<~mj*Nv5IKaDx)E*y}CKBCjNt
zJiu*g!hkD2)hn}RK`GDrehn_f${%ypkDGFrPPW_(kjonz-sguB*LIIi*If30gV8*3
z%9%Biy@l)Pgl;qfp*54Q*-P?>iY9?-^ph`}ppUFkquXHD-;n?S8G(ivJvS2+(gvoc
z(eOh+jT-q5X7_8D-S<ATn^bsQWm6}Lq<|}18cyv=bG4KE{g2u03QY!`2jT4h4ZGoq
zI($7FV1R3;2-uHBYDssbh`pUsYSl{WlO8O>_>3k_v$);W=^fVa?2U*caV$7>!D)MY
zoBgpm4W>$Jv*?fXj=k|&>1ipM2Kig!w^0}O+TL{3Am?5oe;hBq=7)1xxeIrO-g)<M
z_~~?sNzWLy>8rW5Vw<`f$bes5Nzb>*+f9v^_N5xR?Q<;KJm+u`KW}**XF0KD>bdqq
zH2dwoH;TwFCRw$`Hm1h!oQquU8Bj2~5aW2+R<f$Ll0T!dqtg6j7PM*9iu(<hdOz0M
zIo&XPad@oBHqoQ~1)dHv@jn_$D)@HKom-u%cdamB`TT0@h;~0=^^50kua>PD3mw|u
zPoMZf!9EM!MD4y~jrHzXiiH0Wfd5FIbjcD{{8pFElZ(qJ^X`V8b50zyVD<TifMQd&
z=1;}EZmZ^ei<Q?N_CK7{G#YpSy%FGuz6`#bwEZ4^yaQSJsLCZ~Y}NG#y92Q)$$Ppu
z38}cg)=AeodYeBj%bqvsP^^>9U5VymE8DPQ*N3IeePjG{9`9*#$(Y+4j&eL4yl)5h
z-Fw$Qp{kVEZ=V#>m;apj+nrkX<gQ2JeP@{CiYkM4f7&>6S9V7Y?Zn>u{=$H)`UB}t
z*WB(edBbnEO>2{zXEN8}FIF9dE?i#n6W?rlSj~<$y}}OKDT?jbLhstzBQY(Sx|qZR
z<*J@7m*($8&9rT<uQpJg7&nJ~#cM&mfCQ<5MwmAHVS#|8|ANv#mdNZyG(dntBVkh3
zFhJ`sOKymQz7`$mIoyMW9MHIof)dH;6&Y`e0~cn-ePlh?yz{W}%-M19dN$~JsAt0K
zuOtfqXf=R{@o2Hmme3c+m2ITouPnY^+5bDGs(t)sqQ#2Z%fw@^g93`*9OX#Y1*Wbm
z1*8XEF0|I4oE^rHm|4wBZoOC0yV%K|JT2g3>5ILA_FIHRm)d1ZloeAG?#(}|aAaBB
zFux-BU=<kUvZtagy3Fgyi?VapkJ?^e{kf_!G^+Z+YRiR8>x!NSURjxm8geMjT)&c}
zPkLviyfG0GCY~GiI{8|*QkZOfXhBcc%i!AwcH$Pt-cCJjH-T8$ZMy!$(VuY+Inlcs
zc^7yzaa)>m?)<FP7D?rX=ClUGv4-VPKXVrbVHcEWM$9yWmU6p0lh<Bj2<|=)uRo*4
zAA7p6o>N5}`B_ZRRPRiH+X<hmg0DV{(IL_B7V=eD3c<)6XhcdeWhhSyz$M2}a)lgn
z9LQ6q@#soOC1MM_)8l-&971*&HQkruD_6+45fOx}WZm52((Z<F^>8|-HOsH3!6dQh
zA=Ky?4`#?;3E2?h_Y+oK<On}JBbAp;2~kSY)5v5MD_sG~2uz+lM99rg6DjaXIpVxr
zKfhRM@(++<34b%)v?w<Ui_I3L^GHfxDkD@Zjo@?gVj!M4#ha1J4v8XgqiIPgxgvsg
zj{&45>c=JM&`}5=bPH15P~9SOI5h7|NvRv7TPY65G=Eb!>c;BU2*a^h)Q>6#T@2lX
zc^HF){!aR=8?KwN42OTh=;klFvAVJzj<p)4BXZqPT`3NSR*(9=Fe4dy16yJM|DM26
I^9N@8FVUaj4gdfE
--- a/security/manager/ssl/tests/unit/test_signed_apps/moz.build
+++ b/security/manager/ssl/tests/unit/test_signed_apps/moz.build
@@ -32,18 +32,18 @@ def SignedAppFile(name, flags):
 # hash algorithms are present in the corresponding file (both may be
 # present).
 # For example, "app_mf-1_sf-1-256_p7-256.zip" means that the manifest
 # file has sha-1 hashes, the signature file has sha-1 hashes and sha-256
 # hashes, and the pkcs#7 file only has sha-256.
 #
 # Temporarily disabled. See bug 1256495.
 #signed_app_files = (
-#    ['unknown_issuer_app.zip', '-i', 'unknown issuer'],
-#    ['unsigned_app.zip', '-n'],
+#    ['unknown_issuer_app.zip', '-i', 'unknown issuer', '-p', 'sha256'],
+#    ['unsigned_app.zip'],
 #    ['empty_signerInfos.zip', '-e'],
 #)
 #
 #for signed_app_file_params in signed_app_files:
 #    SignedAppFile(signed_app_file_params[0], signed_app_file_params[1:])
 #
 #for mf_algs in [['1'], ['256'], ['1', '256']]:
 #    for sf_algs in [['1'], ['256'], ['1', '256']]:
@@ -55,12 +55,15 @@ def SignedAppFile(name, flags):
 #                args.append('sha%s' % mf_alg)
 #            for sf_alg in sf_algs:
 #                args.append('-s')
 #                args.append('sha%s' % sf_alg)
 #            for p7_alg in p7_algs:
 #                args.append('-p')
 #                args.append('sha%s' % p7_alg)
 #            SignedAppFile(filename, args)
-
+#
 # COSE test-cases
-#SignedAppFile('cose_signed.zip', ['-c', 'ES256'])
-#SignedAppFile('cose_multiple_signed.zip', ['-c', 'ES256', '-c', 'ES384'])
+#SignedAppFile('cose_signed_with_pkcs7.zip', ['-c', 'ES256', '-p', 'sha256'])
+#SignedAppFile('cose_int_signed_with_pkcs7.zip', ['-c', 'ES256', '-r', 'xpcshell signed apps test root', '-p', 'sha256'])
+#SignedAppFile('cose_multiple_signed_with_pkcs7.zip', ['-c', 'ES256', '-c', 'ES384', '-p', 'sha256'])
+#SignedAppFile('only_cose_signed.zip', ['-c', 'ES256'])
+#SignedAppFile('only_cose_multiple_signed.zip', ['-c', 'ES384', '-c', 'ES256'])
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..69b03d154c5aefbd229a32d4f9b9e84276dafecc
GIT binary patch
literal 2822
zc$^FHW@Zs#00E(F4Iil(jZJ<)HVE?qac*K>W?E`-iC$K5eqJ?~f`SrEB)%-Qs5mn}
zPsvKbNCza5mzbLh<S2yzB^6vNN>cN{(qK7+S|tNL13g0}u3D}D6pO!k80u&P*&xgY
z#6hl(F21fI8JWcjKva^Es!)`gn39{Skd|Kr=9Yl0NrhRXhi2UDCQEiPCI$u&<^zhQ
zB$g!VXXYlRr|K2trFRDSx$|;Kae+MP>ERLtq^E%}2gqg{#==Jo42*X@T^vIy=Da<(
zk(0qd;K+vC^)Js0F*X-2jJy4A(*F+*b4JmSMLlu}1xi)>WQ6yC(u=37pUXO@geKG!
z^oo1NQf5X51`rkliUAX&qpqi)n|^YBajG6H7x+SH-7rWBw^A_FGvMO#1Lg%Q1(eLg
z73|??WNN1Cl9>(^vQlsg$#X6UF*G&tGcpT`%C$(!NO3VS4v$DND9JKSN;k_-^EI^e
z^YJwBceRBX2+0)aCM880<XBb|x_d=B7ZgUOdKq||6`Ht&hXxjw8sz#px%rxSn55=r
zWMz7#!%afX59lVk24rRXMU_`3T1IFW6qWkqRJd!qIXe54yE~g$M1-0ITjodkI~wGK
zg$3H8WxV|vPb7j^f%zAR1u=rHI5Yi5Qj7CKmWBo2nwle-Viqx4D6vE`g%~t31sF6j
zS}b5@Vq{_xk@xwh|D)-~&RZ|O%~${bF}gI$D$9VEjZ>@5qwPB{BO^B}gMp@@x`8Si
zb0`Zlk6cATa&bm#PL2Z5g1poeg~Wn_Vn_*5l%HQ>pd`U>WMF7!XlP_^00vQD0ZRiT
z15>Dgfr+7!fdRxgO)SPiOat?a6pB-m3ydvHiVO|P3<TKNfv!4d%f!gWs@=%Kpv0WS
zz_Ku-$k|Lgrdp!&bET-8=)&XnTYBHM*)eH~-cIOK)qS#ESa-#_87~Zj{j%opaC4rx
zX1Vr-5!=&UjV8ql<rf<~h+T0q&$;=Zdb{n)LgsxM9p^tVeTe!lC4cu!bIGc_mFE`o
z8}J%%16?c2&%(mY#NL1wILu9qj11+1N8kBa+P7Q_(ZBZ5dEwH~S!*}Qp1f)w@nPGe
z^a(fkOGD<IKK}DcwU6m*zZr+`-DYX=uq}Bed(PXwXz`2Xv$cX<LSyHvXuss;xZ1n(
z+>7vE`%@dI|7tlJBVE_v<n+f;e(}w8{;*Vsnu5-E92QS}3j=3~YMHfEozBq?>G~A0
z;iJ~s{0V8S9DL^z<HEjar0>$cpI^lBm1Aj$)tiJBtgQDla_cMQZdqCs9cn6`qTYJ>
zmk{@U{@ZVPHYWNm>~60Q?s`}K_2vzS3vZmiy?Ce0z42tIO-YRw3){+jO-dSOll5=R
zyk9f%*TaxW6ICakd9=NF)fF32Q6n}68+Oe+k?qqLL?parQ@2}~VHL9FhLm$ji^nvZ
zXLkD<#hKq+w=MdxD1<HY${Sa=7h%uiQbV^-UiqEjv-gt7=D9hA(?X}r<M`55`u5I)
zhgHV+&g$0MZcIFQaT9xlqT<CrYgQgV@4w`#pwGQFU=p@l#Ha>L!REjeYz$1n($Ex~
zuIK%-@VR;Q_WM7&`id>GQ+(`A23ZOQ=6GNVjx-QPq+kv(gPD<?*@=P0fB){?i4T7K
z+_;P@a!otSqc^PFPIflm^(NWt_*Z(n#%N_;GIq@|J0dujo$UeN+Y=WjPq;o)x>}cg
zG0Uq3Uds*;l}I@<W~-h(6wT<7c!T-6#pNo~)t)?&jQne(f;0|&&-Knz3$U4Gy=V8u
zjNE+wH;WxsU!SCQuIX~b_6fIFZTR=~{GN{8oH@!tNlePWwurvlmBKG1P&TXZc8~M%
z+r7KvS4b_gDH9YfY+AN!@y7J(+~ptcwz1tZ+H}%7F2Uzma#?8nZr+Q_p4+#4>8?*(
z>TqdIeM4~wTkC#?6R&(`HGj`%T(2vynP6%y?CSQ*$0&YkZkcfIMFrh^Wdht1o71H>
zub+MO&b>(&_9hqG?hV(rIatccyUJ_Un#Corgz`2AeGO*1oEIOwS+MnZ-l5s%ai8x*
zt+qIkt9aA-vd7v}6)$}Bw>Y*hh;WE04V*757;rYW>z=~mJ!}RO|8FWTjW<kr^Y^q<
z16RQ_1LwUy9~f#D@{8a9o-pV4gI(W?8v3+$tz79ji*uTL_LBf_MkWzv+-*1*XkcVO
zZ_%M^MQ?>6v{u5~WaxU(n_37xComdb=z7sBS%h9LW?WS+x*6y-4#Esa7A*BofHy1H
PXRJV|2ekGOCx{0CTnrq|
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..95fadc59cba10a5593a955f1cef77effd4bb4389
GIT binary patch
literal 2115
zc$^FHW@Zs#0D(!R9o|wg8k_upY!K!J;@rf%%(T?v61}YA{Jd%|1qCITNPJmpQE_H|
zo|2V<kq$^AFEKY2$WaObN-DTkl%(c?rNMFtwMqth26~1{T(w*QC>DS7Fx1fovO$;)
zh=W`mU3^_bGBS%5fT$!RRiP*~F(o%uAuYcM%q;;~lM1s&56!sQO_uCpObiSl%m)-p
zNi0d!&&*9sPt_~POYaQubLZuf;sSZn)59eQNKXS{4v@_@jD?RF7#Qz*x;TbZ%z1lm
zBPWA_z>y8N>tCK1Vr(v47<c>Kr2iir=8U2ti+bb|3Y4n$$q4TOr58_EKbLh*2~DUe
z=oR;jrOb>B3?M896aywkM_o@pH~r-N;#56YF7SoYx?zwMZlz$TXTZhf2h0mr3MiR}
zE7-%)$ka^NB{Ll;WToH~lIL6yVrXjOXJi%>m1~idk>X-v93GKkP?BYulx~)v=4)u_
z=i_PM?`jJ(5Rxg-O-hP1$g!*_boYvME+~vl^)m1_D>QKl4-G6VHOTdIa`QFuFiFkL
z$jbCehns|&AJ9#74amy&iz=^7w2aU$C@S^Isc_eJb9DA8cXu|ihzK<aw#<+6cQnWe
z3k$SG%Xn&2!u$GxnGS>nF@mi)GyO(Vi}OO3h6Udmn<JU*7BQ-^L^7EhG%*<)G%-pq
zU}j=uViM8+FIe^Jn1*=fv?B{0rs;2<&9czPfR~L^tIebBJ1-+6H!FjIrlGolDjRbs
z3p0;gML}|LMruxu0?_=t)D(rpf`Vd50a28nUt*vn!Ea<>XliI^WMKdXQD6ZJ10w@d
zsDOcqp^<?B#5heX#z9O2^NSRUQ<DpT!Bu2v5NROH#twAVIa?-1HV!a@nUS5@iGjs`
z|L)z14}SdIxQr`uO*_k@H>})Fb~fMjCfV!wS9-g~Xk}h9cFi$6A~=_w?E&B06Bj2>
zxIR<5T9<t>%c})m%ML8&H{dnk20BQVpM`~)iM;{M|IAH{j11{qe$!7rimjYK+vkSi
z9N!L|^6ODPqAFe2KUT^F7d)w+9RKVM<4&VkBN;hW&tr4VX0X;6J0G%d*uXLAa&BjI
zP}mBgj*G87x&pVg>j+$$b}O7meaiK+BOflQ$5=0Ch}{>>uv6xQ<aLEa?erV>qoX!^
z@cmW3xy$jJw$Svn^>bZbEWEHzK67f~+}JZ3vky#t)-l^yep%7KpoJn@5exV~Y>e;d
zd%fJ()Bd;4CyO}@22+}C(x2ptbY-ZXWZj_n*?Utz3kzd`+B3z2#|1;vs%Aa9)e+&u
zROY^i?Ye@j$V0cQ)ePVD`<#WVe(o{ubY=IGx)#1yrTS-K{*$<Qe%l@M=XfrNaEK`l
zoG&aGa5lE<p2FfiYz7nmZz?X0H%xi+_q0<3SHZK0re}L9dNo9rFgj1!zU60?yX~yk
z0@-uUSbk-j^IWw&KERuiNrV}91qcHTj11`2A-Y!dDh#2u5?-O9>p`!l5PD8v)LQ6z
o(Mu?VUM^-_<rTUa=-Cxvh9e7>%p2g%3icT*5b6P~{SW2=000^PSpWb4
--- a/taskcluster/ci/test/web-platform.yml
+++ b/taskcluster/ci/test/web-platform.yml
@@ -17,16 +17,17 @@ job-defaults:
 web-platform-tests:
     description: "Web platform test run"
     suite: web-platform-tests
     treeherder-symbol: tc-W(wpt)
     chunks:
         by-test-platform:
             macosx64/opt: 5
             macosx64/debug: 10
+            windows10-64-ccov/debug: 15
             default: 12
     max-run-time: 7200
     e10s:
         by-test-platform:
             windows7-32/debug: both
             default: true
     mozharness:
         chunked: true
--- a/testing/mozharness/mozharness/mozilla/testing/codecoverage.py
+++ b/testing/mozharness/mozharness/mozilla/testing/codecoverage.py
@@ -154,19 +154,19 @@ class CodeCoverageMixin(object):
 
         del os.environ['GCOV_PREFIX_STRIP']
         del os.environ['GCOV_PREFIX']
         del os.environ['JS_CODE_COVERAGE_OUTPUT_DIR']
 
         if not self.ccov_upload_disabled:
             dirs = self.query_abs_dirs()
 
-            # Package GCOV coverage data.
-            file_path_gcda = os.path.join(dirs['abs_blob_upload_dir'], 'code-coverage-gcda.zip')
-            self.run_command(['zip', '-r', file_path_gcda, '.'], cwd=self.gcov_dir)
+            # Zip gcda files (will be given in input to grcov).
+            file_path_gcda = 'code-coverage-gcda.zip'
+            self.run_command(['zip', '-q', '-0', '-r', file_path_gcda, '.'], cwd=self.gcov_dir)
 
             # Package JSVM coverage data.
             file_path_jsvm = os.path.join(dirs['abs_blob_upload_dir'], 'code-coverage-jsvm.zip')
             self.run_command(['zip', '-r', file_path_jsvm, '.'], cwd=self.jsvm_dir)
 
             # GRCOV post-processing
             # Download the gcno fom the build machine.
             self.download_file(self.url_to_gcno, file_name=None, parent_dir=self.grcov_dir)
--- a/testing/web-platform/meta/credential-management/credentialscontainer-create-basics.https.html.ini
+++ b/testing/web-platform/meta/credential-management/credentialscontainer-create-basics.https.html.ini
@@ -1,46 +1,27 @@
 [credentialscontainer-create-basics.https.html]
+  prefs: [security.webauth.webauthn: true]
+
   [navigator.credentials.create() with no argument.]
     expected: FAIL
 
   [navigator.credentials.create() with empty argument.]
     expected: FAIL
 
   [navigator.credentials.create() with valid PasswordCredentialData]
     expected: FAIL
 
   [navigator.credentials.create() with valid HTMLFormElement]
     expected: FAIL
 
-  [navigator.credentials.create() with bogus password data]
-    expected: FAIL
-
   [navigator.credentials.create() with valid FederatedCredentialData]
     expected: FAIL
 
-  [navigator.credentials.create() with bogus federated data]
-    expected: FAIL
-
   [navigator.credentials.create() with both PasswordCredentialData and FederatedCredentialData]
     expected: FAIL
 
-  [navigator.credentials.create() with bogus password and federated data]
-    expected: FAIL
-
   [navigator.credentials.create() with bogus data]
     expected: FAIL
 
-  [navigator.credentials.create() with bogus publicKey data]
-    expected: FAIL
-
   [navigator.credentials.create() returns PublicKeyCredential]
     expected: FAIL
 
-  [navigator.credentials.create() with bogus federated and publicKey data]
-    expected: FAIL
-
-  [navigator.credentials.create() with bogus password and publicKey data]
-    expected: FAIL
-
-  [navigator.credentials.create() with bogus password, federated, and publicKey data]
-    expected: FAIL
-
--- a/testing/web-platform/meta/credential-management/idl.https.html.ini
+++ b/testing/web-platform/meta/credential-management/idl.https.html.ini
@@ -1,51 +1,14 @@
 [idl.https.html]
-  [CredentialsContainer interface: existence and properties of interface object]
-    expected: FAIL
-
-  [CredentialsContainer interface object length]
-    expected: FAIL
-
-  [CredentialsContainer interface object name]
-    expected: FAIL
-
-  [CredentialsContainer interface: existence and properties of interface prototype object]
-    expected: FAIL
-
-  [CredentialsContainer interface: existence and properties of interface prototype object's "constructor" property]
-    expected: FAIL
-
-  [CredentialsContainer interface: operation get(CredentialRequestOptions)]
-    expected: FAIL
-
-  [CredentialsContainer interface: operation store(Credential)]
-    expected: FAIL
+  prefs: [security.webauth.webauthn: true]
 
   [CredentialsContainer interface: operation requireUserMediation()]
     expected: FAIL
 
-  [CredentialsContainer must be primary interface of navigator.credentials]
-    expected: FAIL
-
-  [Stringification of navigator.credentials]
-    expected: FAIL
-
-  [CredentialsContainer interface: navigator.credentials must inherit property "get" with the proper type (0)]
-    expected: FAIL
-
-  [CredentialsContainer interface: calling get(CredentialRequestOptions) on navigator.credentials with too few arguments must throw TypeError]
-    expected: FAIL
-
-  [CredentialsContainer interface: navigator.credentials must inherit property "store" with the proper type (1)]
-    expected: FAIL
-
-  [CredentialsContainer interface: calling store(Credential) on navigator.credentials with too few arguments must throw TypeError]
-    expected: FAIL
-
   [CredentialsContainer interface: navigator.credentials must inherit property "requireUserMediation" with the proper type (2)]
     expected: FAIL
 
   [PasswordCredential interface: existence and properties of interface object]
     expected: FAIL
 
   [PasswordCredential interface object length]
     expected: FAIL
@@ -135,46 +98,28 @@
     expected: FAIL
 
   [Credential interface: new FederatedCredential({ id: "id", provider: "https://example.com", iconURL: "https://example.com/", name: "name" }) must inherit property "id" with the proper type (0)]
     expected: FAIL
 
   [Credential interface: new FederatedCredential({ id: "id", provider: "https://example.com", iconURL: "https://example.com/", name: "name" }) must inherit property "type" with the proper type (1)]
     expected: FAIL
 
-  [CredentialsContainer interface: operation create(CredentialCreationOptions)]
-    expected: FAIL
-
   [CredentialsContainer interface: operation preventSilentAccess()]
     expected: FAIL
 
-  [CredentialsContainer interface: navigator.credentials must inherit property "create" with the proper type (2)]
-    expected: FAIL
-
-  [CredentialsContainer interface: calling create(CredentialCreationOptions) on navigator.credentials with too few arguments must throw TypeError]
-    expected: FAIL
-
   [CredentialsContainer interface: navigator.credentials must inherit property "preventSilentAccess" with the proper type (3)]
     expected: FAIL
 
   [PasswordCredential interface: attribute password]
     expected: FAIL
 
   [PasswordCredential interface: new PasswordCredential({ id: "id", password: "pencil", iconURL: "https://example.com/", name: "name" }) must inherit property "password" with the proper type (0)]
     expected: FAIL
 
-  [CredentialsContainer interface: navigator.credentials must inherit property "get(CredentialRequestOptions)" with the proper type]
-    expected: FAIL
-
-  [CredentialsContainer interface: navigator.credentials must inherit property "store(Credential)" with the proper type]
-    expected: FAIL
-
-  [CredentialsContainer interface: navigator.credentials must inherit property "create(CredentialCreationOptions)" with the proper type]
-    expected: FAIL
-
   [CredentialsContainer interface: navigator.credentials must inherit property "preventSilentAccess()" with the proper type]
     expected: FAIL
 
   [PasswordCredential interface: new PasswordCredential({ id: "id", password: "pencil", iconURL: "https://example.com/", name: "name" }) must inherit property "password" with the proper type]
     expected: FAIL
 
   [FederatedCredential interface: new FederatedCredential({ id: "id", provider: "https://example.com", iconURL: "https://example.com/", name: "name" }) must inherit property "provider" with the proper type]
     expected: FAIL
--- a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/script-type-and-language-js.html.ini
+++ b/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/script-type-and-language-js.html.ini
@@ -1,199 +1,10 @@
 [script-type-and-language-js.html]
-  [Script should run with type="application/ecmascript\\f"]
-    expected: FAIL
-
-  [Script should run with type="application/javascript\\f"]
-    expected: FAIL
-
-  [Script should run with type="application/x-ecmascript\\f"]
-    expected: FAIL
-
-  [Script should run with type="application/x-javascript\\f"]
-    expected: FAIL
-
-  [Script should run with type="\\fapplication/ecmascript"]
-    expected: FAIL
-
-  [Script should run with type="\\fapplication/javascript"]
-    expected: FAIL
-
-  [Script should run with type="\\fapplication/x-ecmascript"]
-    expected: FAIL
-
-  [Script should run with type="\\fapplication/x-javascript"]
-    expected: FAIL
-
-  [Script shouldn't run with type="application/ecmascript\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="application/javascript\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="application/x-ecmascript\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="application/x-javascript\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="application/ecmascript\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="application/javascript\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="application/x-ecmascript\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="application/x-javascript\\0foo"]
-    expected: FAIL
-
-  [Script should run with type="text/ecmascript\\f"]
-    expected: FAIL
-
-  [Script should run with type="text/javascript\\f"]
-    expected: FAIL
-
-  [Script should run with type="text/javascript1.0\\f"]
-    expected: FAIL
-
-  [Script should run with type="text/javascript1.1\\f"]
-    expected: FAIL
-
-  [Script should run with type="text/javascript1.2\\f"]
-    expected: FAIL
-
-  [Script should run with type="text/javascript1.3\\f"]
-    expected: FAIL
-
-  [Script should run with type="text/javascript1.4\\f"]
-    expected: FAIL
-
-  [Script should run with type="text/javascript1.5\\f"]
-    expected: FAIL
-
-  [Script should run with type="text/jscript\\f"]
-    expected: FAIL
-
-  [Script should run with type="text/livescript\\f"]
-    expected: FAIL
-
-  [Script should run with type="text/x-ecmascript\\f"]
-    expected: FAIL
-
-  [Script should run with type="text/x-javascript\\f"]
-    expected: FAIL
-
-  [Script should run with type="\\ftext/ecmascript"]
-    expected: FAIL
-
-  [Script should run with type="\\ftext/javascript"]
-    expected: FAIL
-
-  [Script should run with type="\\ftext/javascript1.0"]
-    expected: FAIL
-
-  [Script should run with type="\\ftext/javascript1.1"]
-    expected: FAIL
-
-  [Script should run with type="\\ftext/javascript1.2"]
-    expected: FAIL
-
-  [Script should run with type="\\ftext/javascript1.3"]
-    expected: FAIL
-
-  [Script should run with type="\\ftext/javascript1.4"]
-    expected: FAIL
-
-  [Script should run with type="\\ftext/javascript1.5"]
-    expected: FAIL
-
-  [Script should run with type="\\ftext/jscript"]
-    expected: FAIL
-
-  [Script should run with type="\\ftext/livescript"]
-    expected: FAIL
-
-  [Script should run with type="\\ftext/x-ecmascript"]
-    expected: FAIL
-
-  [Script should run with type="\\ftext/x-javascript"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/ecmascript\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript1.0\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript1.1\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript1.2\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript1.3\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript1.4\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript1.5\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/jscript\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/livescript\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/x-ecmascript\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/x-javascript\\0"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/ecmascript\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript1.0\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript1.1\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript1.2\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript1.3\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript1.4\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/javascript1.5\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/jscript\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/livescript\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/x-ecmascript\\0foo"]
-    expected: FAIL
-
-  [Script shouldn't run with type="text/x-javascript\\0foo"]
+  [Script shouldn't run with type=" "]
     expected: FAIL
 
   [Script should run with language="ecmascript"]
     expected: FAIL
 
   [Script should run with language="jscript"]
     expected: FAIL
 
@@ -209,9 +20,8 @@
   [Script should run with language="JSCRIPT"]
     expected: FAIL
 
   [Script should run with language="X-ECMASCRIPT"]
     expected: FAIL
 
   [Script should run with language="X-JAVASCRIPT"]
     expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/script-type-and-language-with-params.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[script-type-and-language-with-params.html]
-  [A script with a charset param in its type should not run]
-    expected: FAIL
-
-  [A script with an x-test param in its type should not run]
-    expected: FAIL
-
-  [A script with a charset param in its type should not run, even with language=javascript]
-    expected: FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/webauthn/__dir__.ini
@@ -0,0 +1,1 @@
+prefs: [security.webauth.webauthn:true]
--- a/third_party/rust/cose-c/.cargo-checksum.json
+++ b/third_party/rust/cose-c/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"6689411cf004e6ebc4645105de26492adbea6f690f9184119cf1689829ff098a","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","include/cosec.h":"9e952f6bf578c812e67a93c3c810f4aaa57d365932fe8d01f36f587e8aa32538","src/lib.rs":"d10a17e4840187711d85058bf4afdbfbda88c74a9483921ee48a1bfc0cc5ff70"},"package":"07cc8bb85ec2e93541ef9369b85a4b6fb7732bc7f4854d317eab20e726b0fc2f"}
\ No newline at end of file
+{"files":{"Cargo.toml":"6e5aa986e80c9f848f8219f46d5e6d445609a3db70da9793f920c56c18814b7d","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","include/cosec.h":"0c6ebd84b6e1ee61a710f86416fc9092653292479556c713c83f193f26ac09b9","src/lib.rs":"0fef8341439e55682d7a7e50dead28427832b5fbd28ca48f60b00277c8a4b9b1"},"package":"49726015ab0ca765144fcca61e4a7a543a16b795a777fa53f554da2fffff9a94"}
\ No newline at end of file
--- a/third_party/rust/cose-c/Cargo.toml
+++ b/third_party/rust/cose-c/Cargo.toml
@@ -7,20 +7,20 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cose-c"
-version = "0.1.1"
+version = "0.1.5"
 authors = ["Franziskus Kiefer <franziskuskiefer@gmail.com>"]
 description = "C API for the cose crate"
 keywords = ["cose", "jose", "cbor"]
 license = "MPL-2.0"
 repository = "https://github.com/franziskuskiefer/cose-c-api"
 
 [lib]
 name = "cosec"
 path = "src/lib.rs"
 [dependencies.cose]
-version = "0.1.2"
+version = "0.1.4"
--- a/third_party/rust/cose-c/include/cosec.h
+++ b/third_party/rust/cose-c/include/cosec.h
@@ -17,16 +17,18 @@ typedef bool (*cose_verify_callback)(con
                                      size_t payload_len,
                                      const uint8_t** cert_chain,
                                      size_t cert_chain_len,
                                      const size_t* certs_len,
                                      const uint8_t* ee_cert,
                                      size_t ee_cert_len,
                                      const uint8_t* signature,
                                      size_t signature_len,
-                                     uint8_t algorithm);
+                                     uint8_t algorithm,
+                                     void* ctx);
 bool
 verify_cose_signature_ffi(const uint8_t* payload,
                           size_t payload_len,
                           const uint8_t* signature,
                           size_t signature_len,
+                          void* ctx,
                           cose_verify_callback);
 }
--- a/third_party/rust/cose-c/src/lib.rs
+++ b/third_party/rust/cose-c/src/lib.rs
@@ -2,39 +2,42 @@
  * 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/. */
 
 extern crate cose;
 
 use std::slice;
 use cose::decoder::decode_signature;
 use cose::SignatureAlgorithm;
+use std::os::raw;
 
 unsafe fn from_raw(ptr: *const u8, len: usize) -> Vec<u8> {
     slice::from_raw_parts(ptr, len).to_vec()
 }
 
 type VerifyCallback = extern "C" fn(*const u8, /* payload */
                                     usize, /* payload len */
                                     *const *const u8, /* cert_chain */
                                     usize, /* # certs */
                                     *const usize, /* cert lengths in cert_chain */
                                     *const u8, /* signer cert */
                                     usize, /* signer cert len */
                                     *const u8, /* signature bytes */
                                     usize, /* signature len */
-                                    u8 /* signature algorithm */)
+                                    u8, /* signature algorithm */
+                                    *const raw::c_void /* some context of the app */)
                                     -> bool;
 
 #[no_mangle]
 pub extern "C" fn verify_cose_signature_ffi(
     payload: *const u8,
     payload_len: usize,
     cose_signature: *const u8,
     cose_signature_len: usize,
+    ctx: *const raw::c_void,
     verify_callback: VerifyCallback,
 ) -> bool {
     if payload.is_null() || cose_signature.is_null() || payload_len == 0 ||
         cose_signature_len == 0
     {
         return false;
     }
 
@@ -75,11 +78,12 @@ pub extern "C" fn verify_cose_signature_
             certs.as_ptr(),
             certs.len(),
             cert_lens.as_ptr(),
             cose_signature.signer_cert.as_ptr(),
             cose_signature.signer_cert.len(),
             signature_bytes.as_ptr(),
             signature_bytes.len(),
             signature_type,
+            ctx,
         )
     });
 }
--- a/third_party/rust/cose/.cargo-checksum.json
+++ b/third_party/rust/cose/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".travis.yml":"be3532bc6d5d823090206ad957c8705436960d1918a2c577342f6914a233ca98","Cargo.toml":"5eb5257aced25840b3af43757478e4dfa38e2f222cb25794ffeeb681b6a46ce2","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"42a12b9a8944a2888ce2622bb03c06850163ab738917414e3413b63be9257a8a","build.rs":"a2b798bbeaf8ef19a9bd8c1e24b3fd3899a5b4b3e121e5e09794e4e2b35971dd","rustfmt.toml":"e97717e906fcd3eeb86dcee52ed26f13e1884597b016a27172229d9c78dd3d57","src/cbor/decoder.rs":"b9e375489131aea75fb461c9ee96e45595e08957c90179f2c449226a31b7e4c5","src/cbor/mod.rs":"f5b767eedbee01b3f697afb2dce777c6043e6fea6f9a7eab8387560caaa40100","src/cbor/serializer.rs":"d86f0123f364046c8c18b45e109437b16c24d29bc7ef01c12a7c465e89878836","src/cbor/test_decoder.rs":"6a47f0f98f54a343f12c78033c94c5892b0a5b5e62de251bef3a722f358978ab","src/cbor/test_serializer.rs":"984fbe0520e77d078fb2e2c60e4e0df077d40ede644b1b92651f3a0696377511","src/cose.rs":"1a5c23f31863c58838f4aa94c2940e9f18252929c990d2a9522490e56593710e","src/decoder.rs":"ce86fd2f72cf02185ea724d63e5cb24aaea9ff6a2f3137c20322764a3ea9d15e","src/nss.rs":"e17101aa957367ee025afd5af37d72a955d9b79098ab7db1631f93b6479230a3","src/test_cose.rs":"35798ef9ee5849204b36a69b07969c0b4f3976d0e44ccfff6f413a2e3684f76b","src/test_nss.rs":"51ececb4a8fd8ddba7e1af179b9326e38a838d4693998092f842db5f30e75703","src/test_setup.rs":"b2c8d5b4a20013fd89bcc9d5732af509331a648a1163a9e44b47e51dde2b6308","src/util.rs":"fbc1a2051230156c2504efcff5044fbf54a6f925aa7dfb97c211208348364425","src/util_test.rs":"49dde5be7202aa2fa3f7ac6d36de189739cd5538e378f5c0a27161b9185e9ca6","tools/certs/certs.md":"7a1acd946f5bb5b9b21ebd7653ef9d5746a1ea237131a69218a91dc26eda545a","tools/certs/certs.sh":"a06e1a7bf99316c7800e388d20c1630da7449937635600d9f21d8d93907011bf","tools/certs/ee-p256.certspec":"5a7246c0abf1ee08edb858ce2fd38010de7785a0e8652f2d9a0b7eee7aa39213","tools/certs/ee-p256.keyspec":"eabd2839f9e57cf2c372e686e5856cf651d7f07d0d396b3699d1d228b5931945","tools/certs/ee-p384.certspec":"d2e4fdd6d8f02f22bffa800ac2b7f899f5d826528e7b7d3248e1abea15cd33bd","tools/certs/ee-p521.certspec":"7ad1fc3cdf024dfa7213f3a2875af0ccfa2bd73fddcfaf73223aa25b24ee2cad","tools/certs/ee-rsa.certspec":"dd69ecbb1cdf322fb8ef6eb50c2f033b62e7983b5448b96f1965eee8f85b7bde","tools/certs/int-p256.certspec":"b42a2286339455626b9a8b6c0811b031bf269440c6fcef7478796d02c5491364","tools/certs/int-rsa.certspec":"a0942438c72a3ce83b54c04e4a5d4bff08036c2c9feb7d75a7105bfa4fdc5499","tools/certs/root-p256.certspec":"99c1bb07505ddfc3ada5737d8a1bf4cff7b1a70a79abda9fd45fc3a6e72061fc","tools/certs/root-rsa.certspec":"67903313b6058aa98be0d98564577b0c878c868b6f2a8758f27bb7af17616d8e"},"package":"ec10816629f38fa557f08e199a3474fab954f4c8d2645550367235afa6e5646b"}
\ No newline at end of file
+{"files":{".travis.yml":"c05a8cdd57b8969a1ab3547181b3d74079b8493132893c15cf3c4f479327359b","Cargo.toml":"40534ef8d01b0269e2ca3b00c4d14f7523222bc85611ee07afcffea45a71ef4b","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"7b9676ec9ed5d7ac38f461b1b257eb0bd80568e732994fb26fa929ce5fe503af","build.rs":"a2b798bbeaf8ef19a9bd8c1e24b3fd3899a5b4b3e121e5e09794e4e2b35971dd","examples/sign_verify/main.rs":"fbe4b9c73b23e1ef364126f453f749fefb67ab45703bf809a5eed910a25e461e","examples/sign_verify/nss.rs":"a1d133142efc0ac6564f0b9587890587f1ecaa7404ac0c4c8907de6d43de3267","examples/sign_verify/test_nss.rs":"be41ebe0a82b6172297b10c13767e4768f0b613ac331b554f6e8c2c7a20c0bc8","examples/sign_verify/test_setup.rs":"82330118e4284d9bf788dbec9e637ab4a3b53fd4ec9c7efaed0e996ffa084de4","examples/sign_verify/util_test.rs":"48d52f3ca3e93b670a1d69f8443358260c1ae61d7977a59d922696811320d4c3","rustfmt.toml":"e97717e906fcd3eeb86dcee52ed26f13e1884597b016a27172229d9c78dd3d57","src/cose.rs":"104e06843f4cdffe2ca6f42f46c51c79d685c18d2ad92b65811e3ceffbd90e07","src/decoder.rs":"a4d2dcd44d179fabdac6ce99cc3512ece3164ba48beab9f313ad85db466c3a55","src/test_cose.rs":"849ec936a00eb438a08eb85380b3e4ba8d8c5a5cf674b272e0fd8e671ab6d5ca","src/test_setup.rs":"e26f290831343cbb4e2b2ec7d1be34c7b900eb8c87abd6f40629372a87b6e992","src/util.rs":"8cdcdc8a120e71a772af61fa63ffa2d2d2eb572d8a53da3b5f1ce9da784f2662","tools/certs/certs.md":"7a1acd946f5bb5b9b21ebd7653ef9d5746a1ea237131a69218a91dc26eda545a","tools/certs/certs.sh":"a06e1a7bf99316c7800e388d20c1630da7449937635600d9f21d8d93907011bf","tools/certs/ee-p256.certspec":"5a7246c0abf1ee08edb858ce2fd38010de7785a0e8652f2d9a0b7eee7aa39213","tools/certs/ee-p256.keyspec":"eabd2839f9e57cf2c372e686e5856cf651d7f07d0d396b3699d1d228b5931945","tools/certs/ee-p384.certspec":"d2e4fdd6d8f02f22bffa800ac2b7f899f5d826528e7b7d3248e1abea15cd33bd","tools/certs/ee-p521.certspec":"7ad1fc3cdf024dfa7213f3a2875af0ccfa2bd73fddcfaf73223aa25b24ee2cad","tools/certs/ee-rsa.certspec":"dd69ecbb1cdf322fb8ef6eb50c2f033b62e7983b5448b96f1965eee8f85b7bde","tools/certs/int-p256.certspec":"b42a2286339455626b9a8b6c0811b031bf269440c6fcef7478796d02c5491364","tools/certs/int-rsa.certspec":"a0942438c72a3ce83b54c04e4a5d4bff08036c2c9feb7d75a7105bfa4fdc5499","tools/certs/root-p256.certspec":"99c1bb07505ddfc3ada5737d8a1bf4cff7b1a70a79abda9fd45fc3a6e72061fc","tools/certs/root-rsa.certspec":"67903313b6058aa98be0d98564577b0c878c868b6f2a8758f27bb7af17616d8e"},"package":"72fa26cb151d3ae4b70f63d67d0fed57ce04220feafafbae7f503bef7aae590d"}
\ No newline at end of file
--- a/third_party/rust/cose/.travis.yml
+++ b/third_party/rust/cose/.travis.yml
@@ -1,31 +1,33 @@
 sudo: true
+dist: trusty
 language: rust
 cache: cargo
 rust:
   - stable
   - beta
   - nightly
 
 addons:
   apt:
     packages:
       - build-essential
       - libnss3-dev
 
-install:
+#install:
 # Apparently cargo install returns a nonzero exit status if
 # caching succeeds, so just make this always "succeed".
-  - (cargo install rustfmt || true)
+#  - (cargo install rustfmt --force || true)
 
 script:
 # The NSS version in Ubuntu is too old. Get a newer one.
 - |
   wget http://de.archive.ubuntu.com/ubuntu/pool/main/n/nss/libnss3_3.32-1ubuntu3_amd64.deb
   wget http://de.archive.ubuntu.com/ubuntu/pool/main/n/nspr/libnspr4_4.16-1ubuntu2_amd64.deb
   sudo dpkg -i libnspr4_4.16-1ubuntu2_amd64.deb
   sudo dpkg -i libnss3_3.32-1ubuntu3_amd64.deb
-- |
-  cargo fmt -- --write-mode=diff
+#- |
+#  cargo fmt -- --write-mode=diff
 - |
   cargo build --features "$FEATURES" &&
-  cargo test
+  cargo test &&
+  cargo run --example sign_verify
--- a/third_party/rust/cose/Cargo.toml
+++ b/third_party/rust/cose/Cargo.toml
@@ -7,24 +7,26 @@
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 name = "cose"
-version = "0.1.2"
+version = "0.1.4"
 authors = ["Franziskus Kiefer <franziskuskiefer@gmail.com>", "David Keeler <dkeeler@mozilla.com>"]
 build = "build.rs"
 description = "Library to use COSE (https://tools.ietf.org/html/rfc8152) in Rust"
-keywords = ["cose", "jose", "cbor"]
+keywords = ["cose", "jose"]
 license = "MPL-2.0"
 repository = "https://github.com/franziskuskiefer/cose-rust"
 
 [lib]
 name = "cose"
 path = "src/cose.rs"
+[dependencies.moz_cbor]
+version = "0.1.0"
 [dev-dependencies.scopeguard]
 version = "0.3"
 
 [features]
 default = []
--- a/third_party/rust/cose/README.md
+++ b/third_party/rust/cose/README.md
@@ -8,8 +8,19 @@ A Rust library for [COSE](https://tools.
 **THIS IS WORK IN PROGRESS. DO NOT USE YET.**
 
 ## Build instructions
 
 If NSS is not installed in the path, use `NSS_LIB_DIR` to set the library path where
 we can find the NSS libraries.
 
     cargo build
+
+### Run Tests and Examples
+
+To run tests and examples you need NSS in your library path. Tests can be run
+with
+
+    cargo test
+
+and examples with
+
+    cargo run --example sign_verify
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/examples/sign_verify/main.rs
@@ -0,0 +1,259 @@
+extern crate moz_cbor as cbor;
+extern crate cose;
+
+#[macro_use(defer)]
+extern crate scopeguard;
+
+mod nss;
+mod test_nss;
+mod test_setup;
+mod util_test;
+
+use util_test::{sign, verify_signature};
+use test_setup as test;
+use std::str::FromStr;
+use cose::{CoseError, SignatureAlgorithm};
+
+// All keys here are from pykey.py/pycert.py from mozilla-central.
+// Certificates can be generated with tools/certs/certs.sh and mozilla-central.
+
+#[derive(Debug)]
+pub struct SignatureParameters<'a> {
+    certificate: &'a [u8],
+    algorithm: SignatureAlgorithm,
+    pkcs8: &'a [u8],
+}
+
+#[derive(Debug)]
+pub struct Signature<'a> {
+    parameter: &'a SignatureParameters<'a>,
+    signature_bytes: Vec<u8>,
+}
+
+const P256_PARAMS: SignatureParameters = SignatureParameters {
+    certificate: &test::P256_EE,
+    algorithm: SignatureAlgorithm::ES256,
+    pkcs8: &test::PKCS8_P256_EE,
+};
+const P384_PARAMS: SignatureParameters = SignatureParameters {
+    certificate: &test::P384_EE,
+    algorithm: SignatureAlgorithm::ES384,
+    pkcs8: &test::PKCS8_P384_EE,
+};
+const P521_PARAMS: SignatureParameters = SignatureParameters {
+    certificate: &test::P521_EE,
+    algorithm: SignatureAlgorithm::ES512,
+    pkcs8: &test::PKCS8_P521_EE,
+};
+
+fn test_verify(payload: &[u8], cert_chain: &[&[u8]], params_vec: Vec<SignatureParameters>) {
+    test::setup();
+    let cose_signature = sign(payload, cert_chain, &params_vec);
+    assert!(cose_signature.is_ok());
+    let cose_signature = cose_signature.unwrap();
+
+    // Verify signature.
+    assert!(verify_signature(payload, cose_signature).is_ok());
+}
+
+fn test_verify_modified_payload(
+    payload: &mut [u8],
+    cert_chain: &[&[u8]],
+    params_vec: Vec<SignatureParameters>,
+) {
+    test::setup();
+    let cose_signature = sign(payload, cert_chain, &params_vec);
+    assert!(cose_signature.is_ok());
+    let cose_signature = cose_signature.unwrap();
+
+    // Verify signature.
+    payload[0] = !payload[0];
+    let verify_result = verify_signature(payload, cose_signature);
+    assert!(verify_result.is_err());
+    assert_eq!(verify_result, Err(CoseError::VerificationFailed));
+}
+
+fn test_verify_modified_signature(
+    payload: &[u8],
+    cert_chain: &[&[u8]],
+    params_vec: Vec<SignatureParameters>,
+) {
+    test::setup();
+    let cose_signature = sign(payload, cert_chain, &params_vec);
+    assert!(cose_signature.is_ok());
+    let mut cose_signature = cose_signature.unwrap();
+
+    // Tamper with the cose signature.
+    let len = cose_signature.len();
+    cose_signature[len - 15] = !cose_signature[len - 15];
+
+    // Verify signature.
+    let verify_result = verify_signature(payload, cose_signature);
+    assert!(verify_result.is_err());
+    assert_eq!(verify_result, Err(CoseError::VerificationFailed));
+}
+
+// This can be used with inconsistent parameters that make the verification fail.
+// In particular, the signing key does not match the certificate used to verify.
+fn test_verify_verification_fails(
+    payload: &[u8],
+    cert_chain: &[&[u8]],
+    params_vec: Vec<SignatureParameters>,
+) {
+    test::setup();
+    let cose_signature = sign(payload, cert_chain, &params_vec);
+    assert!(cose_signature.is_ok());
+    let cose_signature = cose_signature.unwrap();
+
+    // Verify signature.
+    let verify_result = verify_signature(payload, cose_signature);
+    assert!(verify_result.is_err());
+    assert_eq!(verify_result, Err(CoseError::VerificationFailed));
+}
+
+fn test_cose_sign_verify() {
+    let payload = b"This is the content.";
+
+    // P256
+    let certs: [&[u8]; 2] = [&test::P256_ROOT,
+                             &test::P256_INT];
+    let params_vec = vec![P256_PARAMS];
+    test_verify(payload, &certs, params_vec);
+
+    // P256, no other certs.
+    let certs: [&[u8]; 0] = [];
+    let params_vec = vec![P256_PARAMS];
+    test_verify(payload, &certs, params_vec);
+
+    // P384
+    let params_vec = vec![P384_PARAMS];
+    test_verify(payload, &certs, params_vec);
+
+    // P521
+    let params_vec = vec![P521_PARAMS];
+    test_verify(payload, &certs, params_vec);
+}
+
+fn test_cose_verify_xpi_signature() {
+    // This signature was created with sign_app.py from m-c.
+    test::setup();
+    assert!(verify_signature(&test::XPI_PAYLOAD, test::XPI_SIGNATURE.to_vec()).is_ok());
+}
+
+fn test_cose_sign_verify_modified_payload() {
+    let mut payload = String::from_str("This is the content.")
+        .unwrap()
+        .into_bytes();
+    let certs: [&[u8]; 2] = [&test::P256_ROOT,
+                             &test::P256_INT];
+    let params_vec = vec![P256_PARAMS];
+    test_verify_modified_payload(&mut payload, &certs, params_vec);
+}
+
+fn test_cose_sign_verify_wrong_cert() {
+    let payload = b"This is the content.";
+    let certs: [&[u8]; 2] = [&test::P256_ROOT,
+                             &test::P256_INT];
+    let params = SignatureParameters {
+        certificate: &test::P384_EE,
+        algorithm: SignatureAlgorithm::ES256,
+        pkcs8: &test::PKCS8_P256_EE,
+    };
+    let params_vec = vec![params];
+    test_verify_verification_fails(payload, &certs, params_vec);
+}
+
+fn test_cose_sign_verify_tampered_signature() {
+    let payload = b"This is the content.";
+    let certs: [&[u8]; 2] = [&test::P256_ROOT,
+                             &test::P256_INT];
+    let params_vec = vec![P256_PARAMS];
+    test_verify_modified_signature(payload, &certs, params_vec);
+}
+
+const RSA_PARAMS: SignatureParameters = SignatureParameters {
+    certificate: &test::RSA_EE,
+    algorithm: SignatureAlgorithm::PS256,
+    pkcs8: &test::PKCS8_RSA_EE,
+};
+
+fn test_cose_sign_verify_rsa() {
+    let payload = b"This is the RSA-signed content.";
+    let certs: [&[u8]; 2] = [&test::RSA_ROOT,
+                             &test::RSA_INT];
+    let params_vec = vec![RSA_PARAMS];
+    test_verify(payload, &certs, params_vec);
+}
+
+fn test_cose_sign_verify_rsa_modified_payload() {
+    let mut payload = String::from_str("This is the RSA-signed content.")
+        .unwrap()
+        .into_bytes();
+    let certs: [&[u8]; 2] = [&test::RSA_ROOT,
+                             &test::RSA_INT];
+    let params_vec = vec![RSA_PARAMS];
+    test_verify_modified_payload(&mut payload, &certs, params_vec);
+}
+
+fn test_cose_sign_verify_rsa_tampered_signature() {
+    let payload = b"This is the RSA-signed content.";
+    let certs: [&[u8]; 2] = [&test::RSA_ROOT,
+                             &test::RSA_INT];
+    let params_vec = vec![RSA_PARAMS];
+    test_verify_modified_signature(payload, &certs, params_vec);
+}
+
+fn test_cose_sign_verify_two_signatures() {
+    let payload = b"This is the content.";
+    let certs: [&[u8]; 4] = [&test::P256_ROOT,
+                             &test::P256_INT,
+                             &test::RSA_ROOT,
+                             &test::RSA_INT];
+    let params_vec = vec![P256_PARAMS,
+                          RSA_PARAMS];
+    test_verify(payload, &certs, params_vec);
+}
+
+fn test_cose_sign_verify_two_signatures_tampered_payload() {
+    let mut payload = String::from_str("This is the content.")
+        .unwrap()
+        .into_bytes();
+    let certs: [&[u8]; 4] = [&test::P256_ROOT,
+                             &test::P256_INT,
+                             &test::RSA_ROOT,
+                             &test::RSA_INT];
+    let params_vec = vec![P256_PARAMS,
+                          RSA_PARAMS];
+    test_verify_modified_payload(&mut payload, &certs, params_vec);
+}
+
+fn test_cose_sign_verify_two_signatures_tampered_signature() {
+    let payload = b"This is the content.";
+    let certs: [&[u8]; 4] = [&test::P256_ROOT,
+                             &test::P256_INT,
+                             &test::RSA_ROOT,
+                             &test::RSA_INT];
+    let params_vec = vec![P256_PARAMS,
+                          RSA_PARAMS];
+    test_verify_modified_signature(payload, &certs, params_vec);
+}
+
+fn main() {
+    // Basic NSS exmaple usage.
+    test_nss::test_nss_sign_verify();
+    test_nss::test_nss_sign_verify_different_payload();
+    test_nss::test_nss_sign_verify_wrong_cert();
+
+    // COSE sign/verify example usages.
+    test_cose_sign_verify_two_signatures_tampered_signature();
+    test_cose_sign_verify_two_signatures_tampered_payload();
+    test_cose_sign_verify_two_signatures();
+    test_cose_sign_verify_rsa_tampered_signature();
+    test_cose_sign_verify_rsa_modified_payload();
+    test_cose_sign_verify_rsa();
+    test_cose_sign_verify_tampered_signature();
+    test_cose_sign_verify_wrong_cert();
+    test_cose_sign_verify_modified_payload();
+    test_cose_verify_xpi_signature();
+    test_cose_sign_verify();
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/examples/sign_verify/nss.rs
@@ -0,0 +1,356 @@
+use std::marker::PhantomData;
+use std::{mem, ptr};
+use std::os::raw;
+use std::os::raw::c_char;
+use cose::SignatureAlgorithm;
+
+type SECItemType = raw::c_uint; // TODO: actually an enum - is this the right size?
+const SI_BUFFER: SECItemType = 0; // called siBuffer in NSS
+
+#[repr(C)]
+struct SECItem {
+    typ: SECItemType,
+    data: *const u8,
+    len: raw::c_uint,
+}
+
+impl SECItem {
+    fn maybe_new(data: &[u8]) -> Result<SECItem, NSSError> {
+        if data.len() > u32::max_value() as usize {
+            return Err(NSSError::InputTooLarge);
+        }
+        Ok(SECItem {
+            typ: SI_BUFFER,
+            data: data.as_ptr(),
+            len: data.len() as u32,
+        })
+    }
+
+    fn maybe_from_parts(data: *const u8, len: usize) -> Result<SECItem, NSSError> {
+        if len > u32::max_value() as usize {
+            return Err(NSSError::InputTooLarge);
+        }
+        Ok(SECItem {
+            typ: SI_BUFFER,
+            data: data,
+            len: len as u32,
+        })
+    }
+}
+
+/// Many NSS APIs take constant data input as SECItems. Some, however, output data as SECItems.
+/// To represent this, we define another type of mutable SECItem.
+#[repr(C)]
+struct SECItemMut<'a> {
+    typ: SECItemType,
+    data: *mut u8,
+    len: raw::c_uint,
+    _marker: PhantomData<&'a mut Vec<u8>>,
+}
+
+impl<'a> SECItemMut<'a> {
+    /// Given a mutable reference to a Vec<u8> that has a particular allocated capacity, create a
+    /// SECItemMut that points to the vec and has the same capacity.
+    /// The input vec is not expected to have any actual contents, and in any case is cleared.
+    fn maybe_from_empty_preallocated_vec(vec: &'a mut Vec<u8>) -> Result<SECItemMut<'a>, NSSError> {
+        if vec.capacity() > u32::max_value() as usize {
+            return Err(NSSError::InputTooLarge);
+        }
+        vec.clear();
+        Ok(SECItemMut {
+            typ: SI_BUFFER,
+            data: vec.as_mut_ptr(),
+            len: vec.capacity() as u32,
+            _marker: PhantomData,
+        })
+    }
+}
+
+#[repr(C)]
+struct CkRsaPkcsPssParams {
+    // Called CK_RSA_PKCS_PSS_PARAMS in NSS
+    hash_alg: CkMechanismType, // Called hashAlg in NSS
+    mgf: CkRsaPkcsMgfType,
+    s_len: raw::c_ulong, // Called sLen in NSS
+}
+
+impl CkRsaPkcsPssParams {
+    fn new() -> CkRsaPkcsPssParams {
+        CkRsaPkcsPssParams {
+            hash_alg: CKM_SHA256,
+            mgf: CKG_MGF1_SHA256,
+            s_len: 32,
+        }
+    }
+
+    fn get_params_item(&self) -> Result<SECItem, NSSError> {
+        // This isn't entirely NSS' fault, but it mostly is.
+        let params_ptr: *const CkRsaPkcsPssParams = self;
+        let params_ptr: *const u8 = params_ptr as *const u8;
+        let params_secitem =
+            SECItem::maybe_from_parts(params_ptr, mem::size_of::<CkRsaPkcsPssParams>())?;
+        Ok(params_secitem)
+    }
+}
+
+type CkMechanismType = raw::c_ulong; // called CK_MECHANISM_TYPE in NSS
+const CKM_ECDSA: CkMechanismType = 0x0000_1041;
+const CKM_RSA_PKCS_PSS: CkMechanismType = 0x0000_000D;
+const CKM_SHA256: CkMechanismType = 0x0000_0250;
+
+type CkRsaPkcsMgfType = raw::c_ulong; // called CK_RSA_PKCS_MGF_TYPE in NSS
+const CKG_MGF1_SHA256: CkRsaPkcsMgfType = 0x0000_0002;
+
+type SECStatus = raw::c_int; // TODO: enum - right size?
+const SEC_SUCCESS: SECStatus = 0; // Called SECSuccess in NSS
+const SEC_FAILURE: SECStatus = -1; // Called SECFailure in NSS
+
+enum SECKEYPublicKey {}
+enum SECKEYPrivateKey {}
+enum PK11SlotInfo {}
+enum CERTCertificate {}
+enum CERTCertDBHandle {}
+
+const SHA256_LENGTH: usize = 32;
+const SHA384_LENGTH: usize = 48;
+const SHA512_LENGTH: usize = 64;
+
+// TODO: ugh this will probably have a platform-specific name...
+#[link(name = "nss3")]
+extern "C" {
+    fn PK11_HashBuf(
+        hashAlg: HashAlgorithm,
+        out: *mut u8,
+        data_in: *const u8, // called "in" in NSS
+        len: raw::c_int,
+    ) -> SECStatus;
+    fn PK11_VerifyWithMechanism(
+        key: *const SECKEYPublicKey,
+        mechanism: CkMechanismType,
+        param: *const SECItem,
+        sig: *const SECItem,
+        hash: *const SECItem,
+        wincx: *const raw::c_void,
+    ) -> SECStatus;
+
+    fn SECKEY_DestroyPublicKey(pubk: *const SECKEYPublicKey);
+
+    fn CERT_GetDefaultCertDB() -> *const CERTCertDBHandle;
+    fn CERT_DestroyCertificate(cert: *mut CERTCertificate);
+    fn CERT_NewTempCertificate(
+        handle: *const CERTCertDBHandle,
+        derCert: *const SECItem,
+        nickname: *const c_char,
+        isperm: bool,
+        copyDER: bool,
+    ) -> *mut CERTCertificate;
+    fn CERT_ExtractPublicKey(cert: *const CERTCertificate) -> *const SECKEYPublicKey;
+
+    fn PK11_ImportDERPrivateKeyInfoAndReturnKey(
+        slot: *mut PK11SlotInfo,
+        derPKI: *const SECItem,
+        nickname: *const SECItem,
+        publicValue: *const SECItem,
+        isPerm: bool,
+        isPrivate: bool,
+        keyUsage: u32,
+        privk: *mut *mut SECKEYPrivateKey,
+        wincx: *const u8,
+    ) -> SECStatus;
+    fn PK11_GetInternalSlot() -> *mut PK11SlotInfo;
+    fn PK11_FreeSlot(slot: *mut PK11SlotInfo);
+    fn PK11_SignatureLen(key: *const SECKEYPrivateKey) -> usize;
+    fn PK11_SignWithMechanism(
+        key: *const SECKEYPrivateKey,
+        mech: CkMechanismType,
+        param: *const SECItem,
+        sig: *mut SECItemMut,
+        hash: *const SECItem,
+    ) -> SECStatus;
+}
+
+/// An error type describing errors that may be encountered during verification.
+#[derive(Debug, PartialEq)]
+pub enum NSSError {
+    ImportCertError,
+    DecodingPKCS8Failed,
+    InputTooLarge,
+    LibraryFailure,
+    SignatureVerificationFailed,
+    SigningFailed,
+    ExtractPublicKeyFailed,
+}
+
+// https://searchfox.org/nss/rev/990c2e793aa731cd66238c6c4f00b9473943bc66/lib/util/secoidt.h#274
+#[derive(Debug, PartialEq, Clone)]
+#[repr(C)]
+enum HashAlgorithm {
+    SHA256 = 191,
+    SHA384 = 192,
+    SHA512 = 193,
+}
+
+fn hash(payload: &[u8], signature_algorithm: &SignatureAlgorithm) -> Result<Vec<u8>, NSSError> {
+    if payload.len() > raw::c_int::max_value() as usize {
+        return Err(NSSError::InputTooLarge);
+    }
+    let (hash_algorithm, digest_length) = match *signature_algorithm {
+        SignatureAlgorithm::ES256 => (HashAlgorithm::SHA256, SHA256_LENGTH),
+        SignatureAlgorithm::ES384 => (HashAlgorithm::SHA384, SHA384_LENGTH),
+        SignatureAlgorithm::ES512 => (HashAlgorithm::SHA512, SHA512_LENGTH),
+        SignatureAlgorithm::PS256 => (HashAlgorithm::SHA256, SHA256_LENGTH),
+    };
+    let mut hash_buf = vec![0; digest_length];
+    let len: raw::c_int = payload.len() as raw::c_int;
+    let hash_result =
+        unsafe { PK11_HashBuf(hash_algorithm, hash_buf.as_mut_ptr(), payload.as_ptr(), len) };
+    if hash_result != SEC_SUCCESS {
+        return Err(NSSError::LibraryFailure);
+    }
+    Ok(hash_buf)
+}
+
+/// Main entrypoint for verification. Given a signature algorithm, the bytes of a subject public key
+/// info, a payload, and a signature over the payload, returns a result based on the outcome of
+/// decoding the subject public key info and running the signature verification algorithm on the
+/// signed data.
+pub fn verify_signature(
+    signature_algorithm: &SignatureAlgorithm,
+    cert: &[u8],
+    payload: &[u8],
+    signature: &[u8],
+) -> Result<(), NSSError> {
+    let slot = unsafe { PK11_GetInternalSlot() };
+    if slot.is_null() {
+        return Err(NSSError::LibraryFailure);
+    }
+    defer!(unsafe {
+        PK11_FreeSlot(slot);
+    });
+
+    let hash_buf = hash(payload, signature_algorithm).unwrap();
+    let hash_item = SECItem::maybe_new(hash_buf.as_slice())?;
+
+    // Import DER cert into NSS.
+    let der_cert = SECItem::maybe_new(cert)?;
+    let db_handle = unsafe { CERT_GetDefaultCertDB() };
+    if db_handle.is_null() {
+        // TODO #28
+        return Err(NSSError::LibraryFailure);
+    }
+    let nss_cert =
+        unsafe { CERT_NewTempCertificate(db_handle, &der_cert, ptr::null(), false, true) };
+    if nss_cert.is_null() {
+        return Err(NSSError::ImportCertError);
+    }
+    defer!(unsafe {
+        CERT_DestroyCertificate(nss_cert);
+    });
+
+    let key = unsafe { CERT_ExtractPublicKey(nss_cert) };
+    if key.is_null() {
+        return Err(NSSError::ExtractPublicKeyFailed);
+    }
+    defer!(unsafe {
+        SECKEY_DestroyPublicKey(key);
+    });
+    let signature_item = SECItem::maybe_new(signature)?;
+    let mechanism = match *signature_algorithm {
+        SignatureAlgorithm::ES256 => CKM_ECDSA,
+        SignatureAlgorithm::ES384 => CKM_ECDSA,
+        SignatureAlgorithm::ES512 => CKM_ECDSA,
+        SignatureAlgorithm::PS256 => CKM_RSA_PKCS_PSS,
+    };
+    let rsa_pss_params = CkRsaPkcsPssParams::new();
+    let rsa_pss_params_item = rsa_pss_params.get_params_item()?;
+    let params_item = match *signature_algorithm {
+        SignatureAlgorithm::ES256 => ptr::null(),
+        SignatureAlgorithm::ES384 => ptr::null(),
+        SignatureAlgorithm::ES512 => ptr::null(),
+        SignatureAlgorithm::PS256 => &rsa_pss_params_item,
+    };
+    let null_cx_ptr: *const raw::c_void = ptr::null();
+    let result = unsafe {
+        PK11_VerifyWithMechanism(
+            key,
+            mechanism,
+            params_item,
+            &signature_item,
+            &hash_item,
+            null_cx_ptr,
+        )
+    };
+    match result {
+        SEC_SUCCESS => Ok(()),
+        SEC_FAILURE => Err(NSSError::SignatureVerificationFailed),
+        _ => Err(NSSError::LibraryFailure),
+    }
+}
+
+pub fn sign(
+    signature_algorithm: &SignatureAlgorithm,
+    pk8: &[u8],
+    payload: &[u8],
+) -> Result<Vec<u8>, NSSError> {
+    let slot = unsafe { PK11_GetInternalSlot() };
+    if slot.is_null() {
+        return Err(NSSError::LibraryFailure);
+    }
+    defer!(unsafe {
+        PK11_FreeSlot(slot);
+    });
+    let pkcs8item = SECItem::maybe_new(pk8)?;
+    let mut key: *mut SECKEYPrivateKey = ptr::null_mut();
+    let ku_all = 0xFF;
+    let rv = unsafe {
+        PK11_ImportDERPrivateKeyInfoAndReturnKey(
+            slot,
+            &pkcs8item,
+            ptr::null(),
+            ptr::null(),
+            false,
+            false,
+            ku_all,
+            &mut key,
+            ptr::null(),
+        )
+    };
+    if rv != SEC_SUCCESS || key.is_null() {
+        return Err(NSSError::DecodingPKCS8Failed);
+    }
+    let mechanism = match *signature_algorithm {
+        SignatureAlgorithm::ES256 => CKM_ECDSA,
+        SignatureAlgorithm::ES384 => CKM_ECDSA,
+        SignatureAlgorithm::ES512 => CKM_ECDSA,
+        SignatureAlgorithm::PS256 => CKM_RSA_PKCS_PSS,
+    };
+    let rsa_pss_params = CkRsaPkcsPssParams::new();
+    let rsa_pss_params_item = rsa_pss_params.get_params_item()?;
+    let params_item = match *signature_algorithm {
+        SignatureAlgorithm::ES256 => ptr::null(),
+        SignatureAlgorithm::ES384 => ptr::null(),
+        SignatureAlgorithm::ES512 => ptr::null(),
+        SignatureAlgorithm::PS256 => &rsa_pss_params_item,
+    };
+    let signature_len = unsafe { PK11_SignatureLen(key) };
+    // Allocate enough space for the signature.
+    let mut signature: Vec<u8> = Vec::with_capacity(signature_len);
+    let hash_buf = hash(payload, signature_algorithm).unwrap();
+    let hash_item = SECItem::maybe_new(hash_buf.as_slice())?;
+    {
+        // Get a mutable SECItem on the preallocated signature buffer. PK11_SignWithMechanism will
+        // fill the SECItem's buf with the bytes of the signature.
+        let mut signature_item = SECItemMut::maybe_from_empty_preallocated_vec(&mut signature)?;
+        let rv = unsafe {
+            PK11_SignWithMechanism(key, mechanism, params_item, &mut signature_item, &hash_item)
+        };
+        if rv != SEC_SUCCESS || signature_item.len as usize != signature_len {
+            return Err(NSSError::SigningFailed);
+        }
+    }
+    unsafe {
+        // Now that the bytes of the signature have been filled out, set its length.
+        signature.set_len(signature_len);
+    }
+    Ok(signature)
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/examples/sign_verify/test_nss.rs
@@ -0,0 +1,65 @@
+use test_setup as test;
+use nss;
+use nss::NSSError;
+use SignatureAlgorithm;
+
+pub fn test_nss_sign_verify() {
+    test::setup();
+    let payload = b"sample";
+
+    // Sign.
+    let signature_result = nss::sign(&SignatureAlgorithm::ES256, &test::PKCS8_P256_EE, payload);
+    assert!(signature_result.is_ok());
+    let signature_result = signature_result.unwrap();
+
+    // Verify the signature.
+    assert!(
+        nss::verify_signature(
+            &SignatureAlgorithm::ES256,
+            &test::P256_EE,
+            payload,
+            &signature_result,
+        ).is_ok()
+    );
+}
+
+pub fn test_nss_sign_verify_different_payload() {
+    test::setup();
+    let payload = b"sample";
+
+    // Sign.
+    let signature_result = nss::sign(&SignatureAlgorithm::ES256, &test::PKCS8_P256_EE, payload);
+    assert!(signature_result.is_ok());
+    let signature_result = signature_result.unwrap();
+
+    // Verify the signature with a different payload.
+    let payload = b"sampli";
+    let verify_result = nss::verify_signature(
+        &SignatureAlgorithm::ES256,
+        &test::P256_EE,
+        payload,
+        &signature_result,
+    );
+    assert!(verify_result.is_err());
+    assert_eq!(verify_result, Err(NSSError::SignatureVerificationFailed));
+}
+
+pub fn test_nss_sign_verify_wrong_cert() {
+    test::setup();
+    let payload = b"sample";
+
+    // Sign.
+    let signature_result = nss::sign(&SignatureAlgorithm::ES256, &test::PKCS8_P256_EE, payload);
+    assert!(signature_result.is_ok());
+    let signature_result = signature_result.unwrap();
+
+    // Verify the signature with a wrong cert.
+    let verify_result = nss::verify_signature(
+        &SignatureAlgorithm::ES256,
+        &test::P384_EE,
+        payload,
+        &signature_result,
+    );
+    assert!(verify_result.is_err());
+    assert_eq!(verify_result, Err(NSSError::SignatureVerificationFailed));
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/examples/sign_verify/test_setup.rs
@@ -0,0 +1,625 @@
+use std::os::raw;
+use std::ptr;
+use std::sync::{ONCE_INIT, Once};
+static START: Once = ONCE_INIT;
+
+type SECStatus = raw::c_int;
+const SEC_SUCCESS: SECStatus = 0;
+// TODO: ugh this will probably have a platform-specific name...
+#[link(name = "nss3")]
+extern "C" {
+    fn NSS_NoDB_Init(configdir: *const u8) -> SECStatus;
+}
+
+pub fn setup() {
+    START.call_once(|| {
+        let null_ptr: *const u8 = ptr::null();
+        unsafe {
+            assert_eq!(NSS_NoDB_Init(null_ptr), SEC_SUCCESS);
+        }
+    });
+}
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const PKCS8_P256_EE: [u8; 139] = [
+    0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a,
+    0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
+    0xce, 0x3d, 0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01,
+    0x01, 0x04, 0x20, 0x21, 0x91, 0x40, 0x3d, 0x57, 0x10, 0xbf, 0x15,
+    0xa2, 0x65, 0x81, 0x8c, 0xd4, 0x2e, 0xd6, 0xfe, 0xdf, 0x09, 0xad,
+    0xd9, 0x2d, 0x78, 0xb1, 0x8e, 0x7a, 0x1e, 0x9f, 0xeb, 0x95, 0x52,
+    0x47, 0x02, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb,
+    0xbb, 0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87,
+    0x04, 0xe2, 0xec, 0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92,
+    0x3f, 0x2c, 0x4f, 0x79, 0x4b, 0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33,
+    0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d, 0x07, 0x06, 0xe0, 0x0e, 0xed,
+    0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b, 0x7b, 0x2d, 0x07, 0xa3,
+    0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0x0a
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const P256_EE: [u8; 300] = [
+    0x30, 0x82, 0x01, 0x28, 0x30, 0x81, 0xcf, 0xa0, 0x03, 0x02, 0x01, 0x02,
+    0x02, 0x14, 0x2f, 0xc3, 0x5f, 0x05, 0x80, 0xb4, 0x49, 0x45, 0x13, 0x92,
+    0xd6, 0x93, 0xb7, 0x2d, 0x71, 0x19, 0xc5, 0x8c, 0x40, 0x39, 0x30, 0x0a,
+    0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x13,
+    0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x69,
+    0x6e, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, 0x32,
+    0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30,
+    0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33, 0x31,
+    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x12, 0x31, 0x10, 0x30,
+    0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x65, 0x65, 0x2d, 0x70,
+    0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48,
+    0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03,
+    0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb, 0xbb, 0x61, 0xe0,
+    0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04, 0xe2, 0xec, 0x05,
+    0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c, 0x4f, 0x79, 0x4b,
+    0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d,
+    0x07, 0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b,
+    0x7b, 0x2d, 0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0x30, 0x0a,
+    0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48,
+    0x00, 0x30, 0x45, 0x02, 0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50,
+    0xcd, 0x5d, 0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2,
+    0x73, 0x75, 0x5f, 0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70,
+    0xe6, 0x02, 0x21, 0x00, 0xff, 0x81, 0xbe, 0xa8, 0x0d, 0x03, 0x36, 0x6b,
+    0x75, 0xe2, 0x70, 0x6a, 0xac, 0x07, 0x2e, 0x4c, 0xdc, 0xf9, 0xc5, 0x89,
+    0xc1, 0xcf, 0x88, 0xc2, 0xc8, 0x2a, 0x32, 0xf5, 0x42, 0x0c, 0xfa, 0x0b
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const PKCS8_P384_EE: [u8; 185] = [
+    0x30, 0x81, 0xb6, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86,
+    0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22,
+    0x04, 0x81, 0x9e, 0x30, 0x81, 0x9b, 0x02, 0x01, 0x01, 0x04, 0x30, 0x03,
+    0x5c, 0x7a, 0x1b, 0x10, 0xd9, 0xfa, 0xfe, 0x83, 0x7b, 0x64, 0xad, 0x92,
+    0xf2, 0x2f, 0x5c, 0xed, 0x07, 0x89, 0x18, 0x65, 0x38, 0x66, 0x9b, 0x5c,
+    0x6d, 0x87, 0x2c, 0xec, 0x3d, 0x92, 0x61, 0x22, 0xb3, 0x93, 0x77, 0x2b,
+    0x57, 0x60, 0x2f, 0xf3, 0x13, 0x65, 0xef, 0xe1, 0x39, 0x32, 0x46, 0xa1,
+    0x64, 0x03, 0x62, 0x00, 0x04, 0xa1, 0x68, 0x72, 0x43, 0x36, 0x2b, 0x5c,
+    0x7b, 0x18, 0x89, 0xf3, 0x79, 0x15, 0x46, 0x15, 0xa1, 0xc7, 0x3f, 0xb4,
+    0x8d, 0xee, 0x86, 0x3e, 0x02, 0x29, 0x15, 0xdb, 0x60, 0x8e, 0x25, 0x2d,
+    0xe4, 0xb7, 0x13, 0x2d, 0xa8, 0xce, 0x98, 0xe8, 0x31, 0x53, 0x4e, 0x6a,
+    0x9c, 0x0c, 0x0b, 0x09, 0xc8, 0xd6, 0x39, 0xad, 0xe8, 0x32, 0x06, 0xe5,
+    0xba, 0x81, 0x34, 0x73, 0xa1, 0x1f, 0xa3, 0x30, 0xe0, 0x5d, 0xa8, 0xc9,
+    0x6e, 0x43, 0x83, 0xfe, 0x27, 0x87, 0x3d, 0xa9, 0x71, 0x03, 0xbe, 0x28,
+    0x88, 0xcf, 0xf0, 0x02, 0xf0, 0x5a, 0xf7, 0x1a, 0x1f, 0xdd, 0xcc, 0x83,
+    0x74, 0xaa, 0x6e, 0xa9, 0xce
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const PKCS8_P521_EE: [u8; 240] = [
+    0x30, 0x81, 0xed, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86,
+    0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23,
+    0x04, 0x81, 0xd5, 0x30, 0x81, 0xd2, 0x02, 0x01, 0x01, 0x04, 0x42, 0x01,
+    0x4f, 0x32, 0x84, 0xfa, 0x69, 0x8d, 0xd9, 0xfe, 0x11, 0x18, 0xdd, 0x33,
+    0x18, 0x51, 0xcd, 0xfa, 0xac, 0x5a, 0x38, 0x29, 0x27, 0x8e, 0xb8, 0x99,
+    0x48, 0x39, 0xde, 0x94, 0x71, 0xc9, 0x40, 0xb8, 0x58, 0xc6, 0x9d, 0x2d,
+    0x05, 0xe8, 0xc0, 0x17, 0x88, 0xa7, 0xd0, 0xb6, 0xe2, 0x35, 0xaa, 0x5e,
+    0x78, 0x3f, 0xc1, 0xbe, 0xe8, 0x07, 0xdc, 0xc3, 0x86, 0x5f, 0x92, 0x0e,
+    0x12, 0xcf, 0x8f, 0x2d, 0x29, 0xa1, 0x81, 0x88, 0x03, 0x81, 0x85, 0x00,
+    0x04, 0x18, 0x94, 0x55, 0x0d, 0x07, 0x85, 0x93, 0x2e, 0x00, 0xea, 0xa2,
+    0x3b, 0x69, 0x4f, 0x21, 0x3f, 0x8c, 0x31, 0x21, 0xf8, 0x6d, 0xc9, 0x7a,
+    0x04, 0xe5, 0xa7, 0x16, 0x7d, 0xb4, 0xe5, 0xbc, 0xd3, 0x71, 0x12, 0x3d,
+    0x46, 0xe4, 0x5d, 0xb6, 0xb5, 0xd5, 0x37, 0x0a, 0x7f, 0x20, 0xfb, 0x63,
+    0x31, 0x55, 0xd3, 0x8f, 0xfa, 0x16, 0xd2, 0xbd, 0x76, 0x1d, 0xca, 0xc4,
+    0x74, 0xb9, 0xa2, 0xf5, 0x02, 0x3a, 0x40, 0x49, 0x31, 0x01, 0xc9, 0x62,
+    0xcd, 0x4d, 0x2f, 0xdd, 0xf7, 0x82, 0x28, 0x5e, 0x64, 0x58, 0x41, 0x39,
+    0xc2, 0xf9, 0x1b, 0x47, 0xf8, 0x7f, 0xf8, 0x23, 0x54, 0xd6, 0x63, 0x0f,
+    0x74, 0x6a, 0x28, 0xa0, 0xdb, 0x25, 0x74, 0x1b, 0x5b, 0x34, 0xa8, 0x28,
+    0x00, 0x8b, 0x22, 0xac, 0xc2, 0x3f, 0x92, 0x4f, 0xaa, 0xfb, 0xd4, 0xd3,
+    0x3f, 0x81, 0xea, 0x66, 0x95, 0x6d, 0xfe, 0xaa, 0x2b, 0xfd, 0xfc, 0xf5
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const P521_EE: [u8; 367] = [
+    0x30, 0x82, 0x01, 0x6b, 0x30, 0x82, 0x01, 0x12, 0xa0, 0x03, 0x02, 0x01,
+    0x02, 0x02, 0x14, 0x49, 0xdb, 0x7d, 0xec, 0x87, 0x2b, 0x95, 0xfc, 0xfb,
+    0x57, 0xfb, 0xc8, 0xd5, 0x57, 0xb7, 0x3a, 0x10, 0xcc, 0xf1, 0x7a, 0x30,
+    0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30,
+    0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08,
+    0x69, 0x6e, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f,
+    0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30,
+    0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33,
+    0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x12, 0x31, 0x10,
+    0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x65, 0x65, 0x2d,
+    0x70, 0x35, 0x32, 0x31, 0x30, 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a,
+    0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00,
+    0x23, 0x03, 0x81, 0x86, 0x00, 0x04, 0x01, 0x4c, 0xdc, 0x9c, 0xac, 0xc4,
+    0x79, 0x41, 0x09, 0x6b, 0xc9, 0xcc, 0x66, 0x75, 0x2e, 0xc2, 0x7f, 0x59,
+    0x77, 0x34, 0xfa, 0x66, 0xc6, 0x2b, 0x79, 0x2f, 0x88, 0xc5, 0x19, 0xd6,
+    0xd3, 0x7f, 0x0d, 0x16, 0xea, 0x1c, 0x48, 0x3a, 0x18, 0x27, 0xa0, 0x10,
+    0xb9, 0x12, 0x8e, 0x3a, 0x08, 0x07, 0x0c, 0xa3, 0x3e, 0xf5, 0xf5, 0x78,
+    0x35, 0xb7, 0xc1, 0xba, 0x25, 0x1f, 0x6c, 0xc3, 0x52, 0x1d, 0xc4, 0x2b,
+    0x01, 0x06, 0x53, 0x45, 0x19, 0x81, 0xb4, 0x45, 0xd3, 0x43, 0xee, 0xd3,
+    0x78, 0x2a, 0x35, 0xd6, 0xcf, 0xf0, 0xff, 0x48, 0x4f, 0x5a, 0x88, 0x3d,
+    0x20, 0x9f, 0x1b, 0x90, 0x42, 0xb7, 0x26, 0x70, 0x35, 0x68, 0xb2, 0xf3,
+    0x26, 0xe1, 0x8b, 0x83, 0x3b, 0xdd, 0x8a, 0xa0, 0x73, 0x43, 0x92, 0xbc,
+    0xd1, 0x95, 0x01, 0xe1, 0x0d, 0x69, 0x8a, 0x79, 0xf5, 0x3e, 0x11, 0xe0,
+    0xa2, 0x2b, 0xdd, 0x2a, 0xad, 0x90, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86,
+    0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02,
+    0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50, 0xcd, 0x5d, 0x8a, 0xde,
+    0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2, 0x73, 0x75, 0x5f, 0x31,
+    0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02, 0x20, 0x35,
+    0x20, 0x7c, 0xff, 0x51, 0xf6, 0x68, 0xce, 0x1d, 0x00, 0xf9, 0xcc, 0x7f,
+    0xa7, 0xbc, 0x79, 0x52, 0xea, 0x56, 0xdf, 0xc1, 0x46, 0x7c, 0x0c, 0xa1,
+    0x2e, 0x32, 0xb1, 0x69, 0x4b, 0x20, 0xc4
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const P384_EE: [u8; 329] = [
+    0x30, 0x82, 0x01, 0x45, 0x30, 0x81, 0xec, 0xa0, 0x03, 0x02, 0x01, 0x02,
+    0x02, 0x14, 0x79, 0xe3, 0x1c, 0x60, 0x97, 0xa4, 0x3c, 0x3b, 0x82, 0x11,
+    0x42, 0x37, 0xaf, 0x57, 0x05, 0xa8, 0xde, 0xd3, 0x40, 0x58, 0x30, 0x0a,
+    0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x13,
+    0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x69,
+    0x6e, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, 0x32,
+    0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30,
+    0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33, 0x31,
+    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x12, 0x31, 0x10, 0x30,
+    0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x65, 0x65, 0x2d, 0x70,
+    0x33, 0x38, 0x34, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48,
+    0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03,
+    0x62, 0x00, 0x04, 0xa1, 0x68, 0x72, 0x43, 0x36, 0x2b, 0x5c, 0x7b, 0x18,
+    0x89, 0xf3, 0x79, 0x15, 0x46, 0x15, 0xa1, 0xc7, 0x3f, 0xb4, 0x8d, 0xee,
+    0x86, 0x3e, 0x02, 0x29, 0x15, 0xdb, 0x60, 0x8e, 0x25, 0x2d, 0xe4, 0xb7,
+    0x13, 0x2d, 0xa8, 0xce, 0x98, 0xe8, 0x31, 0x53, 0x4e, 0x6a, 0x9c, 0x0c,
+    0x0b, 0x09, 0xc8, 0xd6, 0x39, 0xad, 0xe8, 0x32, 0x06, 0xe5, 0xba, 0x81,
+    0x34, 0x73, 0xa1, 0x1f, 0xa3, 0x30, 0xe0, 0x5d, 0xa8, 0xc9, 0x6e, 0x43,
+    0x83, 0xfe, 0x27, 0x87, 0x3d, 0xa9, 0x71, 0x03, 0xbe, 0x28, 0x88, 0xcf,
+    0xf0, 0x02, 0xf0, 0x5a, 0xf7, 0x1a, 0x1f, 0xdd, 0xcc, 0x83, 0x74, 0xaa,
+    0x6e, 0xa9, 0xce, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+    0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5c, 0x75,
+    0x51, 0x9f, 0x13, 0x11, 0x50, 0xcd, 0x5d, 0x8a, 0xde, 0x20, 0xa3, 0xbc,
+    0x06, 0x30, 0x91, 0xff, 0xb2, 0x73, 0x75, 0x5f, 0x31, 0x64, 0xec, 0xfd,
+    0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02, 0x21, 0x00, 0xf3, 0x04, 0x26,
+    0xf2, 0xfd, 0xbc, 0x89, 0x3f, 0x29, 0x3b, 0x70, 0xbc, 0x72, 0xa6, 0xc2,
+    0x23, 0xcc, 0x43, 0x4d, 0x84, 0x71, 0xaf, 0x53, 0xe4, 0x4b, 0x3e, 0xc0,
+    0xbf, 0xe5, 0x68, 0x86, 0x49
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const P256_INT: [u8; 332] = [
+    0x30, 0x82, 0x01, 0x48, 0x30, 0x81, 0xf0, 0xa0, 0x03, 0x02, 0x01,
+    0x02, 0x02, 0x14, 0x43, 0x63, 0x59, 0xad, 0x04, 0x34, 0x56, 0x80,
+    0x43, 0xec, 0x90, 0x6a, 0xd4, 0x10, 0x64, 0x7c, 0x7f, 0x38, 0x32,
+    0xe2, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04,
+    0x03, 0x02, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
+    0x04, 0x03, 0x0c, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32,
+    0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30,
+    0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18,
+    0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33, 0x31, 0x30, 0x30,
+    0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x13, 0x31, 0x11, 0x30, 0x0f,
+    0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x69, 0x6e, 0x74, 0x2d,
+    0x70, 0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a,
+    0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
+    0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf,
+    0xbb, 0xbb, 0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac,
+    0x87, 0x04, 0xe2, 0xec, 0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e,
+    0x92, 0x3f, 0x2c, 0x4f, 0x79, 0x4b, 0x45, 0x5c, 0x2a, 0x69, 0xd2,
+    0x33, 0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d, 0x07, 0x06, 0xe0, 0x0e,
+    0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b, 0x7b, 0x2d, 0x07,
+    0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0xa3, 0x1d, 0x30, 0x1b,
+    0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03,
+    0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04,
+    0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86,
+    0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44,
+    0x02, 0x20, 0x63, 0x59, 0x02, 0x01, 0x89, 0xd7, 0x3e, 0x5b, 0xff,
+    0xd1, 0x16, 0x4e, 0xe3, 0xe2, 0x0a, 0xe0, 0x4a, 0xd8, 0x75, 0xaf,
+    0x77, 0x5c, 0x93, 0x60, 0xba, 0x10, 0x1f, 0x97, 0xdd, 0x27, 0x2d,
+    0x24, 0x02, 0x20, 0x3d, 0x87, 0x0f, 0xac, 0x22, 0x4d, 0x16, 0xd9,
+    0xa1, 0x95, 0xbb, 0x56, 0xe0, 0x21, 0x05, 0x93, 0xd1, 0x07, 0xb5,
+    0x25, 0x3b, 0xf4, 0x57, 0x20, 0x87, 0x13, 0xa2, 0xf7, 0x78, 0x15,
+    0x30, 0xa7
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const P256_ROOT: [u8; 334] = [
+    0x30, 0x82, 0x01, 0x4a, 0x30, 0x81, 0xf1, 0xa0, 0x03, 0x02, 0x01, 0x02,
+    0x02, 0x14, 0x5f, 0x3f, 0xae, 0x90, 0x49, 0x30, 0x2f, 0x33, 0x6e, 0x95,
+    0x23, 0xa7, 0xcb, 0x23, 0xd7, 0x65, 0x4f, 0xea, 0x3c, 0xf7, 0x30, 0x0a,
+    0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x14,
+    0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x72,
+    0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f,
+    0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30,
+    0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33,
+    0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14, 0x31, 0x12,
+    0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x72, 0x6f, 0x6f,
+    0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
+    0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb,
+    0xbb, 0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04,
+    0xe2, 0xec, 0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c,
+    0x4f, 0x79, 0x4b, 0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36,
+    0xc4, 0x11, 0x9d, 0x07, 0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90,
+    0xd7, 0x99, 0x1b, 0x7b, 0x2d, 0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6,
+    0xc0, 0xa3, 0x1d, 0x30, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+    0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55,
+    0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0a, 0x06, 0x08,
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30,
+    0x45, 0x02, 0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50, 0xcd, 0x5d,
+    0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2, 0x73, 0x75,
+    0x5f, 0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02,
+    0x21, 0x00, 0xc2, 0xe4, 0xc1, 0xa8, 0xe2, 0x89, 0xdc, 0xa1, 0xbb, 0xe7,
+    0xd5, 0x4f, 0x5c, 0x88, 0xad, 0xeb, 0xa4, 0x78, 0xa1, 0x19, 0xbe, 0x22,
+    0x54, 0xc8, 0x9f, 0xef, 0xb8, 0x5d, 0xa2, 0x40, 0xd9, 0x8b
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const PKCS8_RSA_EE: [u8; 1218] = [
+    0x30, 0x82, 0x04, 0xbe, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+    0x04, 0xa8, 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
+    0x01, 0x00, 0xba, 0x88, 0x51, 0xa8, 0x44, 0x8e, 0x16, 0xd6, 0x41, 0xfd,
+    0x6e, 0xb6, 0x88, 0x06, 0x36, 0x10, 0x3d, 0x3c, 0x13, 0xd9, 0xea, 0xe4,
+    0x35, 0x4a, 0xb4, 0xec, 0xf5, 0x68, 0x57, 0x6c, 0x24, 0x7b, 0xc1, 0xc7,
+    0x25, 0xa8, 0xe0, 0xd8, 0x1f, 0xbd, 0xb1, 0x9c, 0x06, 0x9b, 0x6e, 0x1a,
+    0x86, 0xf2, 0x6b, 0xe2, 0xaf, 0x5a, 0x75, 0x6b, 0x6a, 0x64, 0x71, 0x08,
+    0x7a, 0xa5, 0x5a, 0xa7, 0x45, 0x87, 0xf7, 0x1c, 0xd5, 0x24, 0x9c, 0x02,
+    0x7e, 0xcd, 0x43, 0xfc, 0x1e, 0x69, 0xd0, 0x38, 0x20, 0x29, 0x93, 0xab,
+    0x20, 0xc3, 0x49, 0xe4, 0xdb, 0xb9, 0x4c, 0xc2, 0x6b, 0x6c, 0x0e, 0xed,
+    0x15, 0x82, 0x0f, 0xf1, 0x7e, 0xad, 0x69, 0x1a, 0xb1, 0xd3, 0x02, 0x3a,
+    0x8b, 0x2a, 0x41, 0xee, 0xa7, 0x70, 0xe0, 0x0f, 0x0d, 0x8d, 0xfd, 0x66,
+    0x0b, 0x2b, 0xb0, 0x24, 0x92, 0xa4, 0x7d, 0xb9, 0x88, 0x61, 0x79, 0x90,
+    0xb1, 0x57, 0x90, 0x3d, 0xd2, 0x3b, 0xc5, 0xe0, 0xb8, 0x48, 0x1f, 0xa8,
+    0x37, 0xd3, 0x88, 0x43, 0xef, 0x27, 0x16, 0xd8, 0x55, 0xb7, 0x66, 0x5a,
+    0xaa, 0x7e, 0x02, 0x90, 0x2f, 0x3a, 0x7b, 0x10, 0x80, 0x06, 0x24, 0xcc,
+    0x1c, 0x6c, 0x97, 0xad, 0x96, 0x61, 0x5b, 0xb7, 0xe2, 0x96, 0x12, 0xc0,
+    0x75, 0x31, 0xa3, 0x0c, 0x91, 0xdd, 0xb4, 0xca, 0xf7, 0xfc, 0xad, 0x1d,
+    0x25, 0xd3, 0x09, 0xef, 0xb9, 0x17, 0x0e, 0xa7, 0x68, 0xe1, 0xb3, 0x7b,
+    0x2f, 0x22, 0x6f, 0x69, 0xe3, 0xb4, 0x8a, 0x95, 0x61, 0x1d, 0xee, 0x26,
+    0xd6, 0x25, 0x9d, 0xab, 0x91, 0x08, 0x4e, 0x36, 0xcb, 0x1c, 0x24, 0x04,
+    0x2c, 0xbf, 0x16, 0x8b, 0x2f, 0xe5, 0xf1, 0x8f, 0x99, 0x17, 0x31, 0xb8,
+    0xb3, 0xfe, 0x49, 0x23, 0xfa, 0x72, 0x51, 0xc4, 0x31, 0xd5, 0x03, 0xac,
+    0xda, 0x18, 0x0a, 0x35, 0xed, 0x8d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
+    0x82, 0x01, 0x01, 0x00, 0x9e, 0xcb, 0xce, 0x38, 0x61, 0xa4, 0x54, 0xec,
+    0xb1, 0xe0, 0xfe, 0x8f, 0x85, 0xdd, 0x43, 0xc9, 0x2f, 0x58, 0x25, 0xce,
+    0x2e, 0x99, 0x78, 0x84, 0xd0, 0xe1, 0xa9, 0x49, 0xda, 0xa2, 0xc5, 0xac,
+    0x55, 0x9b, 0x24, 0x04, 0x50, 0xe5, 0xac, 0x9f, 0xe0, 0xc3, 0xe3, 0x1c,
+    0x0e, 0xef, 0xa6, 0x52, 0x5a, 0x65, 0xf0, 0xc2, 0x21, 0x94, 0x00, 0x4e,
+    0xe1, 0xab, 0x46, 0x3d, 0xde, 0x9e, 0xe8, 0x22, 0x87, 0xcc, 0x93, 0xe7,
+    0x46, 0xa9, 0x19, 0x29, 0xc5, 0xe6, 0xac, 0x3d, 0x88, 0x75, 0x3f, 0x6c,
+    0x25, 0xba, 0x59, 0x79, 0xe7, 0x3e, 0x5d, 0x8f, 0xb2, 0x39, 0x11, 0x1a,
+    0x3c, 0xda, 0xb8, 0xa4, 0xb0, 0xcd, 0xf5, 0xf9, 0xca, 0xb0, 0x5f, 0x12,
+    0x33, 0xa3, 0x83, 0x35, 0xc6, 0x4b, 0x55, 0x60, 0x52, 0x5e, 0x7e, 0x3b,
+    0x92, 0xad, 0x7c, 0x75, 0x04, 0xcf, 0x1d, 0xc7, 0xcb, 0x00, 0x57, 0x88,
+    0xaf, 0xcb, 0xe1, 0xe8, 0xf9, 0x5d, 0xf7, 0x40, 0x2a, 0x15, 0x15, 0x30,
+    0xd5, 0x80, 0x83, 0x46, 0x86, 0x4e, 0xb3, 0x70, 0xaa, 0x79, 0x95, 0x6a,
+    0x58, 0x78, 0x62, 0xcb, 0x53, 0x37, 0x91, 0x30, 0x7f, 0x70, 0xd9, 0x1c,
+    0x96, 0xd2, 0x2d, 0x00, 0x1a, 0x69, 0x00, 0x9b, 0x92, 0x3c, 0x68, 0x33,
+    0x88, 0xc9, 0xf3, 0x6c, 0xb9, 0xb5, 0xeb, 0xe6, 0x43, 0x02, 0x04, 0x1c,
+    0x78, 0xd9, 0x08, 0x20, 0x6b, 0x87, 0x00, 0x9c, 0xb8, 0xca, 0xba, 0xca,
+    0xd3, 0xdb, 0xdb, 0x27, 0x92, 0xfb, 0x91, 0x1b, 0x2c, 0xf4, 0xdb, 0x66,
+    0x03, 0x58, 0x5b, 0xe9, 0xae, 0x0c, 0xa3, 0xb8, 0xe6, 0x41, 0x7a, 0xa0,
+    0x4b, 0x06, 0xe4, 0x70, 0xea, 0x1a, 0x3b, 0x58, 0x1c, 0xa0, 0x3a, 0x67,
+    0x81, 0xc9, 0x31, 0x5b, 0x62, 0xb3, 0x0e, 0x60, 0x11, 0xf2, 0x24, 0x72,
+    0x59, 0x46, 0xee, 0xc5, 0x7c, 0x6d, 0x94, 0x41, 0x02, 0x81, 0x81, 0x00,
+    0xdd, 0x6e, 0x1d, 0x4f, 0xff, 0xeb, 0xf6, 0x8d, 0x88, 0x9c, 0x4d, 0x11,
+    0x4c, 0xda, 0xaa, 0x9c, 0xaa, 0x63, 0xa5, 0x93, 0x74, 0x28, 0x6c, 0x8a,
+    0x5c, 0x29, 0xa7, 0x17, 0xbb, 0xa6, 0x03, 0x75, 0x64, 0x4d, 0x5c, 0xaa,
+    0x67, 0x4c, 0x4b, 0x8b, 0xc7, 0x32, 0x63, 0x58, 0x64, 0x62, 0x20, 0xe4,
+    0x55, 0x0d, 0x76, 0x08, 0xac, 0x27, 0xd5, 0x5b, 0x6d, 0xb7, 0x4f, 0x8d,
+    0x81, 0x27, 0xef, 0x8f, 0xa0, 0x90, 0x98, 0xb6, 0x91, 0x47, 0xde, 0x06,
+    0x55, 0x73, 0x44, 0x7e, 0x18, 0x3d, 0x22, 0xfe, 0x7d, 0x88, 0x5a, 0xce,
+    0xb5, 0x13, 0xd9, 0x58, 0x1d, 0xd5, 0xe0, 0x7c, 0x1a, 0x90, 0xf5, 0xce,
+    0x08, 0x79, 0xde, 0x13, 0x13, 0x71, 0xec, 0xef, 0xc9, 0xce, 0x72, 0xe9,
+    0xc4, 0x3d, 0xc1, 0x27, 0xd2, 0x38, 0x19, 0x0d, 0xe8, 0x11, 0x77, 0x3c,
+    0xa5, 0xd1, 0x93, 0x01, 0xf4, 0x8c, 0x74, 0x2b, 0x02, 0x81, 0x81, 0x00,
+    0xd7, 0xa7, 0x73, 0xd9, 0xeb, 0xc3, 0x80, 0xa7, 0x67, 0xd2, 0xfe, 0xc0,
+    0x93, 0x4a, 0xd4, 0xe8, 0xb5, 0x66, 0x72, 0x40, 0x77, 0x1a, 0xcd, 0xeb,
+    0xb5, 0xad, 0x79, 0x6f, 0x47, 0x8f, 0xec, 0x4d, 0x45, 0x98, 0x5e, 0xfb,
+    0xc9, 0x53, 0x29, 0x68, 0x28, 0x9c, 0x8d, 0x89, 0x10, 0x2f, 0xad, 0xf2,
+    0x1f, 0x34, 0xe2, 0xdd, 0x49, 0x40, 0xeb, 0xa8, 0xc0, 0x9d, 0x6d, 0x1f,
+    0x16, 0xdc, 0xc2, 0x97, 0x29, 0x77, 0x4c, 0x43, 0x27, 0x5e, 0x92, 0x51,
+    0xdd, 0xbe, 0x49, 0x09, 0xe1, 0xfd, 0x3b, 0xf1, 0xe4, 0xbe, 0xdf, 0x46,
+    0xa3, 0x9b, 0x8b, 0x38, 0x33, 0x28, 0xef, 0x4a, 0xe3, 0xb9, 0x5b, 0x92,
+    0xf2, 0x07, 0x0a, 0xf2, 0x6c, 0x9e, 0x7c, 0x5c, 0x9b, 0x58, 0x7f, 0xed,
+    0xde, 0x05, 0xe8, 0xe7, 0xd8, 0x6c, 0xa5, 0x78, 0x86, 0xfb, 0x16, 0x58,
+    0x10, 0xa7, 0x7b, 0x98, 0x45, 0xbc, 0x31, 0x27, 0x02, 0x81, 0x81, 0x00,
+    0x96, 0x47, 0x2b, 0x41, 0xa6, 0x10, 0xc0, 0xad, 0xe1, 0xaf, 0x22, 0x66,
+    0xc1, 0x60, 0x0e, 0x36, 0x71, 0x35, 0x5b, 0xa4, 0x2d, 0x4b, 0x5a, 0x0e,
+    0xb4, 0xe9, 0xd7, 0xeb, 0x35, 0x81, 0x40, 0x0b, 0xa5, 0xdd, 0x13, 0x2c,
+    0xdb, 0x1a, 0x5e, 0x93, 0x28, 0xc7, 0xbb, 0xc0, 0xbb, 0xb0, 0x15, 0x5e,
+    0xa1, 0x92, 0x97, 0x2e, 0xdf, 0x97, 0xd1, 0x27, 0x51, 0xd8, 0xfc, 0xf6,
+    0xae, 0x57, 0x2a, 0x30, 0xb1, 0xea, 0x30, 0x9a, 0x87, 0x12, 0xdd, 0x4e,
+    0x33, 0x24, 0x1d, 0xb1, 0xee, 0x45, 0x5f, 0xc0, 0x93, 0xf5, 0xbc, 0x9b,
+    0x59, 0x2d, 0x75, 0x6e, 0x66, 0x21, 0x47, 0x4f, 0x32, 0xc0, 0x7a, 0xf2,
+    0x2f, 0xb2, 0x75, 0xd3, 0x40, 0x79, 0x2b, 0x32, 0xba, 0x25, 0x90, 0xbb,
+    0xb2, 0x61, 0xae, 0xfb, 0x95, 0xa2, 0x58, 0xee, 0xa5, 0x37, 0x65, 0x53,
+    0x15, 0xbe, 0x9c, 0x24, 0xd1, 0x91, 0x99, 0x2d, 0x02, 0x81, 0x80, 0x28,
+    0xb4, 0x50, 0xa7, 0xa7, 0x5a, 0x85, 0x64, 0x13, 0xb2, 0xbd, 0xa6, 0xf7,
+    0xa6, 0x3e, 0x3d, 0x96, 0x4f, 0xb9, 0xec, 0xf5, 0x0e, 0x38, 0x23, 0xef,
+    0x6c, 0xc8, 0xe8, 0xfa, 0x26, 0xee, 0x41, 0x3f, 0x8b, 0x9d, 0x12, 0x05,
+    0x54, 0x0f, 0x12, 0xbb, 0xe7, 0xa0, 0xc7, 0x68, 0x28, 0xb7, 0xba, 0x65,
+    0xad, 0x83, 0xcc, 0xa4, 0xd0, 0xfe, 0x2a, 0x22, 0x01, 0x14, 0xe1, 0xb3,
+    0x5d, 0x03, 0xd5, 0xa8, 0x5b, 0xfe, 0x27, 0x06, 0xbd, 0x50, 0xfc, 0xe6,
+    0xcf, 0xcd, 0xd5, 0x71, 0xb4, 0x6c, 0xa6, 0x21, 0xb8, 0xed, 0x47, 0xd6,
+    0x05, 0xbb, 0xe7, 0x65, 0xb0, 0xaa, 0x4a, 0x06, 0x65, 0xac, 0x25, 0x36,
+    0x4d, 0xa2, 0x01, 0x54, 0x03, 0x2e, 0x12, 0x04, 0xb8, 0x55, 0x9d, 0x3e,
+    0x34, 0xfb, 0x5b, 0x17, 0x7c, 0x9a, 0x56, 0xff, 0x93, 0x51, 0x0a, 0x5a,
+    0x4a, 0x62, 0x87, 0xc1, 0x51, 0xde, 0x2d, 0x02, 0x81, 0x80, 0x28, 0x06,
+    0x7b, 0x93, 0x55, 0x80, 0x1d, 0x2e, 0xf5, 0x2d, 0xfa, 0x96, 0xd8, 0xad,
+    0xb5, 0x89, 0x67, 0x3c, 0xf8, 0xee, 0x8a, 0x9c, 0x6f, 0xf7, 0x2a, 0xee,
+    0xab, 0xe9, 0xef, 0x6b, 0xe5, 0x8a, 0x4f, 0x4a, 0xbf, 0x05, 0xf7, 0x88,
+    0x94, 0x7d, 0xc8, 0x51, 0xfd, 0xaa, 0x34, 0x54, 0x21, 0x47, 0xa7, 0x1a,
+    0x24, 0x6b, 0xfb, 0x05, 0x4e, 0xe7, 0x6a, 0xa3, 0x46, 0xab, 0xcd, 0x26,
+    0x92, 0xcf, 0xc9, 0xe4, 0x4c, 0x51, 0xe6, 0xf0, 0x69, 0xc7, 0x35, 0xe0,
+    0x73, 0xba, 0x01, 0x9f, 0x6a, 0x72, 0x14, 0x96, 0x1c, 0x91, 0xb2, 0x68,
+    0x71, 0xca, 0xea, 0xbf, 0x8f, 0x06, 0x44, 0x18, 0xa0, 0x26, 0x90, 0xe3,
+    0x9a, 0x8d, 0x5f, 0xf3, 0x06, 0x7b, 0x7c, 0xdb, 0x7f, 0x50, 0xb1, 0xf5,
+    0x34, 0x18, 0xa7, 0x03, 0x96, 0x6c, 0x4f, 0xc7, 0x74, 0xbf, 0x74, 0x02,
+    0xaf, 0x6c, 0x43, 0x24, 0x7f, 0x43
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const RSA_EE: [u8; 691] = [
+    0x30, 0x82, 0x02, 0xaf, 0x30, 0x82, 0x01, 0x99, 0xa0, 0x03, 0x02, 0x01,
+    0x02, 0x02, 0x14, 0x07, 0x1c, 0x3b, 0x71, 0x08, 0xbe, 0xd7, 0x9f, 0xfd,
+    0xaf, 0x26, 0xb6, 0x08, 0xa3, 0x99, 0x06, 0x77, 0x69, 0x32, 0x7e, 0x30,
+    0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+    0x30, 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+    0x07, 0x69, 0x6e, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x22, 0x18, 0x0f,
+    0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30,
+    0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33,
+    0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x11, 0x31, 0x0f,
+    0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x06, 0x65, 0x65, 0x2d,
+    0x72, 0x73, 0x61, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82,
+    0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
+    0xba, 0x88, 0x51, 0xa8, 0x44, 0x8e, 0x16, 0xd6, 0x41, 0xfd, 0x6e, 0xb6,
+    0x88, 0x06, 0x36, 0x10, 0x3d, 0x3c, 0x13, 0xd9, 0xea, 0xe4, 0x35, 0x4a,
+    0xb4, 0xec, 0xf5, 0x68, 0x57, 0x6c, 0x24, 0x7b, 0xc1, 0xc7, 0x25, 0xa8,
+    0xe0, 0xd8, 0x1f, 0xbd, 0xb1, 0x9c, 0x06, 0x9b, 0x6e, 0x1a, 0x86, 0xf2,
+    0x6b, 0xe2, 0xaf, 0x5a, 0x75, 0x6b, 0x6a, 0x64, 0x71, 0x08, 0x7a, 0xa5,
+    0x5a, 0xa7, 0x45, 0x87, 0xf7, 0x1c, 0xd5, 0x24, 0x9c, 0x02, 0x7e, 0xcd,
+    0x43, 0xfc, 0x1e, 0x69, 0xd0, 0x38, 0x20, 0x29, 0x93, 0xab, 0x20, 0xc3,
+    0x49, 0xe4, 0xdb, 0xb9, 0x4c, 0xc2, 0x6b, 0x6c, 0x0e, 0xed, 0x15, 0x82,
+    0x0f, 0xf1, 0x7e, 0xad, 0x69, 0x1a, 0xb1, 0xd3, 0x02, 0x3a, 0x8b, 0x2a,
+    0x41, 0xee, 0xa7, 0x70, 0xe0, 0x0f, 0x0d, 0x8d, 0xfd, 0x66, 0x0b, 0x2b,
+    0xb0, 0x24, 0x92, 0xa4, 0x7d, 0xb9, 0x88, 0x61, 0x79, 0x90, 0xb1, 0x57,
+    0x90, 0x3d, 0xd2, 0x3b, 0xc5, 0xe0, 0xb8, 0x48, 0x1f, 0xa8, 0x37, 0xd3,
+    0x88, 0x43, 0xef, 0x27, 0x16, 0xd8, 0x55, 0xb7, 0x66, 0x5a, 0xaa, 0x7e,
+    0x02, 0x90, 0x2f, 0x3a, 0x7b, 0x10, 0x80, 0x06, 0x24, 0xcc, 0x1c, 0x6c,
+    0x97, 0xad, 0x96, 0x61, 0x5b, 0xb7, 0xe2, 0x96, 0x12, 0xc0, 0x75, 0x31,
+    0xa3, 0x0c, 0x91, 0xdd, 0xb4, 0xca, 0xf7, 0xfc, 0xad, 0x1d, 0x25, 0xd3,
+    0x09, 0xef, 0xb9, 0x17, 0x0e, 0xa7, 0x68, 0xe1, 0xb3, 0x7b, 0x2f, 0x22,
+    0x6f, 0x69, 0xe3, 0xb4, 0x8a, 0x95, 0x61, 0x1d, 0xee, 0x26, 0xd6, 0x25,
+    0x9d, 0xab, 0x91, 0x08, 0x4e, 0x36, 0xcb, 0x1c, 0x24, 0x04, 0x2c, 0xbf,
+    0x16, 0x8b, 0x2f, 0xe5, 0xf1, 0x8f, 0x99, 0x17, 0x31, 0xb8, 0xb3, 0xfe,
+    0x49, 0x23, 0xfa, 0x72, 0x51, 0xc4, 0x31, 0xd5, 0x03, 0xac, 0xda, 0x18,
+    0x0a, 0x35, 0xed, 0x8d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0b, 0x06,
+    0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x03, 0x82,
+    0x01, 0x01, 0x00, 0x44, 0x92, 0xbb, 0x8e, 0x83, 0x58, 0x56, 0x2e, 0x7a,
+    0x86, 0xfa, 0x1d, 0x77, 0x50, 0x3f, 0x45, 0x8d, 0x90, 0xc4, 0x62, 0x27,
+    0x21, 0x96, 0x5a, 0xef, 0x51, 0x78, 0xd7, 0x7d, 0x0d, 0x02, 0x2d, 0x5a,
+    0x0e, 0x3c, 0x82, 0x6f, 0x1d, 0x92, 0x87, 0xd5, 0x1a, 0x44, 0xae, 0xa7,
+    0x92, 0xd1, 0x8b, 0xfa, 0x16, 0x53, 0x7f, 0xa3, 0x22, 0x96, 0x1a, 0x51,
+    0x8c, 0xeb, 0xa1, 0xe6, 0xf6, 0x37, 0x11, 0xfe, 0x7d, 0x53, 0x3f, 0xae,
+    0xf0, 0x6b, 0xb9, 0xb1, 0x7a, 0x73, 0x07, 0x14, 0xcf, 0x04, 0x05, 0x93,
+    0x9e, 0xe3, 0xd2, 0x4d, 0x9d, 0x6d, 0x35, 0x68, 0xf9, 0x36, 0xe5, 0x10,
+    0x0a, 0x36, 0xd9, 0x48, 0xb0, 0x83, 0xd0, 0xb9, 0x58, 0x74, 0x53, 0xb3,
+    0xbc, 0x99, 0xab, 0xe1, 0x3e, 0xd5, 0x01, 0x8e, 0xcf, 0x3a, 0x69, 0x93,
+    0x9e, 0xa7, 0x88, 0xd4, 0xad, 0x95, 0xf9, 0x2a, 0xb4, 0x7f, 0x95, 0x97,
+    0x86, 0x50, 0x38, 0xb1, 0x04, 0x0a, 0xe4, 0x7a, 0xd5, 0x2d, 0x6c, 0xde,
+    0x3e, 0x1a, 0x47, 0x17, 0x88, 0x63, 0x20, 0x9d, 0x21, 0x3e, 0x0c, 0x6f,
+    0xfd, 0x20, 0x54, 0xd0, 0x67, 0xd2, 0x6b, 0x06, 0xfe, 0x60, 0x13, 0x42,
+    0x3d, 0xb7, 0xca, 0xcb, 0xab, 0x7b, 0x5f, 0x5d, 0x01, 0x56, 0xd3, 0x99,
+    0x80, 0x0f, 0xde, 0x7f, 0x3a, 0x61, 0x9c, 0xd3, 0x6b, 0x5e, 0xfe, 0xb5,
+    0xfc, 0x39, 0x8b, 0x8e, 0xf0, 0x8c, 0x8b, 0x65, 0x46, 0x45, 0xff, 0x47,
+    0x8f, 0xd4, 0xdd, 0xae, 0xc9, 0x72, 0xc7, 0x7f, 0x28, 0x86, 0xf1, 0xf7,
+    0x6e, 0xcb, 0x86, 0x03, 0xeb, 0x0c, 0x46, 0xe5, 0xa0, 0x6b, 0xef, 0xd4,
+    0x5e, 0xa4, 0x0f, 0x53, 0xe1, 0xbc, 0xb4, 0xc9, 0x37, 0x0e, 0x75, 0xdd,
+    0x93, 0xe8, 0x0f, 0x18, 0x0a, 0x02, 0x83, 0x17, 0x74, 0xbb, 0x1a, 0x42,
+    0x5b, 0x63, 0x2c, 0x80, 0x80, 0xa6, 0x84
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const RSA_INT: [u8; 724] = [
+    0x30, 0x82, 0x02, 0xd0, 0x30, 0x82, 0x01, 0xba, 0xa0, 0x03, 0x02, 0x01,
+    0x02, 0x02, 0x14, 0x07, 0x10, 0xaf, 0xc4, 0x1a, 0x3a, 0x56, 0x4f, 0xd8,
+    0xc2, 0xcc, 0x46, 0xd7, 0x5b, 0xdf, 0x1c, 0x4e, 0x2f, 0x49, 0x3a, 0x30,
+    0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+    0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+    0x08, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x22, 0x18,
+    0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30,
+    0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32,
+    0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x12, 0x31,
+    0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x69, 0x6e,
+    0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06,
+    0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
+    0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01,
+    0x01, 0x00, 0xba, 0x88, 0x51, 0xa8, 0x44, 0x8e, 0x16, 0xd6, 0x41, 0xfd,
+    0x6e, 0xb6, 0x88, 0x06, 0x36, 0x10, 0x3d, 0x3c, 0x13, 0xd9, 0xea, 0xe4,
+    0x35, 0x4a, 0xb4, 0xec, 0xf5, 0x68, 0x57, 0x6c, 0x24, 0x7b, 0xc1, 0xc7,
+    0x25, 0xa8, 0xe0, 0xd8, 0x1f, 0xbd, 0xb1, 0x9c, 0x06, 0x9b, 0x6e, 0x1a,
+    0x86, 0xf2, 0x6b, 0xe2, 0xaf, 0x5a, 0x75, 0x6b, 0x6a, 0x64, 0x71, 0x08,
+    0x7a, 0xa5, 0x5a, 0xa7, 0x45, 0x87, 0xf7, 0x1c, 0xd5, 0x24, 0x9c, 0x02,
+    0x7e, 0xcd, 0x43, 0xfc, 0x1e, 0x69, 0xd0, 0x38, 0x20, 0x29, 0x93, 0xab,
+    0x20, 0xc3, 0x49, 0xe4, 0xdb, 0xb9, 0x4c, 0xc2, 0x6b, 0x6c, 0x0e, 0xed,
+    0x15, 0x82, 0x0f, 0xf1, 0x7e, 0xad, 0x69, 0x1a, 0xb1, 0xd3, 0x02, 0x3a,
+    0x8b, 0x2a, 0x41, 0xee, 0xa7, 0x70, 0xe0, 0x0f, 0x0d, 0x8d, 0xfd, 0x66,
+    0x0b, 0x2b, 0xb0, 0x24, 0x92, 0xa4, 0x7d, 0xb9, 0x88, 0x61, 0x79, 0x90,
+    0xb1, 0x57, 0x90, 0x3d, 0xd2, 0x3b, 0xc5, 0xe0, 0xb8, 0x48, 0x1f, 0xa8,
+    0x37, 0xd3, 0x88, 0x43, 0xef, 0x27, 0x16, 0xd8, 0x55, 0xb7, 0x66, 0x5a,
+    0xaa, 0x7e, 0x02, 0x90, 0x2f, 0x3a, 0x7b, 0x10, 0x80, 0x06, 0x24, 0xcc,
+    0x1c, 0x6c, 0x97, 0xad, 0x96, 0x61, 0x5b, 0xb7, 0xe2, 0x96, 0x12, 0xc0,
+    0x75, 0x31, 0xa3, 0x0c, 0x91, 0xdd, 0xb4, 0xca, 0xf7, 0xfc, 0xad, 0x1d,
+    0x25, 0xd3, 0x09, 0xef, 0xb9, 0x17, 0x0e, 0xa7, 0x68, 0xe1, 0xb3, 0x7b,
+    0x2f, 0x22, 0x6f, 0x69, 0xe3, 0xb4, 0x8a, 0x95, 0x61, 0x1d, 0xee, 0x26,
+    0xd6, 0x25, 0x9d, 0xab, 0x91, 0x08, 0x4e, 0x36, 0xcb, 0x1c, 0x24, 0x04,
+    0x2c, 0xbf, 0x16, 0x8b, 0x2f, 0xe5, 0xf1, 0x8f, 0x99, 0x17, 0x31, 0xb8,
+    0xb3, 0xfe, 0x49, 0x23, 0xfa, 0x72, 0x51, 0xc4, 0x31, 0xd5, 0x03, 0xac,
+    0xda, 0x18, 0x0a, 0x35, 0xed, 0x8d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3,
+    0x1d, 0x30, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+    0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f,
+    0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86,
+    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x03, 0x82, 0x01, 0x01, 0x00,
+    0x5e, 0xba, 0x69, 0x55, 0x9f, 0xf8, 0xeb, 0x16, 0x21, 0x98, 0xde, 0xb7,
+    0x31, 0x3e, 0x66, 0xe1, 0x3b, 0x0c, 0x29, 0xf7, 0x48, 0x73, 0x05, 0xd9,
+    0xce, 0x5e, 0x4c, 0xbe, 0x03, 0xc4, 0x51, 0xd6, 0x21, 0x92, 0x40, 0x38,
+    0xaa, 0x5b, 0x28, 0xb5, 0xa1, 0x10, 0x52, 0x57, 0xff, 0x91, 0x54, 0x82,
+    0x86, 0x9e, 0x74, 0xd5, 0x3d, 0x82, 0x29, 0xee, 0xd1, 0xcf, 0x93, 0xb1,
+    0x24, 0x76, 0xbb, 0x95, 0x41, 0x06, 0x7e, 0x40, 0x9b, 0xb4, 0xab, 0x44,
+    0x34, 0x10, 0x8f, 0xb1, 0x51, 0x6f, 0xc0, 0x89, 0xd1, 0xa3, 0xc4, 0x9f,
+    0xb3, 0x48, 0xe1, 0xcd, 0x73, 0xad, 0xff, 0x42, 0x5f, 0x76, 0x05, 0x60,
+    0xc5, 0xe0, 0x45, 0x79, 0x18, 0xa1, 0x19, 0xb8, 0xa7, 0x3a, 0x64, 0xb3,
+    0x19, 0xba, 0x14, 0xa1, 0xb5, 0xdc, 0x32, 0xec, 0x09, 0x39, 0x58, 0x54,
+    0x5b, 0x04, 0xdc, 0x1b, 0x66, 0x0d, 0x1d, 0x0d, 0xce, 0x7f, 0xfa, 0x24,
+    0x52, 0x6a, 0xad, 0xe2, 0xc8, 0x30, 0xaf, 0xf2, 0xaf, 0x63, 0xc5, 0xe2,
+    0xbf, 0xe2, 0x20, 0x1b, 0x9e, 0xf9, 0x3d, 0xbc, 0xfb, 0x04, 0x8e, 0xda,
+    0x7a, 0x1a, 0x5d, 0xd3, 0x13, 0xd7, 0x00, 0x8e, 0x9b, 0x5d, 0x85, 0x51,
+    0xda, 0xd3, 0x91, 0x25, 0xf5, 0x67, 0x85, 0x3e, 0x25, 0x89, 0x5e, 0xcb,
+    0x89, 0x8a, 0xec, 0x8a, 0xde, 0x8b, 0xf4, 0x33, 0x5f, 0x76, 0xdb, 0x3d,
+    0xfc, 0x6a, 0x05, 0x21, 0x43, 0xb2, 0x41, 0xd8, 0x33, 0x8d, 0xfd, 0x05,
+    0x5c, 0x22, 0x0a, 0xf6, 0x90, 0x65, 0x9c, 0x4f, 0x8c, 0x44, 0x9f, 0x2d,
+    0xca, 0xf3, 0x49, 0x9c, 0x3a, 0x14, 0x88, 0xab, 0xe4, 0xce, 0xb7, 0xbc,
+    0x95, 0x22, 0x2e, 0xb1, 0x82, 0x4c, 0xbf, 0x83, 0x3e, 0x49, 0x72, 0x03,
+    0x2a, 0x68, 0xe7, 0x2d, 0xe5, 0x2d, 0x4b, 0x61, 0xb0, 0x8d, 0x0d, 0x0c,
+    0x87, 0xc6, 0x5c, 0x51
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const RSA_ROOT: [u8; 725] = [
+    0x30, 0x82, 0x02, 0xd1, 0x30, 0x82, 0x01, 0xbb, 0xa0, 0x03, 0x02, 0x01,
+    0x02, 0x02, 0x14, 0x29, 0x6c, 0x1a, 0xd8, 0x20, 0xcd, 0x74, 0x6d, 0x4b,
+    0x00, 0xf3, 0x16, 0x88, 0xd9, 0x66, 0x87, 0x5f, 0x28, 0x56, 0x6a, 0x30,
+    0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+    0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+    0x08, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x22, 0x18,
+    0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30,
+    0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32,
+    0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x13, 0x31,
+    0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x72, 0x6f,
+    0x6f, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
+    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+    0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82,
+    0x01, 0x01, 0x00, 0xba, 0x88, 0x51, 0xa8, 0x44, 0x8e, 0x16, 0xd6, 0x41,
+    0xfd, 0x6e, 0xb6, 0x88, 0x06, 0x36, 0x10, 0x3d, 0x3c, 0x13, 0xd9, 0xea,
+    0xe4, 0x35, 0x4a, 0xb4, 0xec, 0xf5, 0x68, 0x57, 0x6c, 0x24, 0x7b, 0xc1,
+    0xc7, 0x25, 0xa8, 0xe0, 0xd8, 0x1f, 0xbd, 0xb1, 0x9c, 0x06, 0x9b, 0x6e,
+    0x1a, 0x86, 0xf2, 0x6b, 0xe2, 0xaf, 0x5a, 0x75, 0x6b, 0x6a, 0x64, 0x71,
+    0x08, 0x7a, 0xa5, 0x5a, 0xa7, 0x45, 0x87, 0xf7, 0x1c, 0xd5, 0x24, 0x9c,
+    0x02, 0x7e, 0xcd, 0x43, 0xfc, 0x1e, 0x69, 0xd0, 0x38, 0x20, 0x29, 0x93,
+    0xab, 0x20, 0xc3, 0x49, 0xe4, 0xdb, 0xb9, 0x4c, 0xc2, 0x6b, 0x6c, 0x0e,
+    0xed, 0x15, 0x82, 0x0f, 0xf1, 0x7e, 0xad, 0x69, 0x1a, 0xb1, 0xd3, 0x02,
+    0x3a, 0x8b, 0x2a, 0x41, 0xee, 0xa7, 0x70, 0xe0, 0x0f, 0x0d, 0x8d, 0xfd,
+    0x66, 0x0b, 0x2b, 0xb0, 0x24, 0x92, 0xa4, 0x7d, 0xb9, 0x88, 0x61, 0x79,
+    0x90, 0xb1, 0x57, 0x90, 0x3d, 0xd2, 0x3b, 0xc5, 0xe0, 0xb8, 0x48, 0x1f,
+    0xa8, 0x37, 0xd3, 0x88, 0x43, 0xef, 0x27, 0x16, 0xd8, 0x55, 0xb7, 0x66,
+    0x5a, 0xaa, 0x7e, 0x02, 0x90, 0x2f, 0x3a, 0x7b, 0x10, 0x80, 0x06, 0x24,
+    0xcc, 0x1c, 0x6c, 0x97, 0xad, 0x96, 0x61, 0x5b, 0xb7, 0xe2, 0x96, 0x12,
+    0xc0, 0x75, 0x31, 0xa3, 0x0c, 0x91, 0xdd, 0xb4, 0xca, 0xf7, 0xfc, 0xad,
+    0x1d, 0x25, 0xd3, 0x09, 0xef, 0xb9, 0x17, 0x0e, 0xa7, 0x68, 0xe1, 0xb3,
+    0x7b, 0x2f, 0x22, 0x6f, 0x69, 0xe3, 0xb4, 0x8a, 0x95, 0x61, 0x1d, 0xee,
+    0x26, 0xd6, 0x25, 0x9d, 0xab, 0x91, 0x08, 0x4e, 0x36, 0xcb, 0x1c, 0x24,
+    0x04, 0x2c, 0xbf, 0x16, 0x8b, 0x2f, 0xe5, 0xf1, 0x8f, 0x99, 0x17, 0x31,
+    0xb8, 0xb3, 0xfe, 0x49, 0x23, 0xfa, 0x72, 0x51, 0xc4, 0x31, 0xd5, 0x03,
+    0xac, 0xda, 0x18, 0x0a, 0x35, 0xed, 0x8d, 0x02, 0x03, 0x01, 0x00, 0x01,
+    0xa3, 0x1d, 0x30, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
+    0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d,
+    0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0b, 0x06, 0x09, 0x2a,
+    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x03, 0x82, 0x01, 0x01,
+    0x00, 0x23, 0x2f, 0x9f, 0x72, 0xeb, 0x70, 0x6d, 0x9e, 0x3e, 0x9f, 0xd7,
+    0x9c, 0xd9, 0x19, 0x7c, 0x99, 0x07, 0xc5, 0x5c, 0x9d, 0xf5, 0x66, 0x9f,
+    0x28, 0x8d, 0xfe, 0x0e, 0x3f, 0x38, 0x75, 0xed, 0xee, 0x4e, 0x3f, 0xf6,
+    0x6e, 0x35, 0xe0, 0x95, 0x3f, 0x08, 0x4a, 0x71, 0x5a, 0xf2, 0x4f, 0xc9,
+    0x96, 0x61, 0x8d, 0x45, 0x4b, 0x97, 0x85, 0xff, 0xb0, 0xe3, 0xbb, 0xb5,
+    0xd7, 0x7e, 0xfb, 0xd2, 0xfc, 0xec, 0xfe, 0x42, 0x9f, 0x4e, 0x7b, 0xbf,
+    0x97, 0xbb, 0xb4, 0x3a, 0x93, 0x0b, 0x13, 0x61, 0x90, 0x0c, 0x3a, 0xce,
+    0xf7, 0x8e, 0xef, 0x80, 0xf5, 0x4a, 0x92, 0xc5, 0xa5, 0x03, 0x78, 0xc2,
+    0xee, 0xb8, 0x66, 0x60, 0x6b, 0x76, 0x4f, 0x32, 0x5a, 0x1a, 0xa2, 0x4b,
+    0x7e, 0x2b, 0xa6, 0x1a, 0x89, 0x01, 0xe3, 0xbb, 0x55, 0x13, 0x7c, 0x4c,
+    0xf4, 0x6a, 0x99, 0x94, 0xd1, 0xa0, 0x84, 0x1c, 0x1a, 0xc2, 0x7b, 0xb4,
+    0xa0, 0xb0, 0x3b, 0xdc, 0x5a, 0x7b, 0xc7, 0xe0, 0x44, 0xb2, 0x1f, 0x46,
+    0xd5, 0x8b, 0x39, 0x8b, 0xdc, 0x9e, 0xce, 0xa8, 0x7f, 0x85, 0x1d, 0x4b,
+    0x63, 0x06, 0x1e, 0x8e, 0xe5, 0xe5, 0x99, 0xd9, 0xf7, 0x4d, 0x89, 0x0b,
+    0x1d, 0x5c, 0x27, 0x33, 0x66, 0x21, 0xcf, 0x9a, 0xbd, 0x98, 0x68, 0x23,
+    0x3a, 0x66, 0x9d, 0xd4, 0x46, 0xed, 0x63, 0x58, 0xf3, 0x42, 0xe4, 0x1d,
+    0xe2, 0x47, 0x65, 0x13, 0x8d, 0xd4, 0x1f, 0x4b, 0x7e, 0xde, 0x11, 0x56,
+    0xf8, 0x6d, 0x01, 0x0c, 0x99, 0xbd, 0x8d, 0xca, 0x8a, 0x2e, 0xe3, 0x8a,
+    0x9c, 0x3d, 0x83, 0x8d, 0x69, 0x62, 0x8d, 0x05, 0xea, 0xb7, 0xf5, 0xa3,
+    0x4b, 0xfc, 0x96, 0xcf, 0x18, 0x21, 0x0a, 0xc7, 0xf3, 0x23, 0x7e, 0x1c,
+    0xab, 0xe2, 0xa2, 0xd1, 0x83, 0xc4, 0x25, 0x93, 0x37, 0x80, 0xca, 0xda,
+    0xf0, 0xef, 0x7d, 0x94, 0xb5
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const XPI_SIGNATURE: [u8; 646] = [
+    0xd8, 0x62, 0x84, 0x43, 0xa1, 0x04, 0x80, 0xa0, 0xf6, 0x81, 0x83, 0x59,
+    0x02, 0x35, 0xa2, 0x01, 0x26, 0x04, 0x59, 0x02, 0x2e, 0x30, 0x82, 0x02,
+    0x2a, 0x30, 0x82, 0x01, 0x12, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14,
+    0x17, 0x03, 0x6b, 0xc1, 0xfe, 0xb4, 0x38, 0xe1, 0x83, 0x8f, 0xe5, 0xa7,
+    0xca, 0xf1, 0x54, 0x32, 0x4c, 0x8b, 0xf3, 0x05, 0x30, 0x0d, 0x06, 0x09,
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30,
+    0x29, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e,
+    0x78, 0x70, 0x63, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x20, 0x73, 0x69, 0x67,
+    0x6e, 0x65, 0x64, 0x20, 0x61, 0x70, 0x70, 0x73, 0x20, 0x74, 0x65, 0x73,
+    0x74, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30,
+    0x31, 0x35, 0x31, 0x31, 0x32, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+    0x5a, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x38, 0x30, 0x32, 0x30, 0x35, 0x30,
+    0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x27,
+    0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x20, 0x20, 0x78, 0x70, 0x63, 0x73,
+    0x68, 0x65, 0x6c, 0x6c, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20,
+    0x61, 0x70, 0x70, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69, 0x67,
+    0x6e, 0x65, 0x72, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48,
+    0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03,
+    0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb, 0xbb, 0x61, 0xe0,
+    0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04, 0xe2, 0xec, 0x05,
+    0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c, 0x4f, 0x79, 0x4b,
+    0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d,
+    0x07, 0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b,
+    0x7b, 0x2d, 0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0xa3, 0x0f,
+    0x30, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03,
+    0x02, 0x07, 0x80, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+    0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4f,
+    0x5c, 0xcb, 0x1d, 0xea, 0x71, 0x58, 0xfe, 0xe2, 0x49, 0x11, 0x16, 0x65,
+    0xbc, 0x23, 0x6d, 0xda, 0x46, 0x7e, 0x98, 0x93, 0x5d, 0x48, 0x2a, 0xa0,
+    0xbb, 0x7f, 0x4e, 0xbd, 0x01, 0x0a, 0x1a, 0x30, 0xff, 0xce, 0x03, 0xf5,
+    0x9c, 0xd9, 0x84, 0x69, 0x7a, 0x5a, 0xe3, 0x43, 0xd2, 0xd4, 0xbc, 0xab,
+    0x4d, 0x17, 0x8f, 0x10, 0x6a, 0xcf, 0xde, 0x17, 0x1d, 0x7d, 0x16, 0x03,
+    0x7e, 0x21, 0xf0, 0x32, 0x02, 0x89, 0x67, 0x32, 0x5a, 0xfe, 0xd5, 0xd9,
+    0x31, 0x53, 0xdc, 0xd7, 0xba, 0x2a, 0x9f, 0xd3, 0x59, 0x8d, 0x61, 0xb9,
+    0x6e, 0xf7, 0x6e, 0x86, 0x61, 0xdd, 0xfd, 0xe1, 0x73, 0xfe, 0xef, 0x9d,
+    0xe9, 0x99, 0x9e, 0x51, 0xe8, 0x5d, 0xf7, 0x48, 0x77, 0x8e, 0xc6, 0xe8,
+    0x53, 0x05, 0x7b, 0x5c, 0x2c, 0x28, 0xe7, 0x0a, 0x07, 0xbf, 0xea, 0xc1,
+    0x06, 0x11, 0x0d, 0xe7, 0x60, 0xd0, 0x79, 0x94, 0xe9, 0x26, 0xf1, 0x93,
+    0x71, 0x7b, 0x5b, 0x02, 0x3b, 0x5d, 0x51, 0xb8, 0x19, 0x38, 0x16, 0xab,
+    0x48, 0x30, 0xf3, 0xec, 0xd9, 0xd5, 0x8f, 0xc7, 0x9a, 0x02, 0xfd, 0x12,
+    0x57, 0x82, 0x0e, 0xde, 0xce, 0xfc, 0x50, 0x42, 0x2a, 0x41, 0xc7, 0xc6,
+    0xa8, 0x80, 0x37, 0x7c, 0xc4, 0x47, 0xad, 0xf5, 0xd8, 0xcb, 0xe8, 0xae,
+    0x0c, 0x01, 0x80, 0x60, 0x35, 0x93, 0x0a, 0x21, 0x81, 0x33, 0xd1, 0xd6,
+    0x6a, 0x1b, 0xe7, 0xb6, 0xd9, 0x91, 0x50, 0xc2, 0xbd, 0x16, 0xda, 0xb7,
+    0x68, 0x60, 0xf2, 0x20, 0xaa, 0x72, 0x8c, 0x76, 0x0a, 0x54, 0x7a, 0x05,
+    0xd8, 0xa1, 0xcd, 0xe9, 0x07, 0x8a, 0x02, 0x07, 0x4b, 0x87, 0x7d, 0xb5,
+    0x27, 0xca, 0x38, 0xb3, 0x30, 0xaf, 0x97, 0xe0, 0xb7, 0x35, 0x14, 0x08,
+    0xab, 0x01, 0xb0, 0x14, 0x08, 0x5c, 0x4b, 0xfb, 0x76, 0x0a, 0x95, 0xfc,
+    0xb4, 0xb8, 0x34, 0xa0, 0x58, 0x40, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11,
+    0x50, 0xcd, 0x5d, 0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff,
+    0xb2, 0x73, 0x75, 0x5f, 0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a,
+    0x70, 0xe6, 0x82, 0x02, 0x0a, 0xe8, 0x69, 0x13, 0xd5, 0xf4, 0x1b, 0xab,
+    0xb6, 0xbb, 0x59, 0x93, 0x08, 0x48, 0x68, 0x9c, 0xbd, 0x72, 0xc7, 0xcb,
+    0x37, 0xde, 0x26, 0xbc, 0xe9, 0x83, 0x0e, 0xd8, 0x90, 0xa3
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const XPI_PAYLOAD: [u8; 236] = [
+    0x4E, 0x61, 0x6D, 0x65, 0x3A, 0x20, 0x6D, 0x61, 0x6E, 0x69, 0x66, 0x65,
+    0x73, 0x74, 0x2E, 0x6A, 0x73, 0x6F, 0x6E, 0x0A, 0x53, 0x48, 0x41, 0x32,
+    0x35, 0x36, 0x2D, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x3A, 0x20, 0x42,
+    0x54, 0x6E, 0x43, 0x70, 0x54, 0x31, 0x35, 0x34, 0x4E, 0x32, 0x36, 0x52,
+    0x5A, 0x6D, 0x38, 0x62, 0x68, 0x64, 0x44, 0x34, 0x33, 0x57, 0x58, 0x64,
+    0x30, 0x74, 0x6A, 0x35, 0x62, 0x67, 0x36, 0x6F, 0x66, 0x4D, 0x31, 0x39,
+    0x4E, 0x4C, 0x49, 0x30, 0x4F, 0x45, 0x3D, 0x0A, 0x0A, 0x4E, 0x61, 0x6D,
+    0x65, 0x3A, 0x20, 0x52, 0x45, 0x41, 0x44, 0x4D, 0x45, 0x0A, 0x53, 0x48,
+    0x41, 0x32, 0x35, 0x36, 0x2D, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x3A,
+    0x20, 0x62, 0x59, 0x30, 0x6C, 0x39, 0x78, 0x71, 0x47, 0x4A, 0x59, 0x43,
+    0x70, 0x71, 0x59, 0x65, 0x4A, 0x30, 0x4B, 0x36, 0x71, 0x34, 0x44, 0x57,
+    0x55, 0x51, 0x71, 0x75, 0x30, 0x6D, 0x4E, 0x42, 0x46, 0x4D, 0x34, 0x48,
+    0x34, 0x65, 0x6D, 0x68, 0x6A, 0x69, 0x4A, 0x67, 0x3D, 0x0A, 0x0A, 0x4E,
+    0x61, 0x6D, 0x65, 0x3A, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2F, 0x69, 0x6D,
+    0x61, 0x67, 0x65, 0x2E, 0x70, 0x6E, 0x67, 0x0A, 0x53, 0x48, 0x41, 0x32,
+    0x35, 0x36, 0x2D, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x3A, 0x20, 0x45,
+    0x50, 0x6A, 0x6B, 0x4E, 0x5A, 0x77, 0x79, 0x61, 0x39, 0x58, 0x2B, 0x70,
+    0x72, 0x75, 0x4C, 0x6C, 0x78, 0x47, 0x2B, 0x46, 0x41, 0x43, 0x4C, 0x77,
+    0x47, 0x43, 0x34, 0x38, 0x58, 0x55, 0x34, 0x53, 0x39, 0x6F, 0x5A, 0x4F,
+    0x41, 0x30, 0x6C, 0x56, 0x56, 0x51, 0x3D, 0x0A
+];
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/examples/sign_verify/util_test.rs
@@ -0,0 +1,194 @@
+/// We don't need COSE signing at the moment. But we need to generate test files.
+/// This module implements basic COSE signing.
+use nss;
+use {CoseError, Signature, SignatureAlgorithm, SignatureParameters};
+use std::collections::BTreeMap;
+use cbor::CborType;
+use cose::util::get_sig_struct_bytes;
+use cose::decoder::decode_signature;
+use cose::decoder::{COSE_TYPE_ES256, COSE_TYPE_ES384, COSE_TYPE_ES512, COSE_TYPE_PS256};
+
+/// Converts a `SignatureAlgorithm` to its corresponding `CborType`.
+/// See RFC 8152 section 8.1 and RFC 8230 section 5.1.
+pub fn signature_type_to_cbor_value(signature_type: &SignatureAlgorithm) -> CborType {
+    CborType::SignedInteger(match signature_type {
+        &SignatureAlgorithm::ES256 => COSE_TYPE_ES256,
+        &SignatureAlgorithm::ES384 => COSE_TYPE_ES384,
+        &SignatureAlgorithm::ES512 => COSE_TYPE_ES512,
+        &SignatureAlgorithm::PS256 => COSE_TYPE_PS256,
+    })
+}
+
+pub fn build_protected_sig_header(ee_cert: &[u8], alg: &SignatureAlgorithm) -> CborType {
+    // Protected signature header
+    let mut header_map: BTreeMap<CborType, CborType> = BTreeMap::new();
+
+    // Signature type.
+    let signature_type_value = signature_type_to_cbor_value(alg);
+    header_map.insert(CborType::Integer(1), signature_type_value);
+
+    // Signer certificate.
+    header_map.insert(CborType::Integer(4), CborType::Bytes(ee_cert.to_vec()));
+
+    let header_map = CborType::Map(header_map).serialize();
+    CborType::Bytes(header_map)
+}
+
+pub fn build_protected_header(cert_chain: &[&[u8]]) -> CborType {
+    let mut cert_array: Vec<CborType> = Vec::new();
+    for cert in cert_chain {
+        cert_array.push(CborType::Bytes(cert.to_vec()));
+    }
+    let mut protected_body_header: BTreeMap<CborType, CborType> = BTreeMap::new();
+    protected_body_header.insert(CborType::Integer(4), CborType::Array(cert_array));
+    let protected_body_header = CborType::Map(protected_body_header).serialize();
+
+    CborType::Bytes(protected_body_header)
+}
+
+pub fn build_sig_struct(ee_cert: &[u8], alg: &SignatureAlgorithm, sig_bytes: &Vec<u8>) -> CborType {
+    // Build the signature item.
+    let mut signature_item: Vec<CborType> = Vec::new();
+
+    // Protected signature header
+    signature_item.push(build_protected_sig_header(ee_cert, alg));
+
+    // The unprotected signature header is empty.
+    let empty_map: BTreeMap<CborType, CborType> = BTreeMap::new();
+    signature_item.push(CborType::Map(empty_map));
+
+    // And finally the signature bytes.
+    signature_item.push(CborType::Bytes(sig_bytes.clone()));
+    CborType::Array(signature_item)
+}
+
+// 98(
+//  [
+//    / protected / h'..', / {
+//          \ kid \ 4:'..' \ Array of DER encoded intermediate certificates  \
+//      } / ,
+//    / unprotected / {},
+//    / payload / nil, / The payload is the contents of the manifest file /
+//    / signatures / [
+//      [
+//        / protected / h'a2012604..' / {
+//            \ alg \ 1:-7, \ ECDSA with SHA-256 \
+//            \ kid \ 4:'..' \ DER encoded signing certificate \
+//          } / ,
+//        / unprotected / {},
+//        / signature / h'e2ae..'
+//      ],
+//      [
+//        / protected / h'a201382404..' / {
+//            \ alg \ 1:-37, \ RSASSA-PSS with SHA-256 \
+//            \ kid \ 4:'..' \ DER encoded signing certificate \
+//          } / ,
+//        / unprotected / {},
+//        / signature / h'00a2..'
+//      ]
+//    ]
+//  ]
+pub fn build_cose_signature(cert_chain: &[&[u8]], signature_vec: &Vec<Signature>) -> Vec<u8> {
+    // Building the COSE signature content.
+    let mut cose_signature: Vec<CborType> = Vec::new();
+
+    // add cert chain as protected header
+    cose_signature.push(build_protected_header(cert_chain));
+
+    // Empty map (unprotected header)
+    let empty_map: BTreeMap<CborType, CborType> = BTreeMap::new();
+    cose_signature.push(CborType::Map(empty_map));
+
+    // No payload (nil).
+    cose_signature.push(CborType::Null);
+
+    // Create signature items.
+    let mut signatures: Vec<CborType> = Vec::new();
+    for signature in signature_vec {
+        let signature_item = build_sig_struct(
+            signature.parameter.certificate,
+            &signature.parameter.algorithm,
+            &signature.signature_bytes,
+        );
+        signatures.push(signature_item);
+    }
+
+    // Pack the signature item and add everything to the cose signature object.
+    cose_signature.push(CborType::Array(signatures));
+
+    // A COSE signature is a tagged array (98).
+    let signature_struct = CborType::Tag(98, Box::new(CborType::Array(cose_signature).clone()));
+
+    return signature_struct.serialize();
+}
+
+pub fn sign(
+    payload: &[u8],
+    cert_chain: &[&[u8]],
+    parameters: &Vec<SignatureParameters>,
+) -> Result<Vec<u8>, CoseError> {
+    assert!(parameters.len() > 0);
+    if parameters.len() < 1 {
+        return Err(CoseError::InvalidArgument);
+    }
+
+    let mut signatures: Vec<Signature> = Vec::new();
+    for param in parameters {
+        // Build the signature structure containing the protected headers and the
+        // payload to generate the payload that is actually signed.
+        let protected_sig_header_serialized =
+            build_protected_sig_header(param.certificate, &param.algorithm);
+        let protected_header_serialized = build_protected_header(cert_chain);
+        let payload = get_sig_struct_bytes(
+            protected_header_serialized,
+            protected_sig_header_serialized,
+            payload,
+        );
+
+        let signature_bytes = match nss::sign(&param.algorithm, &param.pkcs8, &payload) {
+            Err(_) => return Err(CoseError::SigningFailed),
+            Ok(signature) => signature,
+        };
+        let signature = Signature {
+            parameter: param,
+            signature_bytes: signature_bytes,
+        };
+        signatures.push(signature);
+    }
+
+    assert!(signatures.len() > 0);
+    if signatures.len() < 1 {
+        return Err(CoseError::MalformedInput);
+    }
+
+    let cose_signature = build_cose_signature(cert_chain, &signatures);
+    Ok(cose_signature)
+}
+
+/// Verify a COSE signature.
+pub fn verify_signature(payload: &[u8], cose_signature: Vec<u8>) -> Result<(), CoseError> {
+    // Parse COSE signature.
+    let cose_signatures = decode_signature(&cose_signature, payload)?;
+    if cose_signatures.len() < 1 {
+        return Err(CoseError::MalformedInput);
+    }
+
+    for signature in cose_signatures {
+        let signature_algorithm = &signature.signature_type;
+        let signature_bytes = &signature.signature;
+        let real_payload = &signature.to_verify;
+
+        // Verify the parsed signatures.
+        // We ignore the certs field here because we don't verify the certificate.
+        let verify_result = nss::verify_signature(
+            &signature_algorithm,
+            &signature.signer_cert,
+            real_payload,
+            signature_bytes,
+        );
+        if !verify_result.is_ok() {
+            return Err(CoseError::VerificationFailed);
+        }
+    }
+    Ok(())
+}
deleted file mode 100644
--- a/third_party/rust/cose/src/cbor/decoder.rs
+++ /dev/null
@@ -1,150 +0,0 @@
-use std::collections::BTreeMap;
-use std::io::{Cursor, Read, Seek, SeekFrom};
-use cbor::{CborError, CborType};
-
-// We limit the length of any cbor byte array to 128MiB. This is a somewhat
-// arbitrary limit that should work on all platforms and is large enough for
-// any benign data.
-pub const MAX_ARRAY_SIZE: usize = 134_217_728;
-
-/// Struct holding a cursor and additional information for decoding.
-#[derive(Debug)]
-struct DecoderCursor<'a> {
-    cursor: Cursor<&'a [u8]>,
-}
-
-/// Apply this mask (with &) to get the value part of the initial byte of a CBOR item.
-const INITIAL_VALUE_MASK: u64 = 0b0001_1111;
-
-impl<'a> DecoderCursor<'a> {
-    /// Read and return the given number of bytes from the cursor. Advances the cursor.
-    fn read_bytes(&mut self, len: usize) -> Result<Vec<u8>, CborError> {
-        if len > MAX_ARRAY_SIZE {
-            return Err(CborError::InputTooLarge);
-        }
-        let mut buf: Vec<u8> = vec![0; len];
-        if self.cursor.read_exact(&mut buf).is_err() {
-            Err(CborError::TruncatedInput)
-        } else {
-            Ok(buf)
-        }
-    }
-
-    /// Convert num bytes to a u64
-    fn read_uint_from_bytes(&mut self, num: usize) -> Result<u64, CborError> {
-        let x = self.read_bytes(num)?;
-        let mut result: u64 = 0;
-        for i in (0..num).rev() {
-            result += u64::from(x[num - 1 - i]) << (i * 8);
-        }
-        Ok(result)
-    }
-
-    /// Read an integer and return it as u64.
-    fn read_int(&mut self) -> Result<u64, CborError> {
-        let first_value = self.read_uint_from_bytes(1)? & INITIAL_VALUE_MASK;
-        match first_value {
-            0...23 => Ok(first_value),
-            24 => self.read_uint_from_bytes(1),
-            25 => self.read_uint_from_bytes(2),
-            26 => self.read_uint_from_bytes(4),
-            27 => self.read_uint_from_bytes(8),
-            _ => Err(CborError::MalformedInput),
-        }
-    }
-
-    fn read_negative_int(&mut self) -> Result<CborType, CborError> {
-        let uint = self.read_int()?;
-        if uint > i64::max_value() as u64 {
-            return Err(CborError::InputValueOutOfRange);
-        }
-        let result: i64 = -1 - uint as i64;
-        Ok(CborType::SignedInteger(result))
-    }
-
-    /// Read an array of data items and return it.
-    fn read_array(&mut self) -> Result<CborType, CborError> {
-        // Create a new array.
-        let mut array: Vec<CborType> = Vec::new();
-        // Read the length of the array.
-        let num_items = self.read_int()?;
-        // Decode each of the num_items data items.
-        for _ in 0..num_items {
-            let new_item = self.decode_item()?;
-            array.push(new_item);
-        }
-        Ok(CborType::Array(array))
-    }
-
-    /// Read a byte string and return it.
-    fn read_byte_string(&mut self) -> Result<CborType, CborError> {
-        let length = self.read_int()?;
-        if length > MAX_ARRAY_SIZE as u64 {
-            return Err(CborError::InputTooLarge);
-        }
-        let byte_string = self.read_bytes(length as usize)?;
-        Ok(CborType::Bytes(byte_string))
-    }
-
-    /// Read a map.
-    fn read_map(&mut self) -> Result<CborType, CborError> {
-        let num_items = self.read_int()?;
-        // Create a new array.
-        let mut map: BTreeMap<CborType, CborType> = BTreeMap::new();
-        // Decode each of the num_items (key, data item) pairs.
-        for _ in 0..num_items {
-            let key_val = self.decode_item()?;
-            let item_value = self.decode_item()?;
-            if map.insert(key_val, item_value).is_some() {
-                return Err(CborError::DuplicateMapKey);
-            }
-        }
-        Ok(CborType::Map(map))
-    }
-
-    fn read_null(&mut self) -> Result<CborType, CborError> {
-        let value = self.read_uint_from_bytes(1)? & INITIAL_VALUE_MASK;
-        if value != 22 {
-            return Err(CborError::UnsupportedType);
-        }
-        Ok(CborType::Null)
-    }
-
-    /// Peeks at the next byte in the cursor, but does not change the position.
-    fn peek_byte(&mut self) -> Result<u8, CborError> {
-        let x = self.read_bytes(1)?;
-        if self.cursor.seek(SeekFrom::Current(-1)).is_err() {
-            return Err(CborError::LibraryError);
-        };
-        Ok(x[0])
-    }
-
-    /// Decodes the next CBOR item.
-    pub fn decode_item(&mut self) -> Result<CborType, CborError> {
-        let major_type = self.peek_byte()? >> 5;
-        match major_type {
-            0 => {
-                let value = self.read_int()?;
-                Ok(CborType::Integer(value))
-            }
-            1 => self.read_negative_int(),
-            2 => self.read_byte_string(),
-            4 => self.read_array(),
-            5 => self.read_map(),
-            6 => {
-                let tag = self.read_int()?;
-                let item = self.decode_item()?;
-                Ok(CborType::Tag(tag, Box::new(item)))
-            }
-            7 => self.read_null(),
-            _ => Err(CborError::UnsupportedType),
-        }
-    }
-}
-
-/// Read the CBOR structure in bytes and return it as a `CborType`.
-pub fn decode(bytes: &[u8]) -> Result<CborType, CborError> {
-    let mut decoder_cursor = DecoderCursor { cursor: Cursor::new(bytes) };
-    decoder_cursor.decode_item()
-    // TODO: check cursor at end?
-}
deleted file mode 100644
--- a/third_party/rust/cose/src/cbor/serializer.rs
+++ /dev/null
@@ -1,121 +0,0 @@
-use std::collections::BTreeMap;
-use cbor::CborType;
-
-/// Given a vector of bytes to append to, a tag to use, and an unsigned value to encode, uses the
-/// CBOR unsigned integer encoding to represent the given value.
-fn common_encode_unsigned(output: &mut Vec<u8>, tag: u8, value: u64) {
-    assert!(tag < 8);
-    let shifted_tag = tag << 5;
-    match value {
-        0...23 => {
-            output.push(shifted_tag | (value as u8));
-        }
-        24...255 => {
-            output.push(shifted_tag | 24);
-            output.push(value as u8);
-        }
-        256...65_535 => {
-            output.push(shifted_tag | 25);
-            output.push((value >> 8) as u8);
-            output.push((value & 255) as u8);
-        }
-        65_536...4_294_967_295 => {
-            output.push(shifted_tag | 26);
-            output.push((value >> 24) as u8);
-            output.push(((value >> 16) & 255) as u8);
-            output.push(((value >> 8) & 255) as u8);
-            output.push((value & 255) as u8);
-        }
-        _ => {
-            output.push(shifted_tag | 27);
-            output.push((value >> 56) as u8);
-            output.push(((value >> 48) & 255) as u8);
-            output.push(((value >> 40) & 255) as u8);
-            output.push(((value >> 32) & 255) as u8);
-            output.push(((value >> 24) & 255) as u8);
-            output.push(((value >> 16) & 255) as u8);
-            output.push(((value >> 8) & 255) as u8);
-            output.push((value & 255) as u8);
-        }
-    };
-}
-
-/// The major type is 0. For values 0 through 23, the 5 bits of additional information is just the
-/// value of the unsigned number. For values representable in one byte, the additional information
-/// has the value 24. If two bytes are necessary, the value is 25. If four bytes are necessary, the
-/// value is 26. If 8 bytes are necessary, the value is 27. The following bytes are the value of the
-/// unsigned number in as many bytes were indicated in network byte order (big endian).
-fn encode_unsigned(output: &mut Vec<u8>, unsigned: u64) {
-    common_encode_unsigned(output, 0, unsigned);
-}
-
-/// The major type is 1. The encoding is the same as for positive (i.e. unsigned) integers, except
-/// the value encoded is -1 minus the value of the negative number.
-fn encode_negative(output: &mut Vec<u8>, negative: i64) {
-    assert!(negative < 0);
-    let value_to_encode: u64 = (-1 - negative) as u64;
-    common_encode_unsigned(output, 1, value_to_encode);
-}
-
-/// The major type is 2. The length of the data is encoded as with positive integers, followed by
-/// the actual data.
-fn encode_bytes(output: &mut Vec<u8>, bstr: &[u8]) {
-    common_encode_unsigned(output, 2, bstr.len() as u64);
-    output.extend_from_slice(bstr);
-}
-
-/// The major type is 3. The length is as with bstr. The UTF-8-encoded bytes of the string follow.
-fn encode_string(output: &mut Vec<u8>, tstr: &str) {
-    let utf8_bytes = tstr.as_bytes();
-    common_encode_unsigned(output, 3, utf8_bytes.len() as u64);
-    output.extend_from_slice(utf8_bytes);
-}
-
-/// The major type is 4. The number of items is encoded as with positive integers. Then follows the
-/// encodings of the items themselves.
-fn encode_array(output: &mut Vec<u8>, array: &[CborType]) {
-    common_encode_unsigned(output, 4, array.len() as u64);
-    for element in array {
-        output.append(&mut element.serialize());
-    }
-}
-
-/// The major type is 5. The number of pairs is encoded as with positive integers. Then follows the
-/// encodings of each key, value pair. In Canonical CBOR, the keys must be sorted lowest value to
-/// highest.
-fn encode_map(output: &mut Vec<u8>, map: &BTreeMap<CborType, CborType>) {
-    common_encode_unsigned(output, 5, map.len() as u64);
-    for (key, value) in map {
-        output.append(&mut key.serialize());
-        output.append(&mut value.serialize());
-    }
-}
-
-fn encode_tag(output: &mut Vec<u8>, tag: &u64, val: &CborType) {
-    common_encode_unsigned(output, 6, *tag);
-    output.append(&mut val.serialize());
-}
-
-/// The major type is 7. The only supported value for this type is 22, which is Null.
-/// This makes the encoded value 246, or 0xf6.
-fn encode_null(output: &mut Vec<u8>) {
-    output.push(0xf6);
-}
-
-impl CborType {
-    /// Serialize a Cbor object.
-    pub fn serialize(&self) -> Vec<u8> {
-        let mut bytes: Vec<u8> = Vec::new();
-        match *self {
-            CborType::Integer(ref unsigned) => encode_unsigned(&mut bytes, *unsigned),
-            CborType::SignedInteger(ref negative) => encode_negative(&mut bytes, *negative),
-            CborType::Bytes(ref bstr) => encode_bytes(&mut bytes, bstr),
-            CborType::String(ref tstr) => encode_string(&mut bytes, tstr),
-            CborType::Array(ref arr) => encode_array(&mut bytes, arr),
-            CborType::Map(ref map) => encode_map(&mut bytes, map),
-            CborType::Tag(ref t, ref val) => encode_tag(&mut bytes, t, val),
-            CborType::Null => encode_null(&mut bytes),
-        };
-        bytes
-    }
-}
deleted file mode 100644
--- a/third_party/rust/cose/src/cbor/test_decoder.rs
+++ /dev/null
@@ -1,405 +0,0 @@
-use cbor::decoder::*;
-use cbor::*;
-use std::collections::BTreeMap;
-
-// First test all the basic types
-fn test_decoder(bytes: Vec<u8>, expected: CborType) {
-    let result = decode(&bytes);
-    assert!(result.is_ok());
-    assert_eq!(result.unwrap(), expected);
-}
-
-fn test_decoder_error(bytes: Vec<u8>, expected_error: CborError) {
-    let result = decode(&bytes);
-    assert!(result.is_err());
-    assert_eq!(result.unwrap_err(), expected_error);
-}
-
-fn test_integer(bytes: Vec<u8>, expected: u64) {
-    let decoded = decode(&bytes).unwrap();
-    match decoded {
-        CborType::Integer(val) => assert_eq!(val, expected),
-        _ => assert_eq!(1, 0),
-    }
-}
-
-fn test_integer_all(bytes: Vec<u8>, expected_value: u64) {
-    let expected = CborType::Integer(expected_value);
-    test_decoder(bytes.clone(), expected);
-    test_integer(bytes, expected_value);
-}
-
-#[test]
-fn test_integer_objects() {
-    let bytes: Vec<u8> = vec![0x00];
-    test_integer_all(bytes, 0);
-
-    let bytes = vec![0x01];
-    test_integer_all(bytes, 1);
-
-    let bytes = vec![0x0A];
-    test_integer_all(bytes, 10);
-
-    let bytes = vec![0x17];
-    test_integer_all(bytes, 23);
-
-    let bytes = vec![0x18, 0x18];
-    test_integer_all(bytes, 24);
-
-    let bytes = vec![0x18, 0x19];
-    test_integer_all(bytes, 25);
-
-    let bytes = vec![0x18, 0x64];
-    test_integer_all(bytes, 100);
-
-    let bytes = vec![0x19, 0x03, 0xe8];
-    test_integer_all(bytes, 1000);
-
-    let bytes = vec![0x1a, 0x00, 0x0f, 0x42, 0x40];
-    test_integer_all(bytes, 1000000);
-
-    let bytes = vec![0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00];
-    test_integer_all(bytes, 1000000000000);
-
-    let bytes = vec![0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
-    test_integer_all(bytes, 18446744073709551615);
-}
-
-#[cfg(test)]
-fn test_tag(bytes: Vec<u8>, expected_tag: u64, expected_value: CborType) {
-    let decoded = decode(&bytes).unwrap();
-    match decoded {
-        CborType::Tag(tag, value) => {
-            assert_eq!(expected_tag, tag);
-            assert_eq!(expected_value, *value);
-        }
-        _ => assert_eq!(1, 0),
-    }
-}
-
-#[test]
-fn test_tagged_objects() {
-    let bytes: Vec<u8> = vec![0xD2, 0x02];
-    let expected_tag_value = 0x12;
-    let expected_value = CborType::Integer(2);
-    let expected = CborType::Tag(expected_tag_value, Box::new(expected_value.clone()));
-    test_decoder(bytes.clone(), expected);
-    test_tag(bytes, expected_tag_value, expected_value);
-}
-
-#[test]
-#[cfg_attr(rustfmt, rustfmt_skip)]
-fn test_arrays() {
-    // []
-    let bytes: Vec<u8> = vec![0x80];
-    let expected = CborType::Array(vec![]);
-    test_decoder(bytes, expected);
-
-    // [1, 2, 3]
-    let bytes: Vec<u8> = vec![0x83, 0x01, 0x02, 0x03];
-    let tmp = vec![
-        CborType::Integer(1),
-        CborType::Integer(2),
-        CborType::Integer(3),
-    ];
-    let expected = CborType::Array(tmp);
-    test_decoder(bytes, expected);
-
-    // [1, [2, 3], [4, 5]]
-    let bytes: Vec<u8> = vec![0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05];
-    let tmp1 = vec![CborType::Integer(2), CborType::Integer(3)];
-    let tmp2 = vec![CborType::Integer(4), CborType::Integer(5)];
-    let tmp = vec![
-        CborType::Integer(1),
-        CborType::Array(tmp1),
-        CborType::Array(tmp2),
-    ];
-    let expected = CborType::Array(tmp);
-    test_decoder(bytes, expected);
-
-    // [1, [[[[1]]]], [1]]
-    let bytes: Vec<u8> = vec![0x83, 0x01, 0x81, 0x81, 0x81, 0x81, 0x01, 0x81, 0x02];
-    let tmp = vec![
-        CborType::Integer(1),
-        CborType::Array(vec![
-            CborType::Array(vec![
-                CborType::Array(vec![
-                    CborType::Array(vec![
-                        CborType::Integer(1)])])])]),
-        CborType::Array(vec![CborType::Integer(2)]),
-    ];
-    let expected = CborType::Array(tmp);
-    test_decoder(bytes, expected);
-
-    let bytes: Vec<u8> = vec![0x98, 0x1A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
-                              0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
-                              0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
-                              0x17, 0x18, 0x18, 0x18, 0x19, 0x82, 0x81, 0x81,
-                              0x81, 0x05, 0x81, 0x1A, 0x49, 0x96, 0x02, 0xD2];
-    // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-    //  21, 22, 23, 24, 25, [[[[5]]], [1234567890]]]
-    let tmp = vec![
-        CborType::Integer(1),
-        CborType::Integer(2),
-        CborType::Integer(3),
-        CborType::Integer(4),
-        CborType::Integer(5),
-        CborType::Integer(6),
-        CborType::Integer(7),
-        CborType::Integer(8),
-        CborType::Integer(9),
-        CborType::Integer(10),
-        CborType::Integer(11),
-        CborType::Integer(12),
-        CborType::Integer(13),
-        CborType::Integer(14),
-        CborType::Integer(15),
-        CborType::Integer(16),
-        CborType::Integer(17),
-        CborType::Integer(18),
-        CborType::Integer(19),
-        CborType::Integer(20),
-        CborType::Integer(21),
-        CborType::Integer(22),
-        CborType::Integer(23),
-        CborType::Integer(24),
-        CborType::Integer(25),
-        CborType::Array(vec![
-            CborType::Array(vec![
-                CborType::Array(vec![
-                    CborType::Array(vec![
-                        CborType::Integer(5)])])]),
-            CborType::Array(vec![CborType::Integer(1234567890)])])
-    ];
-    let expected = CborType::Array(tmp);
-    test_decoder(bytes, expected);
-}
-
-#[test]
-fn test_signed_integer() {
-    let bytes: Vec<u8> = vec![0x20];
-    let expected = CborType::SignedInteger(-1);
-    test_decoder(bytes, expected);
-
-    let bytes = vec![0x29];
-    let expected = CborType::SignedInteger(-10);
-    test_decoder(bytes, expected);
-
-    let bytes = vec![0x38, 0x63];
-    let expected = CborType::SignedInteger(-100);
-    test_decoder(bytes, expected);
-
-    let bytes = vec![0x39, 0x03, 0xe7];
-    let expected = CborType::SignedInteger(-1000);
-    test_decoder(bytes, expected);
-
-    let bytes = vec![0x39, 0x27, 0x0F];
-    let expected = CborType::SignedInteger(-10000);
-    test_decoder(bytes, expected);
-
-    let bytes = vec![0x3A, 0x00, 0x01, 0x86, 0x9F];
-    let expected = CborType::SignedInteger(-100000);
-    test_decoder(bytes, expected);
-
-    let bytes = vec![0x3B, 0x00, 0x00, 0x00, 0xE8, 0xD4, 0xA5, 0x0F, 0xFF];
-    let expected = CborType::SignedInteger(-1000000000000);
-    test_decoder(bytes, expected);
-}
-
-#[test]
-fn test_byte_strings() {
-    let bytes: Vec<u8> = vec![0x40];
-    let expected = CborType::Bytes(vec![]);
-    test_decoder(bytes, expected);
-
-    // 01020304
-    let bytes: Vec<u8> = vec![0x44, 0x01, 0x02, 0x03, 0x04];
-    let expected = CborType::Bytes(vec![0x01, 0x02, 0x03, 0x04]);
-    test_decoder(bytes, expected);
-
-    // 0102030405060708090A0B0C0D0E0F10203040506070
-    let bytes: Vec<u8> = vec![0x56, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
-                              0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
-                              0x70];
-    let expected = CborType::Bytes(vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
-         0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x20, 0x30,
-         0x40, 0x50, 0x60, 0x70]);
-    test_decoder(bytes, expected);
-
-    let bytes: Vec<u8> =
-        vec![0x59, 0x01, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
-    let expected = CborType::Bytes(vec![0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-         0xFF, 0xFF, 0xFF, 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_decoder(bytes, expected);
-}
-
-#[test]
-fn test_maps() {
-    // {}
-    let bytes: Vec<u8> = vec![0xa0];
-    let expected: BTreeMap<CborType, CborType> = BTreeMap::new();
-    test_decoder(bytes, CborType::Map(expected));
-
-    // {1: 2, 3: 4}
-    let bytes: Vec<u8> = vec![0xa2, 0x01, 0x02, 0x03, 0x04];
-    let mut expected: BTreeMap<CborType, CborType> = BTreeMap::new();
-    expected.insert(CborType::Integer(1), CborType::Integer(2));
-    expected.insert(CborType::Integer(3), CborType::Integer(4));
-    test_decoder(bytes, CborType::Map(expected));
-
-    // TODO: strings aren't properly supported as keys yet.
-    // {"a": 1, "b": [2, 3]}
-    // let bytes: Vec<u8> = vec![0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03];
-    // let expected =
-    //     CborType::Map(vec![
-    //         CborMap{key: CborType::Integer(1), value: CborType::Integer(2)},
-    //         CborMap{key: CborType::Integer(3), value: CborType::Integer(4)}]);
-    // test_decoder(bytes, expected);
-
-    // let bytes: Vec<u8> = vec![0x82, 0x61, 0x61, 0xa1, 0x61, 0x62, 0x61, 0x63];
-    // test_decoder(bytes, "[a, {b: c}]");
-
-    // let bytes: Vec<u8> = vec![0xa5, 0x61, 0x61, 0x61, 0x41, 0x61, 0x62, 0x61,
-    //                           0x42, 0x61, 0x63, 0x61, 0x43, 0x61, 0x64, 0x61,
-    //                           0x44, 0x61, 0x65, 0x61, 0x45];
-    // test_decoder(bytes, "{a: A, b: B, c: C, d: D, e: E}");
-}
-
-#[test]
-fn test_map_duplicate_keys() {
-    let bytes: Vec<u8> = vec![0xa4, 0x01, 0x02, 0x02, 0x03, 0x01, 0x03, 0x04, 0x04];
-    test_decoder_error(bytes, CborError::DuplicateMapKey);
-}
-
-#[test]
-fn test_tag_with_no_value() {
-    let bytes: Vec<u8> = vec![0xc0];
-    test_decoder_error(bytes, CborError::TruncatedInput);
-}
-
-#[test]
-fn test_truncated_int() {
-    let bytes: Vec<u8> = vec![0x19, 0x03];
-    test_decoder_error(bytes, CborError::TruncatedInput);
-}
-
-#[test]
-fn test_truncated_array() {
-    let bytes: Vec<u8> = vec![0x83, 0x01, 0x02];
-    test_decoder_error(bytes, CborError::TruncatedInput);
-}
-
-#[test]
-fn test_truncated_map() {
-    let bytes: Vec<u8> = vec![0xa2, 0x01, 0x02, 0x00];
-    test_decoder_error(bytes, CborError::TruncatedInput);
-}
-
-#[test]
-fn test_malformed_integer() {
-    let bytes: Vec<u8> = vec![0x1c];
-    test_decoder_error(bytes, CborError::MalformedInput);
-}
-
-#[test]
-fn test_signed_integer_too_large() {
-    let bytes = vec![0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
-    test_decoder_error(bytes, CborError::InputValueOutOfRange);
-}
-
-#[test]
-fn test_null() {
-    let bytes = vec![0xf6];
-    test_decoder(bytes, CborType::Null);
-}
-
-#[test]
-fn test_null_in_array() {
-    let bytes = vec![0x82, 0xf6, 0xf6];
-    test_decoder(
-        bytes,
-        CborType::Array(vec![CborType::Null,
-             CborType::Null]),
-    );
-}
-
-#[test]
-fn test_major_type_7() {
-    for i in 0..0x20 {
-        if i != 22 {
-            let bytes = vec![0xe0 | i];
-            test_decoder_error(bytes, CborError::UnsupportedType);
-        }
-    }
-}
-
-#[test]
-fn test_large_input() {
-    let array = vec![0xFF; MAX_ARRAY_SIZE];
-    let expected = CborType::Bytes(array.clone());
-    let mut bytes = vec![0x5A, 0x08, 0x00, 0x00, 0x00];
-    bytes.extend_from_slice(&array);
-    test_decoder(bytes, expected);
-}
-
-#[test]
-fn test_too_large_input() {
-    let array = vec![0xFF; MAX_ARRAY_SIZE + 1];
-    let mut bytes = vec![0x5A, 0x08, 0x00, 0x00, 0x01];
-    bytes.extend_from_slice(&array);
-    test_decoder_error(bytes, CborError::InputTooLarge);
-}
-
-// We currently don't support CBOR strings (issue #39).
-#[test]
-fn test_invalid_input() {
-    let bytes = vec![0x60];
-    test_decoder_error(bytes, CborError::UnsupportedType);
-}
deleted file mode 100644
--- a/third_party/rust/cose/src/cbor/test_serializer.rs
+++ /dev/null
@@ -1,310 +0,0 @@
-use cbor::CborType;
-use std::collections::BTreeMap;
-
-#[test]
-fn test_nint() {
-    struct Testcase {
-        value: i64,
-        expected: Vec<u8>,
-    }
-    let testcases: Vec<Testcase> = vec![Testcase {
-                                            value: -1,
-                                            expected: vec![0x20],
-                                        },
-                                        Testcase {
-                                            value: -10,
-                                            expected: vec![0x29],
-                                        },
-                                        Testcase {
-                                            value: -100,
-                                            expected: vec![0x38, 0x63],
-                                        },
-                                        Testcase {
-                                            value: -1000,
-                                            expected: vec![0x39, 0x03, 0xe7],
-                                        },
-                                        Testcase {
-                                            value: -1000000,
-                                            expected: vec![0x3a, 0x00, 0x0f, 0x42, 0x3f],
-                                        },
-                                        Testcase {
-                                            value: -4611686018427387903,
-                                            expected: vec![0x3b, 0x3f, 0xff, 0xff, 0xff, 0xff,
-                                                           0xff, 0xff, 0xfe],
-                                        }];
-    for testcase in testcases {
-        let cbor = CborType::SignedInteger(testcase.value);
-        assert_eq!(testcase.expected, cbor.serialize());
-    }
-}
-
-#[test]
-fn test_bstr() {
-    struct Testcase {
-        value: Vec<u8>,
-        expected: Vec<u8>,
-    }
-    let testcases: Vec<Testcase> =
-        vec![Testcase {
-                 value: vec![],
-                 expected: vec![0x40],
-             },
-             Testcase {
-                 value: vec![0x01, 0x02, 0x03, 0x04],
-                 expected: vec![0x44, 0x01, 0x02, 0x03, 0x04],
-             },
-             Testcase {
-                 value: vec![0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
-                             0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
-                             0xaf, 0xaf, 0xaf],
-                 expected: vec![0x58, 0x19, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
-                                0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
-                                0xaf, 0xaf, 0xaf, 0xaf, 0xaf],
-             }];
-    for testcase in testcases {
-        let cbor = CborType::Bytes(testcase.value);
-        assert_eq!(testcase.expected, cbor.serialize());
-    }
-}
-
-#[test]
-fn test_tstr() {
-    struct Testcase {
-        value: String,
-        expected: Vec<u8>,
-    }
-    let testcases: Vec<Testcase> = vec![Testcase {
-                                            value: String::new(),
-                                            expected: vec![0x60],
-                                        },
-                                        Testcase {
-                                            value: String::from("a"),
-                                            expected: vec![0x61, 0x61],
-                                        },
-                                        Testcase {
-                                            value: String::from("IETF"),
-                                            expected: vec![0x64, 0x49, 0x45, 0x54, 0x46],
-                                        },
-                                        Testcase {
-                                            value: String::from("\"\\"),
-                                            expected: vec![0x62, 0x22, 0x5c],
-                                        },
-                                        Testcase {
-                                            value: String::from("水"),
-                                            expected: vec![0x63, 0xe6, 0xb0, 0xb4],
-                                        }];
-    for testcase in testcases {
-        let cbor = CborType::String(testcase.value);
-        assert_eq!(testcase.expected, cbor.serialize());
-    }
-}
-
-#[test]
-fn test_arr() {
-    struct Testcase {
-        value: Vec<CborType>,
-        expected: Vec<u8>,
-    }
-    let nested_arr_1 = vec![CborType::Integer(2),
-                            CborType::Integer(3)];
-    let nested_arr_2 = vec![CborType::Integer(4),
-                            CborType::Integer(5)];
-    let testcases: Vec<Testcase> =
-        vec![Testcase {
-                 value: vec![],
-                 expected: vec![0x80],
-             },
-             Testcase {
-                 value: vec![CborType::Integer(1),
-                             CborType::Integer(2),
-                             CborType::Integer(3)],
-                 expected: vec![0x83, 0x01, 0x02, 0x03],
-             },
-             Testcase {
-                 value: vec![CborType::Integer(1),
-                             CborType::Array(nested_arr_1),
-                             CborType::Array(nested_arr_2)],
-                 expected: vec![0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05],
-             },
-             Testcase {
-                 value: vec![CborType::Integer(1),
-                             CborType::Integer(2),
-                             CborType::Integer(3),
-                             CborType::Integer(4),
-                             CborType::Integer(5),
-                             CborType::Integer(6),
-                             CborType::Integer(7),
-                             CborType::Integer(8),
-                             CborType::Integer(9),
-                             CborType::Integer(10),
-                             CborType::Integer(11),
-                             CborType::Integer(12),
-                             CborType::Integer(13),
-                             CborType::Integer(14),
-                             CborType::Integer(15),
-                             CborType::Integer(16),
-                             CborType::Integer(17),
-                             CborType::Integer(18),
-                             CborType::Integer(19),
-                             CborType::Integer(20),
-                             CborType::Integer(21),
-                             CborType::Integer(22),
-                             CborType::Integer(23),
-                             CborType::Integer(24),
-                             CborType::Integer(25)],
-                 expected: vec![0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
-                                0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
-                                0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19],
-             }];
-    for testcase in testcases {
-        let cbor = CborType::Array(testcase.value);
-        assert_eq!(testcase.expected, cbor.serialize());
-    }
-}
-
-#[test]
-fn test_map() {
-    let empty_map: BTreeMap<CborType, CborType> = BTreeMap::new();
-    assert_eq!(vec![0xa0], CborType::Map(empty_map).serialize());
-
-    let mut positive_map: BTreeMap<CborType, CborType> = BTreeMap::new();
-    positive_map.insert(CborType::Integer(20), CborType::Integer(10));
-    positive_map.insert(CborType::Integer(10), CborType::Integer(20));
-    positive_map.insert(CborType::Integer(15), CborType::Integer(15));
-    assert_eq!(
-        vec![0xa3, 0x0a, 0x14, 0x0f, 0x0f, 0x14, 0x0a],
-        CborType::Map(positive_map).serialize()
-    );
-
-    let mut negative_map: BTreeMap<CborType, CborType> = BTreeMap::new();
-    negative_map.insert(CborType::SignedInteger(-4), CborType::Integer(10));
-    negative_map.insert(CborType::SignedInteger(-1), CborType::Integer(20));
-    negative_map.insert(CborType::SignedInteger(-5), CborType::Integer(15));
-    negative_map.insert(CborType::SignedInteger(-6), CborType::Integer(10));
-    assert_eq!(
-        vec![0xa4, 0x20, 0x14, 0x23, 0x0a, 0x24, 0x0f, 0x25, 0x0a],
-        CborType::Map(negative_map).serialize()
-    );
-
-    let mut mixed_map: BTreeMap<CborType, CborType> = BTreeMap::new();
-    mixed_map.insert(CborType::Integer(0), CborType::Integer(10));
-    mixed_map.insert(CborType::SignedInteger(-10), CborType::Integer(20));
-    mixed_map.insert(CborType::Integer(15), CborType::Integer(15));
-    assert_eq!(
-        vec![0xa3, 0x00, 0x0a, 0x0f, 0x0f, 0x29, 0x14],
-        CborType::Map(mixed_map).serialize()
-    );
-
-    let mut very_mixed_map: BTreeMap<CborType, CborType> = BTreeMap::new();
-    very_mixed_map.insert(CborType::Integer(0), CborType::Integer(10));
-    very_mixed_map.insert(
-        CborType::SignedInteger(-10000),
-        CborType::String("low".to_string()),
-    );
-    very_mixed_map.insert(CborType::SignedInteger(-10), CborType::Integer(20));
-    very_mixed_map.insert(
-        CborType::Integer(10001),
-        CborType::String("high".to_string()),
-    );
-    very_mixed_map.insert(
-        CborType::Integer(10000),
-        CborType::String("high".to_string()),
-    );
-    very_mixed_map.insert(CborType::Integer(15), CborType::Integer(15));
-    let expected = vec![0xa6, 0x00, 0x0a, 0x0f, 0x0f, 0x29, 0x14, 0x19, 0x27, 0x10, 0x64, 0x68,
-                        0x69, 0x67, 0x68, 0x19, 0x27, 0x11, 0x64, 0x68, 0x69, 0x67, 0x68, 0x39,
-                        0x27, 0x0F, 0x63, 0x6C, 0x6F, 0x77];
-    assert_eq!(expected, CborType::Map(very_mixed_map).serialize());
-}
-
-#[test]
-#[ignore]
-// XXX: The string isn't put into the map at the moment, so we can't actually
-//      test this.
-fn test_invalid_map() {
-    let mut invalid_map: BTreeMap<CborType, CborType> = BTreeMap::new();
-    invalid_map.insert(CborType::SignedInteger(-10), CborType::Integer(20));
-    invalid_map.insert(CborType::String("0".to_string()), CborType::Integer(10));
-    invalid_map.insert(CborType::Integer(15), CborType::Integer(15));
-    let expected: Vec<u8> = vec![];
-    assert_eq!(expected, CborType::Map(invalid_map).serialize());
-}
-
-#[test]
-fn test_integer() {
-    struct Testcase {
-        value: u64,
-        expected: Vec<u8>,
-    }
-    let testcases: Vec<Testcase> =
-        vec![Testcase {
-                 value: 0,
-                 expected: vec![0],
-             },
-             Testcase {
-                 value: 1,
-                 expected: vec![1],
-             },
-             Testcase {
-                 value: 10,
-                 expected: vec![0x0a],
-             },
-             Testcase {
-                 value: 23,
-                 expected: vec![0x17],
-             },
-             Testcase {
-                 value: 24,
-                 expected: vec![0x18, 0x18],
-             },
-             Testcase {
-                 value: 25,
-                 expected: vec![0x18, 0x19],
-             },
-             Testcase {
-                 value: 100,
-                 expected: vec![0x18, 0x64],
-             },
-             Testcase {
-                 value: 1000,
-                 expected: vec![0x19, 0x03, 0xe8],
-             },
-             Testcase {
-                 value: 1000000,
-                 expected: vec![0x1a, 0x00, 0x0f, 0x42, 0x40],
-             },
-             Testcase {
-                 value: 1000000000000,
-                 expected: vec![0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00],
-             },
-             Testcase {
-                 value: 18446744073709551615,
-                 expected: vec![0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
-             }];
-    for testcase in testcases {
-        let cbor = CborType::Integer(testcase.value);
-        assert_eq!(testcase.expected, cbor.serialize());
-    }
-}
-
-#[test]
-fn test_tagged_item() {
-    let cbor = CborType::Tag(0x12, Box::new(CborType::Integer(2).clone()));
-    assert_eq!(vec![0xD2, 0x02], cbor.serialize());
-
-    let cbor = CborType::Tag(0x62, Box::new(CborType::Array(vec![]).clone()));
-    assert_eq!(vec![0xD8, 0x62, 0x80], cbor.serialize());
-}
-
-#[test]
-fn test_null() {
-    let cbor = CborType::Null;
-    assert_eq!(vec![0xf6], cbor.serialize());
-}
-
-#[test]
-fn test_null_in_array() {
-    let cbor = CborType::Array(vec![CborType::Null,
-         CborType::Null]);
-    assert_eq!(vec![0x82, 0xf6, 0xf6], cbor.serialize());
-}
--- a/third_party/rust/cose/src/cose.rs
+++ b/third_party/rust/cose/src/cose.rs
@@ -25,21 +25,20 @@
 //!     result &= verify_callback(cose_signature);
 //!
 //!     // We can stop early. The cose_signature is not valid.
 //!     if !result {
 //!         return result;
 //!     }
 //! }
 //!```
+extern crate moz_cbor as cbor;
 
-#[macro_use]
 pub mod decoder;
-mod cbor;
-mod util;
+pub mod util;
 
 /// Errors that can be returned from COSE functions.
 #[derive(Debug, PartialEq)]
 pub enum CoseError {
     DecodingFailure,
     LibraryFailure,
     MalformedInput,
     MissingHeader,
@@ -63,36 +62,11 @@ pub enum CoseError {
 pub enum SignatureAlgorithm {
     ES256,
     ES384,
     ES512,
     PS256,
 }
 
 #[cfg(test)]
-#[macro_use(defer)]
-extern crate scopeguard;
-
-#[cfg(test)]
-mod nss;
-#[cfg(test)]
 mod test_setup;
 #[cfg(test)]
-mod test_nss;
-#[cfg(test)]
-mod util_test;
-#[cfg(test)]
 mod test_cose;
-
-#[derive(Debug)]
-#[cfg(test)]
-pub struct SignatureParameters<'a> {
-    certificate: &'a [u8],
-    algorithm: SignatureAlgorithm,
-    pkcs8: &'a [u8],
-}
-
-#[derive(Debug)]
-#[cfg(test)]
-pub struct Signature<'a> {
-    parameter: &'a SignatureParameters<'a>,
-    signature_bytes: Vec<u8>,
-}
--- a/third_party/rust/cose/src/decoder.rs
+++ b/third_party/rust/cose/src/decoder.rs
@@ -1,55 +1,66 @@
 //! Parse and decode COSE signatures.
 
 use cbor::CborType;
 use cbor::decoder::decode;
 use {CoseError, SignatureAlgorithm};
 use util::get_sig_struct_bytes;
+use std::collections::BTreeMap;
 
-const COSE_SIGN_TAG: u64 = 98;
+pub const COSE_SIGN_TAG: u64 = 98;
 
 /// The result of `decode_signature` holding a decoded COSE signature.
 #[derive(Debug)]
 pub struct CoseSignature {
     pub signature_type: SignatureAlgorithm,
     pub signature: Vec<u8>,
     pub signer_cert: Vec<u8>,
     pub certs: Vec<Vec<u8>>,
     pub to_verify: Vec<u8>,
 }
 
 pub const COSE_TYPE_ES256: i64 = -7;
 pub const COSE_TYPE_ES384: i64 = -35;
 pub const COSE_TYPE_ES512: i64 = -36;
 pub const COSE_TYPE_PS256: i64 = -37;
 
+pub const COSE_HEADER_ALG: u64 = 1;
+pub const COSE_HEADER_KID: u64 = 4;
+
 macro_rules! unpack {
    ($to:tt, $var:ident) => (
         match *$var {
             CborType::$to(ref cbor_object) => {
                 cbor_object
             }
             _ => return Err(CoseError::UnexpectedType),
         };
     )
 }
 
-fn get_map_value(map: &CborType, key: &CborType) -> Result<CborType, CoseError> {
-    match *map {
-        CborType::Map(ref values) => {
-            match values.get(key) {
-                Some(x) => Ok(x.clone()),
-                _ => Err(CoseError::MissingHeader),
-            }
-        }
-        _ => Err(CoseError::UnexpectedType),
+fn get_map_value(
+    map: &BTreeMap<CborType, CborType>,
+    key: &CborType,
+) -> Result<CborType, CoseError> {
+    match map.get(key) {
+        Some(x) => Ok(x.clone()),
+        _ => Err(CoseError::MissingHeader),
     }
 }
 
+/// Ensure that the referenced `CborType` is an empty map.
+fn ensure_empty_map(map: &CborType) -> Result<(), CoseError> {
+    let unpacked = unpack!(Map, map);
+    if !unpacked.is_empty() {
+        return Err(CoseError::MalformedInput);
+    }
+    Ok(())
+}
+
 // This syntax is a little unintuitive. Taken together, the two previous definitions essentially
 // mean:
 //
 // COSE_Sign = [
 //     protected : empty_or_serialized_map,
 //     unprotected : header_map
 //     payload : bstr / nil,
 //     signatures : [+ COSE_Signature]
@@ -80,53 +91,75 @@ fn decode_signature_struct(
     let cose_signature = unpack!(Array, cose_signature);
     if cose_signature.len() != 3 {
         return Err(CoseError::MalformedInput);
     }
     let protected_signature_header_serialized = &cose_signature[0];
     let protected_signature_header_bytes = unpack!(Bytes, protected_signature_header_serialized);
 
     // Parse the protected signature header.
-    let protected_signature_header = match decode(&protected_signature_header_bytes) {
+    let protected_signature_header = &match decode(protected_signature_header_bytes) {
         Err(_) => return Err(CoseError::DecodingFailure),
         Ok(value) => value,
     };
-    let signature_algorithm = get_map_value(&protected_signature_header, &CborType::Integer(1))?;
+    let protected_signature_header = unpack!(Map, protected_signature_header);
+    if protected_signature_header.len() != 2 {
+        return Err(CoseError::MalformedInput);
+    }
+    let signature_algorithm = get_map_value(
+        protected_signature_header,
+        &CborType::Integer(COSE_HEADER_ALG),
+    )?;
     let signature_algorithm = match signature_algorithm {
         CborType::SignedInteger(val) => {
             match val {
                 COSE_TYPE_ES256 => SignatureAlgorithm::ES256,
                 COSE_TYPE_ES384 => SignatureAlgorithm::ES384,
                 COSE_TYPE_ES512 => SignatureAlgorithm::ES512,
                 COSE_TYPE_PS256 => SignatureAlgorithm::PS256,
                 _ => return Err(CoseError::UnexpectedHeaderValue),
             }
         }
         _ => return Err(CoseError::UnexpectedType),
     };
 
-    let ee_cert = &get_map_value(&protected_signature_header, &CborType::Integer(4))?;
+    let ee_cert = &get_map_value(
+        protected_signature_header,
+        &CborType::Integer(COSE_HEADER_KID),
+    )?;
     let ee_cert = unpack!(Bytes, ee_cert).clone();
 
+    // The unprotected header section is expected to be an empty map.
+    ensure_empty_map(&cose_signature[1])?;
+
     // Build signature structure to verify.
     let signature_bytes = &cose_signature[2];
     let signature_bytes = unpack!(Bytes, signature_bytes).clone();
     let sig_structure_bytes = get_sig_struct_bytes(
         protected_body_head.clone(),
         protected_signature_header_serialized.clone(),
         payload,
     );
 
     // Read intermediate certificates from protected_body_head.
-    let protected_body_head = unpack!(Bytes, protected_body_head);
-    let protected_body_head_map = match decode(protected_body_head) {
+    // Any tampering of the protected header during transport will be detected
+    // because it is input to the signature verification.
+    // Note that a protected header has to be present and hold a kid with an
+    // empty list of intermediate certificates.
+    let protected_body_head_bytes = unpack!(Bytes, protected_body_head);
+    let protected_body_head_map = &match decode(protected_body_head_bytes) {
         Ok(value) => value,
         Err(_) => return Err(CoseError::DecodingFailure),
     };
-    let intermediate_certs_array = &get_map_value(&protected_body_head_map, &CborType::Integer(4))?;
+    let protected_body_head_map = unpack!(Map, protected_body_head_map);
+    if protected_body_head_map.len() != 1 {
+        return Err(CoseError::MalformedInput);
+    }
+    let intermediate_certs_array =
+        &get_map_value(protected_body_head_map, &CborType::Integer(COSE_HEADER_KID))?;
     let intermediate_certs = unpack!(Array, intermediate_certs_array);
     let mut certs: Vec<Vec<u8>> = Vec::new();
     for cert in intermediate_certs {
         let cert = unpack!(Bytes, cert);
         certs.push(cert.clone());
     }
 
     Ok(CoseSignature {
@@ -149,17 +182,17 @@ fn decode_signature_struct(
 ///
 /// Headers = (
 ///     protected : empty_or_serialized_map,
 ///     unprotected : header_map
 /// )
 ///```
 pub fn decode_signature(bytes: &[u8], payload: &[u8]) -> Result<Vec<CoseSignature>, CoseError> {
     // This has to be a COSE_Sign object, which is a tagged array.
-    let tagged_cose_sign = match decode(&bytes) {
+    let tagged_cose_sign = match decode(bytes) {
         Err(_) => return Err(CoseError::DecodingFailure),
         Ok(value) => value,
     };
     let cose_sign_array = match tagged_cose_sign {
         CborType::Tag(tag, cose_sign) => {
             if tag != COSE_SIGN_TAG {
                 return Err(CoseError::UnexpectedTag);
             }
@@ -168,25 +201,35 @@ pub fn decode_signature(bytes: &[u8], pa
                 _ => return Err(CoseError::UnexpectedType),
             }
         }
         _ => return Err(CoseError::UnexpectedType),
     };
     if cose_sign_array.len() != 4 {
         return Err(CoseError::MalformedInput);
     }
+
+    // The unprotected header section is expected to be an empty map.
+    ensure_empty_map(&cose_sign_array[1])?;
+
+    // The payload is expected to be Null (i.e. this is a detached signature).
+    match cose_sign_array[2] {
+        CborType::Null => {}
+        _ => return Err(CoseError::UnexpectedType),
+    };
+
     let signatures = &cose_sign_array[3];
     let signatures = unpack!(Array, signatures);
 
     // Decode COSE_Signatures.
     // There has to be at least one signature to make this a valid COSE signature.
     if signatures.len() < 1 {
         return Err(CoseError::MalformedInput);
     }
     let mut result = Vec::new();
     for cose_signature in signatures {
-        // cose_sign_array holds the protected body header.
+        // cose_sign_array[0] holds the protected body header.
         let signature = decode_signature_struct(cose_signature, payload, &cose_sign_array[0])?;
         result.push(signature);
     }
 
     Ok(result)
 }
deleted file mode 100644
--- a/third_party/rust/cose/src/nss.rs
+++ /dev/null
@@ -1,356 +0,0 @@
-use std::marker::PhantomData;
-use std::{mem, ptr};
-use std::os::raw;
-use std::os::raw::c_char;
-use SignatureAlgorithm;
-
-type SECItemType = raw::c_uint; // TODO: actually an enum - is this the right size?
-const SI_BUFFER: SECItemType = 0; // called siBuffer in NSS
-
-#[repr(C)]
-struct SECItem {
-    typ: SECItemType,
-    data: *const u8,
-    len: raw::c_uint,
-}
-
-impl SECItem {
-    fn maybe_new(data: &[u8]) -> Result<SECItem, NSSError> {
-        if data.len() > u32::max_value() as usize {
-            return Err(NSSError::InputTooLarge);
-        }
-        Ok(SECItem {
-            typ: SI_BUFFER,
-            data: data.as_ptr(),
-            len: data.len() as u32,
-        })
-    }
-
-    fn maybe_from_parts(data: *const u8, len: usize) -> Result<SECItem, NSSError> {
-        if len > u32::max_value() as usize {
-            return Err(NSSError::InputTooLarge);
-        }
-        Ok(SECItem {
-            typ: SI_BUFFER,
-            data: data,
-            len: len as u32,
-        })
-    }
-}
-
-/// Many NSS APIs take constant data input as SECItems. Some, however, output data as SECItems.
-/// To represent this, we define another type of mutable SECItem.
-#[repr(C)]
-struct SECItemMut<'a> {
-    typ: SECItemType,
-    data: *mut u8,
-    len: raw::c_uint,
-    _marker: PhantomData<&'a mut Vec<u8>>,
-}
-
-impl<'a> SECItemMut<'a> {
-    /// Given a mutable reference to a Vec<u8> that has a particular allocated capacity, create a
-    /// SECItemMut that points to the vec and has the same capacity.
-    /// The input vec is not expected to have any actual contents, and in any case is cleared.
-    fn maybe_from_empty_preallocated_vec(vec: &'a mut Vec<u8>) -> Result<SECItemMut<'a>, NSSError> {
-        if vec.capacity() > u32::max_value() as usize {
-            return Err(NSSError::InputTooLarge);
-        }
-        vec.clear();
-        Ok(SECItemMut {
-            typ: SI_BUFFER,
-            data: vec.as_mut_ptr(),
-            len: vec.capacity() as u32,
-            _marker: PhantomData,
-        })
-    }
-}
-
-#[repr(C)]
-struct CkRsaPkcsPssParams {
-    // Called CK_RSA_PKCS_PSS_PARAMS in NSS
-    hash_alg: CkMechanismType, // Called hashAlg in NSS
-    mgf: CkRsaPkcsMgfType,
-    s_len: raw::c_ulong, // Called sLen in NSS
-}
-
-impl CkRsaPkcsPssParams {
-    fn new() -> CkRsaPkcsPssParams {
-        CkRsaPkcsPssParams {
-            hash_alg: CKM_SHA256,
-            mgf: CKG_MGF1_SHA256,
-            s_len: 32,
-        }
-    }
-
-    fn get_params_item(&self) -> Result<SECItem, NSSError> {
-        // This isn't entirely NSS' fault, but it mostly is.
-        let params_ptr: *const CkRsaPkcsPssParams = self;
-        let params_ptr: *const u8 = params_ptr as *const u8;
-        let params_secitem =
-            SECItem::maybe_from_parts(params_ptr, mem::size_of::<CkRsaPkcsPssParams>())?;
-        Ok(params_secitem)
-    }
-}
-
-type CkMechanismType = raw::c_ulong; // called CK_MECHANISM_TYPE in NSS
-const CKM_ECDSA: CkMechanismType = 0x0000_1041;
-const CKM_RSA_PKCS_PSS: CkMechanismType = 0x0000_000D;
-const CKM_SHA256: CkMechanismType = 0x0000_0250;
-
-type CkRsaPkcsMgfType = raw::c_ulong; // called CK_RSA_PKCS_MGF_TYPE in NSS
-const CKG_MGF1_SHA256: CkRsaPkcsMgfType = 0x0000_0002;
-
-type SECStatus = raw::c_int; // TODO: enum - right size?
-const SEC_SUCCESS: SECStatus = 0; // Called SECSuccess in NSS
-const SEC_FAILURE: SECStatus = -1; // Called SECFailure in NSS
-
-enum SECKEYPublicKey {}
-enum SECKEYPrivateKey {}
-enum PK11SlotInfo {}
-enum CERTCertificate {}
-enum CERTCertDBHandle {}
-
-const SHA256_LENGTH: usize = 32;
-const SHA384_LENGTH: usize = 48;
-const SHA512_LENGTH: usize = 64;
-
-// TODO: ugh this will probably have a platform-specific name...
-#[link(name = "nss3")]
-extern "C" {
-    fn PK11_HashBuf(
-        hashAlg: HashAlgorithm,
-        out: *mut u8,
-        data_in: *const u8, // called "in" in NSS
-        len: raw::c_int,
-    ) -> SECStatus;
-    fn PK11_VerifyWithMechanism(
-        key: *const SECKEYPublicKey,
-        mechanism: CkMechanismType,
-        param: *const SECItem,
-        sig: *const SECItem,
-        hash: *const SECItem,
-        wincx: *const raw::c_void,
-    ) -> SECStatus;
-
-    fn SECKEY_DestroyPublicKey(pubk: *const SECKEYPublicKey);
-
-    fn CERT_GetDefaultCertDB() -> *const CERTCertDBHandle;
-    fn CERT_DestroyCertificate(cert: *mut CERTCertificate);
-    fn CERT_NewTempCertificate(
-        handle: *const CERTCertDBHandle,
-        derCert: *const SECItem,
-        nickname: *const c_char,
-        isperm: bool,
-        copyDER: bool,
-    ) -> *mut CERTCertificate;
-    fn CERT_ExtractPublicKey(cert: *const CERTCertificate) -> *const SECKEYPublicKey;
-
-    fn PK11_ImportDERPrivateKeyInfoAndReturnKey(
-        slot: *mut PK11SlotInfo,
-        derPKI: *const SECItem,
-        nickname: *const SECItem,
-        publicValue: *const SECItem,
-        isPerm: bool,
-        isPrivate: bool,
-        keyUsage: u32,
-        privk: *mut *mut SECKEYPrivateKey,
-        wincx: *const u8,
-    ) -> SECStatus;
-    fn PK11_GetInternalSlot() -> *mut PK11SlotInfo;
-    fn PK11_FreeSlot(slot: *mut PK11SlotInfo);
-    fn PK11_SignatureLen(key: *const SECKEYPrivateKey) -> usize;
-    fn PK11_SignWithMechanism(
-        key: *const SECKEYPrivateKey,
-        mech: CkMechanismType,
-        param: *const SECItem,
-        sig: *mut SECItemMut,
-        hash: *const SECItem,
-    ) -> SECStatus;
-}
-
-/// An error type describing errors that may be encountered during verification.
-#[derive(Debug, PartialEq)]
-pub enum NSSError {
-    ImportCertError,
-    DecodingPKCS8Failed,
-    InputTooLarge,
-    LibraryFailure,
-    SignatureVerificationFailed,
-    SigningFailed,
-    ExtractPublicKeyFailed,
-}
-
-// https://searchfox.org/nss/rev/990c2e793aa731cd66238c6c4f00b9473943bc66/lib/util/secoidt.h#274
-#[derive(Debug, PartialEq, Clone)]
-#[repr(C)]
-enum HashAlgorithm {
-    SHA256 = 191,
-    SHA384 = 192,
-    SHA512 = 193,
-}
-
-fn hash(payload: &[u8], signature_algorithm: &SignatureAlgorithm) -> Result<Vec<u8>, NSSError> {
-    if payload.len() > raw::c_int::max_value() as usize {
-        return Err(NSSError::InputTooLarge);
-    }
-    let (hash_algorithm, digest_length) = match *signature_algorithm {
-        SignatureAlgorithm::ES256 => (HashAlgorithm::SHA256, SHA256_LENGTH),
-        SignatureAlgorithm::ES384 => (HashAlgorithm::SHA384, SHA384_LENGTH),
-        SignatureAlgorithm::ES512 => (HashAlgorithm::SHA512, SHA512_LENGTH),
-        SignatureAlgorithm::PS256 => (HashAlgorithm::SHA256, SHA256_LENGTH),
-    };
-    let mut hash_buf = vec![0; digest_length];
-    let len: raw::c_int = payload.len() as raw::c_int;
-    let hash_result =
-        unsafe { PK11_HashBuf(hash_algorithm, hash_buf.as_mut_ptr(), payload.as_ptr(), len) };
-    if hash_result != SEC_SUCCESS {
-        return Err(NSSError::LibraryFailure);
-    }
-    Ok(hash_buf)
-}
-
-/// Main entrypoint for verification. Given a signature algorithm, the bytes of a subject public key
-/// info, a payload, and a signature over the payload, returns a result based on the outcome of
-/// decoding the subject public key info and running the signature verification algorithm on the
-/// signed data.
-pub fn verify_signature(
-    signature_algorithm: &SignatureAlgorithm,
-    cert: &[u8],
-    payload: &[u8],
-    signature: &[u8],
-) -> Result<(), NSSError> {
-    let slot = unsafe { PK11_GetInternalSlot() };
-    if slot.is_null() {
-        return Err(NSSError::LibraryFailure);
-    }
-    defer!(unsafe {
-        PK11_FreeSlot(slot);
-    });
-
-    let hash_buf = hash(payload, signature_algorithm).unwrap();
-    let hash_item = SECItem::maybe_new(hash_buf.as_slice())?;
-
-    // Import DER cert into NSS.
-    let der_cert = SECItem::maybe_new(cert)?;
-    let db_handle = unsafe { CERT_GetDefaultCertDB() };
-    if db_handle.is_null() {
-        // TODO #28
-        return Err(NSSError::LibraryFailure);
-    }
-    let nss_cert =
-        unsafe { CERT_NewTempCertificate(db_handle, &der_cert, ptr::null(), false, true) };
-    if nss_cert.is_null() {
-        return Err(NSSError::ImportCertError);
-    }
-    defer!(unsafe {
-        CERT_DestroyCertificate(nss_cert);
-    });
-
-    let key = unsafe { CERT_ExtractPublicKey(nss_cert) };
-    if key.is_null() {
-        return Err(NSSError::ExtractPublicKeyFailed);
-    }
-    defer!(unsafe {
-        SECKEY_DestroyPublicKey(key);
-    });
-    let signature_item = SECItem::maybe_new(signature)?;
-    let mechanism = match *signature_algorithm {
-        SignatureAlgorithm::ES256 => CKM_ECDSA,
-        SignatureAlgorithm::ES384 => CKM_ECDSA,
-        SignatureAlgorithm::ES512 => CKM_ECDSA,
-        SignatureAlgorithm::PS256 => CKM_RSA_PKCS_PSS,
-    };
-    let rsa_pss_params = CkRsaPkcsPssParams::new();
-    let rsa_pss_params_item = rsa_pss_params.get_params_item()?;
-    let params_item = match *signature_algorithm {
-        SignatureAlgorithm::ES256 => ptr::null(),
-        SignatureAlgorithm::ES384 => ptr::null(),
-        SignatureAlgorithm::ES512 => ptr::null(),
-        SignatureAlgorithm::PS256 => &rsa_pss_params_item,
-    };
-    let null_cx_ptr: *const raw::c_void = ptr::null();
-    let result = unsafe {
-        PK11_VerifyWithMechanism(
-            key,
-            mechanism,
-            params_item,
-            &signature_item,
-            &hash_item,
-            null_cx_ptr,
-        )
-    };
-    match result {
-        SEC_SUCCESS => Ok(()),
-        SEC_FAILURE => Err(NSSError::SignatureVerificationFailed),
-        _ => Err(NSSError::LibraryFailure),
-    }
-}
-
-pub fn sign(
-    signature_algorithm: &SignatureAlgorithm,
-    pk8: &[u8],
-    payload: &[u8],
-) -> Result<Vec<u8>, NSSError> {
-    let slot = unsafe { PK11_GetInternalSlot() };
-    if slot.is_null() {
-        return Err(NSSError::LibraryFailure);
-    }
-    defer!(unsafe {
-        PK11_FreeSlot(slot);
-    });
-    let pkcs8item = SECItem::maybe_new(pk8)?;
-    let mut key: *mut SECKEYPrivateKey = ptr::null_mut();
-    let ku_all = 0xFF;
-    let rv = unsafe {
-        PK11_ImportDERPrivateKeyInfoAndReturnKey(
-            slot,
-            &pkcs8item,
-            ptr::null(),
-            ptr::null(),
-            false,
-            false,
-            ku_all,
-            &mut key,
-            ptr::null(),
-        )
-    };
-    if rv != SEC_SUCCESS || key.is_null() {
-        return Err(NSSError::DecodingPKCS8Failed);
-    }
-    let mechanism = match *signature_algorithm {
-        SignatureAlgorithm::ES256 => CKM_ECDSA,
-        SignatureAlgorithm::ES384 => CKM_ECDSA,
-        SignatureAlgorithm::ES512 => CKM_ECDSA,
-        SignatureAlgorithm::PS256 => CKM_RSA_PKCS_PSS,
-    };
-    let rsa_pss_params = CkRsaPkcsPssParams::new();
-    let rsa_pss_params_item = rsa_pss_params.get_params_item()?;
-    let params_item = match *signature_algorithm {
-        SignatureAlgorithm::ES256 => ptr::null(),
-        SignatureAlgorithm::ES384 => ptr::null(),
-        SignatureAlgorithm::ES512 => ptr::null(),
-        SignatureAlgorithm::PS256 => &rsa_pss_params_item,
-    };
-    let signature_len = unsafe { PK11_SignatureLen(key) };
-    // Allocate enough space for the signature.
-    let mut signature: Vec<u8> = Vec::with_capacity(signature_len);
-    let hash_buf = hash(payload, signature_algorithm).unwrap();
-    let hash_item = SECItem::maybe_new(hash_buf.as_slice())?;
-    {
-        // Get a mutable SECItem on the preallocated signature buffer. PK11_SignWithMechanism will
-        // fill the SECItem's buf with the bytes of the signature.
-        let mut signature_item = SECItemMut::maybe_from_empty_preallocated_vec(&mut signature)?;
-        let rv = unsafe {
-            PK11_SignWithMechanism(key, mechanism, params_item, &mut signature_item, &hash_item)
-        };
-        if rv != SEC_SUCCESS || signature_item.len as usize != signature_len {
-            return Err(NSSError::SigningFailed);
-        }
-    }
-    unsafe {
-        // Now that the bytes of the signature have been filled out, set its length.
-        signature.set_len(signature_len);
-    }
-    Ok(signature)
-}
--- a/third_party/rust/cose/src/test_cose.rs
+++ b/third_party/rust/cose/src/test_cose.rs
@@ -1,230 +1,496 @@
 use test_setup as test;
-use util_test::{sign, verify_signature};
-use {CoseError, SignatureAlgorithm, SignatureParameters};
-use std::str::FromStr;
-use decoder::decode_signature;
+use {CoseError, SignatureAlgorithm};
+use decoder::{COSE_HEADER_ALG, COSE_HEADER_KID, COSE_SIGN_TAG, COSE_TYPE_ES256, decode_signature};
+use cbor::CborType;
+use std::collections::BTreeMap;
 
 #[test]
 fn test_cose_decode() {
     let payload = b"This is the content.";
     let cose_signatures = decode_signature(&test::COSE_SIGNATURE_BYTES, payload).unwrap();
     assert_eq!(cose_signatures.len(), 1);
     assert_eq!(cose_signatures[0].signature_type, SignatureAlgorithm::ES256);
     assert_eq!(cose_signatures[0].signature, test::SIGNATURE_BYTES.to_vec());
     assert_eq!(cose_signatures[0].certs[0], test::P256_ROOT.to_vec());
     assert_eq!(cose_signatures[0].certs[1], test::P256_INT.to_vec());
 }
 
-// All keys here are from pykey.py/pycert.py from mozilla-central.
-// Certificates can be generated with tools/certs/certs.sh and mozilla-central.
+fn test_cose_format_error(bytes: &[u8], expected_error: CoseError) {
+    let payload = vec![0];
+    let result = decode_signature(bytes, &payload);
+    assert!(result.is_err());
+    assert_eq!(result.err(), Some(expected_error));
+}
+
+// Helper function to take a `Vec<CborType>`, wrap it in a `CborType::Array`, tag it with the
+// COSE_Sign tag (COSE_SIGN_TAG = 98), and serialize it to a `Vec<u8>`.
+fn wrap_tag_and_encode_array(array: Vec<CborType>) -> Vec<u8> {
+    CborType::Tag(COSE_SIGN_TAG, Box::new(CborType::Array(array))).serialize()
+}
+
+// Helper function to create an encoded protected header for a COSE_Sign or COSE_Signature
+// structure.
+fn encode_test_protected_header(keys: Vec<CborType>, values: Vec<CborType>) -> Vec<u8> {
+    assert_eq!(keys.len(), values.len());
+    let mut map: BTreeMap<CborType, CborType> = BTreeMap::new();
+    for (key, value) in keys.iter().zip(values) {
+        map.insert(key.clone(), value.clone());
+    }
+    CborType::Map(map).serialize()
+}
+
+// Helper function to create a test COSE_Signature structure with the given protected header.
+fn build_test_cose_signature(protected_header: Vec<u8>) -> CborType {
+    CborType::Array(vec![CborType::Bytes(protected_header),
+         CborType::Map(BTreeMap::new()),
+         CborType::Bytes(Vec::new())])
+}
+
+// Helper function to create the minimally-valid COSE_Sign (i.e. "body") protected header.
+fn make_minimally_valid_cose_sign_protected_header() -> Vec<u8> {
+    encode_test_protected_header(
+        vec![CborType::Integer(COSE_HEADER_KID)],
+        vec![CborType::Array(Vec::new())],
+    )
+}
+
+// Helper function to create a minimally-valid COSE_Signature (i.e. "body").
+fn make_minimally_valid_cose_signature_protected_header() -> Vec<u8> {
+    encode_test_protected_header(
+        vec![CborType::Integer(COSE_HEADER_ALG),
+             CborType::Integer(COSE_HEADER_KID)],
+        vec![CborType::SignedInteger(COSE_TYPE_ES256),
+             CborType::Bytes(Vec::new())],
+    )
+}
 
-const P256_PARAMS: SignatureParameters = SignatureParameters {
-    certificate: &test::P256_EE,
-    algorithm: SignatureAlgorithm::ES256,
-    pkcs8: &test::PKCS8_P256_EE,
-};
-const P384_PARAMS: SignatureParameters = SignatureParameters {
-    certificate: &test::P384_EE,
-    algorithm: SignatureAlgorithm::ES384,
-    pkcs8: &test::PKCS8_P384_EE,
-};
-const P521_PARAMS: SignatureParameters = SignatureParameters {
-    certificate: &test::P521_EE,
-    algorithm: SignatureAlgorithm::ES512,
-    pkcs8: &test::PKCS8_P521_EE,
-};
+// This tests the minimally-valid COSE_Sign structure according to this implementation.
+// The structure must be a CBOR array of length 4 tagged with the integer 98.
+// The COSE_Sign protected header must have the `kid` integer key and no others. The value for `kid`
+// must be an array (although it may be empty). Each element of the array must be of type bytes.
+// The COSE_Sign unprotected header must be an empty map.
+// The COSE_Sign payload must be nil.
+// The COSE_Sign signatures must be an array with at least one COSE_Signature.
+// Each COSE_Signature must be an array of length 3.
+// Each COSE_Signature protected header must have the `alg` and `kid` integer keys and no others.
+// The value for `alg` must be a valid algorithm identifier. The value for `kid` must be bytes,
+// although it may be empty.
+// Each COSE_Signature unprotected header must be an empty map.
+// Each COSE_Signature signature must be of type bytes (although it may be empty).
+#[test]
+fn test_cose_sign_minimally_valid() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = make_minimally_valid_cose_signature_protected_header();
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    let payload = vec![0];
+    let result = decode_signature(&bytes, &payload);
+    assert!(result.is_ok());
+    let decoded = result.unwrap();
+    assert_eq!(decoded.len(), 1);
+    assert_eq!(decoded[0].signer_cert.len(), 0);
+    assert_eq!(decoded[0].certs.len(), 0);
+}
 
-#[cfg(test)]
-fn test_verify(payload: &[u8], cert_chain: &[&[u8]], params_vec: Vec<SignatureParameters>) {
-    test::setup();
-    let cose_signature = sign(payload, cert_chain, &params_vec);
-    assert!(cose_signature.is_ok());
-    let cose_signature = cose_signature.unwrap();
+#[test]
+fn test_cose_sign_not_tagged() {
+    let bytes = CborType::Array(vec![CborType::Integer(0)]).serialize();
+    test_cose_format_error(&bytes, CoseError::UnexpectedType);
+}
+
+#[test]
+fn test_cose_sign_wrong_tag() {
+    // The expected COSE_Sign tag is 98.
+    let bytes = CborType::Tag(99, Box::new(CborType::Integer(0))).serialize();
+    test_cose_format_error(&bytes, CoseError::UnexpectedTag);
+}
 
-    // Verify signature.
-    assert!(verify_signature(payload, cose_signature).is_ok());
+#[test]
+fn test_cose_sign_right_tag_wrong_contents() {
+    // The COSE_Sign tag is 98, but the contents should be an array.
+    let bytes = CborType::Tag(98, Box::new(CborType::Integer(0))).serialize();
+    test_cose_format_error(&bytes, CoseError::UnexpectedType);
+}
+
+#[test]
+fn test_cose_sign_too_small() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MalformedInput);
 }
 
-#[cfg(test)]
-fn test_verify_modified_payload(
-    payload: &mut [u8],
-    cert_chain: &[&[u8]],
-    params_vec: Vec<SignatureParameters>,
-) {
-    test::setup();
-    let cose_signature = sign(payload, cert_chain, &params_vec);
-    assert!(cose_signature.is_ok());
-    let cose_signature = cose_signature.unwrap();
+#[test]
+fn test_cose_sign_too_large() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(Vec::new()),
+                      CborType::Array(Vec::new())];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MalformedInput);
+}
+
+#[test]
+fn test_cose_sign_protected_header_empty() {
+    let body_protected_header = encode_test_protected_header(Vec::new(), Vec::new());
+    let signature_protected_header = make_minimally_valid_cose_signature_protected_header();
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MalformedInput);
+}
 
-    // Verify signature.
-    payload[0] = !payload[0];
-    let verify_result = verify_signature(payload, cose_signature);
-    assert!(verify_result.is_err());
-    assert_eq!(verify_result, Err(CoseError::VerificationFailed));
+#[test]
+fn test_cose_sign_protected_header_missing_kid() {
+    let body_protected_header =
+        encode_test_protected_header(vec![CborType::Integer(2)], vec![CborType::Integer(2)]);
+    let signature_protected_header = make_minimally_valid_cose_signature_protected_header();
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MissingHeader);
+}
+
+#[test]
+fn test_cose_sign_protected_header_kid_wrong_type() {
+    let body_protected_header = encode_test_protected_header(
+        vec![CborType::Integer(COSE_HEADER_KID)],
+        vec![CborType::Integer(2)],
+    );
+    let signature_protected_header = make_minimally_valid_cose_signature_protected_header();
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::UnexpectedType);
 }
 
-#[cfg(test)]
-fn test_verify_modified_signature(
-    payload: &[u8],
-    cert_chain: &[&[u8]],
-    params_vec: Vec<SignatureParameters>,
-) {
-    test::setup();
-    let cose_signature = sign(payload, cert_chain, &params_vec);
-    assert!(cose_signature.is_ok());
-    let mut cose_signature = cose_signature.unwrap();
+#[test]
+fn test_cose_sign_protected_header_extra_header_key() {
+    let body_protected_header = encode_test_protected_header(
+        vec![CborType::Integer(COSE_HEADER_KID),
+             CborType::Integer(2)],
+        vec![CborType::Bytes(Vec::new()),
+             CborType::Integer(2)],
+    );
+    let signature_protected_header = make_minimally_valid_cose_signature_protected_header();
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MalformedInput);
+}
 
-    // Tamper with the cose signature.
-    let len = cose_signature.len();
-    cose_signature[len - 15] = !cose_signature[len - 15];
-
-    // Verify signature.
-    let verify_result = verify_signature(payload, cose_signature);
-    assert!(verify_result.is_err());
-    assert_eq!(verify_result, Err(CoseError::VerificationFailed));
+#[test]
+fn test_cose_sign_unprotected_header_wrong_type() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = make_minimally_valid_cose_signature_protected_header();
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Integer(1),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::UnexpectedType);
 }
 
-// This can be used with inconsistent parameters that make the verification fail.
-// In particular, the signing key does not match the certificate used to verify.
-#[cfg(test)]
-fn test_verify_verification_fails(
-    payload: &[u8],
-    cert_chain: &[&[u8]],
-    params_vec: Vec<SignatureParameters>,
-) {
-    test::setup();
-    let cose_signature = sign(payload, cert_chain, &params_vec);
-    assert!(cose_signature.is_ok());
-    let cose_signature = cose_signature.unwrap();
+#[test]
+fn test_cose_sign_unprotected_header_not_empty() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = make_minimally_valid_cose_signature_protected_header();
+    let signature = build_test_cose_signature(signature_protected_header);
+    let mut unprotected_header_map: BTreeMap<CborType, CborType> = BTreeMap::new();
+    unprotected_header_map.insert(CborType::Integer(0), CborType::SignedInteger(-1));
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(unprotected_header_map),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MalformedInput);
+}
 
-    // Verify signature.
-    let verify_result = verify_signature(payload, cose_signature);
-    assert!(verify_result.is_err());
-    assert_eq!(verify_result, Err(CoseError::VerificationFailed));
+#[test]
+fn test_cose_sign_payload_not_null() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = make_minimally_valid_cose_signature_protected_header();
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Integer(0),
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::UnexpectedType);
+}
+
+#[test]
+fn test_cose_signatures_not_array() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Integer(0)];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::UnexpectedType);
 }
 
 #[test]
-fn test_cose_sign_verify() {
-    let payload = b"This is the content.";
+fn test_cose_signatures_empty() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(Vec::new())];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MalformedInput);
+}
 
-    // P256
-    let certs: [&[u8]; 2] = [&test::P256_ROOT,
-                             &test::P256_INT];
-    let params_vec = vec![P256_PARAMS];
-    test_verify(payload, &certs, params_vec);
+#[test]
+fn test_cose_signature_protected_header_wrong_type() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature = CborType::Array(vec![CborType::Null,
+         CborType::Map(BTreeMap::new()),
+         CborType::SignedInteger(-1)]);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::UnexpectedType);
+}
 
-    // P384
-    let params_vec = vec![P384_PARAMS];
-    test_verify(payload, &certs, params_vec);
-
-    // P521
-    let params_vec = vec![P521_PARAMS];
-    test_verify(payload, &certs, params_vec);
+#[test]
+fn test_cose_signature_protected_header_empty() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = encode_test_protected_header(Vec::new(), Vec::new());
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MalformedInput);
 }
 
 #[test]
-fn test_cose_sign_verify_modified_payload() {
-    let mut payload = String::from_str("This is the content.")
-        .unwrap()
-        .into_bytes();
-    let certs: [&[u8]; 2] = [&test::P256_ROOT,
-                             &test::P256_INT];
-    let params_vec = vec![P256_PARAMS];
-    test_verify_modified_payload(&mut payload, &certs, params_vec);
+fn test_cose_signature_protected_header_too_large() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = make_minimally_valid_cose_signature_protected_header();
+    let signature = CborType::Array(vec![CborType::Bytes(signature_protected_header),
+         CborType::Map(BTreeMap::new()),
+         CborType::Bytes(Vec::new()),
+         CborType::Null]);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MalformedInput);
+}
+
+#[test]
+fn test_cose_signature_protected_header_bad_encoding() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    // The bytes here are a truncated integer encoding.
+    let signature = CborType::Array(vec![CborType::Bytes(vec![0x1a, 0x00, 0x00]),
+         CborType::Map(BTreeMap::new()),
+         CborType::Bytes(Vec::new())]);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::DecodingFailure);
 }
 
 #[test]
-fn test_cose_sign_verify_wrong_cert() {
-    let payload = b"This is the content.";
-    let certs: [&[u8]; 2] = [&test::P256_ROOT,
-                             &test::P256_INT];
-    let params = SignatureParameters {
-        certificate: &test::P384_EE,
-        algorithm: SignatureAlgorithm::ES256,
-        pkcs8: &test::PKCS8_P256_EE,
-    };
-    let params_vec = vec![params];
-    test_verify_verification_fails(payload, &certs, params_vec);
+fn test_cose_signature_protected_header_missing_alg() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = encode_test_protected_header(
+        vec![CborType::Integer(2),
+             CborType::Integer(COSE_HEADER_KID)],
+        vec![CborType::SignedInteger(COSE_TYPE_ES256),
+             CborType::Bytes(Vec::new())],
+    );
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MissingHeader);
+}
+
+#[test]
+fn test_cose_signature_protected_header_missing_kid() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = encode_test_protected_header(
+        vec![CborType::Integer(COSE_HEADER_ALG),
+             CborType::Integer(3)],
+        vec![CborType::SignedInteger(COSE_TYPE_ES256),
+             CborType::Bytes(Vec::new())],
+    );
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MissingHeader);
 }
 
 #[test]
-fn test_cose_sign_verify_tampered_signature() {
-    let payload = b"This is the content.";
-    let certs: [&[u8]; 2] = [&test::P256_ROOT,
-                             &test::P256_INT];
-    let params_vec = vec![P256_PARAMS];
-    test_verify_modified_signature(payload, &certs, params_vec);
-}
-
-const RSA_PARAMS: SignatureParameters = SignatureParameters {
-    certificate: &test::RSA_EE,
-    algorithm: SignatureAlgorithm::PS256,
-    pkcs8: &test::PKCS8_RSA_EE,
-};
-
-#[test]
-fn test_cose_sign_verify_rsa() {
-    let payload = b"This is the RSA-signed content.";
-    let certs: [&[u8]; 2] = [&test::RSA_ROOT,
-                             &test::RSA_INT];
-    let params_vec = vec![RSA_PARAMS];
-    test_verify(payload, &certs, params_vec);
+fn test_cose_signature_protected_header_wrong_key_types() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = encode_test_protected_header(
+        vec![CborType::SignedInteger(-1),
+             CborType::Bytes(vec![0])],
+        vec![CborType::SignedInteger(COSE_TYPE_ES256),
+             CborType::Bytes(Vec::new())],
+    );
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MissingHeader);
 }
 
 #[test]
-fn test_cose_sign_verify_rsa_modified_payload() {
-    let mut payload = String::from_str("This is the RSA-signed content.")
-        .unwrap()
-        .into_bytes();
-    let certs: [&[u8]; 2] = [&test::RSA_ROOT,
-                             &test::RSA_INT];
-    let params_vec = vec![RSA_PARAMS];
-    test_verify_modified_payload(&mut payload, &certs, params_vec);
+fn test_cose_signature_protected_header_unexpected_alg_type() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = encode_test_protected_header(
+        vec![CborType::Integer(COSE_HEADER_ALG),
+             CborType::Integer(COSE_HEADER_KID)],
+        vec![CborType::Integer(10),
+             CborType::Integer(4)],
+    );
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::UnexpectedType);
+}
+
+#[test]
+fn test_cose_signature_protected_header_unsupported_alg() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = encode_test_protected_header(
+        vec![CborType::Integer(COSE_HEADER_ALG),
+             CborType::Integer(COSE_HEADER_KID)],
+        vec![CborType::SignedInteger(-10),
+             CborType::Bytes(Vec::new())],
+    );
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::UnexpectedHeaderValue);
 }
 
 #[test]
-fn test_cose_sign_verify_rsa_tampered_signature() {
-    let payload = b"This is the RSA-signed content.";
-    let certs: [&[u8]; 2] = [&test::RSA_ROOT,
-                             &test::RSA_INT];
-    let params_vec = vec![RSA_PARAMS];
-    test_verify_modified_signature(payload, &certs, params_vec);
+fn test_cose_signature_protected_header_unexpected_kid_type() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = encode_test_protected_header(
+        vec![CborType::Integer(COSE_HEADER_ALG),
+             CborType::Integer(COSE_HEADER_KID)],
+        vec![CborType::SignedInteger(COSE_TYPE_ES256),
+             CborType::Integer(0)],
+    );
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::UnexpectedType);
 }
 
 #[test]
-fn test_cose_sign_verify_two_signatures() {
-    let payload = b"This is the content.";
-    let certs: [&[u8]; 4] = [&test::P256_ROOT,
-                             &test::P256_INT,
-                             &test::RSA_ROOT,
-                             &test::RSA_INT];
-    let params_vec = vec![P256_PARAMS,
-                          RSA_PARAMS];
-    test_verify(payload, &certs, params_vec);
+fn test_cose_signature_protected_header_extra_key() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = encode_test_protected_header(
+        vec![CborType::Integer(COSE_HEADER_ALG),
+             CborType::Integer(COSE_HEADER_KID),
+             CborType::Integer(5)],
+        vec![CborType::SignedInteger(COSE_TYPE_ES256),
+             CborType::Bytes(Vec::new()),
+             CborType::Integer(5)],
+    );
+    let signature = build_test_cose_signature(signature_protected_header);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MalformedInput);
 }
 
 #[test]
-fn test_cose_sign_verify_two_signatures_tampered_payload() {
-    let mut payload = String::from_str("This is the content.")
-        .unwrap()
-        .into_bytes();
-    let certs: [&[u8]; 4] = [&test::P256_ROOT,
-                             &test::P256_INT,
-                             &test::RSA_ROOT,
-                             &test::RSA_INT];
-    let params_vec = vec![P256_PARAMS,
-                          RSA_PARAMS];
-    test_verify_modified_payload(&mut payload, &certs, params_vec);
+fn test_cose_signature_unprotected_header_wrong_type() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = make_minimally_valid_cose_signature_protected_header();
+    let signature = CborType::Array(vec![CborType::Bytes(signature_protected_header),
+         CborType::Integer(1),
+         CborType::Bytes(Vec::new())]);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::UnexpectedType);
 }
 
 #[test]
-fn test_cose_sign_verify_two_signatures_tampered_signature() {
-    let payload = b"This is the content.";
-    let certs: [&[u8]; 4] = [&test::P256_ROOT,
-                             &test::P256_INT,
-                             &test::RSA_ROOT,
-                             &test::RSA_INT];
-    let params_vec = vec![P256_PARAMS,
-                          RSA_PARAMS];
-    test_verify_modified_signature(payload, &certs, params_vec);
+fn test_cose_signature_unprotected_header_not_empty() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = make_minimally_valid_cose_signature_protected_header();
+    let mut unprotected_header_map: BTreeMap<CborType, CborType> = BTreeMap::new();
+    unprotected_header_map.insert(CborType::Integer(0), CborType::SignedInteger(-1));
+    let signature = CborType::Array(vec![CborType::Bytes(signature_protected_header),
+         CborType::Map(unprotected_header_map),
+         CborType::Bytes(Vec::new())]);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::MalformedInput);
 }
+
+#[test]
+fn test_cose_signature_signature_wrong_type() {
+    let body_protected_header = make_minimally_valid_cose_sign_protected_header();
+    let signature_protected_header = make_minimally_valid_cose_signature_protected_header();
+    let signature = CborType::Array(vec![CborType::Bytes(signature_protected_header),
+         CborType::Map(BTreeMap::new()),
+         CborType::SignedInteger(-1)]);
+    let values = vec![CborType::Bytes(body_protected_header),
+                      CborType::Map(BTreeMap::new()),
+                      CborType::Null,
+                      CborType::Array(vec![signature])];
+    let bytes = wrap_tag_and_encode_array(values);
+    test_cose_format_error(&bytes, CoseError::UnexpectedType);
+}
deleted file mode 100644
--- a/third_party/rust/cose/src/test_nss.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-use test_setup as test;
-use nss;
-use nss::NSSError;
-use SignatureAlgorithm;
-
-#[test]
-fn test_nss_sign_verify() {
-    test::setup();
-    let payload = b"sample";
-
-    // Sign.
-    let signature_result = nss::sign(&SignatureAlgorithm::ES256, &test::PKCS8_P256_EE, payload);
-    assert!(signature_result.is_ok());
-    let signature_result = signature_result.unwrap();
-
-    // Verify the signature.
-    assert!(
-        nss::verify_signature(
-            &SignatureAlgorithm::ES256,
-            &test::P256_EE,
-            payload,
-            &signature_result,
-        ).is_ok()
-    );
-}
-
-#[test]
-fn test_nss_sign_verify_different_payload() {
-    test::setup();
-    let payload = b"sample";
-
-    // Sign.
-    let signature_result = nss::sign(&SignatureAlgorithm::ES256, &test::PKCS8_P256_EE, payload);
-    assert!(signature_result.is_ok());
-    let signature_result = signature_result.unwrap();
-
-    // Verify the signature with a different payload.
-    let payload = b"sampli";
-    let verify_result = nss::verify_signature(
-        &SignatureAlgorithm::ES256,
-        &test::P256_EE,
-        payload,
-        &signature_result,
-    );
-    assert!(verify_result.is_err());
-    assert_eq!(verify_result, Err(NSSError::SignatureVerificationFailed));
-}
-
-#[test]
-fn test_nss_sign_verify_wrong_cert() {
-    test::setup();
-    let payload = b"sample";
-
-    // Sign.
-    let signature_result = nss::sign(&SignatureAlgorithm::ES256, &test::PKCS8_P256_EE, payload);
-    assert!(signature_result.is_ok());
-    let signature_result = signature_result.unwrap();
-
-    // Verify the signature with a wrong cert.
-    let verify_result = nss::verify_signature(
-        &SignatureAlgorithm::ES256,
-        &test::P384_EE,
-        payload,
-        &signature_result,
-    );
-    assert!(verify_result.is_err());
-    assert_eq!(verify_result, Err(NSSError::SignatureVerificationFailed));
-}
--- a/third_party/rust/cose/src/test_setup.rs
+++ b/third_party/rust/cose/src/test_setup.rs
@@ -1,187 +1,8 @@
-use std::os::raw;
-use std::ptr;
-use std::sync::{ONCE_INIT, Once};
-static START: Once = ONCE_INIT;
-
-type SECStatus = raw::c_int;
-const SEC_SUCCESS: SECStatus = 0;
-// TODO: ugh this will probably have a platform-specific name...
-#[link(name = "nss3")]
-extern "C" {
-    fn NSS_NoDB_Init(configdir: *const u8) -> SECStatus;
-}
-
-pub fn setup() {
-    START.call_once(|| {
-        let null_ptr: *const u8 = ptr::null();
-        unsafe {
-            assert_eq!(NSS_NoDB_Init(null_ptr), SEC_SUCCESS);
-        }
-    });
-}
-
-#[cfg_attr(rustfmt, rustfmt_skip)]
-pub const PKCS8_P256_EE: [u8; 139] = [
-    0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a,
-    0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
-    0xce, 0x3d, 0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01,
-    0x01, 0x04, 0x20, 0x21, 0x91, 0x40, 0x3d, 0x57, 0x10, 0xbf, 0x15,
-    0xa2, 0x65, 0x81, 0x8c, 0xd4, 0x2e, 0xd6, 0xfe, 0xdf, 0x09, 0xad,
-    0xd9, 0x2d, 0x78, 0xb1, 0x8e, 0x7a, 0x1e, 0x9f, 0xeb, 0x95, 0x52,
-    0x47, 0x02, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb,
-    0xbb, 0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87,
-    0x04, 0xe2, 0xec, 0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92,
-    0x3f, 0x2c, 0x4f, 0x79, 0x4b, 0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33,
-    0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d, 0x07, 0x06, 0xe0, 0x0e, 0xed,
-    0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b, 0x7b, 0x2d, 0x07, 0xa3,
-    0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0x0a
-];
-
-#[cfg_attr(rustfmt, rustfmt_skip)]
-pub const P256_EE: [u8; 300] = [
-    0x30, 0x82, 0x01, 0x28, 0x30, 0x81, 0xcf, 0xa0, 0x03, 0x02, 0x01, 0x02,
-    0x02, 0x14, 0x2f, 0xc3, 0x5f, 0x05, 0x80, 0xb4, 0x49, 0x45, 0x13, 0x92,
-    0xd6, 0x93, 0xb7, 0x2d, 0x71, 0x19, 0xc5, 0x8c, 0x40, 0x39, 0x30, 0x0a,
-    0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x13,
-    0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x69,
-    0x6e, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, 0x32,
-    0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30,
-    0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33, 0x31,
-    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x12, 0x31, 0x10, 0x30,
-    0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x65, 0x65, 0x2d, 0x70,
-    0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48,
-    0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03,
-    0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb, 0xbb, 0x61, 0xe0,
-    0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04, 0xe2, 0xec, 0x05,
-    0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c, 0x4f, 0x79, 0x4b,
-    0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d,
-    0x07, 0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b,
-    0x7b, 0x2d, 0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0x30, 0x0a,
-    0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48,
-    0x00, 0x30, 0x45, 0x02, 0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50,
-    0xcd, 0x5d, 0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2,
-    0x73, 0x75, 0x5f, 0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70,
-    0xe6, 0x02, 0x21, 0x00, 0xff, 0x81, 0xbe, 0xa8, 0x0d, 0x03, 0x36, 0x6b,
-    0x75, 0xe2, 0x70, 0x6a, 0xac, 0x07, 0x2e, 0x4c, 0xdc, 0xf9, 0xc5, 0x89,
-    0xc1, 0xcf, 0x88, 0xc2, 0xc8, 0x2a, 0x32, 0xf5, 0x42, 0x0c, 0xfa, 0x0b
-];
-
-#[cfg_attr(rustfmt, rustfmt_skip)]
-pub const PKCS8_P384_EE: [u8; 185] = [
-    0x30, 0x81, 0xb6, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86,
-    0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22,
-    0x04, 0x81, 0x9e, 0x30, 0x81, 0x9b, 0x02, 0x01, 0x01, 0x04, 0x30, 0x03,
-    0x5c, 0x7a, 0x1b, 0x10, 0xd9, 0xfa, 0xfe, 0x83, 0x7b, 0x64, 0xad, 0x92,
-    0xf2, 0x2f, 0x5c, 0xed, 0x07, 0x89, 0x18, 0x65, 0x38, 0x66, 0x9b, 0x5c,
-    0x6d, 0x87, 0x2c, 0xec, 0x3d, 0x92, 0x61, 0x22, 0xb3, 0x93, 0x77, 0x2b,
-    0x57, 0x60, 0x2f, 0xf3, 0x13, 0x65, 0xef, 0xe1, 0x39, 0x32, 0x46, 0xa1,
-    0x64, 0x03, 0x62, 0x00, 0x04, 0xa1, 0x68, 0x72, 0x43, 0x36, 0x2b, 0x5c,
-    0x7b, 0x18, 0x89, 0xf3, 0x79, 0x15, 0x46, 0x15, 0xa1, 0xc7, 0x3f, 0xb4,
-    0x8d, 0xee, 0x86, 0x3e, 0x02, 0x29, 0x15, 0xdb, 0x60, 0x8e, 0x25, 0x2d,
-    0xe4, 0xb7, 0x13, 0x2d, 0xa8, 0xce, 0x98, 0xe8, 0x31, 0x53, 0x4e, 0x6a,
-    0x9c, 0x0c, 0x0b, 0x09, 0xc8, 0xd6, 0x39, 0xad, 0xe8, 0x32, 0x06, 0xe5,
-    0xba, 0x81, 0x34, 0x73, 0xa1, 0x1f, 0xa3, 0x30, 0xe0, 0x5d, 0xa8, 0xc9,
-    0x6e, 0x43, 0x83, 0xfe, 0x27, 0x87, 0x3d, 0xa9, 0x71, 0x03, 0xbe, 0x28,
-    0x88, 0xcf, 0xf0, 0x02, 0xf0, 0x5a, 0xf7, 0x1a, 0x1f, 0xdd, 0xcc, 0x83,
-    0x74, 0xaa, 0x6e, 0xa9, 0xce
-];
-
-#[cfg_attr(rustfmt, rustfmt_skip)]
-pub const PKCS8_P521_EE: [u8; 240] = [
-    0x30, 0x81, 0xed, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86,
-    0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23,
-    0x04, 0x81, 0xd5, 0x30, 0x81, 0xd2, 0x02, 0x01, 0x01, 0x04, 0x42, 0x01,
-    0x4f, 0x32, 0x84, 0xfa, 0x69, 0x8d, 0xd9, 0xfe, 0x11, 0x18, 0xdd, 0x33,
-    0x18, 0x51, 0xcd, 0xfa, 0xac, 0x5a, 0x38, 0x29, 0x27, 0x8e, 0xb8, 0x99,
-    0x48, 0x39, 0xde, 0x94, 0x71, 0xc9, 0x40, 0xb8, 0x58, 0xc6, 0x9d, 0x2d,
-    0x05, 0xe8, 0xc0, 0x17, 0x88, 0xa7, 0xd0, 0xb6, 0xe2, 0x35, 0xaa, 0x5e,
-    0x78, 0x3f, 0xc1, 0xbe, 0xe8, 0x07, 0xdc, 0xc3, 0x86, 0x5f, 0x92, 0x0e,
-    0x12, 0xcf, 0x8f, 0x2d, 0x29, 0xa1, 0x81, 0x88, 0x03, 0x81, 0x85, 0x00,
-    0x04, 0x18, 0x94, 0x55, 0x0d, 0x07, 0x85, 0x93, 0x2e, 0x00, 0xea, 0xa2,
-    0x3b, 0x69, 0x4f, 0x21, 0x3f, 0x8c, 0x31, 0x21, 0xf8, 0x6d, 0xc9, 0x7a,
-    0x04, 0xe5, 0xa7, 0x16, 0x7d, 0xb4, 0xe5, 0xbc, 0xd3, 0x71, 0x12, 0x3d,
-    0x46, 0xe4, 0x5d, 0xb6, 0xb5, 0xd5, 0x37, 0x0a, 0x7f, 0x20, 0xfb, 0x63,
-    0x31, 0x55, 0xd3, 0x8f, 0xfa, 0x16, 0xd2, 0xbd, 0x76, 0x1d, 0xca, 0xc4,
-    0x74, 0xb9, 0xa2, 0xf5, 0x02, 0x3a, 0x40, 0x49, 0x31, 0x01, 0xc9, 0x62,
-    0xcd, 0x4d, 0x2f, 0xdd, 0xf7, 0x82, 0x28, 0x5e, 0x64, 0x58, 0x41, 0x39,
-    0xc2, 0xf9, 0x1b, 0x47, 0xf8, 0x7f, 0xf8, 0x23, 0x54, 0xd6, 0x63, 0x0f,
-    0x74, 0x6a, 0x28, 0xa0, 0xdb, 0x25, 0x74, 0x1b, 0x5b, 0x34, 0xa8, 0x28,
-    0x00, 0x8b, 0x22, 0xac, 0xc2, 0x3f, 0x92, 0x4f, 0xaa, 0xfb, 0xd4, 0xd3,
-    0x3f, 0x81, 0xea, 0x66, 0x95, 0x6d, 0xfe, 0xaa, 0x2b, 0xfd, 0xfc, 0xf5
-];
-
-#[cfg_attr(rustfmt, rustfmt_skip)]
-pub const P521_EE: [u8; 367] = [
-    0x30, 0x82, 0x01, 0x6b, 0x30, 0x82, 0x01, 0x12, 0xa0, 0x03, 0x02, 0x01,
-    0x02, 0x02, 0x14, 0x49, 0xdb, 0x7d, 0xec, 0x87, 0x2b, 0x95, 0xfc, 0xfb,
-    0x57, 0xfb, 0xc8, 0xd5, 0x57, 0xb7, 0x3a, 0x10, 0xcc, 0xf1, 0x7a, 0x30,
-    0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30,
-    0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08,
-    0x69, 0x6e, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f,
-    0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30,
-    0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33,
-    0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x12, 0x31, 0x10,
-    0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x65, 0x65, 0x2d,
-    0x70, 0x35, 0x32, 0x31, 0x30, 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a,
-    0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00,
-    0x23, 0x03, 0x81, 0x86, 0x00, 0x04, 0x01, 0x4c, 0xdc, 0x9c, 0xac, 0xc4,
-    0x79, 0x41, 0x09, 0x6b, 0xc9, 0xcc, 0x66, 0x75, 0x2e, 0xc2, 0x7f, 0x59,
-    0x77, 0x34, 0xfa, 0x66, 0xc6, 0x2b, 0x79, 0x2f, 0x88, 0xc5, 0x19, 0xd6,
-    0xd3, 0x7f, 0x0d, 0x16, 0xea, 0x1c, 0x48, 0x3a, 0x18, 0x27, 0xa0, 0x10,
-    0xb9, 0x12, 0x8e, 0x3a, 0x08, 0x07, 0x0c, 0xa3, 0x3e, 0xf5, 0xf5, 0x78,
-    0x35, 0xb7, 0xc1, 0xba, 0x25, 0x1f, 0x6c, 0xc3, 0x52, 0x1d, 0xc4, 0x2b,
-    0x01, 0x06, 0x53, 0x45, 0x19, 0x81, 0xb4, 0x45, 0xd3, 0x43, 0xee, 0xd3,
-    0x78, 0x2a, 0x35, 0xd6, 0xcf, 0xf0, 0xff, 0x48, 0x4f, 0x5a, 0x88, 0x3d,
-    0x20, 0x9f, 0x1b, 0x90, 0x42, 0xb7, 0x26, 0x70, 0x35, 0x68, 0xb2, 0xf3,
-    0x26, 0xe1, 0x8b, 0x83, 0x3b, 0xdd, 0x8a, 0xa0, 0x73, 0x43, 0x92, 0xbc,
-    0xd1, 0x95, 0x01, 0xe1, 0x0d, 0x69, 0x8a, 0x79, 0xf5, 0x3e, 0x11, 0xe0,
-    0xa2, 0x2b, 0xdd, 0x2a, 0xad, 0x90, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86,
-    0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02,
-    0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50, 0xcd, 0x5d, 0x8a, 0xde,
-    0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2, 0x73, 0x75, 0x5f, 0x31,
-    0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02, 0x20, 0x35,
-    0x20, 0x7c, 0xff, 0x51, 0xf6, 0x68, 0xce, 0x1d, 0x00, 0xf9, 0xcc, 0x7f,
-    0xa7, 0xbc, 0x79, 0x52, 0xea, 0x56, 0xdf, 0xc1, 0x46, 0x7c, 0x0c, 0xa1,
-    0x2e, 0x32, 0xb1, 0x69, 0x4b, 0x20, 0xc4
-];
-
-#[cfg_attr(rustfmt, rustfmt_skip)]
-pub const P384_EE: [u8; 329] = [
-    0x30, 0x82, 0x01, 0x45, 0x30, 0x81, 0xec, 0xa0, 0x03, 0x02, 0x01, 0x02,
-    0x02, 0x14, 0x79, 0xe3, 0x1c, 0x60, 0x97, 0xa4, 0x3c, 0x3b, 0x82, 0x11,
-    0x42, 0x37, 0xaf, 0x57, 0x05, 0xa8, 0xde, 0xd3, 0x40, 0x58, 0x30, 0x0a,
-    0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x13,
-    0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x69,
-    0x6e, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, 0x32,
-    0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30,
-    0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33, 0x31,
-    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x12, 0x31, 0x10, 0x30,
-    0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x65, 0x65, 0x2d, 0x70,
-    0x33, 0x38, 0x34, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48,
-    0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03,
-    0x62, 0x00, 0x04, 0xa1, 0x68, 0x72, 0x43, 0x36, 0x2b, 0x5c, 0x7b, 0x18,
-    0x89, 0xf3, 0x79, 0x15, 0x46, 0x15, 0xa1, 0xc7, 0x3f, 0xb4, 0x8d, 0xee,
-    0x86, 0x3e, 0x02, 0x29, 0x15, 0xdb, 0x60, 0x8e, 0x25, 0x2d, 0xe4, 0xb7,
-    0x13, 0x2d, 0xa8, 0xce, 0x98, 0xe8, 0x31, 0x53, 0x4e, 0x6a, 0x9c, 0x0c,
-    0x0b, 0x09, 0xc8, 0xd6, 0x39, 0xad, 0xe8, 0x32, 0x06, 0xe5, 0xba, 0x81,
-    0x34, 0x73, 0xa1, 0x1f, 0xa3, 0x30, 0xe0, 0x5d, 0xa8, 0xc9, 0x6e, 0x43,
-    0x83, 0xfe, 0x27, 0x87, 0x3d, 0xa9, 0x71, 0x03, 0xbe, 0x28, 0x88, 0xcf,
-    0xf0, 0x02, 0xf0, 0x5a, 0xf7, 0x1a, 0x1f, 0xdd, 0xcc, 0x83, 0x74, 0xaa,
-    0x6e, 0xa9, 0xce, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
-    0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5c, 0x75,
-    0x51, 0x9f, 0x13, 0x11, 0x50, 0xcd, 0x5d, 0x8a, 0xde, 0x20, 0xa3, 0xbc,
-    0x06, 0x30, 0x91, 0xff, 0xb2, 0x73, 0x75, 0x5f, 0x31, 0x64, 0xec, 0xfd,
-    0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02, 0x21, 0x00, 0xf3, 0x04, 0x26,
-    0xf2, 0xfd, 0xbc, 0x89, 0x3f, 0x29, 0x3b, 0x70, 0xbc, 0x72, 0xa6, 0xc2,
-    0x23, 0xcc, 0x43, 0x4d, 0x84, 0x71, 0xaf, 0x53, 0xe4, 0x4b, 0x3e, 0xc0,
-    0xbf, 0xe5, 0x68, 0x86, 0x49
-];
-
 #[cfg_attr(rustfmt, rustfmt_skip)]
 pub const P256_INT: [u8; 332] = [
     0x30, 0x82, 0x01, 0x48, 0x30, 0x81, 0xf0, 0xa0, 0x03, 0x02, 0x01,
     0x02, 0x02, 0x14, 0x43, 0x63, 0x59, 0xad, 0x04, 0x34, 0x56, 0x80,
     0x43, 0xec, 0x90, 0x6a, 0xd4, 0x10, 0x64, 0x7c, 0x7f, 0x38, 0x32,
     0xe2, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04,
     0x03, 0x02, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
     0x04, 0x03, 0x0c, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32,
@@ -240,314 +61,16 @@ pub const P256_ROOT: [u8; 334] = [
     0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2, 0x73, 0x75,
     0x5f, 0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02,
     0x21, 0x00, 0xc2, 0xe4, 0xc1, 0xa8, 0xe2, 0x89, 0xdc, 0xa1, 0xbb, 0xe7,
     0xd5, 0x4f, 0x5c, 0x88, 0xad, 0xeb, 0xa4, 0x78, 0xa1, 0x19, 0xbe, 0x22,
     0x54, 0xc8, 0x9f, 0xef, 0xb8, 0x5d, 0xa2, 0x40, 0xd9, 0x8b
 ];
 
 #[cfg_attr(rustfmt, rustfmt_skip)]
-pub const PKCS8_RSA_EE: [u8; 1218] = [
-    0x30, 0x82, 0x04, 0xbe, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
-    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
-    0x04, 0xa8, 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
-    0x01, 0x00, 0xba, 0x88, 0x51, 0xa8, 0x44, 0x8e, 0x16, 0xd6, 0x41, 0xfd,
-    0x6e, 0xb6, 0x88, 0x06, 0x36, 0x10, 0x3d, 0x3c, 0x13, 0xd9, 0xea, 0xe4,
-    0x35, 0x4a, 0xb4, 0xec, 0xf5, 0x68, 0x57, 0x6c, 0x24, 0x7b, 0xc1, 0xc7,
-    0x25, 0xa8, 0xe0, 0xd8, 0x1f, 0xbd, 0xb1, 0x9c, 0x06, 0x9b, 0x6e, 0x1a,
-    0x86, 0xf2, 0x6b, 0xe2, 0xaf, 0x5a, 0x75, 0x6b, 0x6a, 0x64, 0x71, 0x08,
-    0x7a, 0xa5, 0x5a, 0xa7, 0x45, 0x87, 0xf7, 0x1c, 0xd5, 0x24, 0x9c, 0x02,
-    0x7e, 0xcd, 0x43, 0xfc, 0x1e, 0x69, 0xd0, 0x38, 0x20, 0x29, 0x93, 0xab,
-    0x20, 0xc3, 0x49, 0xe4, 0xdb, 0xb9, 0x4c, 0xc2, 0x6b, 0x6c, 0x0e, 0xed,
-    0x15, 0x82, 0x0f, 0xf1, 0x7e, 0xad, 0x69, 0x1a, 0xb1, 0xd3, 0x02, 0x3a,
-    0x8b, 0x2a, 0x41, 0xee, 0xa7, 0x70, 0xe0, 0x0f, 0x0d, 0x8d, 0xfd, 0x66,
-    0x0b, 0x2b, 0xb0, 0x24, 0x92, 0xa4, 0x7d, 0xb9, 0x88, 0x61, 0x79, 0x90,
-    0xb1, 0x57, 0x90, 0x3d, 0xd2, 0x3b, 0xc5, 0xe0, 0xb8, 0x48, 0x1f, 0xa8,
-    0x37, 0xd3, 0x88, 0x43, 0xef, 0x27, 0x16, 0xd8, 0x55, 0xb7, 0x66, 0x5a,
-    0xaa, 0x7e, 0x02, 0x90, 0x2f, 0x3a, 0x7b, 0x10, 0x80, 0x06, 0x24, 0xcc,
-    0x1c, 0x6c, 0x97, 0xad, 0x96, 0x61, 0x5b, 0xb7, 0xe2, 0x96, 0x12, 0xc0,
-    0x75, 0x31, 0xa3, 0x0c, 0x91, 0xdd, 0xb4, 0xca, 0xf7, 0xfc, 0xad, 0x1d,
-    0x25, 0xd3, 0x09, 0xef, 0xb9, 0x17, 0x0e, 0xa7, 0x68, 0xe1, 0xb3, 0x7b,
-    0x2f, 0x22, 0x6f, 0x69, 0xe3, 0xb4, 0x8a, 0x95, 0x61, 0x1d, 0xee, 0x26,
-    0xd6, 0x25, 0x9d, 0xab, 0x91, 0x08, 0x4e, 0x36, 0xcb, 0x1c, 0x24, 0x04,
-    0x2c, 0xbf, 0x16, 0x8b, 0x2f, 0xe5, 0xf1, 0x8f, 0x99, 0x17, 0x31, 0xb8,
-    0xb3, 0xfe, 0x49, 0x23, 0xfa, 0x72, 0x51, 0xc4, 0x31, 0xd5, 0x03, 0xac,
-    0xda, 0x18, 0x0a, 0x35, 0xed, 0x8d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
-    0x82, 0x01, 0x01, 0x00, 0x9e, 0xcb, 0xce, 0x38, 0x61, 0xa4, 0x54, 0xec,
-    0xb1, 0xe0, 0xfe, 0x8f, 0x85, 0xdd, 0x43, 0xc9, 0x2f, 0x58, 0x25, 0xce,
-    0x2e, 0x99, 0x78, 0x84, 0xd0, 0xe1, 0xa9, 0x49, 0xda, 0xa2, 0xc5, 0xac,
-    0x55, 0x9b, 0x24, 0x04, 0x50, 0xe5, 0xac, 0x9f, 0xe0, 0xc3, 0xe3, 0x1c,
-    0x0e, 0xef, 0xa6, 0x52, 0x5a, 0x65, 0xf0, 0xc2, 0x21, 0x94, 0x00, 0x4e,
-    0xe1, 0xab, 0x46, 0x3d, 0xde, 0x9e, 0xe8, 0x22, 0x87, 0xcc, 0x93, 0xe7,
-    0x46, 0xa9, 0x19, 0x29, 0xc5, 0xe6, 0xac, 0x3d, 0x88, 0x75, 0x3f, 0x6c,
-    0x25, 0xba, 0x59, 0x79, 0xe7, 0x3e, 0x5d, 0x8f, 0xb2, 0x39, 0x11, 0x1a,
-    0x3c, 0xda, 0xb8, 0xa4, 0xb0, 0xcd, 0xf5, 0xf9, 0xca, 0xb0, 0x5f, 0x12,
-    0x33, 0xa3, 0x83, 0x35, 0xc6, 0x4b, 0x55, 0x60, 0x52, 0x5e, 0x7e, 0x3b,
-    0x92, 0xad, 0x7c, 0x75, 0x04, 0xcf, 0x1d, 0xc7, 0xcb, 0x00, 0x57, 0x88,
-    0xaf, 0xcb, 0xe1, 0xe8, 0xf9, 0x5d, 0xf7, 0x40, 0x2a, 0x15, 0x15, 0x30,
-    0xd5, 0x80, 0x83, 0x46, 0x86, 0x4e, 0xb3, 0x70, 0xaa, 0x79, 0x95, 0x6a,
-    0x58, 0x78, 0x62, 0xcb, 0x53, 0x37, 0x91, 0x30, 0x7f, 0x70, 0xd9, 0x1c,
-    0x96, 0xd2, 0x2d, 0x00, 0x1a, 0x69, 0x00, 0x9b, 0x92, 0x3c, 0x68, 0x33,
-    0x88, 0xc9, 0xf3, 0x6c, 0xb9, 0xb5, 0xeb, 0xe6, 0x43, 0x02, 0x04, 0x1c,
-    0x78, 0xd9, 0x08, 0x20, 0x6b, 0x87, 0x00, 0x9c, 0xb8, 0xca, 0xba, 0xca,
-    0xd3, 0xdb, 0xdb, 0x27, 0x92, 0xfb, 0x91, 0x1b, 0x2c, 0xf4, 0xdb, 0x66,
-    0x03, 0x58, 0x5b, 0xe9, 0xae, 0x0c, 0xa3, 0xb8, 0xe6, 0x41, 0x7a, 0xa0,
-    0x4b, 0x06, 0xe4, 0x70, 0xea, 0x1a, 0x3b, 0x58, 0x1c, 0xa0, 0x3a, 0x67,
-    0x81, 0xc9, 0x31, 0x5b, 0x62, 0xb3, 0x0e, 0x60, 0x11, 0xf2, 0x24, 0x72,
-    0x59, 0x46, 0xee, 0xc5, 0x7c, 0x6d, 0x94, 0x41, 0x02, 0x81, 0x81, 0x00,
-    0xdd, 0x6e, 0x1d, 0x4f, 0xff, 0xeb, 0xf6, 0x8d, 0x88, 0x9c, 0x4d, 0x11,
-    0x4c, 0xda, 0xaa, 0x9c, 0xaa, 0x63, 0xa5, 0x93, 0x74, 0x28, 0x6c, 0x8a,
-    0x5c, 0x29, 0xa7, 0x17, 0xbb, 0xa6, 0x03, 0x75, 0x64, 0x4d, 0x5c, 0xaa,
-    0x67, 0x4c, 0x4b, 0x8b, 0xc7, 0x32, 0x63, 0x58, 0x64, 0x62, 0x20, 0xe4,
-    0x55, 0x0d, 0x76, 0x08, 0xac, 0x27, 0xd5, 0x5b, 0x6d, 0xb7, 0x4f, 0x8d,
-    0x81, 0x27, 0xef, 0x8f, 0xa0, 0x90, 0x98, 0xb6, 0x91, 0x47, 0xde, 0x06,
-    0x55, 0x73, 0x44, 0x7e, 0x18, 0x3d, 0x22, 0xfe, 0x7d, 0x88, 0x5a, 0xce,
-    0xb5, 0x13, 0xd9, 0x58, 0x1d, 0xd5, 0xe0, 0x7c, 0x1a, 0x90, 0xf5, 0xce,
-    0x08, 0x79, 0xde, 0x13, 0x13, 0x71, 0xec, 0xef, 0xc9, 0xce, 0x72, 0xe9,
-    0xc4, 0x3d, 0xc1, 0x27, 0xd2, 0x38, 0x19, 0x0d, 0xe8, 0x11, 0x77, 0x3c,
-    0xa5, 0xd1, 0x93, 0x01, 0xf4, 0x8c, 0x74, 0x2b, 0x02, 0x81, 0x81, 0x00,
-    0xd7, 0xa7, 0x73, 0xd9, 0xeb, 0xc3, 0x80, 0xa7, 0x67, 0xd2, 0xfe, 0xc0,
-    0x93, 0x4a, 0xd4, 0xe8, 0xb5, 0x66, 0x72, 0x40, 0x77, 0x1a, 0xcd, 0xeb,
-    0xb5, 0xad, 0x79, 0x6f, 0x47, 0x8f, 0xec, 0x4d, 0x45, 0x98, 0x5e, 0xfb,
-    0xc9, 0x53, 0x29, 0x68, 0x28, 0x9c, 0x8d, 0x89, 0x10, 0x2f, 0xad, 0xf2,
-    0x1f, 0x34, 0xe2, 0xdd, 0x49, 0x40, 0xeb, 0xa8, 0xc0, 0x9d, 0x6d, 0x1f,
-    0x16, 0xdc, 0xc2, 0x97, 0x29, 0x77, 0x4c, 0x43, 0x27, 0x5e, 0x92, 0x51,
-    0xdd, 0xbe, 0x49, 0x09, 0xe1, 0xfd, 0x3b, 0xf1, 0xe4, 0xbe, 0xdf, 0x46,
-    0xa3, 0x9b, 0x8b, 0x38, 0x33, 0x28, 0xef, 0x4a, 0xe3, 0xb9, 0x5b, 0x92,
-    0xf2, 0x07, 0x0a, 0xf2, 0x6c, 0x9e, 0x7c, 0x5c, 0x9b, 0x58, 0x7f, 0xed,
-    0xde, 0x05, 0xe8, 0xe7, 0xd8, 0x6c, 0xa5, 0x78, 0x86, 0xfb, 0x16, 0x58,
-    0x10, 0xa7, 0x7b, 0x98, 0x45, 0xbc, 0x31, 0x27, 0x02, 0x81, 0x81, 0x00,
-    0x96, 0x47, 0x2b, 0x41, 0xa6, 0x10, 0xc0, 0xad, 0xe1, 0xaf, 0x22, 0x66,
-    0xc1, 0x60, 0x0e, 0x36, 0x71, 0x35, 0x5b, 0xa4, 0x2d, 0x4b, 0x5a, 0x0e,
-    0xb4, 0xe9, 0xd7, 0xeb, 0x35, 0x81, 0x40, 0x0b, 0xa5, 0xdd, 0x13, 0x2c,
-    0xdb, 0x1a, 0x5e, 0x93, 0x28, 0xc7, 0xbb, 0xc0, 0xbb, 0xb0, 0x15, 0x5e,
-    0xa1, 0x92, 0x97, 0x2e, 0xdf, 0x97, 0xd1, 0x27, 0x51, 0xd8, 0xfc, 0xf6,
-    0xae, 0x57, 0x2a, 0x30, 0xb1, 0xea, 0x30, 0x9a, 0x87, 0x12, 0xdd, 0x4e,
-    0x33, 0x24, 0x1d, 0xb1, 0xee, 0x45, 0x5f, 0xc0, 0x93, 0xf5, 0xbc, 0x9b,
-    0x59, 0x2d, 0x75, 0x6e, 0x66, 0x21, 0x47, 0x4f, 0x32, 0xc0, 0x7a, 0xf2,
-    0x2f, 0xb2, 0x75, 0xd3, 0x40, 0x79, 0x2b, 0x32, 0xba, 0x25, 0x90, 0xbb,
-    0xb2, 0x61, 0xae, 0xfb, 0x95, 0xa2, 0x58, 0xee, 0xa5, 0x37, 0x65, 0x53,
-    0x15, 0xbe, 0x9c, 0x24, 0xd1, 0x91, 0x99, 0x2d, 0x02, 0x81, 0x80, 0x28,
-    0xb4, 0x50, 0xa7, 0xa7, 0x5a, 0x85, 0x64, 0x13, 0xb2, 0xbd, 0xa6, 0xf7,
-    0xa6, 0x3e, 0x3d, 0x96, 0x4f, 0xb9, 0xec, 0xf5, 0x0e, 0x38, 0x23, 0xef,
-    0x6c, 0xc8, 0xe8, 0xfa, 0x26, 0xee, 0x41, 0x3f, 0x8b, 0x9d, 0x12, 0x05,
-    0x54, 0x0f, 0x12, 0xbb, 0xe7, 0xa0, 0xc7, 0x68, 0x28, 0xb7, 0xba, 0x65,
-    0xad, 0x83, 0xcc, 0xa4, 0xd0, 0xfe, 0x2a, 0x22, 0x01, 0x14, 0xe1, 0xb3,
-    0x5d, 0x03, 0xd5, 0xa8, 0x5b, 0xfe, 0x27, 0x06, 0xbd, 0x50, 0xfc, 0xe6,
-    0xcf, 0xcd, 0xd5, 0x71, 0xb4, 0x6c, 0xa6, 0x21, 0xb8, 0xed, 0x47, 0xd6,
-    0x05, 0xbb, 0xe7, 0x65, 0xb0, 0xaa, 0x4a, 0x06, 0x65, 0xac, 0x25, 0x36,
-    0x4d, 0xa2, 0x01, 0x54, 0x03, 0x2e, 0x12, 0x04, 0xb8, 0x55, 0x9d, 0x3e,
-    0x34, 0xfb, 0x5b, 0x17, 0x7c, 0x9a, 0x56, 0xff, 0x93, 0x51, 0x0a, 0x5a,
-    0x4a, 0x62, 0x87, 0xc1, 0x51, 0xde, 0x2d, 0x02, 0x81, 0x80, 0x28, 0x06,
-    0x7b, 0x93, 0x55, 0x80, 0x1d, 0x2e, 0xf5, 0x2d, 0xfa, 0x96, 0xd8, 0xad,
-    0xb5, 0x89, 0x67, 0x3c, 0xf8, 0xee, 0x8a, 0x9c, 0x6f, 0xf7, 0x2a, 0xee,
-    0xab, 0xe9, 0xef, 0x6b, 0xe5, 0x8a, 0x4f, 0x4a, 0xbf, 0x05, 0xf7, 0x88,
-    0x94, 0x7d, 0xc8, 0x51, 0xfd, 0xaa, 0x34, 0x54, 0x21, 0x47, 0xa7, 0x1a,
-    0x24, 0x6b, 0xfb, 0x05, 0x4e, 0xe7, 0x6a, 0xa3, 0x46, 0xab, 0xcd, 0x26,
-    0x92, 0xcf, 0xc9, 0xe4, 0x4c, 0x51, 0xe6, 0xf0, 0x69, 0xc7, 0x35, 0xe0,
-    0x73, 0xba, 0x01, 0x9f, 0x6a, 0x72, 0x14, 0x96, 0x1c, 0x91, 0xb2, 0x68,
-    0x71, 0xca, 0xea, 0xbf, 0x8f, 0x06, 0x44, 0x18, 0xa0, 0x26, 0x90, 0xe3,
-    0x9a, 0x8d, 0x5f, 0xf3, 0x06, 0x7b, 0x7c, 0xdb, 0x7f, 0x50, 0xb1, 0xf5,
-    0x34, 0x18, 0xa7, 0x03, 0x96, 0x6c, 0x4f, 0xc7, 0x74, 0xbf, 0x74, 0x02,
-    0xaf, 0x6c, 0x43, 0x24, 0x7f, 0x43
-];
-
-#[cfg_attr(rustfmt, rustfmt_skip)]
-pub const RSA_EE: [u8; 691] = [
-    0x30, 0x82, 0x02, 0xaf, 0x30, 0x82, 0x01, 0x99, 0xa0, 0x03, 0x02, 0x01,
-    0x02, 0x02, 0x14, 0x07, 0x1c, 0x3b, 0x71, 0x08, 0xbe, 0xd7, 0x9f, 0xfd,
-    0xaf, 0x26, 0xb6, 0x08, 0xa3, 0x99, 0x06, 0x77, 0x69, 0x32, 0x7e, 0x30,
-    0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
-    0x30, 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
-    0x07, 0x69, 0x6e, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x22, 0x18, 0x0f,
-    0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30,
-    0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33,
-    0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x11, 0x31, 0x0f,
-    0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x06, 0x65, 0x65, 0x2d,
-    0x72, 0x73, 0x61, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
-    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82,
-    0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
-    0xba, 0x88, 0x51, 0xa8, 0x44, 0x8e, 0x16, 0xd6, 0x41, 0xfd, 0x6e, 0xb6,
-    0x88, 0x06, 0x36, 0x10, 0x3d, 0x3c, 0x13, 0xd9, 0xea, 0xe4, 0x35, 0x4a,
-    0xb4, 0xec, 0xf5, 0x68, 0x57, 0x6c, 0x24, 0x7b, 0xc1, 0xc7, 0x25, 0xa8,
-    0xe0, 0xd8, 0x1f, 0xbd, 0xb1, 0x9c, 0x06, 0x9b, 0x6e, 0x1a, 0x86, 0xf2,
-    0x6b, 0xe2, 0xaf, 0x5a, 0x75, 0x6b, 0x6a, 0x64, 0x71, 0x08, 0x7a, 0xa5,
-    0x5a, 0xa7, 0x45, 0x87, 0xf7, 0x1c, 0xd5, 0x24, 0x9c, 0x02, 0x7e, 0xcd,
-    0x43, 0xfc, 0x1e, 0x69, 0xd0, 0x38, 0x20, 0x29, 0x93, 0xab, 0x20, 0xc3,
-    0x49, 0xe4, 0xdb, 0xb9, 0x4c, 0xc2, 0x6b, 0x6c, 0x0e, 0xed, 0x15, 0x82,
-    0x0f, 0xf1, 0x7e, 0xad, 0x69, 0x1a, 0xb1, 0xd3, 0x02, 0x3a, 0x8b, 0x2a,
-    0x41, 0xee, 0xa7, 0x70, 0xe0, 0x0f, 0x0d, 0x8d, 0xfd, 0x66, 0x0b, 0x2b,
-    0xb0, 0x24, 0x92, 0xa4, 0x7d, 0xb9, 0x88, 0x61, 0x79, 0x90, 0xb1, 0x57,
-    0x90, 0x3d, 0xd2, 0x3b, 0xc5, 0xe0, 0xb8, 0x48, 0x1f, 0xa8, 0x37, 0xd3,
-    0x88, 0x43, 0xef, 0x27, 0x16, 0xd8, 0x55, 0xb7, 0x66, 0x5a, 0xaa, 0x7e,
-    0x02, 0x90, 0x2f, 0x3a, 0x7b, 0x10, 0x80, 0x06, 0x24, 0xcc, 0x1c, 0x6c,
-    0x97, 0xad, 0x96, 0x61, 0x5b, 0xb7, 0xe2, 0x96, 0x12, 0xc0, 0x75, 0x31,
-    0xa3, 0x0c, 0x91, 0xdd, 0xb4, 0xca, 0xf7, 0xfc, 0xad, 0x1d, 0x25, 0xd3,
-    0x09, 0xef, 0xb9, 0x17, 0x0e, 0xa7, 0x68, 0xe1, 0xb3, 0x7b, 0x2f, 0x22,
-    0x6f, 0x69, 0xe3, 0xb4, 0x8a, 0x95, 0x61, 0x1d, 0xee, 0x26, 0xd6, 0x25,
-    0x9d, 0xab, 0x91, 0x08, 0x4e, 0x36, 0xcb, 0x1c, 0x24, 0x04, 0x2c, 0xbf,
-    0x16, 0x8b, 0x2f, 0xe5, 0xf1, 0x8f, 0x99, 0x17, 0x31, 0xb8, 0xb3, 0xfe,
-    0x49, 0x23, 0xfa, 0x72, 0x51, 0xc4, 0x31, 0xd5, 0x03, 0xac, 0xda, 0x18,
-    0x0a, 0x35, 0xed, 0x8d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0b, 0x06,
-    0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x03, 0x82,
-    0x01, 0x01, 0x00, 0x44, 0x92, 0xbb, 0x8e, 0x83, 0x58, 0x56, 0x2e, 0x7a,
-    0x86, 0xfa, 0x1d, 0x77, 0x50, 0x3f, 0x45, 0x8d, 0x90, 0xc4, 0x62, 0x27,
-    0x21, 0x96, 0x5a, 0xef, 0x51, 0x78, 0xd7, 0x7d, 0x0d, 0x02, 0x2d, 0x5a,
-    0x0e, 0x3c, 0x82, 0x6f, 0x1d, 0x92, 0x87, 0xd5, 0x1a, 0x44, 0xae, 0xa7,
-    0x92, 0xd1, 0x8b, 0xfa, 0x16, 0x53, 0x7f, 0xa3, 0x22, 0x96, 0x1a, 0x51,
-    0x8c, 0xeb, 0xa1, 0xe6, 0xf6, 0x37, 0x11, 0xfe, 0x7d, 0x53, 0x3f, 0xae,
-    0xf0, 0x6b, 0xb9, 0xb1, 0x7a, 0x73, 0x07, 0x14, 0xcf, 0x04, 0x05, 0x93,
-    0x9e, 0xe3, 0xd2, 0x4d, 0x9d, 0x6d, 0x35, 0x68, 0xf9, 0x36, 0xe5, 0x10,
-    0x0a, 0x36, 0xd9, 0x48, 0xb0, 0x83, 0xd0, 0xb9, 0x58, 0x74, 0x53, 0xb3,
-    0xbc, 0x99, 0xab, 0xe1, 0x3e, 0xd5, 0x01, 0x8e, 0xcf, 0x3a, 0x69, 0x93,
-    0x9e, 0xa7, 0x88, 0xd4, 0xad, 0x95, 0xf9, 0x2a, 0xb4, 0x7f, 0x95, 0x97,
-    0x86, 0x50, 0x38, 0xb1, 0x04, 0x0a, 0xe4, 0x7a, 0xd5, 0x2d, 0x6c, 0xde,
-    0x3e, 0x1a, 0x47, 0x17, 0x88, 0x63, 0x20, 0x9d, 0x21, 0x3e, 0x0c, 0x6f,
-    0xfd, 0x20, 0x54, 0xd0, 0x67, 0xd2, 0x6b, 0x06, 0xfe, 0x60, 0x13, 0x42,
-    0x3d, 0xb7, 0xca, 0xcb, 0xab, 0x7b, 0x5f, 0x5d, 0x01, 0x56, 0xd3, 0x99,
-    0x80, 0x0f, 0xde, 0x7f, 0x3a, 0x61, 0x9c, 0xd3, 0x6b, 0x5e, 0xfe, 0xb5,
-    0xfc, 0x39, 0x8b, 0x8e, 0xf0, 0x8c, 0x8b, 0x65, 0x46, 0x45, 0xff, 0x47,
-    0x8f, 0xd4, 0xdd, 0xae, 0xc9, 0x72, 0xc7, 0x7f, 0x28, 0x86, 0xf1, 0xf7,
-    0x6e, 0xcb, 0x86, 0x03, 0xeb, 0x0c, 0x46, 0xe5, 0xa0, 0x6b, 0xef, 0xd4,
-    0x5e, 0xa4, 0x0f, 0x53, 0xe1, 0xbc, 0xb4, 0xc9, 0x37, 0x0e, 0x75, 0xdd,
-    0x93, 0xe8, 0x0f, 0x18, 0x0a, 0x02, 0x83, 0x17, 0x74, 0xbb, 0x1a, 0x42,
-    0x5b, 0x63, 0x2c, 0x80, 0x80, 0xa6, 0x84
-];
-
-#[cfg_attr(rustfmt, rustfmt_skip)]
-pub const RSA_INT: [u8; 724] = [
-    0x30, 0x82, 0x02, 0xd0, 0x30, 0x82, 0x01, 0xba, 0xa0, 0x03, 0x02, 0x01,
-    0x02, 0x02, 0x14, 0x07, 0x10, 0xaf, 0xc4, 0x1a, 0x3a, 0x56, 0x4f, 0xd8,
-    0xc2, 0xcc, 0x46, 0xd7, 0x5b, 0xdf, 0x1c, 0x4e, 0x2f, 0x49, 0x3a, 0x30,
-    0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
-    0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
-    0x08, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x22, 0x18,
-    0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30,
-    0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32,
-    0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x12, 0x31,
-    0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x69, 0x6e,
-    0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06,
-    0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
-    0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01,
-    0x01, 0x00, 0xba, 0x88, 0x51, 0xa8, 0x44, 0x8e, 0x16, 0xd6, 0x41, 0xfd,
-    0x6e, 0xb6, 0x88, 0x06, 0x36, 0x10, 0x3d, 0x3c, 0x13, 0xd9, 0xea, 0xe4,
-    0x35, 0x4a, 0xb4, 0xec, 0xf5, 0x68, 0x57, 0x6c, 0x24, 0x7b, 0xc1, 0xc7,
-    0x25, 0xa8, 0xe0, 0xd8, 0x1f, 0xbd, 0xb1, 0x9c, 0x06, 0x9b, 0x6e, 0x1a,
-    0x86, 0xf2, 0x6b, 0xe2, 0xaf, 0x5a, 0x75, 0x6b, 0x6a, 0x64, 0x71, 0x08,
-    0x7a, 0xa5, 0x5a, 0xa7, 0x45, 0x87, 0xf7, 0x1c, 0xd5, 0x24, 0x9c, 0x02,
-    0x7e, 0xcd, 0x43, 0xfc, 0x1e, 0x69, 0xd0, 0x38, 0x20, 0x29, 0x93, 0xab,
-    0x20, 0xc3, 0x49, 0xe4, 0xdb, 0xb9, 0x4c, 0xc2, 0x6b, 0x6c, 0x0e, 0xed,
-    0x15, 0x82, 0x0f, 0xf1, 0x7e, 0xad, 0x69, 0x1a, 0xb1, 0xd3, 0x02, 0x3a,
-    0x8b, 0x2a, 0x41, 0xee, 0xa7, 0x70, 0xe0, 0x0f, 0x0d, 0x8d, 0xfd, 0x66,
-    0x0b, 0x2b, 0xb0, 0x24, 0x92, 0xa4, 0x7d, 0xb9, 0x88, 0x61, 0x79, 0x90,
-    0xb1, 0x57, 0x90, 0x3d, 0xd2, 0x3b, 0xc5, 0xe0, 0xb8, 0x48, 0x1f, 0xa8,
-    0x37, 0xd3, 0x88, 0x43, 0xef, 0x27, 0x16, 0xd8, 0x55, 0xb7, 0x66, 0x5a,
-    0xaa, 0x7e, 0x02, 0x90, 0x2f, 0x3a, 0x7b, 0x10, 0x80, 0x06, 0x24, 0xcc,
-    0x1c, 0x6c, 0x97, 0xad, 0x96, 0x61, 0x5b, 0xb7, 0xe2, 0x96, 0x12, 0xc0,
-    0x75, 0x31, 0xa3, 0x0c, 0x91, 0xdd, 0xb4, 0xca, 0xf7, 0xfc, 0xad, 0x1d,
-    0x25, 0xd3, 0x09, 0xef, 0xb9, 0x17, 0x0e, 0xa7, 0x68, 0xe1, 0xb3, 0x7b,
-    0x2f, 0x22, 0x6f, 0x69, 0xe3, 0xb4, 0x8a, 0x95, 0x61, 0x1d, 0xee, 0x26,
-    0xd6, 0x25, 0x9d, 0xab, 0x91, 0x08, 0x4e, 0x36, 0xcb, 0x1c, 0x24, 0x04,
-    0x2c, 0xbf, 0x16, 0x8b, 0x2f, 0xe5, 0xf1, 0x8f, 0x99, 0x17, 0x31, 0xb8,
-    0xb3, 0xfe, 0x49, 0x23, 0xfa, 0x72, 0x51, 0xc4, 0x31, 0xd5, 0x03, 0xac,
-    0xda, 0x18, 0x0a, 0x35, 0xed, 0x8d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3,
-    0x1d, 0x30, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
-    0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f,
-    0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86,
-    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x03, 0x82, 0x01, 0x01, 0x00,
-    0x5e, 0xba, 0x69, 0x55, 0x9f, 0xf8, 0xeb, 0x16, 0x21, 0x98, 0xde, 0xb7,
-    0x31, 0x3e, 0x66, 0xe1, 0x3b, 0x0c, 0x29, 0xf7, 0x48, 0x73, 0x05, 0xd9,
-    0xce, 0x5e, 0x4c, 0xbe, 0x03, 0xc4, 0x51, 0xd6, 0x21, 0x92, 0x40, 0x38,
-    0xaa, 0x5b, 0x28, 0xb5, 0xa1, 0x10, 0x52, 0x57, 0xff, 0x91, 0x54, 0x82,
-    0x86, 0x9e, 0x74, 0xd5, 0x3d, 0x82, 0x29, 0xee, 0xd1, 0xcf, 0x93, 0xb1,
-    0x24, 0x76, 0xbb, 0x95, 0x41, 0x06, 0x7e, 0x40, 0x9b, 0xb4, 0xab, 0x44,
-    0x34, 0x10, 0x8f, 0xb1, 0x51, 0x6f, 0xc0, 0x89, 0xd1, 0xa3, 0xc4, 0x9f,
-    0xb3, 0x48, 0xe1, 0xcd, 0x73, 0xad, 0xff, 0x42, 0x5f, 0x76, 0x05, 0x60,
-    0xc5, 0xe0, 0x45, 0x79, 0x18, 0xa1, 0x19, 0xb8, 0xa7, 0x3a, 0x64, 0xb3,
-    0x19, 0xba, 0x14, 0xa1, 0xb5, 0xdc, 0x32, 0xec, 0x09, 0x39, 0x58, 0x54,
-    0x5b, 0x04, 0xdc, 0x1b, 0x66, 0x0d, 0x1d, 0x0d, 0xce, 0x7f, 0xfa, 0x24,
-    0x52, 0x6a, 0xad, 0xe2, 0xc8, 0x30, 0xaf, 0xf2, 0xaf, 0x63, 0xc5, 0xe2,
-    0xbf, 0xe2, 0x20, 0x1b, 0x9e, 0xf9, 0x3d, 0xbc, 0xfb, 0x04, 0x8e, 0xda,
-    0x7a, 0x1a, 0x5d, 0xd3, 0x13, 0xd7, 0x00, 0x8e, 0x9b, 0x5d, 0x85, 0x51,
-    0xda, 0xd3, 0x91, 0x25, 0xf5, 0x67, 0x85, 0x3e, 0x25, 0x89, 0x5e, 0xcb,
-    0x89, 0x8a, 0xec, 0x8a, 0xde, 0x8b, 0xf4, 0x33, 0x5f, 0x76, 0xdb, 0x3d,
-    0xfc, 0x6a, 0x05, 0x21, 0x43, 0xb2, 0x41, 0xd8, 0x33, 0x8d, 0xfd, 0x05,
-    0x5c, 0x22, 0x0a, 0xf6, 0x90, 0x65, 0x9c, 0x4f, 0x8c, 0x44, 0x9f, 0x2d,
-    0xca, 0xf3, 0x49, 0x9c, 0x3a, 0x14, 0x88, 0xab, 0xe4, 0xce, 0xb7, 0xbc,
-    0x95, 0x22, 0x2e, 0xb1, 0x82, 0x4c, 0xbf, 0x83, 0x3e, 0x49, 0x72, 0x03,
-    0x2a, 0x68, 0xe7, 0x2d, 0xe5, 0x2d, 0x4b, 0x61, 0xb0, 0x8d, 0x0d, 0x0c,
-    0x87, 0xc6, 0x5c, 0x51
-];
-
-#[cfg_attr(rustfmt, rustfmt_skip)]
-pub const RSA_ROOT: [u8; 725] = [
-    0x30, 0x82, 0x02, 0xd1, 0x30, 0x82, 0x01, 0xbb, 0xa0, 0x03, 0x02, 0x01,
-    0x02, 0x02, 0x14, 0x29, 0x6c, 0x1a, 0xd8, 0x20, 0xcd, 0x74, 0x6d, 0x4b,
-    0x00, 0xf3, 0x16, 0x88, 0xd9, 0x66, 0x87, 0x5f, 0x28, 0x56, 0x6a, 0x30,
-    0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
-    0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
-    0x08, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x22, 0x18,
-    0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30,
-    0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32,
-    0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x13, 0x31,
-    0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x72, 0x6f,
-    0x6f, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
-    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
-    0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82,
-    0x01, 0x01, 0x00, 0xba, 0x88, 0x51, 0xa8, 0x44, 0x8e, 0x16, 0xd6, 0x41,
-    0xfd, 0x6e, 0xb6, 0x88, 0x06, 0x36, 0x10, 0x3d, 0x3c, 0x13, 0xd9, 0xea,
-    0xe4, 0x35, 0x4a, 0xb4, 0xec, 0xf5, 0x68, 0x57, 0x6c, 0x24, 0x7b, 0xc1,
-    0xc7, 0x25, 0xa8, 0xe0, 0xd8, 0x1f, 0xbd, 0xb1, 0x9c, 0x06, 0x9b, 0x6e,
-    0x1a, 0x86, 0xf2, 0x6b, 0xe2, 0xaf, 0x5a, 0x75, 0x6b, 0x6a, 0x64, 0x71,
-    0x08, 0x7a, 0xa5, 0x5a, 0xa7, 0x45, 0x87, 0xf7, 0x1c, 0xd5, 0x24, 0x9c,
-    0x02, 0x7e, 0xcd, 0x43, 0xfc, 0x1e, 0x69, 0xd0, 0x38, 0x20, 0x29, 0x93,
-    0xab, 0x20, 0xc3, 0x49, 0xe4, 0xdb, 0xb9, 0x4c, 0xc2, 0x6b, 0x6c, 0x0e,
-    0xed, 0x15, 0x82, 0x0f, 0xf1, 0x7e, 0xad, 0x69, 0x1a, 0xb1, 0xd3, 0x02,
-    0x3a, 0x8b, 0x2a, 0x41, 0xee, 0xa7, 0x70, 0xe0, 0x0f, 0x0d, 0x8d, 0xfd,
-    0x66, 0x0b, 0x2b, 0xb0, 0x24, 0x92, 0xa4, 0x7d, 0xb9, 0x88, 0x61, 0x79,
-    0x90, 0xb1, 0x57, 0x90, 0x3d, 0xd2, 0x3b, 0xc5, 0xe0, 0xb8, 0x48, 0x1f,
-    0xa8, 0x37, 0xd3, 0x88, 0x43, 0xef, 0x27, 0x16, 0xd8, 0x55, 0xb7, 0x66,
-    0x5a, 0xaa, 0x7e, 0x02, 0x90, 0x2f, 0x3a, 0x7b, 0x10, 0x80, 0x06, 0x24,
-    0xcc, 0x1c, 0x6c, 0x97, 0xad, 0x96, 0x61, 0x5b, 0xb7, 0xe2, 0x96, 0x12,
-    0xc0, 0x75, 0x31, 0xa3, 0x0c, 0x91, 0xdd, 0xb4, 0xca, 0xf7, 0xfc, 0xad,
-    0x1d, 0x25, 0xd3, 0x09, 0xef, 0xb9, 0x17, 0x0e, 0xa7, 0x68, 0xe1, 0xb3,
-    0x7b, 0x2f, 0x22, 0x6f, 0x69, 0xe3, 0xb4, 0x8a, 0x95, 0x61, 0x1d, 0xee,
-    0x26, 0xd6, 0x25, 0x9d, 0xab, 0x91, 0x08, 0x4e, 0x36, 0xcb, 0x1c, 0x24,
-    0x04, 0x2c, 0xbf, 0x16, 0x8b, 0x2f, 0xe5, 0xf1, 0x8f, 0x99, 0x17, 0x31,
-    0xb8, 0xb3, 0xfe, 0x49, 0x23, 0xfa, 0x72, 0x51, 0xc4, 0x31, 0xd5, 0x03,
-    0xac, 0xda, 0x18, 0x0a, 0x35, 0xed, 0x8d, 0x02, 0x03, 0x01, 0x00, 0x01,
-    0xa3, 0x1d, 0x30, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
-    0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d,
-    0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0b, 0x06, 0x09, 0x2a,
-    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x03, 0x82, 0x01, 0x01,
-    0x00, 0x23, 0x2f, 0x9f, 0x72, 0xeb, 0x70, 0x6d, 0x9e, 0x3e, 0x9f, 0xd7,
-    0x9c, 0xd9, 0x19, 0x7c, 0x99, 0x07, 0xc5, 0x5c, 0x9d, 0xf5, 0x66, 0x9f,
-    0x28, 0x8d, 0xfe, 0x0e, 0x3f, 0x38, 0x75, 0xed, 0xee, 0x4e, 0x3f, 0xf6,
-    0x6e, 0x35, 0xe0, 0x95, 0x3f, 0x08, 0x4a, 0x71, 0x5a, 0xf2, 0x4f, 0xc9,
-    0x96, 0x61, 0x8d, 0x45, 0x4b, 0x97, 0x85, 0xff, 0xb0, 0xe3, 0xbb, 0xb5,
-    0xd7, 0x7e, 0xfb, 0xd2, 0xfc, 0xec, 0xfe, 0x42, 0x9f, 0x4e, 0x7b, 0xbf,
-    0x97, 0xbb, 0xb4, 0x3a, 0x93, 0x0b, 0x13, 0x61, 0x90, 0x0c, 0x3a, 0xce,
-    0xf7, 0x8e, 0xef, 0x80, 0xf5, 0x4a, 0x92, 0xc5, 0xa5, 0x03, 0x78, 0xc2,
-    0xee, 0xb8, 0x66, 0x60, 0x6b, 0x76, 0x4f, 0x32, 0x5a, 0x1a, 0xa2, 0x4b,
-    0x7e, 0x2b, 0xa6, 0x1a, 0x89, 0x01, 0xe3, 0xbb, 0x55, 0x13, 0x7c, 0x4c,
-    0xf4, 0x6a, 0x99, 0x94, 0xd1, 0xa0, 0x84, 0x1c, 0x1a, 0xc2, 0x7b, 0xb4,
-    0xa0, 0xb0, 0x3b, 0xdc, 0x5a, 0x7b, 0xc7, 0xe0, 0x44, 0xb2, 0x1f, 0x46,
-    0xd5, 0x8b, 0x39, 0x8b, 0xdc, 0x9e, 0xce, 0xa8, 0x7f, 0x85, 0x1d, 0x4b,
-    0x63, 0x06, 0x1e, 0x8e, 0xe5, 0xe5, 0x99, 0xd9, 0xf7, 0x4d, 0x89, 0x0b,
-    0x1d, 0x5c, 0x27, 0x33, 0x66, 0x21, 0xcf, 0x9a, 0xbd, 0x98, 0x68, 0x23,
-    0x3a, 0x66, 0x9d, 0xd4, 0x46, 0xed, 0x63, 0x58, 0xf3, 0x42, 0xe4, 0x1d,
-    0xe2, 0x47, 0x65, 0x13, 0x8d, 0xd4, 0x1f, 0x4b, 0x7e, 0xde, 0x11, 0x56,
-    0xf8, 0x6d, 0x01, 0x0c, 0x99, 0xbd, 0x8d, 0xca, 0x8a, 0x2e, 0xe3, 0x8a,
-    0x9c, 0x3d, 0x83, 0x8d, 0x69, 0x62, 0x8d, 0x05, 0xea, 0xb7, 0xf5, 0xa3,
-    0x4b, 0xfc, 0x96, 0xcf, 0x18, 0x21, 0x0a, 0xc7, 0xf3, 0x23, 0x7e, 0x1c,
-    0xab, 0xe2, 0xa2, 0xd1, 0x83, 0xc4, 0x25, 0x93, 0x37, 0x80, 0xca, 0xda,
-    0xf0, 0xef, 0x7d, 0x94, 0xb5
<