Merge mozilla-central to autoland. r=merge a=merge CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Wed, 10 Jan 2018 12:07:47 +0200
changeset 450321 7f1a490e8af146f19fcb3f52afccba015cc6a45b
parent 450320 b273f48a1ab59695ab3651cd72550fc9bc9e0b64 (current diff)
parent 450276 d5f42a23909eb181274731b07e4984bfbd18557d (diff)
child 450322 7b110713598d9ca1e8b0656a7cccc9662ae84bcc
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to autoland. r=merge a=merge CLOSED TREE
security/manager/ssl/tests/unit/test_signed_apps/cose_multiple_signed.zip
security/manager/ssl/tests/unit/test_signed_apps/cose_multiple_signed_with_pkcs7.zip
security/manager/ssl/tests/unit/test_signed_apps/cose_signed.zip
security/manager/ssl/tests/unit/test_signed_apps/cose_signed_with_pkcs7.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
third_party/rust/moz_cbor/src/lib.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/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -378459,35 +378459,43 @@
      {
       "timeout": "long"
      }
     ]
    ],
    "webdriver/tests/state/get_element_attribute.py": [
     [
      "/webdriver/tests/state/get_element_attribute.py",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "webdriver/tests/state/get_element_property.py": [
     [
      "/webdriver/tests/state/get_element_property.py",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "webdriver/tests/state/get_element_tag_name.py": [
     [
      "/webdriver/tests/state/get_element_tag_name.py",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "webdriver/tests/state/is_element_selected.py": [
     [
      "/webdriver/tests/state/is_element_selected.py",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "webdriver/tests/state/text/get_text.py": [
     [
      "/webdriver/tests/state/text/get_text.py",
      {}
     ]
    ],
@@ -583372,29 +583380,29 @@
    "8a124f80e6e7732a651a80da3f6cdf8e2ed99e3e",
    "wdspec"
   ],
   "webdriver/tests/state/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/state/get_element_attribute.py": [
-   "75620b583be6495d9b7b5d65c57cbda217cd2e01",
+   "1fcd451313d40a0b0a84ced63596d032ffc97f2a",
    "wdspec"
   ],
   "webdriver/tests/state/get_element_property.py": [
-   "042f184dd54153fe5ff46e886ddcf27ffe4bae6d",
+   "c0fdf271eebb7dcef16a37a897362ed48eec2df1",
    "wdspec"
   ],
   "webdriver/tests/state/get_element_tag_name.py": [
-   "0887f71ceb4b4959989ee9f589707624f46e0ce3",
+   "ce749e286bd030083fcac15dd75c49caf032f990",
    "wdspec"
   ],
   "webdriver/tests/state/is_element_selected.py": [
-   "fb7825918c186d97abe69c4ab06fea1ed62f5387",
+   "f52c565da22038a41db7344cbcfa2a6a101cc61d",
    "wdspec"
   ],
   "webdriver/tests/state/text/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/state/text/get_text.py": [
    "570274d59020c4d8d0b8ecd604660ee7d710a165",
--- 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,
<