Bug 1403840 - add cose rust lib with a test, r=keeler,ttaubert
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Wed, 22 Nov 2017 16:37:15 +0100
changeset 393315 cfcbb8333389ccf2ff91176f1aecf50199be018b
parent 393314 5d44a5636d44d0a8797aac01c922d01d8e0a6a5c
child 393316 fedc2d408840d81fdb3550c83121b400a2e63a0b
push id32956
push usercsabou@mozilla.com
push dateThu, 23 Nov 2017 09:44:48 +0000
treeherdermozilla-central@b6bed1b710c3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler, ttaubert
bugs1403840
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
Bug 1403840 - add cose rust lib with a test, r=keeler,ttaubert Summary: This adds the COSE rust library from https://github.com/franziskuskiefer/cose-rust with its C API from https://github.com/franziskuskiefer/cose-c-api to gecko with a basic test. The COSE library will be used for verifying add-on signatures in future. Reviewers: keeler, ttaubert Reviewed By: keeler Bug #: 1403840 Differential Revision: https://phabricator.services.mozilla.com/D232
security/manager/ssl/tests/gtest/CoseTest.cpp
security/manager/ssl/tests/gtest/moz.build
third_party/rust/cose-c/.cargo-checksum.json
third_party/rust/cose-c/Cargo.toml
third_party/rust/cose-c/LICENSE
third_party/rust/cose-c/include/cosec.h
third_party/rust/cose-c/src/lib.rs
third_party/rust/cose/.cargo-checksum.json
third_party/rust/cose/.travis.yml
third_party/rust/cose/Cargo.toml
third_party/rust/cose/LICENSE
third_party/rust/cose/README.md
third_party/rust/cose/build.rs
third_party/rust/cose/rustfmt.toml
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/cose.rs
third_party/rust/cose/src/decoder.rs
third_party/rust/cose/src/nss.rs
third_party/rust/cose/src/test_cose.rs
third_party/rust/cose/src/test_nss.rs
third_party/rust/cose/src/test_setup.rs
third_party/rust/cose/src/util.rs
third_party/rust/cose/src/util_test.rs
third_party/rust/cose/tools/certs/certs.md
third_party/rust/cose/tools/certs/certs.sh
third_party/rust/cose/tools/certs/ee-p256.certspec
third_party/rust/cose/tools/certs/ee-p256.keyspec
third_party/rust/cose/tools/certs/ee-p384.certspec
third_party/rust/cose/tools/certs/ee-p521.certspec
third_party/rust/cose/tools/certs/ee-rsa.certspec
third_party/rust/cose/tools/certs/int-p256.certspec
third_party/rust/cose/tools/certs/int-rsa.certspec
third_party/rust/cose/tools/certs/root-p256.certspec
third_party/rust/cose/tools/certs/root-rsa.certspec
toolkit/library/gtest/rust/Cargo.lock
toolkit/library/rust/Cargo.lock
toolkit/library/rust/shared/Cargo.toml
toolkit/library/rust/shared/lib.rs
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/gtest/CoseTest.cpp
@@ -0,0 +1,738 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "gtest/gtest.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <cstddef>
+#include <memory>
+
+#include <keyhi.h>
+#include <nss.h>
+#include <pk11pub.h>
+
+#include <pkcs11t.h>
+#include <secmodt.h>
+#include <cert.h>
+
+#include "ScopedNSSTypes.h"
+#include "cosec.h"
+
+namespace mozilla {
+
+// "This is the content."
+const uint8_t PAYLOAD[] = { 84,  104, 105, 115, 32,  105, 115, 32,  116, 104,
+                            101, 32,  99,  111, 110, 116, 101, 110, 116, 46 };
+
+// This is a COSE signature generated with the cose rust library (see
+// third-party/rust/cose). The payload is signed with the P256 key from
+// pykey.py.
+const uint8_t SIGNATURE[] = {
+  0xd8, 0x62, 0x84, 0x59, 0x02, 0xa3, 0xa1, 0x04, 0x82, 0x59, 0x01, 0x4e, 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, 0x59, 0x01, 0x4c, 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, 0xa0, 0xf6, 0x81, 0x83, 0x59, 0x01, 0x33, 0xa2,
+  0x01, 0x26, 0x04, 0x59, 0x01, 0x2c, 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, 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
+};
+
+// 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,
+  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, 0x59, 0x01, 0x4c, 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, 0x59, 0x02, 0xd5, 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, 0x59, 0x02, 0xd4, 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, 0xa0, 0xf6, 0x82, 0x83, 0x59, 0x01, 0x33, 0xa2, 0x01,
+  0x26, 0x04, 0x59, 0x01, 0x2c, 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, 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,
+  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,
+  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, 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
+};
+
+// 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,
+  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
+};
+
+// The RSA root certificate that issued the RSA intermediate certificate above.
+// The certificate was generated with pycert.py
+const uint8_t RSA_ROOT[] = {
+  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
+};
+
+// The P256 intermediate certificate that issued the EE cert used in the
+// signatures above. The certificate was generated with pycert.py
+const uint8_t P256_INT[] = {
+  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
+};
+
+// The P256 root certificate that issued the P256 intermediate certificate
+// above. The certificate was generated with pycert.py
+const uint8_t P256_ROOT[] = {
+  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
+};
+
+void
+check_hard_coded_certs(const uint8_t** cert_chain,
+                       size_t cert_chain_len,
+                       const size_t* certs_len)
+{
+  // Very hacky and fragile check that the intermediate certs are correct.
+  switch (cert_chain_len) {
+    case 2: {
+      const uint8_t* cert = cert_chain[0];
+      size_t cert_len = certs_len[0];
+      ASSERT_EQ(cert_len, sizeof(P256_ROOT));
+      ASSERT_EQ(0, memcmp(cert, P256_ROOT, cert_len));
+      cert = cert_chain[1];
+      cert_len = certs_len[1];
+      ASSERT_EQ(cert_len, sizeof(P256_INT));
+      ASSERT_EQ(0, memcmp(cert, P256_INT, cert_len));
+      break;
+    }
+    case 4: {
+      const uint8_t* cert = cert_chain[0];
+      size_t cert_len = certs_len[0];
+      ASSERT_EQ(cert_len, sizeof(P256_ROOT));
+      ASSERT_EQ(0, memcmp(cert, P256_ROOT, cert_len));
+      cert = cert_chain[1];
+      cert_len = certs_len[1];
+      ASSERT_EQ(cert_len, sizeof(P256_INT));
+      ASSERT_EQ(0, memcmp(cert, P256_INT, cert_len));
+      cert = cert_chain[2];
+      cert_len = certs_len[2];
+      ASSERT_EQ(cert_len, sizeof(RSA_ROOT));
+      ASSERT_EQ(0, memcmp(cert, RSA_ROOT, cert_len));
+      cert = cert_chain[3];
+      cert_len = certs_len[3];
+      ASSERT_EQ(cert_len, sizeof(RSA_INT));
+      ASSERT_EQ(0, memcmp(cert, RSA_INT, cert_len));
+      break;
+    }
+    default:
+      // In this case something went wrong.
+      ASSERT_EQ(true, false);
+  }
+}
+
+/* Verification function called from cose-rust.
+ * Returns true if everything goes well and the signature is good, false in any
+ * other case. */
+bool
+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)
+{
+  UniquePK11SlotInfo slot(PK11_GetInternalSlot());
+  if (!slot) {
+    return false;
+  }
+
+  CK_MECHANISM_TYPE mechanism;
+  SECOidTag oid;
+  uint32_t hash_length;
+  SECItem param = { siBuffer, nullptr, 0 };
+  CK_RSA_PKCS_PSS_PARAMS rsa_pss_params = { CKM_SHA256, CKG_MGF1_SHA256, SHA256_LENGTH };
+  switch (signature_algorithm) {
+    case (ES256):
+      mechanism = CKM_ECDSA;
+      oid = SEC_OID_SHA256;
+      hash_length = SHA256_LENGTH;
+      break;
+    case (PS256):
+      mechanism = CKM_RSA_PKCS_PSS;
+      oid = SEC_OID_SHA256;
+      hash_length = SHA256_LENGTH;
+      param = { siBuffer,
+                reinterpret_cast<unsigned char*>(&rsa_pss_params),
+                sizeof(rsa_pss_params) };
+      break;
+    default:
+      return false;
+  }
+  check_hard_coded_certs(cert_chain, cert_chain_len, certs_len);
+
+  uint8_t hash_buf[HASH_LENGTH_MAX];
+  SECStatus rv = PK11_HashBuf(oid, hash_buf, payload, payload_len);
+  if (rv != SECSuccess) {
+    return false;
+  }
+  SECItem hash_item = { siBuffer, hash_buf, hash_length };
+  CERTCertDBHandle* db_handle = CERT_GetDefaultCertDB();
+  if (!db_handle) {
+    return false;
+  }
+  SECItem der_cert = { siBuffer,
+                       const_cast<uint8_t*>(ee_cert),
+                       static_cast<unsigned int>(ee_cert_len) };
+  UniqueCERTCertificate cert(
+    CERT_NewTempCertificate(db_handle, &der_cert, nullptr, false, true));
+  if (!cert) {
+    return false;
+  }
+  UniqueSECKEYPublicKey key(CERT_ExtractPublicKey(cert.get()));
+  if (!key) {
+    return false;
+  }
+  SECItem signature_item = { siBuffer,
+                             const_cast<uint8_t*>(signature),
+                             static_cast<unsigned int>(signature_len) };
+  rv = PK11_VerifyWithMechanism(
+    key.get(), mechanism, &param, &signature_item, &hash_item, nullptr);
+  if (rv != SECSuccess) {
+    return false;
+  }
+
+  return true;
+}
+
+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);
+  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),
+                                          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),
+                                          verify_callback);
+  ASSERT_FALSE(result);
+}
+
+} // namespace mozilla
--- a/security/manager/ssl/tests/gtest/moz.build
+++ b/security/manager/ssl/tests/gtest/moz.build
@@ -2,28 +2,30 @@
 # vim: set filetype=python:
 # 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/.
 
 SOURCES += [
     'CertDBTest.cpp',
     'CertListTest.cpp',
+    'CoseTest.cpp',
     'DataStorageTest.cpp',
     'DeserializeCertTest.cpp',
     'MD4Test.cpp',
     'OCSPCacheTest.cpp',
     'TLSIntoleranceTest.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/security/certverifier',
     '/security/manager/ssl',
     '/security/pkix/include',
     '/security/pkix/test/lib',
+    '/third_party/rust/cose-c/include',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul-gtest'
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wno-error=shadow']
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose-c/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"Cargo.toml":"6689411cf004e6ebc4645105de26492adbea6f690f9184119cf1689829ff098a","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","include/cosec.h":"9e952f6bf578c812e67a93c3c810f4aaa57d365932fe8d01f36f587e8aa32538","src/lib.rs":"d10a17e4840187711d85058bf4afdbfbda88c74a9483921ee48a1bfc0cc5ff70"},"package":"07cc8bb85ec2e93541ef9369b85a4b6fb7732bc7f4854d317eab20e726b0fc2f"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose-c/Cargo.toml
@@ -0,0 +1,26 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# 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"
+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"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose-c/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  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/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+  This Source Code Form is "Incompatible With Secondary Licenses", as
+  defined by the Mozilla Public License, v. 2.0.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose-c/include/cosec.h
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <stdint.h>
+
+enum CoseSignatureType
+{
+  ES256 = 0,
+  ES384 = 1,
+  ES512 = 2,
+  PS256 = 3
+};
+
+extern "C" {
+typedef bool (*cose_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 algorithm);
+bool
+verify_cose_signature_ffi(const uint8_t* payload,
+                          size_t payload_len,
+                          const uint8_t* signature,
+                          size_t signature_len,
+                          cose_verify_callback);
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose-c/src/lib.rs
@@ -0,0 +1,85 @@
+/* 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/. */
+
+extern crate cose;
+
+use std::slice;
+use cose::decoder::decode_signature;
+use cose::SignatureAlgorithm;
+
+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 */)
+                                    -> 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,
+    verify_callback: VerifyCallback,
+) -> bool {
+    if payload.is_null() || cose_signature.is_null() || payload_len == 0 ||
+        cose_signature_len == 0
+    {
+        return false;
+    }
+
+    // Build Rust variables from C parameters.
+    let payload = unsafe { from_raw(payload, payload_len) };
+    let cose_signature = unsafe { from_raw(cose_signature, cose_signature_len) };
+
+    // Parse the incoming signature.
+    let cose_signatures = decode_signature(&cose_signature, &payload);
+    let cose_signatures = match cose_signatures {
+        Ok(signatures) => signatures,
+        Err(_) => Vec::new(),
+    };
+    if cose_signatures.len() == 0 {
+        return false;
+    }
+
+    return cose_signatures.into_iter().all(|cose_signature| {
+        let signature_type = cose_signature.signature_type;
+        // ES256 = 0, ES384 = 1, ES512 = 2, PS256 = 3
+        let signature_type = match signature_type {
+            SignatureAlgorithm::ES256 => 0,
+            SignatureAlgorithm::ES384 => 1,
+            SignatureAlgorithm::ES512 => 2,
+            SignatureAlgorithm::PS256 => 3,
+        };
+        let signature_bytes = cose_signature.signature;
+        let real_payload = cose_signature.to_verify;
+
+        // Build cert chain params.
+        let certs: Vec<_> = cose_signature.certs.iter().map(|c| c.as_ptr()).collect();
+        let cert_lens: Vec<_> = cose_signature.certs.iter().map(|c| c.len()).collect();
+
+        // Call callback to verify the parsed signatures.
+        verify_callback(
+            real_payload.as_ptr(),
+            real_payload.len(),
+            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,
+        )
+    });
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/.cargo-checksum.json
@@ -0,0 +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
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/.travis.yml
@@ -0,0 +1,31 @@
+sudo: true
+language: rust
+cache: cargo
+rust:
+  - stable
+  - beta
+  - nightly
+
+addons:
+  apt:
+    packages:
+      - build-essential
+      - libnss3-dev
+
+install:
+# Apparently cargo install returns a nonzero exit status if
+# caching succeeds, so just make this always "succeed".
+  - (cargo install rustfmt || 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 build --features "$FEATURES" &&
+  cargo test
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/Cargo.toml
@@ -0,0 +1,30 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# 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"
+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"]
+license = "MPL-2.0"
+repository = "https://github.com/franziskuskiefer/cose-rust"
+
+[lib]
+name = "cose"
+path = "src/cose.rs"
+[dev-dependencies.scopeguard]
+version = "0.3"
+
+[features]
+default = []
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  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/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+  This Source Code Form is "Incompatible With Secondary Licenses", as
+  defined by the Mozilla Public License, v. 2.0.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/README.md
@@ -0,0 +1,15 @@
+# cose-rust
+
+A Rust library for [COSE](https://tools.ietf.org/html/rfc8152) using [NSS](https://github.com/nss-dev/nss/).
+
+[![Build Status](https://travis-ci.org/franziskuskiefer/cose-rust.svg?branch=master)](https://travis-ci.org/franziskuskiefer/cose-rust/)
+![Maturity Level](https://img.shields.io/badge/maturity-alpha-red.svg)
+
+**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
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/build.rs
@@ -0,0 +1,11 @@
+use std::env;
+
+fn main() {
+    // Use NSS_LIB_DIR lazily. If it's not set and we can't find NSS in the path,
+    // the build will fail.
+    #[cfg(test)]
+    let lib_dir = env::var("NSS_LIB_DIR");
+    if let Ok(lib_dir) = env::var("NSS_LIB_DIR") {
+        println!("cargo:rustc-link-search={}", lib_dir);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/rustfmt.toml
@@ -0,0 +1,4 @@
+array_layout = "Visual"
+array_width = 0
+reorder_imported_names = true
+array_horizontal_layout_threshold = 0
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/src/cbor/decoder.rs
@@ -0,0 +1,150 @@
+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?
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/src/cbor/mod.rs
@@ -0,0 +1,56 @@
+pub mod decoder;
+pub mod serializer;
+#[cfg(test)]
+mod test_decoder;
+#[cfg(test)]
+mod test_serializer;
+
+use std::collections::BTreeMap;
+use std::cmp::Ordering;
+
+#[derive(Debug)]
+#[derive(Clone)]
+#[derive(PartialEq)]
+#[derive(PartialOrd)]
+#[derive(Eq)]
+pub enum CborType {
+    Integer(u64),
+    SignedInteger(i64),
+    Tag(u64, Box<CborType>),
+    Bytes(Vec<u8>),
+    String(String),
+    Array(Vec<CborType>),
+    Map(BTreeMap<CborType, CborType>),
+    Null,
+}
+
+#[derive(Debug)]
+#[derive(PartialEq)]
+pub enum CborError {
+    DuplicateMapKey,
+    InputTooLarge,
+    InputValueOutOfRange,
+    LibraryError,
+    MalformedInput,
+    TruncatedInput,
+    UnsupportedType,
+}
+
+impl Ord for CborType {
+    /// Sorting for maps: RFC 7049 Section 3.9
+    ///
+    /// The keys in every map must be sorted lowest value to highest.
+    ///  *  If two keys have different lengths, the shorter one sorts
+    ///     earlier;
+    ///
+    ///  *  If two keys have the same length, the one with the lower value
+    ///     in (byte-wise) lexical order sorts earlier.
+    fn cmp(&self, other: &Self) -> Ordering {
+        let self_bytes = self.serialize();
+        let other_bytes = other.serialize();
+        if self_bytes.len() == other_bytes.len() {
+            return self_bytes.cmp(&other_bytes);
+        }
+        self_bytes.len().cmp(&other_bytes.len())
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/src/cbor/serializer.rs
@@ -0,0 +1,121 @@
+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
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/src/cbor/test_decoder.rs
@@ -0,0 +1,405 @@
+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);
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/src/cbor/test_serializer.rs
@@ -0,0 +1,310 @@
+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());
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/src/cose.rs
@@ -0,0 +1,98 @@
+//! This crate implements [COSE](https://tools.ietf.org/html/rfc8152) signature
+//! parsing. Verification has to be performed by the caller.
+//!
+//! Example usage: Let `payload` and `cose_signature` be variables holding the
+//! signed payload and the COSE signature bytes respectively.
+//! Let further `verify_callback` be a function callback that implements
+//! signature verification.
+//!
+//!```rust,ignore
+//! use cose::decoder::decode_signature;
+//!
+//! // Parse the incoming signature.
+//! let cose_signatures = decode_signature(cose_signature, &payload);
+//! let cose_signatures = match cose_signatures {
+//!     Ok(signature) => signature,
+//!     Err(_) => Vec::new(),
+//! };
+//! if cose_signatures.len() < 1 {
+//!     return false;
+//! }
+//!
+//! let mut result = true;
+//! for cose_signature in cose_signatures {
+//!     // Call callback to verify the parsed signatures.
+//!     result &= verify_callback(cose_signature);
+//!
+//!     // We can stop early. The cose_signature is not valid.
+//!     if !result {
+//!         return result;
+//!     }
+//! }
+//!```
+
+#[macro_use]
+pub mod decoder;
+mod cbor;
+mod util;
+
+/// Errors that can be returned from COSE functions.
+#[derive(Debug, PartialEq)]
+pub enum CoseError {
+    DecodingFailure,
+    LibraryFailure,
+    MalformedInput,
+    MissingHeader,
+    UnexpectedHeaderValue,
+    UnexpectedTag,
+    UnexpectedType,
+    Unimplemented,
+    VerificationFailed,
+    UnknownSignatureScheme,
+    SigningFailed,
+    InvalidArgument,
+}
+
+/// An enum identifying supported signature algorithms.
+/// Currently ES256 (ECDSA with P256 and SHA256), ES384 (ECDSA with P384 and SHA384)
+/// ES512 (ECDSA with P521 and SHA512), and PS256 (RSASSA-PSS with SHA256)
+/// are supported. Note that with PS256, the salt length is defined
+/// to be 32 bytes.
+#[derive(Debug)]
+#[derive(PartialEq)]
+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>,
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/src/decoder.rs
@@ -0,0 +1,192 @@
+//! Parse and decode COSE signatures.
+
+use cbor::CborType;
+use cbor::decoder::decode;
+use {CoseError, SignatureAlgorithm};
+use util::get_sig_struct_bytes;
+
+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;
+
+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),
+    }
+}
+
+// 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]
+// ]
+//
+// (COSE_Sign is an array. The first element is an empty or serialized map (in our case, it is
+// never expected to be empty). The second element is a map (it is expected to be empty. The third
+// element is a bstr or nil (it is expected to be nil). The fourth element is an array of
+// COSE_Signature.)
+//
+// COSE_Signature =  [
+//     Headers,
+//     signature : bstr
+// ]
+//
+// but again, unpacking this:
+//
+// COSE_Signature =  [
+//     protected : empty_or_serialized_map,
+//     unprotected : header_map
+//     signature : bstr
+// ]
+fn decode_signature_struct(
+    cose_signature: &CborType,
+    payload: &[u8],
+    protected_body_head: &CborType,
+) -> Result<CoseSignature, CoseError> {
+    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) {
+        Err(_) => return Err(CoseError::DecodingFailure),
+        Ok(value) => value,
+    };
+    let signature_algorithm = get_map_value(&protected_signature_header, &CborType::Integer(1))?;
+    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 = unpack!(Bytes, ee_cert).clone();
+
+    // 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) {
+        Ok(value) => value,
+        Err(_) => return Err(CoseError::DecodingFailure),
+    };
+    let intermediate_certs_array = &get_map_value(&protected_body_head_map, &CborType::Integer(4))?;
+    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 {
+        signature_type: signature_algorithm,
+        signature: signature_bytes,
+        signer_cert: ee_cert,
+        certs: certs,
+        to_verify: sig_structure_bytes,
+    })
+}
+
+/// Decode COSE signature bytes and return a vector of `CoseSignature`.
+///
+///```rust,ignore
+/// COSE_Sign = [
+///     Headers,
+///     payload : bstr / nil,
+///     signatures : [+ COSE_Signature]
+/// ]
+///
+/// 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) {
+        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);
+            }
+            match *cose_sign {
+                CborType::Array(values) => values,
+                _ => return Err(CoseError::UnexpectedType),
+            }
+        }
+        _ => return Err(CoseError::UnexpectedType),
+    };
+    if cose_sign_array.len() != 4 {
+        return Err(CoseError::MalformedInput);
+    }
+    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.
+        let signature = decode_signature_struct(cose_signature, payload, &cose_sign_array[0])?;
+        result.push(signature);
+    }
+
+    Ok(result)
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/src/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 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/src/test_cose.rs
@@ -0,0 +1,230 @@
+use test_setup as test;
+use util_test::{sign, verify_signature};
+use {CoseError, SignatureAlgorithm, SignatureParameters};
+use std::str::FromStr;
+use decoder::decode_signature;
+
+#[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.
+
+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,
+};
+
+#[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();
+
+    // Verify signature.
+    assert!(verify_signature(payload, cose_signature).is_ok());
+}
+
+#[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();
+
+    // 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));
+}
+
+#[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();
+
+    // 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.
+#[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();
+
+    // 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_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);
+
+    // 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_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);
+}
+
+#[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);
+}
+
+#[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);
+}
+
+#[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);
+}
+
+#[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);
+}
+
+#[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);
+}
+
+#[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);
+}
+
+#[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);
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/src/test_nss.rs
@@ -0,0 +1,68 @@
+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));
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/src/test_setup.rs
@@ -0,0 +1,646 @@
+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 COSE_SIGNATURE_BYTES: [u8; 1062] = [
+    0xd8, 0x62, 0x84, 0x59, 0x02, 0xa3, 0xa1, 0x04, 0x82, 0x59, 0x01, 0x4e,
+    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, 0x59, 0x01,
+    0x4c, 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, 0xa0, 0xf6, 0x81,
+    0x83, 0x59, 0x01, 0x33, 0xa2, 0x01, 0x26, 0x04, 0x59, 0x01, 0x2c, 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, 0xa0,
+    0x58, 0x40, 0x11, 0xe5, 0x73, 0x2c, 0x23, 0x31, 0x6f, 0xb4, 0x17, 0xcf,
+    0xa9, 0xee, 0xc5, 0xe3, 0x57, 0xcc, 0x77, 0x82, 0x29, 0x1f, 0xba, 0x97,
+    0xbf, 0x32, 0xaf, 0x8d, 0x88, 0x27, 0xde, 0x69, 0xd2, 0xdf, 0xd6, 0xec,
+    0x9e, 0x5b, 0xd3, 0x9d, 0xf8, 0x9d, 0x68, 0xc6, 0xce, 0x91, 0x32, 0x41,
+    0x50, 0x5f, 0xd8, 0x72, 0xb0, 0x41, 0xb9, 0x39, 0x3d, 0xdf, 0x44, 0xee,
+    0x89, 0x74, 0x4d, 0x9e, 0xb4, 0xd7
+];
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub const SIGNATURE_BYTES: [u8; 64] = [
+    0x11, 0xe5, 0x73, 0x2c, 0x23, 0x31, 0x6f, 0xb4, 0x17, 0xcf,
+    0xa9, 0xee, 0xc5, 0xe3, 0x57, 0xcc, 0x77, 0x82, 0x29, 0x1f, 0xba, 0x97,
+    0xbf, 0x32, 0xaf, 0x8d, 0x88, 0x27, 0xde, 0x69, 0xd2, 0xdf, 0xd6, 0xec,
+    0x9e, 0x5b, 0xd3, 0x9d, 0xf8, 0x9d, 0x68, 0xc6, 0xce, 0x91, 0x32, 0x41,
+    0x50, 0x5f, 0xd8, 0x72, 0xb0, 0x41, 0xb9, 0x39, 0x3d, 0xdf, 0x44, 0xee,
+    0x89, 0x74, 0x4d, 0x9e, 0xb4, 0xd7
+];
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/src/util.rs
@@ -0,0 +1,27 @@
+use cbor::CborType;
+
+// Sig_structure is a CBOR array:
+//
+// Sig_structure = [
+//   context : "Signature" / "Signature1" / "CounterSignature",
+//   body_protected : empty_or_serialized_map,
+//   ? sign_protected : empty_or_serialized_map,
+//   external_aad : bstr,
+//   payload : bstr
+// ]
+//
+// In this case, the context is "Signature". There is no external_aad, so this defaults to a
+// zero-length bstr.
+pub fn get_sig_struct_bytes(
+    protected_body_header_serialized: CborType,
+    protected_signature_header_serialized: CborType,
+    payload: &[u8],
+) -> Vec<u8> {
+    let sig_structure_array: Vec<CborType> = vec![CborType::String(String::from("Signature")),
+                                                  protected_body_header_serialized,
+                                                  protected_signature_header_serialized,
+                                                  CborType::Bytes(Vec::new()),
+                                                  CborType::Bytes(payload.to_vec())];
+
+    CborType::Array(sig_structure_array).serialize()
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/src/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 util::get_sig_struct_bytes;
+use decoder::decode_signature;
+use 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(())
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/tools/certs/certs.md
@@ -0,0 +1,9 @@
+## This folder holds everything to generate certificates and keys for tests
+
+Scripts in this folder require a copy of [mozilla-central](https://hg.mozilla.org/mozilla-central/) and use scripts from `security/manager/ssl/tests/unit`. The default path for `MOZILLA_CENTRAL` is next to the root of this project.
+
+The helper script `certs.sh` sets all necessary paths and generates certificates.
+The following command generates the end-entity certificate with P256, ECDSA, SHA256.
+
+    MOZILLA_CENTRAL=<path to mc> ./certs.sh < ee-p256.certspec
+
new file mode 100755
--- /dev/null
+++ b/third_party/rust/cose/tools/certs/certs.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+cwd=$(cd $(dirname $0); pwd -P)
+MOZILLA_CENTRAL=${MOZILLA_CENTRAL:-"$cwd/../../../mc"}
+script_path="$MOZILLA_CENTRAL/security/manager/ssl/tests/unit"
+
+python_path="$MOZILLA_CENTRAL/third_party/python/pyasn1/"
+python_path="$python_path:$MOZILLA_CENTRAL/third_party/python/pyasn1-modules/"
+python_path="$python_path:$MOZILLA_CENTRAL/third_party/python/PyECC/"
+python_path="$python_path:$MOZILLA_CENTRAL/third_party/python/mock-1.0.0/"
+python_path="$python_path:$MOZILLA_CENTRAL/third_party/python/rsa/"
+
+gen_cert() {
+    PYTHONPATH=$python_path "$script_path"/pycert.py "$@" > /tmp/cert.pem
+    openssl x509 -in /tmp/cert.pem -out /tmp/cert.der -outform DER
+    xxd -ps /tmp/cert.der | sed 's/\([0-9A-Fa-f]\{2\}\)/0x\1, /g' \
+                          | tr -d '\n'
+    echo ""
+}
+
+gen_cert "${@:1}"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/tools/certs/ee-p256.certspec
@@ -0,0 +1,6 @@
+issuer:int-p256
+subject:ee-p256
+issuerKey:secp256r1
+subjectKey:secp256r1
+signature:ecdsaWithSHA256
+validity:3650
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/tools/certs/ee-p256.keyspec
@@ -0,0 +1,1 @@
+secp256r1
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/tools/certs/ee-p384.certspec
@@ -0,0 +1,6 @@
+issuer:int-p256
+subject:ee-p384
+issuerKey:secp256r1
+subjectKey:secp384r1
+signature:ecdsaWithSHA256
+validity:3650
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/tools/certs/ee-p521.certspec
@@ -0,0 +1,6 @@
+issuer:int-p256
+subject:ee-p521
+issuerKey:secp256r1
+subjectKey:secp521r1
+signature:ecdsaWithSHA256
+validity:3650
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/tools/certs/ee-rsa.certspec
@@ -0,0 +1,3 @@
+issuer:int-rsa
+subject:ee-rsa
+validity:3650
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/tools/certs/int-p256.certspec
@@ -0,0 +1,8 @@
+issuer:root-p256
+subject:int-p256
+issuerKey:secp256k1
+subjectKey:secp256r1
+signature:ecdsaWithSHA256
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
+validity:3650
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/tools/certs/int-rsa.certspec
@@ -0,0 +1,5 @@
+issuer:root-rsa
+subject:int-rsa
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
+validity:3650
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/tools/certs/root-p256.certspec
@@ -0,0 +1,8 @@
+issuer:root-p256
+subject:root-p256
+issuerKey:secp256r1
+subjectKey:secp256r1
+signature:ecdsaWithSHA256
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
+validity:3650
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/cose/tools/certs/root-rsa.certspec
@@ -0,0 +1,5 @@
+issuer:root-rsa
+subject:root-rsa
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
+validity:3650
--- a/toolkit/library/gtest/rust/Cargo.lock
+++ b/toolkit/library/gtest/rust/Cargo.lock
@@ -263,16 +263,29 @@ source = "registry+https://github.com/ru
 dependencies = [
  "core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "cose"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cose-c"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cose 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "cssparser"
 version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -549,16 +562,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "gkrust-shared"
 version = "0.1.0"
 dependencies = [
  "audioipc-client 0.1.0",
  "audioipc-server 0.1.0",
+ "cose-c 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cubeb 0.3.0",
  "cubeb-backend 0.2.0",
  "cubeb-core 0.1.0",
  "cubeb-pulse 0.0.1",
  "encoding_c 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding_glue 0.1.0",
  "geckoservo 0.0.1",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1596,16 +1610,18 @@ dependencies = [
 "checksum clang-sys 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5955eab05fa8e6ff2b353753dc73a0608daa36e472a21c69f2eb51f43f593544"
 "checksum clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "867a885995b4184be051b70a592d4d70e32d7a188db6e8dff626af286a962771"
 "checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
 "checksum core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5909502e547762013619f4c4e01cc7393c20fe2d52d7fa471c1210adb2320dc7"
 "checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
 "checksum core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bc9fb3d6cb663e6fd7cf1c63f9b144ee2b1e4a78595a0451dd34bff85b9a3387"
 "checksum core-graphics 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5dc0a78ab2ac23b6ea7b3fe5fe93b227900dc0956979735b8f68032417976dd4"
 "checksum core-text 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bcad23756dd1dc4b47bf6a914ace27aadb8fa68889db5837af2308d018d0467c"
+"checksum cose 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ec10816629f38fa557f08e199a3474fab954f4c8d2645550367235afa6e5646b"
+"checksum cose-c 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07cc8bb85ec2e93541ef9369b85a4b6fb7732bc7f4854d317eab20e726b0fc2f"
 "checksum cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44313341610282488e1156ad1fedebca51c54766c87a041d0287b10499c04ba1"
 "checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
 "checksum darling 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9861a8495606435477df581bc858ccf15a3469747edf175b94a4704fd9aaedac"
 "checksum darling_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1486a8b00b45062c997f767738178b43219133dd0c8c826cb811e60563810821"
 "checksum darling_macro 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a86ec160aa0c3dd492dd4a14ec8104ad8f1a9400a820624db857998cc1f80f9"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "068d4026697c1a18f0b0bb8cfcad1b0c151b90d8edb9bf4c235ad68128920d1d"
 "checksum dwrote 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "36e3b27cd0b8a68e00f07e8d8e1e4f4d8a6b8b873290a734f63bd56d792d23e1"
--- a/toolkit/library/rust/Cargo.lock
+++ b/toolkit/library/rust/Cargo.lock
@@ -263,16 +263,29 @@ source = "registry+https://github.com/ru
 dependencies = [
  "core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "cose"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cose-c"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cose 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "cssparser"
 version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -548,16 +561,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "gkrust-shared"
 version = "0.1.0"
 dependencies = [
  "audioipc-client 0.1.0",
  "audioipc-server 0.1.0",
+ "cose-c 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cubeb 0.3.0",
  "cubeb-backend 0.2.0",
  "cubeb-core 0.1.0",
  "cubeb-pulse 0.0.1",
  "encoding_c 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding_glue 0.1.0",
  "geckoservo 0.0.1",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1608,16 +1622,18 @@ dependencies = [
 "checksum clang-sys 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5955eab05fa8e6ff2b353753dc73a0608daa36e472a21c69f2eb51f43f593544"
 "checksum clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "867a885995b4184be051b70a592d4d70e32d7a188db6e8dff626af286a962771"
 "checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
 "checksum core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5909502e547762013619f4c4e01cc7393c20fe2d52d7fa471c1210adb2320dc7"
 "checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
 "checksum core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bc9fb3d6cb663e6fd7cf1c63f9b144ee2b1e4a78595a0451dd34bff85b9a3387"
 "checksum core-graphics 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5dc0a78ab2ac23b6ea7b3fe5fe93b227900dc0956979735b8f68032417976dd4"
 "checksum core-text 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bcad23756dd1dc4b47bf6a914ace27aadb8fa68889db5837af2308d018d0467c"
+"checksum cose 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ec10816629f38fa557f08e199a3474fab954f4c8d2645550367235afa6e5646b"
+"checksum cose-c 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07cc8bb85ec2e93541ef9369b85a4b6fb7732bc7f4854d317eab20e726b0fc2f"
 "checksum cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44313341610282488e1156ad1fedebca51c54766c87a041d0287b10499c04ba1"
 "checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
 "checksum darling 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9861a8495606435477df581bc858ccf15a3469747edf175b94a4704fd9aaedac"
 "checksum darling_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1486a8b00b45062c997f767738178b43219133dd0c8c826cb811e60563810821"
 "checksum darling_macro 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a86ec160aa0c3dd492dd4a14ec8104ad8f1a9400a820624db857998cc1f80f9"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "068d4026697c1a18f0b0bb8cfcad1b0c151b90d8edb9bf4c235ad68128920d1d"
 "checksum dwrote 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "36e3b27cd0b8a68e00f07e8d8e1e4f4d8a6b8b873290a734f63bd56d792d23e1"
--- a/toolkit/library/rust/shared/Cargo.toml
+++ b/toolkit/library/rust/shared/Cargo.toml
@@ -20,16 +20,17 @@ cubeb-backend = { path = "../../../../me
 encoding_c = "0.8.0"
 encoding_glue = { path = "../../../../intl/encoding_glue" }
 audioipc-client = { path = "../../../../media/audioipc/client", optional = true }
 audioipc-server = { path = "../../../../media/audioipc/server", optional = true }
 u2fhid = { path = "../../../../dom/webauthn/u2f-hid-rs" }
 # We have these to enforce common feature sets for said crates.
 log = {version = "0.3", features = ["release_max_level_info"]}
 syn = { version = "0.11", features = ["full", "visit", "parsing"] }
+cose-c = { version = "0.1.1" }
 
 [features]
 default = []
 bindgen = ["geckoservo/bindgen"]
 servo = ["geckoservo"]
 quantum_render = ["webrender_bindings"]
 cubeb-remoting = ["cubeb-core", "cubeb", "cubeb-backend", "audioipc-client", "audioipc-server"]
 cubeb_pulse_rust = ["cubeb-pulse"]
--- a/toolkit/library/rust/shared/lib.rs
+++ b/toolkit/library/rust/shared/lib.rs
@@ -18,16 +18,17 @@ extern crate encoding_c;
 extern crate encoding_glue;
 #[cfg(feature = "cubeb-remoting")]
 extern crate audioipc_client;
 #[cfg(feature = "cubeb-remoting")]
 extern crate audioipc_server;
 extern crate u2fhid;
 extern crate log;
 extern crate syn;
+extern crate cosec;
 
 use std::boxed::Box;
 use std::ffi::CStr;
 use std::os::raw::c_char;
 use std::panic;