Snap for 5234541 from 8829ced538f854607988056c67906568319bfe38 to sdk-release

Change-Id: Ibfe03d44534bc799dfdf43e2e9424312005711c7
diff --git a/BUILD b/BUILD
index aac392c..7aae4d5 100644
--- a/BUILD
+++ b/BUILD
@@ -17,11 +17,13 @@
         "src/runtests.cc",
         "src/weaver_tests.cc",
         "src/avb_tests.cc",
+        "src/transport_tests.cc",
     ],
     copts = COPTS,
     deps = [
         ":dcrypto_test_data",
         ":km_test_lib",
+        ":reset_key_data_lib",
         ":util",
         "@boringssl//:ssl",
         "@com_github_gflags_gflags//:gflags",
@@ -81,7 +83,6 @@
         "src/util.cc",
     ],
     hdrs = [
-        "src/blob.h",
         "src/macros.h",
         "src/util.h",
     ],
@@ -96,6 +97,16 @@
 )
 
 cc_library(
+    name = "reset_key_data_lib",
+    srcs = [
+        "src/test-data/test-keys/reset_key_data.cc",
+    ],
+    hdrs = [
+        "src/test-data/test-keys/reset_key_data.h",
+    ],
+)
+
+cc_library(
     name = "km_test_lib",
     srcs = [
         "src/test-data/test-keys/rsa.cc",
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..39b2298
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,6 @@
+# Default owners are top 3 or more active developers of the past 1 or 2 years
+# or people with more than 10 commits last year.
+# Please update this list if you find better owner candidates.
+ascull@google.com
+ngm@google.com
+wfrichar@google.com
diff --git a/scripts/release-tests.sh b/scripts/release-tests.sh
index b14ab75..155e9ac 100755
--- a/scripts/release-tests.sh
+++ b/scripts/release-tests.sh
@@ -1,13 +1,15 @@
 #!/bin/bash
 set -e
 
+source build/envsetup.sh
+
 function integration_tests() {
     m -j citadel_integration_tests || return 1
     adb shell stop || return 1
     adb sync || return 1
     adb shell start || return 1
-    adb exec-out \
-        '/vendor/bin/hw/citadel_integration_tests --release-tests' || return 1
+    adb shell \
+        /vendor/bin/hw/citadel_integration_tests --release-tests || return 1
 }
 
 # TODO: add AVB / Weaver / Keymaster VTS / CTS tests with filters here.
@@ -21,7 +23,14 @@
 }
 
 function keymaster_vts_tests() {
-    return 0
+    m -j VtsHalKeymasterV4_0TargetTest || return 1
+    adb sync data || return 1
+    # TODO(b/109771020): remove test filter below.
+    adb shell \
+        /data/nativetest64/VtsHalKeymasterV4_0TargetTest/VtsHalKeymasterV4_0TargetTest \
+        --verbose \
+        --hal_service_instance=android.hardware.keymaster@4.0::IKeymasterDevice/strongbox \
+        --gtest_filter=-EncryptionOperationsTest.RsaNoPaddingShortMessage || return 1
 }
 
 function weaver_cts_tests() {
@@ -40,10 +49,8 @@
 }
 
 function pay_cts_tests() {
-  :
-    # TODO(ngm): uncomment once these are working.
-    # runtest --path \
-    #     cts/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java || return 1
+    runtest --path \
+            cts/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java || return 1
 }
 
 # TODO: add any other tests
@@ -53,18 +60,25 @@
   exit 1
 fi
 
-for t in integration_tests \
-	     oem_lock_vts_tests \
-	     keymaster_cts_tests \
-	     keymaster_vts_tests \
-	     weaver_cts_tests \
-	     weaver_vts_tests \
-             auth_secret_vts_tests \
-             pay_cts_tests; do
+adb root && adb remount
+
+# keymaster tests need to run before integration tests, which mess
+# with factory reset, and break keymaster on-boot info.
+for t in \
+             keymaster_vts_tests \
+             keymaster_cts_tests \
+             pay_cts_tests \
+             integration_tests \
+             oem_lock_vts_tests \
+             weaver_cts_tests \
+             weaver_vts_tests \
+             auth_secret_vts_tests; do
     if eval "${t}"; then
-	echo "PASS: ${t}"
+        echo "PASS: ${t}"
     else
-	echo "FAIL: ${t}"
-	exit 1
+        echo "FAIL: ${t}"
+        exit 1
     fi
 done
+
+# TODO: factory reset the device to original state.
diff --git a/src/avb_tests.cc b/src/avb_tests.cc
index 32ff5ef..f6e3161 100644
--- a/src/avb_tests.cc
+++ b/src/avb_tests.cc
@@ -5,6 +5,7 @@
 #include "nugget_tools.h"
 #include "nugget/app/avb/avb.pb.h"
 #include "Avb.client.h"
+#include "src/test-data/test-keys/reset_key_data.h"
 #include <avb.h>
 #include <application.h>
 #include <nos/AppClient.h>
@@ -139,38 +140,10 @@
   EXPECT_EQ(locks[OWNER], 0x00);
 }
 
-static const uint8_t kResetKeyPem[] =
-"-----BEGIN RSA PRIVATE KEY-----\n\
-MIIEpAIBAAKCAQEAo0IoAa5cK7XyAj7u1jFStsfEcxkgAZVF9VWKzH1bofKxLioA\n\
-r5Lo4D33glKehxkOlDo6GkBj1PoI8WuvYYvEUyxJNUdlVpa1C2lbewEL0rfyBrZ9\n\
-4cp0ZeUknymYHn3ynW4Z8sYMlj7BNxGttV/jbxtgtT5WHJ+hg5/4/ifCPucN17Bt\n\
-heUKIBoAjy6DlB/pMg1NUQ82DaASMFe89mEzI9Zk4CRtkWjEhknY0bYm46U1ABJb\n\
-YmIsHlxdADskvWFDmq8CfJr/jXstTXxZeqaxPPdSP+WPwXN/ku5W7qkF2qimEKiy\n\
-DYHzY65JhfWmHOLLGNuz6iHkq93uzkKsGIIPGQIDAQABAoIBABGTvdrwetv56uRz\n\
-AiPti4pCV9RMkDWbbLzNSPRbStJU3t6phwlgN9Js2YkefBLvj7JF0pug8x6rDOtx\n\
-PKCz+5841Wj3FuILt9JStZa4th0p0NUIMOVudrnBwf+g6s/dn5FzmTeaOyCyAPt8\n\
-28b7W/FKcU8SNxM93JXfU1+JyFAdREqsXQfqLhCAXBb46fs5D8hg0c99RdWuJSuY\n\
-HKyVXDrjmYAHS5qUDeMx0OY/q1qM03FBvHekvJ78WPpUKF7B/gYH9lBHIHE0KLJY\n\
-JR6kKkzN/Ii6BsSubKKeuNntzlzd2ukvFdX4uc42dDpIXPdaQAn84KRYN7++KoGz\n\
-2LqtAAECgYEAzQt5kt9c+xDeKMPR92XQ4uMeLxTufBei1PFGZbJnJT8aEMkVhKT/\n\
-Pbh1Z8OnN9YvFprDNpEilUm7xyffrE7p0pI1/qiBXZExy6pIcGAo4ZcB8ayN0JV3\n\
-k+RilE73x+sKAyWOm82b273PiyHNsQI4flkO5Ev9rpZbPMKlvZYsmxkCgYEAy9RR\n\
-RwxwCpvFi3um0Rwz7CI2uvVXGaLVXyR2oNGLcJG7AhusYi4FX6XJQ3vAgiDmzu/c\n\
-SaEF9w7uqeueIUA7L7njYP1ojfJAUJEtQRfVJF2tDntN5YgYUTsx8n3IKTs4xFT4\n\
-dBthKo16zzLv92+8m4sWJhFW2zzFFLwk+G5jlAECgYEAln1piSZus8Y5h2nRXOZZ\n\
-XWyb5qpSLrmaRPegV1uM4IVjuBYduPDwdHhBkxrCS/TjMo/73ry+yRsIuq7FN03j\n\
-xyyQfItoByhdh8E+0VuCJbATOTEQFJre3KiuwXMD4LLc8lpKRIevcKPrA46XzOZ4\n\
-WCM9DsnHMrAf3oRt6KujqWECgYEAyu43fWUEp4suwg/5pXdOumnV040vinZzuKW0\n\
-9aeqDAkLBq5Gkfj/oJqOJoGux9+5640i5KtMJQzY0JOke7ZXNsz7dDTXQ3tMTOo9\n\
-A/GWYv5grWpVw5AbpcQpliNkhKhRfCactfwMYTE6c89i2haE0NdI1d2te9ik3l/y\n\
-7uP4gAECgYA3u2CumlkjHq+LbMK6Ry+Ajyy4ssM5PKJUqSogJDUkHsG/C7yaCdq/\n\
-Ljt2x2220H0pM9885C3PpKxoYwRih9dzOamnARJocAElp2b5AQB+tKddlMdwx1pQ\n\
-0IMGQ3fBYkDFLGYDk7hGYkLLlSJCZwi64xKmmfEwl83RL6JDSFupDg==\n\
------END RSA PRIVATE KEY-----";
-
-static RSA *GetResetKey()
+RSA *GetResetKey()
 {
-  BIO *bio = BIO_new_mem_buf((void*)kResetKeyPem, sizeof(kResetKeyPem) - 1);
+  BIO *bio = BIO_new_mem_buf((void*)test_data::kResetKeyPem,
+                              test_data::kResetKeyPemSize - 1);
   RSA *rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, 0, NULL);
   BIO_free(bio);
   return rsa;
@@ -747,7 +720,7 @@
   ASSERT_LE(sizeof(data), len);
   ASSERT_NO_ERROR(code, "");
   EXPECT_NE(0ULL, nonce);
-  EXPECT_EQ((uint32_t)ResetToken::CURRENT, selector);
+  EXPECT_LE(selector, (uint32_t)ResetToken::CURRENT);
   EXPECT_EQ(32UL, len);
   // We didn't set a device id.
   EXPECT_EQ(0, memcmp(data, empty, sizeof(empty)));
@@ -805,33 +778,6 @@
   ASSERT_NO_ERROR(code, "");
 }
 
-static const uint8_t kNullSig[] = {
-  0x95, 0x35, 0x5a, 0xb6, 0xe3, 0x8e, 0x43, 0x03, 0xd9, 0xd9, 0xd5, 0x6e,
-  0x99, 0x86, 0xff, 0x8e, 0x6a, 0xf1, 0x54, 0x6f, 0xa8, 0xff, 0x37, 0x38,
-  0xc6, 0x9b, 0x4d, 0xc6, 0x99, 0x1f, 0x37, 0x5c, 0xec, 0xf4, 0x32, 0xd8,
-  0xe6, 0x00, 0xcc, 0x74, 0xde, 0xa9, 0x68, 0x1a, 0xab, 0x6a, 0x6e, 0xe7,
-  0xa7, 0xa1, 0x59, 0xe0, 0x7c, 0x86, 0x95, 0x28, 0x94, 0x18, 0x3f, 0x0f,
-  0xb9, 0x0f, 0x05, 0x6c, 0x86, 0x5a, 0x6a, 0xe4, 0x6d, 0x36, 0x71, 0x86,
-  0x38, 0xab, 0x7a, 0x2d, 0x9c, 0xa5, 0xfa, 0xc8, 0x7c, 0x48, 0x02, 0x8c,
-  0x6b, 0x4d, 0xda, 0xa4, 0xb5, 0xa8, 0x17, 0x39, 0x5e, 0xe3, 0x1a, 0xd5,
-  0xf8, 0x87, 0x6e, 0xd9, 0xc0, 0x0c, 0x29, 0x4d, 0x93, 0xa2, 0x3b, 0xfc,
-  0x2d, 0x38, 0x8e, 0x2b, 0xc7, 0x49, 0x26, 0xd9, 0xcb, 0x47, 0x89, 0x4c,
-  0x79, 0xd3, 0x60, 0x62, 0xf9, 0x71, 0xa7, 0x73, 0x6a, 0x03, 0x65, 0x1f,
-  0x11, 0x0d, 0x9e, 0x27, 0x99, 0x6b, 0xa7, 0x46, 0x85, 0x75, 0xec, 0xff,
-  0x5b, 0x1d, 0x8d, 0x1b, 0x34, 0xd8, 0xb9, 0x4f, 0x63, 0x88, 0x08, 0xa8,
-  0x16, 0xba, 0xfc, 0xe7, 0x66, 0xa4, 0xe5, 0xde, 0x4e, 0x0b, 0x98, 0x80,
-  0xd5, 0x16, 0x55, 0xfb, 0xdb, 0xe8, 0xa2, 0x90, 0x85, 0x4e, 0xa9, 0xb6,
-  0x81, 0x55, 0xef, 0xbf, 0x12, 0xe3, 0xd2, 0xa9, 0xae, 0x2c, 0x43, 0x67,
-  0x4c, 0x09, 0x6d, 0x95, 0xaf, 0x44, 0xc2, 0xb9, 0x9d, 0x7c, 0xb1, 0x88,
-  0xf8, 0x6c, 0xa0, 0x13, 0x4c, 0xbf, 0x85, 0xa2, 0x8b, 0x9d, 0x06, 0xc8,
-  0x11, 0xdb, 0x1f, 0xfb, 0x05, 0x15, 0xd6, 0x1f, 0xe5, 0x52, 0x9c, 0xd5,
-  0xbd, 0xff, 0xb0, 0xce, 0x29, 0xec, 0xd8, 0x9e, 0xdb, 0x5b, 0xc9, 0x52,
-  0x24, 0xaf, 0x22, 0xeb, 0xce, 0x15, 0x0d, 0xfd, 0x6c, 0x76, 0x90, 0x3e,
-  0x4f, 0x63, 0xfd, 0xb1
-};
-
-const static unsigned int kNullSigLen = 256;
-
 TEST_F(AvbTest, ProductionResetTestValid)
 {
   static const uint8_t kDeviceHash[] = {
@@ -876,7 +822,8 @@
   message.nonce = 0;
   memset(message.data, 0, sizeof(message.data));
   code = ProductionResetTest(selector, message.nonce, message.data, len,
-                             kNullSig, kNullSigLen);
+                             test_data::kResetSignatures[selector],
+                             test_data::kResetSignatureLengths[selector]);
   ASSERT_NO_ERROR(code, "");
 }
 
@@ -889,4 +836,29 @@
   EXPECT_EQ(locks[DEVICE], 0x00);
 }
 
+TEST_F(AvbTest, ResetKeyNullTokenSignatureTest)
+{
+  struct ResetMessage message;
+  int code;
+
+  uint32_t selector;
+  uint64_t nonce;
+  uint8_t device_data[AVB_DEVICE_DATA_SIZE];
+  size_t len = sizeof(device_data);
+
+  // Get the selector
+  code = GetResetChallenge(client.get(), &selector, &nonce,
+                           device_data, &len);
+  ASSERT_NO_ERROR(code, "");
+  ASSERT_LT(selector, test_data::kResetSignatureCount);
+
+  memset(&message, 0, sizeof(message));
+  // Now use a good one, but without getting a new nonce.
+  cout << "Testing key: " << selector << "\n";
+  code = ProductionResetTest(selector, message.nonce, message.data, 32,
+                             test_data::kResetSignatures[selector],
+                             test_data::kResetSignatureLengths[selector]);
+  ASSERT_NO_ERROR(code, "");
+}
+
 }  // namespace
diff --git a/src/blob.h b/src/blob.h
deleted file mode 100644
index 4a88b45..0000000
--- a/src/blob.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef SRC_BLOB_H
-#define SRC_BLOB_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-struct LITE_BIGNUM {
-	uint32_t dmax;              /* Size of d, in 32-bit words. */
-	uint32_t d;  /* Word array, little endian format ... */
-} __attribute__((packed));
-
-struct LITE_RSA {
-	uint32_t e;
-	struct LITE_BIGNUM N;
-	struct LITE_BIGNUM d;
-} __attribute__((packed));
-
-/* TODO: maybe use protos? */
-struct blob_params {
-	uint32_t tag;
-	uint32_t integer;
-	uint64_t long_integer;
-	/* TODO: save space for opaque data (APP_DATA etc). */
-} __attribute__((packed));
-
-struct blob_enforcements {
-	uint32_t params_count;
-	/* TODO: sizeof(proto-params) instead of constant here. */
-	struct blob_params params[20];
-} __attribute__((packed));
-
-/* TODO: refactor RSA_MAX_BYTES from dcrypto.h */
-struct blob_rsa {
-	struct	LITE_RSA rsa;
-	uint8_t N_bytes[3072 >> 3];
-	uint8_t d_bytes[3072 >> 3];
-} __attribute__((packed));
-
-struct blob_ec {
-	uint32_t curve;
-	uint8_t d[32];
-	uint8_t x[32];
-	uint8_t y[32];
-} __attribute__((packed));
-
-struct blob_sym {
-	uint32_t key_bits;
-	uint8_t bytes[512 >> 3];
-} __attribute__((packed));
-
-enum blob_alg {
-	BLOB_RSA = 1,
-	BLOB_EC = 2,
-	BLOB_AES = 3,
-	BLOB_DES = 4,
-	BLOB_HMAC = 5,
-};
-
-#define KM_BLOB_MAGIC	0x474F4F47
-#define KM_BLOB_VERSION 1
-
-struct km_blob {
-	struct {
-		uint32_t magic;
-		uint32_t version;
-		uint32_t id;
-		uint32_t iv[4];
-	} h __attribute__((packed));
-	struct {
-		/* TODO: is sw_enforced expected to be managed by h/w? */
-		struct blob_enforcements sw_enforced;
-		struct blob_enforcements tee_enforced;
-		uint32_t algorithm;
-		union {
-			struct blob_rsa rsa;
-			struct blob_ec	ec;
-			struct blob_sym sym;
-		} key;
-		/* TODO: pad to block size. */
-	} b __attribute__((packed));
-	uint8_t hmac[32];
-} __attribute__((packed));
-
-#endif	// SRC_BLOB_H
diff --git a/src/cavptests.cc b/src/cavptests.cc
index fc9c9b2..1bbc01f 100644
--- a/src/cavptests.cc
+++ b/src/cavptests.cc
@@ -22,6 +22,8 @@
 using std::stringstream;
 using std::unique_ptr;
 
+using test_harness::TestHarness;
+
 DEFINE_bool(nos_test_dump_protos, false, "Dump binary protobufs to a file.");
 DEFINE_int32(test_input_number, -1, "Run a specific test input.");
 
diff --git a/src/gtest_with_gflags_main.cc b/src/gtest_with_gflags_main.cc
index 3bf7958..fd92102 100644
--- a/src/gtest_with_gflags_main.cc
+++ b/src/gtest_with_gflags_main.cc
@@ -5,6 +5,8 @@
 #include <iostream>
 #include <sstream>
 
+#include "nugget_tools.h"
+
 #ifdef ANDROID
 #define FLAGS_list_slow_tests false
 #define FLAGS_disable_slow_tests false
@@ -68,6 +70,10 @@
       "ImportWrappedKeyTest.ImportSuccess",
   };
 
+  const std::vector<std::string> disabled_for_non_direct_device_tests{
+      "TransportTest.*",
+  };
+
   testing::InitGoogleMock(&argc, argv);
 #ifndef ANDROID
   google::ParseCommandLineFlags(&argc, &argv, true);
@@ -89,6 +95,9 @@
   if (FLAGS_release_tests) {
     generate_disabled_test_list(disabled_for_release_tests, &ss);
   }
+  if (!nugget_tools::IsDirectDeviceClient()) {
+    generate_disabled_test_list(disabled_for_non_direct_device_tests, &ss);
+  }
 
   if (FLAGS_disable_slow_tests || FLAGS_release_tests) {
     ::testing::GTEST_FLAG(filter) = ss.str();
diff --git a/src/keymaster-import-key-tests.cc b/src/keymaster-import-key-tests.cc
index 0392de7..4e2e531 100644
--- a/src/keymaster-import-key-tests.cc
+++ b/src/keymaster-import-key-tests.cc
@@ -8,7 +8,6 @@
 #include "Keymaster.client.h"
 #include "util.h"
 
-#include "src/blob.h"
 #include "src/macros.h"
 #include "src/test-data/test-keys/rsa.h"
 
@@ -94,6 +93,7 @@
 
   // Do setup that is normally done by the bootloader.
   keymaster_tools::SetRootOfTrust(client.get());
+  keymaster_tools::SetBootState(client.get());
 }
 
 void ImportKeyTest::TearDownTestCase() {
@@ -142,7 +142,7 @@
   ImportKeyResponse response;
 
   // Unsupported exponent
-  initRSARequest(&request, Algorithm::RSA, 512, 2, 2,
+  initRSARequest(&request, Algorithm::RSA, 1024, 2, 2,
                  string(64, '\0'), string(64, '\0'));
 
   ASSERT_NO_ERROR(service->ImportKey(request, &response), "");
@@ -155,7 +155,7 @@
   ImportKeyResponse response;
 
   // N does not match KEY_SIZE.
-  initRSARequest(&request, Algorithm::RSA, 512, 3, 3,
+  initRSARequest(&request, Algorithm::RSA, 1024, 3, 3,
                  string(64, '\0'), string(63, '\0'));
   ASSERT_NO_ERROR(service->ImportKey(request, &response), "");
   EXPECT_EQ((ErrorCode)response.error_code(),
@@ -167,7 +167,7 @@
   ImportKeyResponse response;
 
   // D does not match KEY_SIZE.
-  initRSARequest(&request, Algorithm::RSA, 512, 3, 3,
+  initRSARequest(&request, Algorithm::RSA, 1024, 3, 3,
                  string(63, '\0'), string(64, '\0'));
   ASSERT_NO_ERROR(service->ImportKey(request, &response), "");
   EXPECT_EQ((ErrorCode)response.error_code(),
@@ -179,7 +179,7 @@
   ImportKeyResponse response;
 
   // e does not match PUBLIC_EXPONENT tag.
-  initRSARequest(&request, Algorithm::RSA, 512, 3, 2,
+  initRSARequest(&request, Algorithm::RSA, 1024, 3, 2,
                  string(64, '\0'), string(64, '\0'));
   ASSERT_NO_ERROR(service->ImportKey(request, &response), "");
   EXPECT_EQ((ErrorCode)response.error_code(),
@@ -246,14 +246,97 @@
     EXPECT_EQ((ErrorCode)response.error_code(), ErrorCode::OK)
         << "Failed at TEST_RSA_KEYS[" << i << "]";
 
-    /* TODO: add separate tests for blobs! */
-    EXPECT_EQ(sizeof(struct km_blob), response.blob().blob().size());
-    const struct km_blob *blob =
-        (const struct km_blob *)response.blob().blob().data();
-    EXPECT_EQ(memcmp(blob->b.key.rsa.N_bytes, TEST_RSA_KEYS[i].n,
-                     TEST_RSA_KEYS[i].size), 0);
-    EXPECT_EQ(memcmp(blob->b.key.rsa.d_bytes,
-                     TEST_RSA_KEYS[i].d, TEST_RSA_KEYS[i].size), 0);
+    /* TODO: do something useful with the imported key */
+  }
+}
+
+TEST_F(ImportKeyTest, UpgradeSuccess) {
+  ImportKeyRequest request;
+  ImportKeyResponse response;
+
+  initRSARequest(&request, Algorithm::RSA);
+  KeyParameters *params = request.mutable_params();
+  KeyParameter *param = params->add_params();
+
+  param->set_tag(Tag::RSA_PUBLIC_EXPONENT);
+  param->set_long_integer(TEST_RSA_KEYS[0].e);
+
+  request.mutable_rsa()->set_e(TEST_RSA_KEYS[0].e);
+  request.mutable_rsa()->set_d(TEST_RSA_KEYS[0].d, TEST_RSA_KEYS[0].size);
+  request.mutable_rsa()->set_n(TEST_RSA_KEYS[0].n, TEST_RSA_KEYS[0].size);
+
+  {
+    EXPECT_TRUE(nugget_tools::RebootNugget(client.get()))
+        << "Failed to reboot nugget";
+
+    SetSystemVersionInfoRequest svRequest;
+    SetSystemVersionInfoResponse svResponse;
+
+    svRequest.set_system_version(1);
+    svRequest.set_system_security_level(1);
+    svRequest.set_vendor_security_level(1);
+
+    ASSERT_NO_ERROR(service->SetSystemVersionInfo(svRequest, &svResponse), "");
+    EXPECT_EQ((ErrorCode)svResponse.error_code(), ErrorCode::OK);
+
+    // Do setup that is normally done by the bootloader.
+    keymaster_tools::SetRootOfTrust(client.get());
+    keymaster_tools::SetBootState(client.get());
+  }
+
+  stringstream ss;
+  ASSERT_NO_ERROR(service->ImportKey(request, &response), "");
+  EXPECT_EQ((ErrorCode)response.error_code(), ErrorCode::OK)
+    << "Failed at TEST_RSA_KEYS[" << 0 << "]";
+
+  {
+    EXPECT_TRUE(nugget_tools::RebootNugget(client.get()))
+      << "Failed to reboot nugget";
+
+    SetSystemVersionInfoRequest svRequest;
+    SetSystemVersionInfoResponse svResponse;
+
+    /* Bump vendor version level, to force Upgrade. */
+    svRequest.set_system_version(1);
+    svRequest.set_system_security_level(1);
+    svRequest.set_vendor_security_level(2);
+
+    ASSERT_NO_ERROR(service->SetSystemVersionInfo(svRequest, &svResponse), "");
+    EXPECT_EQ((ErrorCode)svResponse.error_code(), ErrorCode::OK);
+
+    // Do setup that is normally done by the bootloader.
+    keymaster_tools::SetRootOfTrust(client.get());
+    keymaster_tools::SetBootState(client.get());
+  }
+
+  {
+    GetKeyCharacteristicsRequest gkRequest;
+    GetKeyCharacteristicsResponse gkResponse;
+
+    gkRequest.mutable_blob()->set_blob(response.blob().blob().data(),
+                                       response.blob().blob().size());
+    ASSERT_NO_ERROR(service->GetKeyCharacteristics(gkRequest, &gkResponse), "");
+    EXPECT_EQ((ErrorCode)gkResponse.error_code(),
+              ErrorCode::KEY_REQUIRES_UPGRADE);
+  }
+
+  {
+    UpgradeKeyRequest ukRequest;
+    UpgradeKeyResponse ukResponse;
+
+    ukRequest.mutable_blob()->set_blob(response.blob().blob().data(),
+                                       response.blob().blob().size());
+    ASSERT_NO_ERROR(service->UpgradeKey(ukRequest, &ukResponse), "");
+    EXPECT_EQ((ErrorCode)ukResponse.error_code(), ErrorCode::OK);
+
+    // GetKeyCharacteristics succeeds after the UpgradeKey().
+    GetKeyCharacteristicsRequest gkRequest;
+    GetKeyCharacteristicsResponse gkResponse;
+
+    gkRequest.mutable_blob()->set_blob(ukResponse.blob().blob().data(),
+                                       ukResponse.blob().blob().size());
+    ASSERT_NO_ERROR(service->GetKeyCharacteristics(gkRequest, &gkResponse), "");
+    EXPECT_EQ((ErrorCode)gkResponse.error_code(), ErrorCode::OK);
   }
 }
 
@@ -268,13 +351,7 @@
   ASSERT_NO_ERROR(service->ImportKey(request, &response), "");
   EXPECT_EQ((ErrorCode)response.error_code(), ErrorCode::OK);
 
-  EXPECT_EQ(sizeof(struct km_blob), response.blob().blob().size());
-  const struct km_blob *blob =
-      (const struct km_blob *)response.blob().blob().data();
-  EXPECT_EQ(memcmp(blob->b.key.rsa.N_bytes, RSA_1024_N,
-                   sizeof(RSA_1024_N)), 0);
-  EXPECT_EQ(memcmp(blob->b.key.rsa.d_bytes,
-                   RSA_1024_D, sizeof(RSA_1024_D)), 0);
+    /* TODO: do something useful with the imported key */
 }
 
 // EC
diff --git a/src/keymaster-import-wrapped-key-tests.cc b/src/keymaster-import-wrapped-key-tests.cc
index 832a5c8..0b6fc4d 100644
--- a/src/keymaster-import-wrapped-key-tests.cc
+++ b/src/keymaster-import-wrapped-key-tests.cc
@@ -8,13 +8,13 @@
 #include "Keymaster.client.h"
 #include "util.h"
 
-#include "src/blob.h"
 #include "src/macros.h"
 #include "src/test-data/test-keys/rsa.h"
 
 #include "openssl/bn.h"
 #include "openssl/ec_key.h"
 #include "openssl/nid.h"
+#include "openssl/sha.h"
 
 using std::cout;
 using std::string;
@@ -51,6 +51,7 @@
 
   // Do setup that is normally done by the bootloader.
   keymaster_tools::SetRootOfTrust(client.get());
+  keymaster_tools::SetBootState(client.get());
 }
 
 void ImportWrappedKeyTest::TearDownTestCase() {
@@ -192,38 +193,58 @@
   0xb6, 0x47, 0x14, 0x43
 };
 
+#if 0
+/* Left here for reference. */
 const uint8_t IMPORTED_KEY[32] = {
   0x8a, 0x28, 0xf1, 0xa8, 0xb8, 0x93, 0x8a, 0x2c, 0x1f, 0x35, 0x72, 0xb0,
   0x4c, 0x48, 0xd5, 0xdf, 0x52, 0x28, 0x1e, 0xe2, 0x11, 0xad, 0x73, 0xf7,
   0x7f, 0x97, 0x04, 0xe6, 0x79, 0x29, 0xff, 0xcf
 };
+#endif
 
 TEST_F(ImportWrappedKeyTest, ImportSuccess) {
+
+  ImportKeyRequest importRequest;
+  ImportKeyResponse importResponse;
+
+  KeyParameters *params = importRequest.mutable_params();
+
+  KeyParameter *param = params->add_params();
+  param->set_tag(Tag::ALGORITHM);
+  param->set_integer((uint32_t)Algorithm::RSA);
+
+  param = params->add_params();
+  param->set_tag(Tag::RSA_PUBLIC_EXPONENT);
+  param->set_long_integer(65537);
+
+  param = params->add_params();
+  param->set_tag(Tag::PURPOSE);
+  param->set_integer((uint32_t)KeyPurpose::WRAP_KEY);
+
+  param = params->add_params();
+  param->set_tag(Tag::PADDING);
+  param->set_integer((uint32_t)PaddingMode::PADDING_RSA_OAEP);
+
+  param = params->add_params();
+  param->set_tag(Tag::KEY_SIZE);
+  param->set_integer(2048);
+
+  importRequest.mutable_rsa()->set_e(65537);
+  importRequest.mutable_rsa()->set_d(
+      string((const char *)wrapping_key_D, sizeof(wrapping_key_D)));
+  importRequest.mutable_rsa()->set_n(
+      string((const char *)wrapping_key_N, sizeof(wrapping_key_N)));
+
+  ASSERT_NO_ERROR(service->ImportKey(importRequest, &importResponse), "");
+  ASSERT_EQ((ErrorCode)importResponse.error_code(), ErrorCode::OK);
+
   ImportWrappedKeyRequest request;
   ImportKeyResponse response;
   const uint8_t masking_key[32] = {};
-  struct km_blob blob;
-
-  /* TODO: do key generation via rpc. */
-  memset(&blob, 0, sizeof(blob));
-  blob.b.algorithm = BLOB_RSA;
-  blob.b.key.rsa.rsa.e = 65537;
-  blob.b.key.rsa.rsa.N.dmax = sizeof(wrapping_key_N) / sizeof(uint32_t);
-  blob.b.key.rsa.rsa.d.dmax = sizeof(wrapping_key_D) / sizeof(uint32_t);
-
-  memcpy(&blob.b.key.rsa.N_bytes, wrapping_key_N, sizeof(wrapping_key_N));
-  memcpy(&blob.b.key.rsa.d_bytes, wrapping_key_D, sizeof(wrapping_key_D));
-
-  blob.b.tee_enforced.params[0].tag = Tag::PADDING;
-  blob.b.tee_enforced.params[0].integer = PaddingMode::PADDING_RSA_OAEP;
-  blob.b.tee_enforced.params_count++;
-  blob.b.tee_enforced.params[1].tag = Tag::PURPOSE;
-  blob.b.tee_enforced.params[1].integer = KeyPurpose::WRAP_KEY;
-  blob.b.tee_enforced.params_count++;
 
   request.set_key_format(KeyFormat::RAW);
-  KeyParameters *params = request.mutable_params();
-  KeyParameter *param = params->add_params();
+  params = request.mutable_params();
+  param = params->add_params();
   param->set_tag(Tag::ALGORITHM);
   param->set_integer((uint32_t)Algorithm::AES);
 
@@ -234,18 +255,13 @@
                                     sizeof(ENCRYPTED_IMPORT_KEY));
   request.set_aad(AAD, sizeof(AAD));
   request.set_gcm_tag(GCM_TAG, sizeof(GCM_TAG));
-  request.mutable_wrapping_key_blob()->set_blob(&blob, sizeof(blob));
+  request.mutable_wrapping_key_blob()->set_blob(importResponse.blob().blob());
   request.set_masking_key(masking_key, sizeof(masking_key));
 
   ASSERT_NO_ERROR(service->ImportWrappedKey(request, &response), "");
   EXPECT_EQ((ErrorCode)response.error_code(), ErrorCode::OK);
 
-  EXPECT_EQ(sizeof(struct km_blob), response.blob().blob().size());
-  const struct km_blob *response_blob =
-      (const struct km_blob *)response.blob().blob().data();
-  EXPECT_EQ(response_blob->b.key.sym.key_bits >> 3, sizeof(IMPORTED_KEY));
-  EXPECT_EQ(memcmp(response_blob->b.key.sym.bytes, IMPORTED_KEY,
-                   sizeof(IMPORTED_KEY)), 0);
+  /* TODO: use the imported key for something. */
 }
 
 } // namespace
diff --git a/src/keymaster-provision-tests.cc b/src/keymaster-provision-tests.cc
index 2edabad..b60339b 100644
--- a/src/keymaster-provision-tests.cc
+++ b/src/keymaster-provision-tests.cc
@@ -9,6 +9,7 @@
 #include <application.h>
 #include <keymaster.h>
 #include <nos/AppClient.h>
+#include <nos/NuggetClient.h>
 #include <nos/NuggetClientInterface.h>
 #include "util.h"
 
@@ -143,7 +144,7 @@
 
   PopulateDefaultRequest(&request);
 
-  string max_serialno(KM_MNF_MAX_ENTRY_SIZE, '5');  
+  string max_serialno(KM_MNF_MAX_ENTRY_SIZE, '5');
   request.set_serialno(max_serialno);
 
   Keymaster service(*client);
@@ -167,4 +168,657 @@
   ASSERT_EQ((ErrorCode)response.error_code(), ErrorCode::OK);
 }
 
+const static uint8_t ATTESTION_CERT_adacb483_0100b022[7 * 1024] = {
+  0x29, 0x81, 0xb0, 0x4a, 0x4c, 0xcf, 0x9d, 0x8e, 0x80, 0xbc, 0xd9, 0xee,
+  0x34, 0x23, 0x50, 0x55, 0x48, 0xb3, 0x7f, 0x79, 0xce, 0x66, 0x76, 0x91,
+  0x7b, 0x98, 0x31, 0xfc, 0x9b, 0x30, 0x44, 0xbf, 0xcd, 0xa0, 0x1e, 0x04,
+  0x51, 0x95, 0x86, 0x2d, 0xa6, 0x49, 0xce, 0x8a, 0x74, 0x0a, 0xf4, 0x96,
+  0x71, 0xf3, 0x5b, 0xe7, 0xf9, 0xb7, 0x7d, 0xe4, 0x0c, 0x76, 0xc4, 0x63,
+  0x7a, 0xba, 0x58, 0xde, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x00, 0x02, 0x00,
+  0x83, 0xb4, 0xac, 0xad, 0x22, 0xb0, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x29, 0x7d, 0x4b, 0x89, 0x03, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0x83, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0x50, 0x50, 0x50, 0x50, 0x00, 0x08, 0x00, 0x00,
+  0xa1, 0x04, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x57, 0x7c, 0xa0, 0xa6,
+  0xac, 0xc2, 0xe3, 0x45, 0x3b, 0x4f, 0xe3, 0x9b, 0x79, 0x68, 0x37, 0x70,
+  0xff, 0xf3, 0x0b, 0x4f, 0xf1, 0x80, 0x99, 0xc8, 0x37, 0xff, 0x3a, 0x8f,
+  0x4a, 0x27, 0x3a, 0x58, 0xe5, 0x03, 0x4b, 0xfd, 0x49, 0x8b, 0x63, 0xc1,
+  0xcb, 0xe6, 0xd9, 0xb0, 0xd3, 0x29, 0xc7, 0xd1, 0xee, 0x05, 0x4f, 0x3a,
+  0x02, 0xd2, 0x69, 0x4f, 0xc0, 0x96, 0x41, 0x69, 0xc1, 0x9e, 0x7e, 0xcb,
+  0xe5, 0xb9, 0x77, 0x2d, 0x73, 0x63, 0xaa, 0xb2, 0x7d, 0x5d, 0x82, 0x83,
+  0xc9, 0x0e, 0x75, 0x25, 0x27, 0x50, 0x65, 0x0d, 0xe8, 0x9d, 0x98, 0xe3,
+  0xd2, 0x5e, 0x7f, 0x4a, 0xca, 0x08, 0x2d, 0x99, 0x94, 0x69, 0xe9, 0x98,
+  0x59, 0x75, 0x73, 0xd5, 0xb0, 0x23, 0x9e, 0xa3, 0x31, 0x3a, 0x24, 0x59,
+  0xaa, 0xea, 0x5a, 0x79, 0x0d, 0xf2, 0x6f, 0xd9, 0x66, 0x4f, 0x1e, 0xd2,
+  0x49, 0x7b, 0xb9, 0xb2, 0xbb, 0x6e, 0xe2, 0xc2, 0x58, 0x19, 0xaf, 0x53,
+  0x22, 0x24, 0x32, 0x52, 0x1d, 0xbf, 0x9e, 0xf2, 0xfa, 0x65, 0xc0, 0x42,
+  0x03, 0x2b, 0xfc, 0x77, 0x04, 0xb7, 0xe0, 0xb8, 0xfd, 0x79, 0xf5, 0xb8,
+  0xee, 0x0e, 0x2d, 0x80, 0x52, 0x22, 0x60, 0x50, 0x60, 0x68, 0xbc, 0x5a,
+  0x01, 0x71, 0x7a, 0x88, 0x6c, 0xe9, 0x55, 0xb1, 0xbb, 0xec, 0x45, 0x5f,
+  0x03, 0x04, 0x19, 0x9b, 0xc0, 0xa0, 0x0b, 0xaa, 0x7b, 0x7a, 0xbf, 0xa7,
+  0x8f, 0x7f, 0x78, 0x4a, 0x48, 0xc8, 0x1e, 0xd5, 0xb7, 0x5e, 0xc7, 0xe5,
+  0x04, 0x6a, 0x9f, 0x8d, 0x6b, 0xb8, 0xf2, 0x0b, 0x30, 0x63, 0xe5, 0x87,
+  0x9c, 0x72, 0xc3, 0x02, 0x81, 0x37, 0x3e, 0x0a, 0xf0, 0xe2, 0xbc, 0x1a,
+  0xef, 0x82, 0x8f, 0x2c, 0xff, 0xd0, 0xe5, 0x70, 0x0a, 0x52, 0x97, 0x6f,
+  0xbc, 0x2c, 0x97, 0x7c, 0x17, 0x61, 0xc1, 0x38, 0xbe, 0x34, 0xd4, 0x69,
+  0xc4, 0x6a, 0xed, 0xed, 0xcc, 0x87, 0xcf, 0x11, 0x23, 0x13, 0x02, 0xeb,
+  0xb0, 0x2c, 0xd0, 0x54, 0x95, 0x03, 0xd2, 0x6d, 0x3c, 0xc7, 0x4b, 0xd5,
+  0xd8, 0x8e, 0xda, 0xef, 0x75, 0x8c, 0xe7, 0x60, 0x58, 0xcc, 0x93, 0x00,
+  0x1d, 0xe6, 0xa2, 0x72, 0xf8, 0xf1, 0x12, 0xc1, 0x04, 0x98, 0xf5, 0x25,
+  0xcd, 0x06, 0x7a, 0xb3, 0xc3, 0x11, 0xad, 0x1b, 0xa7, 0xc7, 0x0a, 0x1f,
+  0x16, 0x2a, 0x1e, 0x62, 0xed, 0x20, 0xb1, 0x53, 0xe1, 0x04, 0x1b, 0xe8,
+  0x98, 0x16, 0xce, 0xed, 0xf7, 0x24, 0xca, 0x8f, 0x25, 0xfa, 0x7c, 0xf8,
+  0x20, 0x59, 0x4e, 0xea, 0xe6, 0x58, 0x9d, 0x2a, 0x7a, 0xfd, 0x65, 0xed,
+  0x64, 0xdc, 0x66, 0x84, 0x08, 0xd3, 0xda, 0x6b, 0xcf, 0x50, 0x77, 0xed,
+  0x42, 0x66, 0x6d, 0x8d, 0xb7, 0xdc, 0xc2, 0x22, 0xaa, 0xec, 0x61, 0x66,
+  0xdb, 0xb5, 0xaf, 0x33, 0x0e, 0xe7, 0xb7, 0xca, 0x30, 0x82, 0x04, 0x9d,
+  0x30, 0x82, 0x02, 0x85, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0a, 0x17,
+  0x10, 0x24, 0x68, 0x40, 0x71, 0x02, 0x97, 0x78, 0x50, 0x30, 0x0d, 0x06,
+  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,
+  0x30, 0x2f, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13,
+  0x10, 0x63, 0x63, 0x64, 0x31, 0x38, 0x62, 0x39, 0x62, 0x36, 0x30, 0x38,
+  0x64, 0x36, 0x35, 0x38, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
+  0x04, 0x0c, 0x0c, 0x09, 0x53, 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x42, 0x6f,
+  0x78, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x35, 0x32, 0x35, 0x32,
+  0x33, 0x32, 0x38, 0x34, 0x37, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30, 0x35,
+  0x32, 0x32, 0x32, 0x33, 0x32, 0x38, 0x34, 0x37, 0x5a, 0x30, 0x2f, 0x31,
+  0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x10, 0x39, 0x30,
+  0x65, 0x38, 0x64, 0x61, 0x33, 0x63, 0x61, 0x64, 0x66, 0x63, 0x37, 0x38,
+  0x32, 0x30, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0c, 0x0c,
+  0x09, 0x53, 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x42, 0x6f, 0x78, 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, 0xa5, 0x09, 0xd4, 0x09, 0xd2,
+  0x30, 0x19, 0x36, 0x34, 0x71, 0xfd, 0x7d, 0x41, 0x89, 0xe6, 0x2c, 0xa5,
+  0x9d, 0x10, 0x1b, 0x4f, 0x40, 0x6a, 0xb0, 0x5f, 0x56, 0x34, 0x16, 0xe6,
+  0xeb, 0xd7, 0xf3, 0xe9, 0xc5, 0xdc, 0x20, 0xf3, 0x86, 0xd1, 0x77, 0x19,
+  0xd7, 0x15, 0x1f, 0xe7, 0xec, 0x62, 0xdc, 0x0a, 0xbc, 0x64, 0xe9, 0x18,
+  0x52, 0xb0, 0xaa, 0xb8, 0xff, 0x58, 0x6a, 0xe0, 0x0f, 0xb8, 0x56, 0xaf,
+  0x77, 0xd3, 0xce, 0x3c, 0xdc, 0x48, 0x52, 0xdd, 0xb2, 0x86, 0x0d, 0x76,
+  0x17, 0x7c, 0xfd, 0xee, 0xb4, 0xe6, 0x6e, 0x0a, 0x08, 0x9e, 0x06, 0xca,
+  0x0f, 0xec, 0x4b, 0xb0, 0x7c, 0xaf, 0xea, 0x82, 0x27, 0xa8, 0xc9, 0xa7,
+  0x63, 0xda, 0x89, 0xf6, 0x30, 0xba, 0x3c, 0x3a, 0xe5, 0xc6, 0xef, 0x11,
+  0x06, 0x42, 0x8a, 0x2e, 0xfe, 0x19, 0xbe, 0xf2, 0xc7, 0x3b, 0x34, 0x16,
+  0xb2, 0xe2, 0x64, 0xc7, 0xca, 0x66, 0x02, 0x85, 0xe3, 0x57, 0x6f, 0x11,
+  0x13, 0x3a, 0xff, 0xd5, 0x30, 0x13, 0x7d, 0xea, 0xe0, 0x22, 0xa2, 0x91,
+  0x0c, 0xaf, 0xf0, 0x5c, 0xd7, 0xc1, 0xb4, 0x85, 0x69, 0x7c, 0xc0, 0x39,
+  0xdb, 0x4e, 0xc1, 0x5a, 0xd8, 0xcc, 0x42, 0x7c, 0x06, 0x74, 0x01, 0x93,
+  0xa3, 0xa4, 0x10, 0x96, 0x29, 0xf2, 0x8e, 0x0a, 0xf7, 0x49, 0x4b, 0x87,
+  0x49, 0x13, 0x89, 0xe5, 0x00, 0x10, 0x96, 0xea, 0x37, 0x0d, 0xd7, 0x5d,
+  0x43, 0x41, 0x2b, 0x4e, 0x59, 0x9a, 0x51, 0xee, 0x73, 0xdb, 0x52, 0x95,
+  0x08, 0xe2, 0x6b, 0xb2, 0x33, 0xf7, 0x04, 0xbe, 0x51, 0x1c, 0x23, 0x62,
+  0x6e, 0xc2, 0x5f, 0x00, 0xc3, 0xa4, 0xc9, 0xbd, 0xe7, 0xc6, 0x65, 0x0d,
+  0xb1, 0xc4, 0x5e, 0x62, 0xb9, 0x9c, 0x2a, 0x26, 0x05, 0x67, 0xd0, 0xa9,
+  0x9a, 0x12, 0x1c, 0x49, 0x7b, 0x36, 0xbe, 0x6f, 0xf2, 0x68, 0x65, 0x02,
+  0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xba, 0x30, 0x81, 0xb7, 0x30, 0x1d,
+  0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x77, 0xa4, 0xad,
+  0xdf, 0x1d, 0x29, 0x89, 0xca, 0x92, 0xe3, 0xba, 0xde, 0x27, 0x3c, 0x70,
+  0xdf, 0x36, 0x03, 0x7c, 0x0c, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23,
+  0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x1b, 0x17, 0x70, 0xc6, 0x97, 0xdc,
+  0x84, 0x54, 0x75, 0x7c, 0x3c, 0x98, 0x5c, 0xe6, 0x1d, 0x1d, 0x08, 0x59,
+  0x5d, 0x53, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+  0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55,
+  0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30,
+  0x54, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x4d, 0x30, 0x4b, 0x30, 0x49,
+  0xa0, 0x47, 0xa0, 0x45, 0x86, 0x43, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a,
+  0x2f, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x67, 0x6f,
+  0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d,
+  0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+  0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x31, 0x37, 0x31, 0x30, 0x32, 0x34, 0x36,
+  0x38, 0x34, 0x30, 0x37, 0x31, 0x30, 0x32, 0x39, 0x37, 0x37, 0x38, 0x35,
+  0x30, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+  0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x13, 0x22, 0xda,
+  0xf2, 0x92, 0x93, 0xce, 0xc0, 0x9f, 0x70, 0x40, 0xc9, 0xda, 0x85, 0x6b,
+  0x61, 0x6f, 0x8f, 0xbe, 0xe0, 0xa4, 0x04, 0x55, 0xc1, 0x63, 0x84, 0x61,
+  0x37, 0xf5, 0x4b, 0x71, 0x6d, 0x62, 0xaa, 0x6f, 0xbf, 0x6c, 0xe8, 0x48,
+  0x03, 0xad, 0x28, 0x85, 0x21, 0x9e, 0x3c, 0x1c, 0x91, 0x48, 0xee, 0x65,
+  0x28, 0x65, 0x70, 0xd0, 0xbd, 0x5b, 0xcc, 0xdb, 0xce, 0xb1, 0xf5, 0xb5,
+  0xc3, 0xca, 0x7a, 0xa9, 0xc8, 0x8a, 0x68, 0x12, 0x8a, 0xca, 0x6a, 0x85,
+  0xa6, 0xbc, 0xda, 0x36, 0xe9, 0xb9, 0x94, 0x35, 0x82, 0x5b, 0xca, 0xbc,
+  0xb6, 0x9f, 0x83, 0x03, 0x7f, 0x21, 0x6c, 0xee, 0x82, 0xc1, 0x3f, 0xbd,
+  0xc1, 0x41, 0x4b, 0xdd, 0x1a, 0x6f, 0x6c, 0xaf, 0x4a, 0x52, 0xfc, 0x19,
+  0x19, 0x17, 0xac, 0x29, 0x0c, 0x5e, 0xd7, 0x57, 0x90, 0xd5, 0xb1, 0x2b,
+  0x36, 0x29, 0x1f, 0x45, 0x33, 0x17, 0xe0, 0x95, 0x50, 0x92, 0x08, 0x44,
+  0xc2, 0x91, 0x11, 0xe8, 0x2e, 0x16, 0x50, 0x32, 0x98, 0xa5, 0x58, 0x82,
+  0xd8, 0x78, 0x26, 0x27, 0xa5, 0x92, 0xa2, 0x47, 0xec, 0x74, 0x9f, 0xbc,
+  0x0e, 0x87, 0x9b, 0xd0, 0x34, 0xce, 0x20, 0xb9, 0x6a, 0x89, 0x2b, 0x35,
+  0xa8, 0xb7, 0x19, 0x18, 0x8d, 0x31, 0x81, 0xf3, 0x0f, 0xb6, 0x95, 0x64,
+  0x4b, 0x79, 0x2e, 0xa1, 0xca, 0x69, 0xa6, 0x13, 0x10, 0x0a, 0x06, 0x1b,
+  0x04, 0x8b, 0x46, 0xa3, 0x89, 0x5b, 0xee, 0xdc, 0xeb, 0x41, 0x7b, 0xbb,
+  0x5c, 0x68, 0x6c, 0xd9, 0xb9, 0x8e, 0xe3, 0xd8, 0x87, 0x79, 0xe5, 0xf0,
+  0x69, 0xe2, 0xe8, 0xb7, 0x98, 0x73, 0xab, 0xfb, 0xfd, 0xb6, 0xaf, 0x3e,
+  0xc5, 0x04, 0xca, 0x9b, 0x70, 0x43, 0xe9, 0x27, 0xa7, 0x5b, 0x04, 0x90,
+  0xc8, 0x6d, 0x5e, 0x94, 0x63, 0xa0, 0x80, 0x07, 0x0d, 0x46, 0xfb, 0x3b,
+  0xd9, 0x9b, 0x5c, 0x6a, 0x6e, 0xb6, 0xf9, 0xa6, 0x82, 0xf4, 0x46, 0x9d,
+  0x9e, 0x14, 0xa7, 0xa2, 0xb7, 0x0f, 0x2c, 0x5e, 0xbe, 0x78, 0xb1, 0x44,
+  0x69, 0xf7, 0x83, 0x37, 0x6c, 0xa2, 0x52, 0xaf, 0x1a, 0x1d, 0xcd, 0x12,
+  0x3f, 0x39, 0x98, 0x24, 0xac, 0xfc, 0x32, 0x8a, 0xba, 0xd7, 0xcf, 0x5e,
+  0xf1, 0x10, 0x13, 0xcc, 0x58, 0x29, 0x26, 0x3f, 0x1d, 0xc1, 0xd4, 0x2a,
+  0xec, 0xb4, 0xa1, 0xaf, 0xd9, 0xdd, 0x16, 0x7b, 0x54, 0x8f, 0xb2, 0x39,
+  0xda, 0xdc, 0x26, 0x7d, 0x3a, 0x4f, 0x36, 0x72, 0x96, 0x12, 0x83, 0x7d,
+  0x98, 0x98, 0xd2, 0x4a, 0x4e, 0xfb, 0x0e, 0xe6, 0x84, 0xee, 0xf4, 0x26,
+  0xda, 0x01, 0x3b, 0xb3, 0x15, 0xda, 0x17, 0xc8, 0x78, 0x57, 0xfb, 0xd3,
+  0x91, 0x17, 0x2d, 0x3c, 0x27, 0xab, 0x00, 0xda, 0xb0, 0x98, 0x95, 0xa4,
+  0x84, 0x6b, 0xcd, 0xbf, 0xa7, 0xa7, 0x95, 0xef, 0xaa, 0xb0, 0x91, 0xf8,
+  0x98, 0xa8, 0x33, 0x3d, 0x90, 0x93, 0x9d, 0x75, 0x11, 0xe9, 0xbd, 0x70,
+  0x16, 0x6d, 0x22, 0xc9, 0x2f, 0x24, 0xb1, 0x55, 0x80, 0xcb, 0x6b, 0x19,
+  0xc1, 0x78, 0xa0, 0xc5, 0x24, 0x86, 0xbd, 0xb8, 0x12, 0x64, 0x87, 0x89,
+  0x91, 0x74, 0xd0, 0xf6, 0xa2, 0x4c, 0x44, 0xf8, 0x7d, 0xf5, 0x3d, 0x0b,
+  0x1d, 0x69, 0xf6, 0xb3, 0xfb, 0x0b, 0x3d, 0x50, 0xd9, 0x5a, 0xe6, 0xbb,
+  0x39, 0xd5, 0x9b, 0x6a, 0x16, 0xee, 0xce, 0xfe, 0x5c, 0x61, 0xc5, 0x2d,
+  0x83, 0xf5, 0xe8, 0x0e, 0x21, 0xfc, 0x2e, 0xb7, 0xc8, 0xbc, 0xf6, 0x4d,
+  0x6f, 0x9b, 0x1d, 0x69, 0x76, 0x6c, 0x89, 0x2c, 0x5f, 0x42, 0xde, 0xc5,
+  0x2f, 0xe4, 0x30, 0x18, 0xcd, 0x47, 0xbc, 0x72, 0xa1, 0x50, 0x87, 0xd0,
+  0x13, 0xc2, 0xe8, 0x2c, 0x55, 0xa1, 0xdc, 0x83, 0x3e, 0x66, 0x65, 0x88,
+  0xc2, 0xa8, 0x2c, 0x81, 0x8d, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0x94, 0x02, 0x84, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0x50, 0x50, 0x50, 0x50, 0x34, 0x02, 0x00, 0x00, 0x60, 0xd1, 0x7e, 0x20,
+  0x53, 0x4f, 0x4a, 0x8e, 0xcc, 0xdc, 0x7f, 0xae, 0x9e, 0x10, 0xfd, 0x62,
+  0x05, 0xd5, 0xd5, 0xcc, 0x78, 0x63, 0x53, 0xfb, 0x61, 0x5c, 0xee, 0x28,
+  0x92, 0x3f, 0x16, 0x88, 0x30, 0x82, 0x02, 0x30, 0x30, 0x82, 0x01, 0xb7,
+  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0a, 0x11, 0x23, 0x38, 0x24, 0x34,
+  0x40, 0x08, 0x68, 0x01, 0x71, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
+  0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x2f, 0x31, 0x19, 0x30, 0x17, 0x06,
+  0x03, 0x55, 0x04, 0x05, 0x13, 0x10, 0x63, 0x63, 0x64, 0x31, 0x38, 0x62,
+  0x39, 0x62, 0x36, 0x30, 0x38, 0x64, 0x36, 0x35, 0x38, 0x65, 0x31, 0x12,
+  0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0c, 0x0c, 0x09, 0x53, 0x74, 0x72,
+  0x6f, 0x6e, 0x67, 0x42, 0x6f, 0x78, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38,
+  0x30, 0x35, 0x32, 0x35, 0x32, 0x33, 0x32, 0x38, 0x35, 0x30, 0x5a, 0x17,
+  0x0d, 0x32, 0x38, 0x30, 0x35, 0x32, 0x32, 0x32, 0x33, 0x32, 0x38, 0x35,
+  0x30, 0x5a, 0x30, 0x2f, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04,
+  0x05, 0x13, 0x10, 0x39, 0x30, 0x65, 0x38, 0x64, 0x61, 0x33, 0x63, 0x61,
+  0x64, 0x66, 0x63, 0x37, 0x38, 0x32, 0x30, 0x31, 0x12, 0x30, 0x10, 0x06,
+  0x03, 0x55, 0x04, 0x0c, 0x0c, 0x09, 0x53, 0x74, 0x72, 0x6f, 0x6e, 0x67,
+  0x42, 0x6f, 0x78, 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, 0xe4, 0x57, 0x44, 0xc2, 0xb1, 0x9f,
+  0xaf, 0x70, 0x8a, 0x17, 0x2b, 0x40, 0x4b, 0x7b, 0x8a, 0xb8, 0xb1, 0x0d,
+  0x6f, 0x78, 0x13, 0xc4, 0xdb, 0x6f, 0x0b, 0xaa, 0x57, 0x50, 0x09, 0x03,
+  0xc2, 0x6f, 0xa2, 0x01, 0x0a, 0x93, 0x3b, 0xac, 0x70, 0xe0, 0x2a, 0x6b,
+  0x1a, 0xbe, 0x25, 0xad, 0xb0, 0x0d, 0x1a, 0x9c, 0x9c, 0x94, 0xa5, 0x71,
+  0xd3, 0x56, 0x2c, 0x74, 0x99, 0xd2, 0x32, 0xf5, 0x77, 0x27, 0xa3, 0x81,
+  0xba, 0x30, 0x81, 0xb7, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
+  0x16, 0x04, 0x14, 0x6f, 0xb1, 0xb5, 0x31, 0x9d, 0xb6, 0xb8, 0x85, 0x15,
+  0xbe, 0xcf, 0xc0, 0x0c, 0x77, 0x1a, 0x8f, 0xe7, 0x54, 0xea, 0x96, 0x30,
+  0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
+  0xbc, 0x5b, 0xcb, 0xd5, 0x79, 0xc6, 0x94, 0xdc, 0x19, 0x8f, 0x9b, 0x9f,
+  0x67, 0x53, 0xcc, 0xeb, 0xe6, 0x62, 0xdf, 0xde, 0x30, 0x0f, 0x06, 0x03,
+  0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01,
+  0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04,
+  0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x54, 0x06, 0x03, 0x55, 0x1d, 0x1f,
+  0x04, 0x4d, 0x30, 0x4b, 0x30, 0x49, 0xa0, 0x47, 0xa0, 0x45, 0x86, 0x43,
+  0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x61, 0x6e, 0x64, 0x72,
+  0x6f, 0x69, 0x64, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70,
+  0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73,
+  0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x31,
+  0x31, 0x32, 0x33, 0x33, 0x38, 0x32, 0x34, 0x33, 0x34, 0x34, 0x30, 0x30,
+  0x38, 0x36, 0x38, 0x30, 0x31, 0x37, 0x31, 0x30, 0x0a, 0x06, 0x08, 0x2a,
+  0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x67, 0x00, 0x30, 0x64,
+  0x02, 0x30, 0x50, 0x73, 0xc6, 0x56, 0xeb, 0x18, 0x96, 0xab, 0x5f, 0xe7,
+  0xbc, 0x77, 0xb5, 0x1f, 0x0f, 0x93, 0x36, 0x06, 0xbd, 0xd0, 0xc4, 0xa5,
+  0x05, 0x01, 0x2d, 0x6d, 0x7c, 0x6c, 0x72, 0xf4, 0xbc, 0x3b, 0xdb, 0x27,
+  0xc5, 0x9f, 0xcb, 0xf7, 0x8f, 0x13, 0x72, 0x09, 0xa9, 0xa0, 0x96, 0xaa,
+  0x70, 0xf2, 0x02, 0x30, 0x62, 0x4c, 0xdb, 0x64, 0x3b, 0xf1, 0xfe, 0xe5,
+  0x3a, 0xbd, 0x72, 0x1a, 0x07, 0x5c, 0xb4, 0x3d, 0x11, 0xaa, 0xe4, 0x9a,
+  0x79, 0xc4, 0x88, 0x0a, 0xa9, 0x41, 0x09, 0xbe, 0xc0, 0x6e, 0xc8, 0xc3,
+  0x7c, 0x25, 0xd2, 0x6c, 0x7f, 0x3b, 0xc7, 0x6e, 0x46, 0x32, 0x65, 0x4b,
+  0xa3, 0x53, 0xf4, 0x95, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0x74, 0x02, 0x85, 0xee, 0xee, 0xee, 0xee, 0xee, 0x50, 0x50, 0x50, 0x50,
+  0x4d, 0x01, 0x00, 0x00, 0x30, 0x82, 0x01, 0x49, 0x30, 0x81, 0xf0, 0xa0,
+  0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x3f, 0x2d, 0x32, 0x42, 0x04, 0x65,
+  0x72, 0x08, 0x12, 0x82, 0x10, 0x2b, 0xaa, 0x66, 0x15, 0x0f, 0x30, 0x0a,
+  0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x25,
+  0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1a, 0x53,
+  0x74, 0x72, 0x6f, 0x6e, 0x67, 0x42, 0x6f, 0x78, 0x2d, 0x32, 0x42, 0x31,
+  0x30, 0x38, 0x32, 0x31, 0x32, 0x30, 0x38, 0x37, 0x32, 0x36, 0x35, 0x30,
+  0x34, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x38, 0x30, 0x37, 0x30,
+  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x5a, 0x18, 0x0f, 0x32, 0x30,
+  0x32, 0x38, 0x30, 0x38, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+  0x5a, 0x30, 0x25, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03,
+  0x13, 0x1a, 0x53, 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x42, 0x6f, 0x78, 0x2d,
+  0x32, 0x42, 0x31, 0x30, 0x38, 0x32, 0x31, 0x32, 0x30, 0x38, 0x37, 0x32,
+  0x36, 0x35, 0x30, 0x34, 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, 0x1c, 0xf7, 0x2d, 0xb6, 0xd3,
+  0x52, 0x3e, 0x34, 0xf2, 0x42, 0x81, 0x1a, 0xf8, 0x04, 0x00, 0xe1, 0x68,
+  0x5e, 0xba, 0x92, 0x4c, 0x07, 0x10, 0xc3, 0x26, 0xc7, 0xe7, 0xa6, 0x35,
+  0x96, 0xaf, 0x31, 0xcc, 0x15, 0x6a, 0xc7, 0x8a, 0x2d, 0x06, 0xdc, 0x40,
+  0xb9, 0xc4, 0x58, 0xd5, 0x77, 0xcd, 0xf7, 0x61, 0x7d, 0x70, 0x85, 0xca,
+  0x32, 0x78, 0x7c, 0x8a, 0x7b, 0x8c, 0x8d, 0x29, 0x5a, 0xa3, 0xeb, 0x30,
+  0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03,
+  0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xf3, 0x9d, 0x47, 0x0b, 0x56,
+  0xe0, 0x67, 0xaa, 0x0e, 0xa2, 0x35, 0xbd, 0xfe, 0xb3, 0x83, 0xb6, 0xc8,
+  0x0b, 0x17, 0xee, 0x36, 0xa0, 0xe4, 0x89, 0xbc, 0x4f, 0xe6, 0x3e, 0x5a,
+  0x38, 0x6f, 0x67, 0x02, 0x20, 0x6f, 0x01, 0xbe, 0x6a, 0xba, 0x84, 0x5d,
+  0xe1, 0xbf, 0x6b, 0x65, 0x74, 0x37, 0xe5, 0xae, 0x5a, 0x56, 0x84, 0x73,
+  0x10, 0xb9, 0xa4, 0x32, 0xa8, 0xd8, 0xde, 0x79, 0xba, 0x2f, 0xfb, 0x6b,
+  0x06, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0x74, 0x02, 0x88, 0xee, 0xee, 0xee, 0xee, 0xee, 0x50, 0x50, 0x50, 0x50,
+  0x4c, 0x01, 0x00, 0x00, 0x30, 0x82, 0x01, 0x48, 0x30, 0x81, 0xf0, 0xa0,
+  0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x3f, 0x2d, 0x32, 0x42, 0x04, 0x65,
+  0x72, 0x08, 0x12, 0x82, 0x10, 0x2b, 0xaa, 0x66, 0x15, 0x0f, 0x30, 0x0a,
+  0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x25,
+  0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1a, 0x55,
+  0x32, 0x46, 0x47, 0x6e, 0x75, 0x62, 0x62, 0x79, 0x2d, 0x32, 0x42, 0x31,
+  0x30, 0x38, 0x32, 0x31, 0x32, 0x30, 0x38, 0x37, 0x32, 0x36, 0x35, 0x30,
+  0x34, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x38, 0x30, 0x37, 0x30,
+  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x5a, 0x18, 0x0f, 0x32, 0x30,
+  0x32, 0x38, 0x30, 0x38, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+  0x5a, 0x30, 0x25, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03,
+  0x13, 0x1a, 0x55, 0x32, 0x46, 0x47, 0x6e, 0x75, 0x62, 0x62, 0x79, 0x2d,
+  0x32, 0x42, 0x31, 0x30, 0x38, 0x32, 0x31, 0x32, 0x30, 0x38, 0x37, 0x32,
+  0x36, 0x35, 0x30, 0x34, 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, 0xf5, 0x0e, 0x32, 0x2a, 0xbf,
+  0x15, 0x7c, 0xf4, 0xe4, 0xf2, 0xe9, 0xdb, 0xf6, 0x89, 0xf6, 0x52, 0x6c,
+  0x85, 0xf4, 0x47, 0xe0, 0x39, 0x6b, 0xa2, 0x68, 0x14, 0xf1, 0x9e, 0x84,
+  0x57, 0x98, 0x58, 0xcb, 0xee, 0xf5, 0x81, 0x72, 0xef, 0x9c, 0xa9, 0x55,
+  0x98, 0x67, 0x90, 0x8c, 0xdc, 0x74, 0xd5, 0xc5, 0xb3, 0x04, 0x14, 0xfc,
+  0xe0, 0x72, 0x06, 0x84, 0x5e, 0x9f, 0xaf, 0x50, 0x3c, 0x05, 0x36, 0x30,
+  0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03,
+  0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x4a, 0x6a, 0x68, 0x92, 0x28, 0x4c,
+  0x8b, 0x36, 0x5e, 0x68, 0x9f, 0x2e, 0x8c, 0xbe, 0xb9, 0x6d, 0x75, 0x12,
+  0x75, 0xf6, 0xd4, 0x56, 0x9a, 0x25, 0x14, 0xcd, 0xe0, 0xce, 0xb5, 0xd9,
+  0x62, 0xcb, 0x02, 0x20, 0x61, 0xf6, 0xa4, 0x9a, 0x8a, 0x4c, 0x08, 0xaf,
+  0x81, 0x16, 0xb4, 0x6e, 0x4f, 0x81, 0xb5, 0x03, 0x87, 0xe3, 0x72, 0xa7,
+  0xbd, 0xfa, 0x94, 0x24, 0xc4, 0xc1, 0x43, 0x93, 0x11, 0x2d, 0x97, 0xfb,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0x08, 0x07, 0x86, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0x50, 0x50, 0x50, 0x50, 0x00, 0x0c, 0x00, 0x00, 0x15, 0x05, 0x00, 0x00,
+  0x01, 0x00, 0x01, 0x00, 0x42, 0xef, 0x49, 0x02, 0x82, 0x92, 0x65, 0xe5,
+  0xd9, 0x18, 0x69, 0x4f, 0x69, 0x12, 0x15, 0x9b, 0x54, 0xf3, 0x62, 0xe4,
+  0xcd, 0xd1, 0xb6, 0x00, 0x59, 0xca, 0xf0, 0xfb, 0x63, 0x33, 0xfa, 0x2c,
+  0xd2, 0x25, 0x8a, 0xb6, 0x62, 0x56, 0xaa, 0x55, 0x5f, 0x26, 0xb8, 0x22,
+  0x88, 0xfc, 0xc1, 0x5a, 0x50, 0xcd, 0xd0, 0xdc, 0x87, 0x5e, 0x43, 0xea,
+  0x26, 0x0a, 0x17, 0xcb, 0x86, 0x0e, 0x15, 0xed, 0xec, 0xb4, 0xf9, 0x68,
+  0x50, 0xcd, 0x26, 0x44, 0x78, 0x0e, 0x98, 0x5e, 0xc1, 0xa2, 0x4b, 0x5d,
+  0xf5, 0xb2, 0x73, 0x55, 0xb9, 0xa5, 0xa2, 0x0e, 0x01, 0xe6, 0x16, 0x7f,
+  0xef, 0xe3, 0xe9, 0x2d, 0x49, 0x00, 0x9d, 0x12, 0xe3, 0x09, 0x0c, 0x5d,
+  0xcc, 0x26, 0xc1, 0x2b, 0xdb, 0xc3, 0xd8, 0x4d, 0x3d, 0x3f, 0x94, 0xdc,
+  0xbf, 0x4b, 0x1b, 0x3e, 0x10, 0x28, 0xd9, 0xad, 0x5b, 0x9d, 0x15, 0xb9,
+  0xc4, 0x48, 0x58, 0x57, 0x43, 0x84, 0xdc, 0x22, 0x18, 0x53, 0xc0, 0x00,
+  0xcd, 0x36, 0x31, 0x99, 0x7b, 0xe0, 0xa8, 0x39, 0x8d, 0xfa, 0xc6, 0xbe,
+  0x4b, 0x61, 0xb1, 0xd1, 0xae, 0x1e, 0xac, 0xa8, 0xae, 0x45, 0xaa, 0x6b,
+  0x7c, 0x00, 0x8e, 0xc7, 0x18, 0xd0, 0x88, 0x95, 0xc9, 0x50, 0x44, 0x48,
+  0xc0, 0xbb, 0x60, 0x02, 0x98, 0x51, 0xa1, 0x0c, 0xaa, 0x44, 0x84, 0x36,
+  0x62, 0x71, 0x1f, 0x94, 0xcd, 0x39, 0x80, 0x6a, 0x82, 0x21, 0x15, 0x1f,
+  0x17, 0xb2, 0x74, 0x1b, 0xc3, 0x99, 0x10, 0x29, 0x4a, 0x28, 0x51, 0x99,
+  0x07, 0xf3, 0x5f, 0xbc, 0xbd, 0x35, 0x07, 0x41, 0x32, 0xd8, 0x59, 0x63,
+  0xbe, 0x4a, 0x2d, 0xf0, 0x06, 0xd7, 0xe2, 0x88, 0x68, 0x72, 0x12, 0xe7,
+  0x2a, 0xa0, 0x33, 0xfd, 0x04, 0xd5, 0xe9, 0xc4, 0x81, 0xeb, 0xe1, 0x97,
+  0x04, 0xcf, 0x08, 0xb5, 0x67, 0x79, 0x39, 0x26, 0xc3, 0x6e, 0x7d, 0x24,
+  0x2d, 0x0b, 0x75, 0x5f, 0x2d, 0x81, 0x63, 0xa9, 0x30, 0x0d, 0xe8, 0x79,
+  0xf0, 0x8d, 0x9e, 0xab, 0x24, 0x79, 0x5c, 0xf6, 0x9c, 0x83, 0x53, 0x88,
+  0x41, 0x92, 0x34, 0xb2, 0xec, 0xfa, 0x37, 0x5c, 0x9a, 0xea, 0x7a, 0xce,
+  0x1f, 0xe3, 0x5f, 0x0e, 0x12, 0x5c, 0xac, 0x1a, 0x0f, 0x3c, 0xf1, 0x9b,
+  0xda, 0xad, 0x06, 0xcc, 0x85, 0xd5, 0xaf, 0x51, 0xef, 0x97, 0x52, 0x4f,
+  0x33, 0xef, 0x82, 0x24, 0x54, 0x19, 0xa2, 0x79, 0x62, 0x0b, 0xcc, 0x29,
+  0xf9, 0xb0, 0xf6, 0xdc, 0xca, 0xae, 0xf9, 0xb3, 0x61, 0x69, 0x15, 0x19,
+  0x36, 0x39, 0x3e, 0x57, 0x1f, 0x2b, 0x15, 0x74, 0x28, 0xb4, 0xb1, 0x13,
+  0x2f, 0xc5, 0x78, 0x57, 0x76, 0x1e, 0xec, 0xa6, 0xfb, 0xa7, 0x72, 0xb7,
+  0xcf, 0x38, 0x86, 0x78, 0x8a, 0x46, 0x97, 0x44, 0x05, 0xa8, 0x24, 0x89,
+  0x9b, 0x6b, 0xcd, 0x56, 0x30, 0x82, 0x05, 0x11, 0x30, 0x82, 0x02, 0xf9,
+  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0a, 0x06, 0x97, 0x36, 0x83, 0x31,
+  0x39, 0x58, 0x14, 0x16, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+  0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x29, 0x31, 0x19,
+  0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x10, 0x39, 0x35, 0x65,
+  0x32, 0x33, 0x66, 0x66, 0x39, 0x62, 0x36, 0x65, 0x62, 0x30, 0x32, 0x35,
+  0x61, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0c, 0x0c, 0x03,
+  0x54, 0x45, 0x45, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x35, 0x32,
+  0x35, 0x32, 0x33, 0x32, 0x38, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x38,
+  0x30, 0x35, 0x32, 0x32, 0x32, 0x33, 0x32, 0x38, 0x34, 0x30, 0x5a, 0x30,
+  0x29, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x10,
+  0x65, 0x65, 0x34, 0x62, 0x65, 0x65, 0x64, 0x33, 0x39, 0x33, 0x34, 0x37,
+  0x32, 0x65, 0x64, 0x62, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04,
+  0x0c, 0x0c, 0x03, 0x54, 0x45, 0x45, 0x30, 0x82, 0x01, 0xa2, 0x30, 0x0d,
+  0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+  0x00, 0x03, 0x82, 0x01, 0x8f, 0x00, 0x30, 0x82, 0x01, 0x8a, 0x02, 0x82,
+  0x01, 0x81, 0x00, 0xfc, 0x02, 0x98, 0x15, 0xa4, 0xd2, 0x71, 0xad, 0x26,
+  0x19, 0xc0, 0x67, 0x90, 0x51, 0x8f, 0xa2, 0x99, 0x81, 0x8e, 0x29, 0xbb,
+  0x3f, 0x01, 0x27, 0xee, 0x9a, 0x5a, 0x6a, 0xfc, 0xfc, 0x97, 0x52, 0xbb,
+  0x6e, 0x9d, 0x25, 0xa4, 0x37, 0x4c, 0x90, 0xaf, 0x02, 0x83, 0xd3, 0xd7,
+  0x8d, 0x02, 0x56, 0x3e, 0xad, 0x53, 0x99, 0x7e, 0xa3, 0x5b, 0x82, 0xfc,
+  0xb0, 0x56, 0x49, 0x0f, 0x51, 0xd4, 0x90, 0xba, 0x95, 0xd9, 0x0f, 0xfa,
+  0x39, 0x96, 0xbf, 0xc0, 0x04, 0x44, 0xf6, 0x4d, 0x10, 0xa5, 0x6c, 0x45,
+  0x80, 0x4c, 0x2d, 0x88, 0x63, 0xa9, 0x96, 0x7e, 0x2c, 0x5f, 0xb9, 0x25,
+  0x69, 0x4c, 0x06, 0x04, 0x5b, 0xc7, 0x0c, 0x1c, 0xfd, 0xf1, 0x3a, 0xdd,
+  0x2e, 0xae, 0x10, 0x01, 0xe1, 0x2a, 0x4a, 0x87, 0x46, 0xb1, 0x76, 0xf3,
+  0x0d, 0xd1, 0x23, 0x11, 0xf7, 0x55, 0x1d, 0x57, 0x2e, 0xa3, 0xfc, 0xb2,
+  0x9a, 0xbb, 0x49, 0xd9, 0xd6, 0x20, 0x5c, 0xf7, 0x29, 0x1c, 0x2a, 0x82,
+  0xf0, 0x7b, 0x7e, 0xcb, 0x5c, 0x71, 0x0c, 0x64, 0x67, 0xda, 0x70, 0x71,
+  0xef, 0x0d, 0xb3, 0x39, 0x9b, 0x9e, 0xea, 0x23, 0x4e, 0xb2, 0x67, 0xd0,
+  0xcb, 0x1b, 0x1c, 0x9a, 0xc0, 0x1c, 0x5a, 0x9a, 0xfe, 0x5a, 0x7a, 0x24,
+  0xb1, 0x89, 0xdc, 0xcb, 0x59, 0xf2, 0xfe, 0xa8, 0x89, 0x90, 0x7e, 0x5e,
+  0xbd, 0xaf, 0x8d, 0xc1, 0x96, 0x2e, 0x0d, 0xb9, 0xb9, 0x2b, 0xd6, 0x49,
+  0xb8, 0x93, 0x70, 0x6e, 0x38, 0x7d, 0x56, 0x88, 0x79, 0xbb, 0xff, 0x21,
+  0x08, 0x6d, 0xf5, 0xae, 0xb4, 0x60, 0x7b, 0xd5, 0xc4, 0x26, 0x12, 0xea,
+  0x95, 0x71, 0x47, 0x3d, 0xf4, 0xee, 0x2e, 0x39, 0x24, 0x91, 0xf0, 0x6c,
+  0x23, 0x4e, 0xb1, 0x02, 0x1a, 0x95, 0xf7, 0x8f, 0x95, 0x9d, 0xce, 0x73,
+  0x13, 0x8b, 0xc9, 0xa7, 0x4f, 0xb2, 0x50, 0x9e, 0x19, 0xe6, 0xe5, 0xf7,
+  0xb8, 0xe3, 0x75, 0xb5, 0x6a, 0x24, 0xdb, 0x5d, 0x91, 0x03, 0x34, 0xc0,
+  0xe4, 0xa2, 0xc2, 0x0a, 0x9a, 0x74, 0x58, 0x7d, 0x3d, 0x3c, 0x40, 0x2a,
+  0x33, 0x14, 0xe1, 0xce, 0xf3, 0x86, 0xbf, 0x68, 0x0f, 0xa8, 0xe2, 0xc0,
+  0xa0, 0xa4, 0x37, 0x10, 0x91, 0x93, 0xee, 0x3f, 0x4c, 0xe9, 0x95, 0x9c,
+  0x70, 0xa9, 0x12, 0xde, 0x3b, 0x92, 0xa6, 0x0b, 0xd7, 0xaf, 0x76, 0x86,
+  0x24, 0x8a, 0x8a, 0xa5, 0x6d, 0x1b, 0x47, 0xe8, 0x21, 0xbe, 0x45, 0x9f,
+  0xb0, 0x92, 0x6f, 0xd0, 0x09, 0x51, 0x4c, 0x6e, 0x8b, 0xfc, 0x83, 0xfb,
+  0xb7, 0x80, 0xc7, 0xa1, 0x09, 0x14, 0x01, 0x63, 0x10, 0xc2, 0x9b, 0x20,
+  0x10, 0xd2, 0x9a, 0xf4, 0x3c, 0x9f, 0x9a, 0xaf, 0xf0, 0xf1, 0xe1, 0xbc,
+  0x85, 0x45, 0x68, 0x90, 0xaa, 0xf0, 0x7d, 0xf3, 0xf7, 0x0e, 0xba, 0x53,
+  0x58, 0x56, 0xb1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xba, 0x30,
+  0x81, 0xb7, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04,
+  0x14, 0x96, 0x55, 0x9d, 0x9e, 0x4c, 0x02, 0x18, 0x85, 0xa7, 0x97, 0xe2,
+  0x17, 0xab, 0x9b, 0x99, 0x4c, 0x36, 0x44, 0xd4, 0x54, 0x30, 0x1f, 0x06,
+  0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x81, 0xf6,
+  0x73, 0x03, 0x40, 0x73, 0x83, 0x6d, 0x3e, 0x83, 0x38, 0x0a, 0x38, 0x3a,
+  0x3d, 0x38, 0xcd, 0x28, 0x8a, 0xdd, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d,
+  0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+  0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03,
+  0x02, 0x02, 0x04, 0x30, 0x54, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x4d,
+  0x30, 0x4b, 0x30, 0x49, 0xa0, 0x47, 0xa0, 0x45, 0x86, 0x43, 0x68, 0x74,
+  0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+  0x64, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73,
+  0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61,
+  0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x30, 0x36, 0x39,
+  0x37, 0x33, 0x36, 0x38, 0x33, 0x33, 0x31, 0x33, 0x39, 0x35, 0x38, 0x31,
+  0x34, 0x31, 0x36, 0x33, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+  0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01,
+  0x00, 0x6f, 0x92, 0x65, 0x9f, 0x8a, 0xe1, 0x7c, 0xff, 0x31, 0x9c, 0xed,
+  0xfa, 0x1e, 0xb6, 0x66, 0xe3, 0x5e, 0xcc, 0xc2, 0x7c, 0xfe, 0x3b, 0xe1,
+  0x61, 0x17, 0x91, 0x65, 0x4c, 0xfa, 0x5a, 0x7e, 0xbc, 0x59, 0x42, 0xda,
+  0xb5, 0x45, 0x7a, 0x98, 0x0a, 0x2f, 0x55, 0x3e, 0x3b, 0x04, 0x95, 0xdd,
+  0x3f, 0xf5, 0xae, 0x44, 0x1f, 0x32, 0x61, 0xa8, 0x7c, 0xca, 0xca, 0x72,
+  0xbf, 0xbe, 0xc3, 0xe3, 0x2b, 0x49, 0x4c, 0x06, 0x03, 0x71, 0x69, 0xc9,
+  0x15, 0xd3, 0xd6, 0xd6, 0x5c, 0xd7, 0xd5, 0x90, 0x31, 0xe6, 0x3c, 0xa0,
+  0x4b, 0x8b, 0xf5, 0x15, 0xa4, 0x08, 0x7d, 0x53, 0x7f, 0xae, 0xb1, 0x95,
+  0x3e, 0x03, 0xec, 0x1a, 0x2a, 0x6b, 0x80, 0x37, 0xe2, 0x78, 0x8d, 0x6d,
+  0x82, 0xa9, 0x10, 0x79, 0x0f, 0x41, 0xc7, 0x25, 0x64, 0x40, 0xbd, 0x77,
+  0x8d, 0x0f, 0x00, 0xe7, 0x2e, 0x1b, 0x0f, 0x33, 0xfa, 0xbc, 0xd0, 0xb6,
+  0x25, 0x4a, 0xf6, 0xa0, 0xd0, 0x4b, 0xfb, 0x0b, 0x1f, 0x74, 0x7a, 0x51,
+  0x3d, 0x94, 0xdb, 0x95, 0x4d, 0x34, 0x98, 0xb6, 0x41, 0x25, 0xc7, 0xb5,
+  0x60, 0xaa, 0x08, 0x71, 0xc4, 0x12, 0xde, 0xa5, 0x5f, 0xc8, 0x59, 0x86,
+  0x8d, 0x51, 0x05, 0x63, 0x20, 0x61, 0x45, 0x73, 0xbd, 0x74, 0xa9, 0xdc,
+  0xae, 0x41, 0x63, 0x3c, 0xed, 0xe9, 0x87, 0xf6, 0xcb, 0xbb, 0xdc, 0x9a,
+  0xbd, 0x14, 0x2f, 0xd4, 0x31, 0xc6, 0x9c, 0xa7, 0x97, 0xa6, 0x1b, 0xa0,
+  0xde, 0xbf, 0xa2, 0xc2, 0x9b, 0x3f, 0xb3, 0x66, 0x64, 0xea, 0xa3, 0xad,
+  0x46, 0x42, 0xf1, 0x6f, 0xe7, 0x31, 0xff, 0x6f, 0x7f, 0x92, 0xbe, 0xab,
+  0x3a, 0x75, 0x2f, 0xfd, 0xa3, 0x48, 0x51, 0x4c, 0xe6, 0x6a, 0x81, 0x6a,
+  0xfe, 0xd5, 0x88, 0x37, 0x32, 0xdb, 0xe8, 0xb6, 0x14, 0x68, 0xb5, 0x53,
+  0xad, 0xb3, 0x4b, 0x06, 0x42, 0xbe, 0xd3, 0xc8, 0x66, 0x2a, 0xfd, 0x74,
+  0xf2, 0xa0, 0xb7, 0xd6, 0xd0, 0xd3, 0xb7, 0xe6, 0xba, 0xb6, 0x00, 0xd9,
+  0xab, 0x53, 0x70, 0x84, 0x35, 0xc4, 0x7e, 0x3d, 0x9b, 0x97, 0xd8, 0x86,
+  0x7f, 0x33, 0x09, 0x83, 0x35, 0x8e, 0xc8, 0x9f, 0x43, 0x0b, 0x64, 0x0c,
+  0xc1, 0xbb, 0xc9, 0x57, 0x2f, 0xb5, 0xe0, 0xfb, 0xea, 0x27, 0x02, 0x03,
+  0xcd, 0xb5, 0x9d, 0x1e, 0xe9, 0xbb, 0x7f, 0x09, 0x7c, 0x28, 0xe4, 0x19,
+  0xce, 0xe4, 0xa3, 0xd2, 0x52, 0xfa, 0x48, 0xa2, 0xdc, 0x50, 0xdb, 0x1a,
+  0x1a, 0x61, 0x13, 0x02, 0x77, 0x28, 0xf1, 0xa2, 0x4a, 0xac, 0xf3, 0x29,
+  0x00, 0x6b, 0x22, 0x37, 0x1a, 0x5c, 0x0c, 0x51, 0xf1, 0x11, 0xa0, 0xb7,
+  0x55, 0x7f, 0x58, 0x19, 0x3c, 0x1b, 0x0c, 0xe8, 0x3f, 0x92, 0x4c, 0xa1,
+  0x1e, 0xf0, 0xfe, 0x81, 0xb2, 0x8a, 0xf3, 0x3c, 0x70, 0xfa, 0x31, 0xec,
+  0x32, 0x55, 0x2d, 0xac, 0x9f, 0x3e, 0x30, 0x01, 0xad, 0x54, 0x13, 0x53,
+  0xf0, 0xd9, 0xb4, 0xa7, 0x14, 0xe7, 0x3c, 0xd2, 0x55, 0x54, 0xcf, 0x33,
+  0x11, 0x81, 0x9c, 0xea, 0xeb, 0x5c, 0x93, 0xfb, 0x0d, 0x9c, 0x02, 0xc7,
+  0x63, 0x64, 0x80, 0xfe, 0x23, 0x85, 0xbb, 0x0a, 0x97, 0x69, 0x84, 0xd4,
+  0x85, 0x5d, 0xae, 0x1c, 0xc3, 0x4d, 0xa3, 0x3f, 0x8e, 0xa4, 0x68, 0xb7,
+  0xf6, 0xc8, 0xef, 0x89, 0xa1, 0x0d, 0xab, 0x4e, 0xec, 0x31, 0xba, 0xca,
+  0xab, 0x1c, 0x61, 0x5c, 0x39, 0xe1, 0x6c, 0xc4, 0xa2, 0xf1, 0x48, 0xba,
+  0x13, 0x30, 0x62, 0x25, 0xb8, 0x81, 0xfd, 0xdc, 0x89, 0x1f, 0xfe, 0x2e,
+  0x5c, 0xee, 0xf2, 0x22, 0xa0, 0x57, 0x2d, 0x71, 0x9e, 0x64, 0xd8, 0x7b,
+  0x87, 0xd4, 0xe8, 0x7e, 0x82, 0x42, 0x66, 0x74, 0xd7, 0x68, 0xe0, 0xfd,
+  0x91, 0x61, 0xa1, 0xff, 0x83, 0x98, 0x75, 0x29, 0xc5, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0x94, 0x02, 0x87, 0xee, 0xee, 0xee, 0xee, 0xee, 0x50, 0x50, 0x50, 0x50,
+  0x29, 0x02, 0x00, 0x00, 0x97, 0xc2, 0xe5, 0x7f, 0x04, 0x8d, 0xab, 0x71,
+  0x5f, 0xe7, 0xf6, 0x31, 0x88, 0xc6, 0x6b, 0xfc, 0x02, 0x65, 0x1b, 0x14,
+  0x49, 0xaa, 0x7c, 0xa2, 0x12, 0x01, 0x08, 0x50, 0x31, 0xf0, 0x5e, 0xf8,
+  0x30, 0x82, 0x02, 0x25, 0x30, 0x82, 0x01, 0xab, 0xa0, 0x03, 0x02, 0x01,
+  0x02, 0x02, 0x0a, 0x15, 0x24, 0x41, 0x18, 0x76, 0x46, 0x31, 0x44, 0x50,
+  0x41, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03,
+  0x02, 0x30, 0x29, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x05,
+  0x13, 0x10, 0x39, 0x35, 0x65, 0x32, 0x33, 0x66, 0x66, 0x39, 0x62, 0x36,
+  0x65, 0x62, 0x30, 0x32, 0x35, 0x61, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03,
+  0x55, 0x04, 0x0c, 0x0c, 0x03, 0x54, 0x45, 0x45, 0x30, 0x1e, 0x17, 0x0d,
+  0x31, 0x38, 0x30, 0x35, 0x32, 0x35, 0x32, 0x33, 0x32, 0x38, 0x34, 0x33,
+  0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30, 0x35, 0x32, 0x32, 0x32, 0x33, 0x32,
+  0x38, 0x34, 0x33, 0x5a, 0x30, 0x29, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03,
+  0x55, 0x04, 0x05, 0x13, 0x10, 0x65, 0x65, 0x34, 0x62, 0x65, 0x65, 0x64,
+  0x33, 0x39, 0x33, 0x34, 0x37, 0x32, 0x65, 0x64, 0x62, 0x31, 0x0c, 0x30,
+  0x0a, 0x06, 0x03, 0x55, 0x04, 0x0c, 0x0c, 0x03, 0x54, 0x45, 0x45, 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, 0x28, 0x3b, 0xf5, 0xc3, 0xb6, 0x12, 0xf2, 0xb7, 0x8d, 0x25,
+  0x90, 0x2f, 0x1d, 0x5e, 0x91, 0x98, 0xd6, 0xad, 0xf7, 0xc9, 0x28, 0x25,
+  0x62, 0xc1, 0xd5, 0x42, 0x7e, 0xd0, 0xa7, 0x0b, 0xd9, 0x9b, 0x25, 0x6a,
+  0x2b, 0xbb, 0x7d, 0x62, 0x0d, 0x78, 0x42, 0xa3, 0x96, 0x42, 0x71, 0xf5,
+  0xc5, 0x7a, 0xe4, 0xac, 0xe2, 0x17, 0xd3, 0x02, 0x33, 0x21, 0x55, 0x92,
+  0x4d, 0x62, 0xd3, 0x3d, 0x9d, 0x3c, 0xa3, 0x81, 0xba, 0x30, 0x81, 0xb7,
+  0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x2d,
+  0xab, 0x5f, 0x1a, 0x58, 0xc2, 0x0c, 0x11, 0x12, 0x44, 0x96, 0x91, 0x66,
+  0x7c, 0xe1, 0xab, 0x47, 0x0d, 0x8a, 0xc4, 0x30, 0x1f, 0x06, 0x03, 0x55,
+  0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xc7, 0xbd, 0xe5, 0x13,
+  0x91, 0x8c, 0x85, 0x2e, 0x04, 0x5c, 0x13, 0xb5, 0xa3, 0x28, 0x93, 0xb7,
+  0x32, 0x63, 0xa3, 0x59, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
+  0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06,
+  0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02,
+  0x04, 0x30, 0x54, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x4d, 0x30, 0x4b,
+  0x30, 0x49, 0xa0, 0x47, 0xa0, 0x45, 0x86, 0x43, 0x68, 0x74, 0x74, 0x70,
+  0x73, 0x3a, 0x2f, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e,
+  0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63,
+  0x6f, 0x6d, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69,
+  0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x31, 0x35, 0x32, 0x34, 0x34,
+  0x31, 0x31, 0x38, 0x37, 0x36, 0x34, 0x36, 0x33, 0x31, 0x34, 0x34, 0x35,
+  0x30, 0x34, 0x31, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+  0x04, 0x03, 0x02, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x30, 0x3c, 0x07,
+  0x1f, 0xac, 0xc8, 0x38, 0x13, 0x81, 0xc5, 0xab, 0x00, 0x21, 0xea, 0xc9,
+  0x26, 0x34, 0xb4, 0xb8, 0xce, 0x7c, 0x19, 0x16, 0xef, 0x12, 0x50, 0x61,
+  0xc5, 0xce, 0x75, 0xec, 0x3b, 0x18, 0x73, 0x7f, 0x9b, 0x38, 0x74, 0xad,
+  0xd4, 0x78, 0xe2, 0xf8, 0x94, 0xf6, 0x1f, 0xa2, 0xa2, 0x12, 0x02, 0x31,
+  0x00, 0xee, 0x42, 0x9b, 0x75, 0x8e, 0x59, 0xe0, 0x9e, 0xfa, 0x93, 0xfd,
+  0x44, 0x82, 0xa7, 0x11, 0x9c, 0x07, 0xfd, 0x07, 0x90, 0x71, 0x27, 0xb2,
+  0x1e, 0x18, 0x58, 0x7e, 0xbe, 0xdf, 0xab, 0xfd, 0x2d, 0x26, 0xe8, 0x40,
+  0xa4, 0x96, 0xbb, 0x08, 0xe8, 0x1b, 0xb5, 0x47, 0xa3, 0xe7, 0xb7, 0xb2,
+  0xdc, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+  0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x8e, 0xe5, 0xcc, 0x90,
+  0xd5, 0xbe, 0xfc, 0x9a, 0x15, 0x3f, 0xce, 0x53, 0xfd, 0x9b, 0x13, 0x65,
+  0x9c, 0x26, 0x48, 0xef, 0x0d, 0xa1, 0xa2, 0x9c, 0x29, 0x1a, 0x71, 0x84,
+  0x7b, 0x61, 0xb4, 0xc0
+
+};
+
+#define CERT_BLOCK_SIZE 1024
+
+TEST_F(KeymasterProvisionTest, ProvisionCertificatesSuccess) {
+  // Fetch dev-id.
+  std::vector<uint8_t> dev_id;
+  nos::AppClient app(*client, APP_ID_NUGGET);
+
+  uint32_t retval;
+  dev_id.reserve(32);
+
+  retval = app.Call(NUGGET_PARAM_DEVICE_ID, dev_id, &dev_id);
+  ASSERT_EQ(retval, APP_SUCCESS);
+
+  // TODO: port this test over to Jenkins.
+  if (std::string(reinterpret_cast<const char *>(dev_id.data()),
+                  dev_id.size() -1) != string("adacb483:0100b022")) {
+    return;
+  }
+
+  for (int i = 0; i < 7; i++) {
+    ProvisionCertificatesRequest request;
+    ProvisionCertificatesResponse response;
+
+    request.set_block_number(i);
+    request.set_cert_block(
+        &ATTESTION_CERT_adacb483_0100b022[i * CERT_BLOCK_SIZE],
+        CERT_BLOCK_SIZE);
+    uint8_t digest[SHA256_DIGEST_LENGTH];
+    request.set_digest(
+        SHA256(&ATTESTION_CERT_adacb483_0100b022[i * CERT_BLOCK_SIZE],
+               CERT_BLOCK_SIZE, &digest[0]), SHA256_DIGEST_LENGTH);
+
+    Keymaster service(*client);
+    ASSERT_NO_ERROR(service.ProvisionCertificates(request, &response), "");
+    ASSERT_EQ((ErrorCode)response.error_code(), ErrorCode::OK);
+
+    if (i == 0) {
+      // On a fresh spiflash, expect certs to be missing.  On re-runs, certs
+      // will already be present.
+      EXPECT_TRUE(response.cert_status() == CertificateStatus::CERT_MISSING ||
+                  response.cert_status() ==
+                  CertificateStatus::CERT_PREVIOUSLY_PROVISIONED);
+    }
+    if (i == 6) {
+      // All done, cert status should indicate accordingly.
+      EXPECT_EQ(response.cert_status(),
+                CertificateStatus::CERT_PREVIOUSLY_PROVISIONED);
+    }
+  }
+}
+
 }  // namespace
diff --git a/src/test-data/test-keys/reset_key_data.cc b/src/test-data/test-keys/reset_key_data.cc
new file mode 100644
index 0000000..9f22c42
--- /dev/null
+++ b/src/test-data/test-keys/reset_key_data.cc
@@ -0,0 +1,124 @@
+
+#include "reset_key_data.h"
+
+namespace test_data {
+
+const uint8_t kResetKeyPem[] =
+"-----BEGIN RSA PRIVATE KEY-----\n\
+MIIEpAIBAAKCAQEAo0IoAa5cK7XyAj7u1jFStsfEcxkgAZVF9VWKzH1bofKxLioA\n\
+r5Lo4D33glKehxkOlDo6GkBj1PoI8WuvYYvEUyxJNUdlVpa1C2lbewEL0rfyBrZ9\n\
+4cp0ZeUknymYHn3ynW4Z8sYMlj7BNxGttV/jbxtgtT5WHJ+hg5/4/ifCPucN17Bt\n\
+heUKIBoAjy6DlB/pMg1NUQ82DaASMFe89mEzI9Zk4CRtkWjEhknY0bYm46U1ABJb\n\
+YmIsHlxdADskvWFDmq8CfJr/jXstTXxZeqaxPPdSP+WPwXN/ku5W7qkF2qimEKiy\n\
+DYHzY65JhfWmHOLLGNuz6iHkq93uzkKsGIIPGQIDAQABAoIBABGTvdrwetv56uRz\n\
+AiPti4pCV9RMkDWbbLzNSPRbStJU3t6phwlgN9Js2YkefBLvj7JF0pug8x6rDOtx\n\
+PKCz+5841Wj3FuILt9JStZa4th0p0NUIMOVudrnBwf+g6s/dn5FzmTeaOyCyAPt8\n\
+28b7W/FKcU8SNxM93JXfU1+JyFAdREqsXQfqLhCAXBb46fs5D8hg0c99RdWuJSuY\n\
+HKyVXDrjmYAHS5qUDeMx0OY/q1qM03FBvHekvJ78WPpUKF7B/gYH9lBHIHE0KLJY\n\
+JR6kKkzN/Ii6BsSubKKeuNntzlzd2ukvFdX4uc42dDpIXPdaQAn84KRYN7++KoGz\n\
+2LqtAAECgYEAzQt5kt9c+xDeKMPR92XQ4uMeLxTufBei1PFGZbJnJT8aEMkVhKT/\n\
+Pbh1Z8OnN9YvFprDNpEilUm7xyffrE7p0pI1/qiBXZExy6pIcGAo4ZcB8ayN0JV3\n\
+k+RilE73x+sKAyWOm82b273PiyHNsQI4flkO5Ev9rpZbPMKlvZYsmxkCgYEAy9RR\n\
+RwxwCpvFi3um0Rwz7CI2uvVXGaLVXyR2oNGLcJG7AhusYi4FX6XJQ3vAgiDmzu/c\n\
+SaEF9w7uqeueIUA7L7njYP1ojfJAUJEtQRfVJF2tDntN5YgYUTsx8n3IKTs4xFT4\n\
+dBthKo16zzLv92+8m4sWJhFW2zzFFLwk+G5jlAECgYEAln1piSZus8Y5h2nRXOZZ\n\
+XWyb5qpSLrmaRPegV1uM4IVjuBYduPDwdHhBkxrCS/TjMo/73ry+yRsIuq7FN03j\n\
+xyyQfItoByhdh8E+0VuCJbATOTEQFJre3KiuwXMD4LLc8lpKRIevcKPrA46XzOZ4\n\
+WCM9DsnHMrAf3oRt6KujqWECgYEAyu43fWUEp4suwg/5pXdOumnV040vinZzuKW0\n\
+9aeqDAkLBq5Gkfj/oJqOJoGux9+5640i5KtMJQzY0JOke7ZXNsz7dDTXQ3tMTOo9\n\
+A/GWYv5grWpVw5AbpcQpliNkhKhRfCactfwMYTE6c89i2haE0NdI1d2te9ik3l/y\n\
+7uP4gAECgYA3u2CumlkjHq+LbMK6Ry+Ajyy4ssM5PKJUqSogJDUkHsG/C7yaCdq/\n\
+Ljt2x2220H0pM9885C3PpKxoYwRih9dzOamnARJocAElp2b5AQB+tKddlMdwx1pQ\n\
+0IMGQ3fBYkDFLGYDk7hGYkLLlSJCZwi64xKmmfEwl83RL6JDSFupDg==\n\
+-----END RSA PRIVATE KEY-----";
+const size_t kResetKeyPemSize = sizeof(kResetKeyPem);
+
+// Dev-signed "null" message.
+static const uint8_t kNullDevSig[] = {
+  0x9d, 0x16, 0x0c, 0x04, 0x64, 0xd6, 0x17, 0xbc, 0xf9, 0x81, 0x4d, 0x7b,
+  0x15, 0x45, 0x2f, 0xa1, 0x66, 0xfa, 0x03, 0x45, 0x50, 0x9b, 0x60, 0x6e,
+  0x77, 0x76, 0x4d, 0x09, 0x99, 0x98, 0xe5, 0x8e, 0x0a, 0xf3, 0x4e, 0x09,
+  0x2c, 0xa0, 0xfd, 0x2e, 0xfa, 0x23, 0x16, 0x53, 0x61, 0x43, 0x6b, 0xba,
+  0xb7, 0xf8, 0x6b, 0xb4, 0xbe, 0x55, 0x3d, 0x21, 0x63, 0x84, 0x64, 0x00,
+  0x2d, 0xf0, 0x3c, 0x4d, 0x63, 0x4d, 0xe8, 0xf6, 0x26, 0xf7, 0x6b, 0x0e,
+  0x08, 0xca, 0xda, 0xa0, 0x8d, 0x0a, 0x3f, 0x06, 0x9d, 0xf7, 0x4d, 0x97,
+  0x86, 0xf4, 0xc2, 0x56, 0x94, 0x85, 0x46, 0xc0, 0x11, 0x0b, 0x9d, 0x12,
+  0x39, 0x9e, 0x3d, 0xb7, 0xcb, 0xac, 0xe9, 0x63, 0x10, 0xd7, 0xeb, 0x1c,
+  0x0b, 0xf7, 0x83, 0x06, 0xa8, 0xdd, 0x61, 0x38, 0xef, 0xe8, 0x13, 0x18,
+  0xda, 0xd8, 0xdc, 0xd6, 0x12, 0x1c, 0xf3, 0x7c, 0x6e, 0x19, 0xd6, 0x94,
+  0xe6, 0x3a, 0x6e, 0x8e, 0x5b, 0xcf, 0x3a, 0x69, 0x1c, 0xcf, 0xc2, 0x48,
+  0xc2, 0xb2, 0x1b, 0xb8, 0x24, 0xc2, 0xc5, 0x7e, 0xdc, 0x5d, 0x01, 0xe6,
+  0xfb, 0x14, 0xbf, 0x96, 0xc1, 0xd3, 0xdf, 0xe5, 0x14, 0x3f, 0xcb, 0xea,
+  0xfa, 0xef, 0xa7, 0x5c, 0xc3, 0xcb, 0x62, 0x09, 0x0e, 0x1f, 0xd9, 0x56,
+  0x35, 0xdb, 0x34, 0x23, 0x6a, 0xac, 0x43, 0x0d, 0x27, 0x90, 0x8e, 0x96,
+  0xcc, 0x89, 0xb6, 0x74, 0x45, 0x1e, 0x8f, 0x48, 0x2a, 0x1d, 0x8f, 0xba,
+  0xd0, 0x80, 0x7e, 0xf9, 0x1f, 0x21, 0x9b, 0x87, 0x80, 0x9b, 0x9e, 0x1a,
+  0xb8, 0xc3, 0xe4, 0x55, 0xaa, 0x67, 0xa5, 0x2d, 0x1a, 0x85, 0xd8, 0x6a,
+  0x9a, 0xc7, 0x5d, 0x1e, 0x1d, 0x51, 0x47, 0x09, 0x51, 0xf6, 0x7c, 0xe9,
+  0xfc, 0x1f, 0x9e, 0xea, 0xc9, 0xce, 0x77, 0xf2, 0xb1, 0x79, 0x7e, 0x17,
+  0xc2, 0x78, 0xab, 0xf7
+};
+
+static const uint8_t kNullProdSig[] = {
+  0x41, 0xcf, 0x80, 0xa7, 0x43, 0xdb, 0xb1, 0x08, 0x36, 0x5f, 0xbb, 0x23,
+  0xa4, 0x1c, 0xa9, 0x28, 0xdf, 0x64, 0x79, 0xeb, 0x41, 0x67, 0x5d, 0x35,
+  0x09, 0x76, 0x4a, 0xca, 0x74, 0xe8, 0xf0, 0x5b, 0x7d, 0x53, 0x8f, 0x5f,
+  0x49, 0xdb, 0x7c, 0x08, 0x70, 0xdb, 0xd3, 0xe2, 0x87, 0x51, 0x08, 0x6f,
+  0x13, 0x40, 0x33, 0x56, 0xa9, 0x99, 0x07, 0xee, 0x18, 0x88, 0xe0, 0x63,
+  0x15, 0x90, 0x4e, 0xd1, 0x4a, 0x51, 0x00, 0x91, 0x63, 0x3e, 0x55, 0x80,
+  0xfc, 0xde, 0x18, 0x55, 0x52, 0x89, 0xa0, 0x05, 0xdc, 0x99, 0x80, 0x2c,
+  0x90, 0xd1, 0x14, 0xea, 0xe0, 0xd7, 0xab, 0x26, 0x67, 0xe3, 0x75, 0xd0,
+  0x06, 0xa9, 0x36, 0x11, 0x21, 0xc8, 0x21, 0x4c, 0x49, 0xe2, 0x81, 0x66,
+  0x25, 0x2c, 0x41, 0xb6, 0x48, 0x65, 0x0b, 0x44, 0xc9, 0xcc, 0x0c, 0xad,
+  0x88, 0x95, 0x9d, 0x9a, 0x25, 0x71, 0xb3, 0x85, 0x22, 0xbf, 0x28, 0x05,
+  0x65, 0x62, 0x61, 0x54, 0x5d, 0xd9, 0xc8, 0x7c, 0x17, 0x5f, 0xec, 0xc7,
+  0x40, 0xaf, 0x66, 0xd3, 0x0a, 0x1f, 0x6a, 0x56, 0xbc, 0x48, 0x84, 0xf6,
+  0x61, 0xa3, 0xab, 0x3c, 0x81, 0x72, 0x75, 0x94, 0x5d, 0x03, 0xeb, 0xca,
+  0x7f, 0xb3, 0x48, 0xbc, 0x8f, 0x4c, 0xb3, 0xc2, 0xae, 0xa9, 0x53, 0x91,
+  0x17, 0x48, 0x48, 0x36, 0xb7, 0x7c, 0xd8, 0xe4, 0x99, 0x86, 0x1e, 0x57,
+  0xaa, 0xaf, 0xab, 0xe4, 0x61, 0x32, 0x58, 0xdb, 0x45, 0x38, 0x26, 0x32,
+  0x2c, 0xa0, 0x21, 0x34, 0xa3, 0xef, 0x6c, 0x2c, 0x8c, 0x74, 0x10, 0x3c,
+  0x70, 0x3e, 0xe2, 0x80, 0x7a, 0xf5, 0x9f, 0xf1, 0x92, 0x43, 0x4f, 0x21,
+  0xb8, 0x21, 0xd5, 0x7a, 0xa7, 0x36, 0xfc, 0x2e, 0x50, 0xd1, 0xa6, 0xbf,
+  0xfc, 0xc7, 0x57, 0x75, 0x19, 0xb7, 0xcf, 0x8f, 0xdb, 0x3d, 0x1c, 0xa2,
+  0xdc, 0x81, 0x71, 0x82
+};
+
+static const uint8_t kNullTestSig[] = {
+  0x95, 0x35, 0x5a, 0xb6, 0xe3, 0x8e, 0x43, 0x03, 0xd9, 0xd9, 0xd5, 0x6e,
+  0x99, 0x86, 0xff, 0x8e, 0x6a, 0xf1, 0x54, 0x6f, 0xa8, 0xff, 0x37, 0x38,
+  0xc6, 0x9b, 0x4d, 0xc6, 0x99, 0x1f, 0x37, 0x5c, 0xec, 0xf4, 0x32, 0xd8,
+  0xe6, 0x00, 0xcc, 0x74, 0xde, 0xa9, 0x68, 0x1a, 0xab, 0x6a, 0x6e, 0xe7,
+  0xa7, 0xa1, 0x59, 0xe0, 0x7c, 0x86, 0x95, 0x28, 0x94, 0x18, 0x3f, 0x0f,
+  0xb9, 0x0f, 0x05, 0x6c, 0x86, 0x5a, 0x6a, 0xe4, 0x6d, 0x36, 0x71, 0x86,
+  0x38, 0xab, 0x7a, 0x2d, 0x9c, 0xa5, 0xfa, 0xc8, 0x7c, 0x48, 0x02, 0x8c,
+  0x6b, 0x4d, 0xda, 0xa4, 0xb5, 0xa8, 0x17, 0x39, 0x5e, 0xe3, 0x1a, 0xd5,
+  0xf8, 0x87, 0x6e, 0xd9, 0xc0, 0x0c, 0x29, 0x4d, 0x93, 0xa2, 0x3b, 0xfc,
+  0x2d, 0x38, 0x8e, 0x2b, 0xc7, 0x49, 0x26, 0xd9, 0xcb, 0x47, 0x89, 0x4c,
+  0x79, 0xd3, 0x60, 0x62, 0xf9, 0x71, 0xa7, 0x73, 0x6a, 0x03, 0x65, 0x1f,
+  0x11, 0x0d, 0x9e, 0x27, 0x99, 0x6b, 0xa7, 0x46, 0x85, 0x75, 0xec, 0xff,
+  0x5b, 0x1d, 0x8d, 0x1b, 0x34, 0xd8, 0xb9, 0x4f, 0x63, 0x88, 0x08, 0xa8,
+  0x16, 0xba, 0xfc, 0xe7, 0x66, 0xa4, 0xe5, 0xde, 0x4e, 0x0b, 0x98, 0x80,
+  0xd5, 0x16, 0x55, 0xfb, 0xdb, 0xe8, 0xa2, 0x90, 0x85, 0x4e, 0xa9, 0xb6,
+  0x81, 0x55, 0xef, 0xbf, 0x12, 0xe3, 0xd2, 0xa9, 0xae, 0x2c, 0x43, 0x67,
+  0x4c, 0x09, 0x6d, 0x95, 0xaf, 0x44, 0xc2, 0xb9, 0x9d, 0x7c, 0xb1, 0x88,
+  0xf8, 0x6c, 0xa0, 0x13, 0x4c, 0xbf, 0x85, 0xa2, 0x8b, 0x9d, 0x06, 0xc8,
+  0x11, 0xdb, 0x1f, 0xfb, 0x05, 0x15, 0xd6, 0x1f, 0xe5, 0x52, 0x9c, 0xd5,
+  0xbd, 0xff, 0xb0, 0xce, 0x29, 0xec, 0xd8, 0x9e, 0xdb, 0x5b, 0xc9, 0x52,
+  0x24, 0xaf, 0x22, 0xeb, 0xce, 0x15, 0x0d, 0xfd, 0x6c, 0x76, 0x90, 0x3e,
+  0x4f, 0x63, 0xfd, 0xb1
+};
+
+const uint8_t *kResetSignatures[] = {
+ [0] = kNullTestSig,
+ [1] = kNullDevSig,
+ [2] = kNullProdSig,
+};
+
+const size_t kResetSignatureLengths[] = {
+ 256, 256, 256,
+};
+
+const size_t kResetSignatureCount = 3;
+
+}  // namespace test_data
diff --git a/src/test-data/test-keys/reset_key_data.h b/src/test-data/test-keys/reset_key_data.h
new file mode 100644
index 0000000..0fb948f
--- /dev/null
+++ b/src/test-data/test-keys/reset_key_data.h
@@ -0,0 +1,17 @@
+#ifndef SRC_TEST_RESET_KEYS_H
+#define SRC_TEST_RESET_KEYS_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace test_data {
+
+extern const uint8_t kResetKeyPem[];
+extern const size_t kResetKeyPemSize;
+extern const uint8_t *kResetSignatures[];
+extern const size_t kResetSignatureLengths[];
+extern const size_t kResetSignatureCount;
+}  // namespace test_data
+
+
+#endif  // SRC_TEST_RESET_KEYS_H
diff --git a/src/test-data/test-keys/rsa.h b/src/test-data/test-keys/rsa.h
index 07965e7..80a163b 100644
--- a/src/test-data/test-keys/rsa.h
+++ b/src/test-data/test-keys/rsa.h
@@ -27,14 +27,8 @@
   const uint8_t *n;
   const size_t size;
 } TEST_RSA_KEYS[] = {
-  {3,     RSA_3_512_D, RSA_3_512_N, sizeof(RSA_3_512_N)},
-  {65537, RSA_512_D,   RSA_512_N,   sizeof(RSA_512_N)},
-  {65537, RSA_768_D,   RSA_768_N,   sizeof(RSA_768_N)},
   {65537, RSA_1024_D,  RSA_1024_N,  sizeof(RSA_1024_N)},
   {65537, RSA_2048_D,  RSA_2048_N,  sizeof(RSA_2048_N)},
-  {65537, RSA_3072_D,  RSA_3072_N,  sizeof(RSA_3072_N)},
-  // TODO: update transport to accept larger messages.
-  //  {RSA_4096_D, RSA_4096_N, sizeof(RSA_4096_N)},
 };
 
 
diff --git a/src/transport_tests.cc b/src/transport_tests.cc
new file mode 100644
index 0000000..b57ccae
--- /dev/null
+++ b/src/transport_tests.cc
@@ -0,0 +1,798 @@
+#include <memory>
+
+#include "gmock/gmock.h"
+#include "nos/device.h"
+#include "nos/NuggetClient.h"
+#include "application.h"
+#include "app_transport_test.h"
+#include "util.h"
+
+using std::cout;
+using std::string;
+using std::unique_ptr;
+
+/*
+ * These test use the datagram protocol diretly to test that Citadel's transport
+ * implementation works as expected.
+ */
+namespace {
+
+static const uint16_t crc16_table[256] = {
+  0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
+  0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
+  0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
+  0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
+  0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
+  0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
+  0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
+  0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
+  0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
+  0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
+  0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
+  0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
+  0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
+  0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
+  0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
+  0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
+  0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
+  0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
+  0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
+  0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
+  0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
+  0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
+  0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
+  0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
+  0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
+  0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
+  0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
+  0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
+  0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
+  0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
+  0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
+  0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
+};
+
+uint16_t crc16_update(const void *buf, uint32_t len, uint16_t crc) {
+  uint32_t i;
+  const uint8_t *bytes = reinterpret_cast<const uint8_t *>(buf);
+  for (i = 0; i < len; ++i) {
+    crc = crc16_table[((crc >> 8) ^ *bytes++) & 0xFF] ^ (crc << 8);
+  }
+  return crc;
+}
+
+uint16_t crc16(const void *buf, uint32_t len) {
+  return crc16_update(buf, len, 0);
+}
+
+#define RETRY_COUNT 30
+#define RETRY_WAIT_TIME_US 5000
+
+/*
+ * Read a datagram from the device, correctly handling retries.
+ */
+static int nos_device_read(const struct nos_device *dev, uint32_t command,
+                           void *buf, uint32_t len) {
+  int retries = RETRY_COUNT;
+  while (retries--) {
+    int err = dev->ops.read(dev->ctx, command, reinterpret_cast<uint8_t *>(buf), len);
+
+    if (err == -EAGAIN) {
+      /* Linux driver returns EAGAIN error if Citadel chip is asleep.
+       * Give to the chip a little bit of time to awake and retry reading
+       * status again. */
+      usleep(RETRY_WAIT_TIME_US);
+      continue;
+    }
+    return -err;
+  }
+
+  return ETIMEDOUT;
+}
+
+/*
+ * Write a datagram to the device, correctly handling retries.
+ */
+static int nos_device_write(const struct nos_device *dev, uint32_t command,
+                            const void *buf, uint32_t len) {
+  int retries = RETRY_COUNT;
+  while (retries--) {
+    int err = dev->ops.write(dev->ctx, command, reinterpret_cast<const uint8_t *>(buf), len);
+
+    if (err == -EAGAIN) {
+      /* Linux driver returns EAGAIN error if Citadel chip is asleep.
+       * Give to the chip a little bit of time to awake and retry reading
+       * status again. */
+      usleep(RETRY_WAIT_TIME_US);
+      continue;
+    }
+    return -err;
+  }
+
+  return ETIMEDOUT;
+}
+
+/*
+ * The transport protocol has 4 stages:
+ *   1. Resetting the slave
+ *   2. Sending a command to the slave
+ *   3. Polling until the slave is done
+ *   4. Fetching the result from the slave
+ *
+ * There are CRCs used on the messages to ensure integrity. If the CRC fails,
+ * the the data transfer is retried. This can happen for the status message,
+ * arguments and command message or the reply data.
+ */
+class TransportTest: public testing::Test {
+ protected:
+  static nos_device* dev;
+  static unique_ptr<nos::NuggetClient> client;
+  static unique_ptr<test_harness::TestHarness> uart_printer;
+
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+
+  virtual void SetUp();
+};
+
+nos_device* TransportTest::dev;
+unique_ptr<nos::NuggetClient> TransportTest::client;
+unique_ptr<test_harness::TestHarness> TransportTest::uart_printer;
+
+void TransportTest::SetUpTestCase() {
+  uart_printer = test_harness::TestHarness::MakeUnique();
+
+  client = nugget_tools::MakeDirectNuggetClient();
+  client->Open();
+  EXPECT_TRUE(client->IsOpen()) << "Unable to connect";
+  dev = client->Device();
+}
+
+void TransportTest::TearDownTestCase() {
+  dev = nullptr;
+  client->Close();
+  client.reset();
+
+  uart_printer = nullptr;
+}
+
+void TransportTest::SetUp() {
+  // Reset and give it a bit of time to settle
+  ASSERT_TRUE(nugget_tools::RebootNuggetUnchecked(client.get()));
+  // Give a bit of time for the reboot to take effect
+  usleep(30000);
+}
+
+bool StatusMatches(const transport_status& arg, uint32_t status, uint16_t flags,
+                   uint8_t* reply, uint16_t reply_len) {
+  bool ok = true;
+
+  // v0 fields
+  ok &= arg.status == status;
+  ok &= arg.reply_len == reply_len;
+
+  // v1 fields
+  ok &= arg.length == sizeof(transport_status);
+  ok &= arg.version == TRANSPORT_V1;
+  ok &= arg.flags == flags;
+
+  // Check the status is a valid length
+  if (arg.length < STATUS_MIN_LENGTH || arg.length > STATUS_MAX_LENGTH) {
+    return false;
+  }
+
+  // As of v1, the length shouldn\t be greater than transport_status
+  if (arg.length > sizeof(transport_status)) {
+    return false;
+  }
+
+  // Check the CRCs are valid
+  transport_status st = arg;
+  st.crc = 0;
+  ok &= arg.crc == crc16(&st, st.length);
+  ok &= arg.reply_crc == crc16(reply, reply_len);
+
+  return ok;
+}
+
+MATCHER(IsIdle, "") {
+  return StatusMatches(arg,
+                       APP_STATUS_IDLE, 0,
+                       nullptr, 0);
+}
+
+MATCHER(IsWorking, "") {
+  return StatusMatches(arg,
+                       APP_STATUS_IDLE, STATUS_FLAG_WORKING,
+                       nullptr, 0);
+}
+
+MATCHER(IsTooMuch, "") {
+  return StatusMatches(arg,
+                       APP_STATUS_DONE | APP_ERROR_TOO_MUCH, 0,
+                       nullptr, 0);
+}
+
+MATCHER(IsBadCrc, "") {
+  return StatusMatches(arg,
+                       APP_STATUS_DONE | APP_ERROR_CHECKSUM, 0,
+                       nullptr, 0);
+}
+
+MATCHER(IsSuccess, "") {
+  return StatusMatches(arg,
+                       APP_STATUS_DONE | APP_SUCCESS, 0,
+                       nullptr, 0);
+}
+
+MATCHER_P2(IsSuccessWithData, data, len, "") {
+  return StatusMatches(arg,
+                       APP_STATUS_DONE | APP_SUCCESS, 0,
+                       data, len);
+}
+
+// Give the app time to complete rather than polling
+void WaitForApp() {
+  usleep(30000);
+}
+
+// Calculate and set the CRC for the command from data or the struct
+void SetCommandInfoCrc(const void* arg, uint16_t arg_len, uint32_t command,
+                       void* command_info, uint16_t command_info_len) {
+    uint16_t crc = crc16(&arg_len, sizeof(arg_len));
+    crc = crc16_update(arg, arg_len, crc);
+    crc = crc16_update(&command, sizeof(command), crc);
+    uint16_t* const info_crc
+        = (uint16_t*)&((uint8_t*)command_info)[offsetof(transport_command_info, crc)];
+    *info_crc = 0;
+    *info_crc = crc16_update(command_info, command_info_len, crc);
+}
+void SetCommandInfoCrc(const void* arg, uint16_t arg_len, uint32_t command,
+                       transport_command_info* info) {
+  SetCommandInfoCrc(arg, arg_len, command, info, sizeof(*info));
+}
+
+/* The initial state is to be idle. */
+TEST_F(TransportTest, ResetToIdle) {
+  transport_status status;
+  const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+  ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+  ASSERT_THAT(status, IsIdle());
+}
+
+/* The master will be polling so need to confirm app is still working. */
+TEST_F(TransportTest, CommandImmediatelyTriggersWorking) {
+  { // Send "go" command
+    transport_command_info command_info = {};
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(0);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsWorking());
+  }
+}
+
+TEST_F(TransportTest, CommandBadCrc) {
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(0);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsBadCrc());
+  }
+}
+
+TEST_F(TransportTest, TooMuchData) {
+  { // Send data
+    uint8_t data[32] = {};
+    uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_DATA | CMD_TRANSPORT;
+    CMD_SET_PARAM(command, sizeof(data));
+    ASSERT_EQ(nos_device_write(dev, command, data, sizeof(data)), 0);
+  }
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(0);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsTooMuch());
+  }
+}
+
+/* Until the app says it is done, it is working. */
+TEST_F(TransportTest, HangKeepsWorking) {
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_HANG);
+    SetCommandInfoCrc(nullptr, 0, command, &command_info);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsWorking());
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsWorking());
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsWorking());
+  }
+}
+
+/* While the app is working, the master can only wait and can't modify memory. */
+TEST_F(TransportTest, CannotClearStatusWhileWorking) {
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_HANG);
+    SetCommandInfoCrc(nullptr, 0, command, &command_info);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  { // Attempt to clear status
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_write(dev, command, nullptr, 0), 0);
+  }
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsWorking());
+  }
+}
+
+/* Protect from any race conditions that could arise. */
+TEST_F(TransportTest, CannotStartNewCommandWhileWorking) {
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_HANG);
+    SetCommandInfoCrc(nullptr, 0, command, &command_info);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_1234);
+    SetCommandInfoCrc(nullptr, 0, command, &command_info);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsWorking());
+  }
+}
+
+TEST_F(TransportTest, CommandSuccess) {
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_NOP);
+    SetCommandInfoCrc(nullptr, 0, command, &command_info);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsSuccess());
+  }
+}
+
+TEST_F(TransportTest, CommandSuccessWithData) {
+  uint8_t data[4];
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    command_info.reply_len_hint = sizeof(data);
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_1234);
+    SetCommandInfoCrc(nullptr, 0, command, &command_info);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_EQ(status.reply_len, sizeof(data));
+
+    const uint32_t data_command = CMD_ID(APP_ID_TRANSPORT_TEST)
+                                | CMD_IS_READ | CMD_IS_DATA | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, data_command, data, sizeof(data)), 0);
+    ASSERT_THAT(status, IsSuccessWithData(data, sizeof(data)));
+  }
+}
+
+/* The crc is only calculated over the data the master will read. */
+TEST_F(TransportTest, CommandSuccessReplyLenHintRespected) {
+  constexpr uint16_t reply_len_hint = 2; // This is less than the actual response
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    command_info.reply_len_hint = reply_len_hint;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_1234);
+    SetCommandInfoCrc(nullptr, 0, command, &command_info);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    uint8_t data[4];
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_EQ(status.reply_len, reply_len_hint);
+
+    const uint32_t data_command = CMD_ID(APP_ID_TRANSPORT_TEST)
+                                | CMD_IS_READ | CMD_IS_DATA | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, data_command, data, reply_len_hint), 0);
+    // crc is only calculated over the data the master will read
+    ASSERT_THAT(status, IsSuccessWithData(data, reply_len_hint));
+  }
+}
+
+/* If there was a transmission error, need to be able to re-read data. */
+TEST_F(TransportTest, CommandSuccessRetryReadingData) {
+  uint8_t data[4];
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    command_info.reply_len_hint = sizeof(data);
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_1234);
+    SetCommandInfoCrc(nullptr, 0, command, &command_info);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_EQ(status.reply_len, sizeof(data));
+
+    // This could happen if there was a crc error
+    for (int i = 0; i < 3; ++i) {
+      const uint32_t data_command = CMD_ID(APP_ID_TRANSPORT_TEST)
+                                  | CMD_IS_READ | CMD_IS_DATA | CMD_TRANSPORT;
+      ASSERT_EQ(nos_device_read(dev, data_command, data, sizeof(data)), 0);
+      ASSERT_THAT(status, IsSuccessWithData(data, sizeof(data)));
+    }
+  }
+}
+
+TEST_F(TransportTest, ClearStatusAfterSuccess) {
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_NOP);
+    SetCommandInfoCrc(nullptr, 0, command, &command_info);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Clear status
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_write(dev, command, nullptr, 0), 0);
+  }
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsIdle());
+  }
+}
+
+TEST_F(TransportTest, ClearStatusAfterError) {
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(0);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Clear status
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_write(dev, command, nullptr, 0), 0);
+  }
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsIdle());
+  }
+}
+
+TEST_F(TransportTest, SendArgumentData) {
+  const uint32_t data = 0x09080706;
+  { // Send data
+    uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_DATA | CMD_TRANSPORT;
+    CMD_SET_PARAM(command, sizeof(data));
+    ASSERT_EQ(nos_device_write(dev, command, &data, sizeof(data)), 0);
+  }
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_9876);
+    SetCommandInfoCrc(&data, sizeof(data), command, &command_info);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsSuccess());
+  }
+}
+
+/* Setting CMD_MORE_TO_COME appends new data. */
+TEST_F(TransportTest, SendArgumentDataInMultipleDatagrams) {
+  const uint32_t data = 0x09080706;
+  { // Send data1
+    const uint16_t data1 = 0x0706;
+    uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_DATA | CMD_TRANSPORT;
+    CMD_SET_PARAM(command, sizeof(data1));
+    ASSERT_EQ(nos_device_write(dev, command, &data1, sizeof(data1)), 0);
+  }
+  { // Send data2
+    const uint16_t data2 = 0x0908;
+    uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST)
+                     | CMD_IS_DATA | CMD_TRANSPORT | CMD_MORE_TO_COME;
+    CMD_SET_PARAM(command, sizeof(data2));
+    ASSERT_EQ(nos_device_write(dev, command, &data2, sizeof(data2)), 0);
+  }
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_9876);
+    SetCommandInfoCrc(&data, sizeof(data), command, &command_info);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsSuccess());
+  }
+}
+
+/* Not setting the CMD_MORE_TO_COME flag overwrites rather than appends. */
+TEST_F(TransportTest, SendWrongArgumentDataByRestarting) {
+  const uint32_t data = 0x09080706;
+  { // Send data1
+    const uint16_t data1 = 0x0706;
+    uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_DATA | CMD_TRANSPORT;
+    CMD_SET_PARAM(command, sizeof(data1));
+    ASSERT_EQ(nos_device_write(dev, command, &data1, sizeof(data1)), 0);
+  }
+  { // Send data2, restarting the args
+    const uint16_t data2 = 0x0908;
+    uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_DATA | CMD_TRANSPORT;
+    CMD_SET_PARAM(command, sizeof(data2));
+    ASSERT_EQ(nos_device_write(dev, command, &data2, sizeof(data2)), 0);
+  }
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_9876);
+    SetCommandInfoCrc(&data, sizeof(data), command, &command_info);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status, bad crc as the args data is wrong
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsBadCrc());
+  }
+}
+
+/* Not setting the CMD_MORE_TO_COME flag clears previous data. */
+TEST_F(TransportTest, SendArgumentDataInMultipleDatagramsWithRestart) {
+  const uint32_t data = 0x09080706;
+  { // Send data1
+    const uint8_t spam[6] = {12, 46, 123, 63, 23, 75};
+    uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_DATA | CMD_TRANSPORT;
+    CMD_SET_PARAM(command, sizeof(spam));
+    ASSERT_EQ(nos_device_write(dev, command, spam, sizeof(spam)), 0);
+  }
+  { // Send data1, restarting the args
+    const uint16_t data1 = 0x0706;
+    uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_DATA | CMD_TRANSPORT;
+    CMD_SET_PARAM(command, sizeof(data1));
+    ASSERT_EQ(nos_device_write(dev, command, &data1, sizeof(data1)), 0);
+  }
+  { // Send data2
+    const uint16_t data2 = 0x0908;
+    uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST)
+                     | CMD_IS_DATA | CMD_TRANSPORT | CMD_MORE_TO_COME;
+    CMD_SET_PARAM(command, sizeof(data2));
+    ASSERT_EQ(nos_device_write(dev, command, &data2, sizeof(data2)), 0);
+  }
+  { // Send "go" command
+    transport_command_info command_info = {};
+    command_info.length = sizeof(transport_command_info);
+    command_info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_9876);
+    SetCommandInfoCrc(&data, sizeof(data), command, &command_info);
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsSuccess());
+  }
+}
+
+// Forward compatibility
+
+/* New command info fields may be add in future versions. The crc is still
+ * calculated over them to ensure data integrity but, otherwise, the values are
+ * ignored. */
+TEST_F(TransportTest, NewCommandInfoIsIgnored) {
+  { // Send "go" command
+    union {
+      transport_command_info info;
+      uint8_t buffer[COMMAND_INFO_MAX_LENGTH];
+    } command_info = {};
+    memset(command_info.buffer, 0x48, COMMAND_INFO_MAX_LENGTH);
+    command_info.info.length = COMMAND_INFO_MAX_LENGTH;
+    command_info.info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_NOP);
+    // CRC is still calculated over all the data but new fields aren't used
+    SetCommandInfoCrc(nullptr, 0, command, &command_info, sizeof(command_info));
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsSuccess());
+  }
+}
+
+/* If the protocol adds more data to the command info datagram, it is not
+ * included in the crc. */
+TEST_F(TransportTest, CommandCrcOnlyCoversCommandInfoStruct) {
+  { // Send "go" command
+    union {
+      transport_command_info info;
+      /* The extra byte should not be included in the crc */
+      uint8_t buffer[COMMAND_INFO_MAX_LENGTH + 1];
+    } command_info = {};
+    command_info.info.length = COMMAND_INFO_MAX_LENGTH;
+    command_info.info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(0);
+    SetCommandInfoCrc(nullptr, 0, command, &command_info, sizeof(command_info));
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsBadCrc());
+  }
+}
+
+/* Future protocol updates may require more command info data which will be
+ * added after the COMMAND_INFO_MAX_LENGTH bytes currently reserved for the
+ * command info struct. The extra data should be ignored to allow for
+ * compatibility with such an upgrade. */
+TEST_F(TransportTest, NewCommandInfoStructIsIgnored) {
+  { // Send "go" command
+    union {
+      transport_command_info info;
+      struct {
+        uint8_t info[COMMAND_INFO_MAX_LENGTH];
+        uint8_t new_struct[48];
+      } buffer;
+    } command_info = {};
+    memset(command_info.buffer.info, 0xB6, COMMAND_INFO_MAX_LENGTH);
+    memset(command_info.buffer.new_struct, 0x19, sizeof(command_info.buffer.new_struct));
+    command_info.info.length = COMMAND_INFO_MAX_LENGTH;
+    command_info.info.version = TRANSPORT_V1;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_NOP);
+    // CRC is still calculated over all the data but new fields aren't used
+    SetCommandInfoCrc(nullptr, 0, command, &command_info, sizeof(command_info));
+    ASSERT_EQ(nos_device_write(dev, command, &command_info, sizeof(command_info)), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsSuccess());
+  }
+}
+
+// Backward compatibility
+
+/* V0 does not send any checksums or command info */
+TEST_F(TransportTest, CompatibleWithV0) {
+  { // Send data
+    uint8_t data[4] = {23, 54, 133, 249};
+    uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_DATA | CMD_TRANSPORT;
+    CMD_SET_PARAM(command, sizeof(data));
+    ASSERT_EQ(nos_device_write(dev, command, &data, sizeof(data)), 0);
+  }
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsIdle());
+  }
+  { // Send "go" command (without command info or crc)
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_PARAM(TRANSPORT_TEST_NOP);
+    ASSERT_EQ(nos_device_write(dev, command, nullptr, 0), 0);
+  }
+  // Let app process command
+  WaitForApp();
+  { // Check status
+    transport_status status;
+    const uint32_t command = CMD_ID(APP_ID_TRANSPORT_TEST) | CMD_IS_READ | CMD_TRANSPORT;
+    ASSERT_EQ(nos_device_read(dev, command, &status, sizeof(transport_status)), 0);
+    ASSERT_THAT(status, IsSuccess());
+  }
+}
+
+}  // namespace
diff --git a/tools/keymaster_tools.cc b/tools/keymaster_tools.cc
index 68697c9..b91a52b 100644
--- a/tools/keymaster_tools.cc
+++ b/tools/keymaster_tools.cc
@@ -43,4 +43,21 @@
   avb_tools::BootloaderDone(client);
 }
 
+void SetBootState(nos::NuggetClientInterface *client)
+{
+
+  // Do keymaster setup that is normally executed by the bootloader.
+  avb_tools::SetBootloader(client);
+
+  SetBootStateRequest request;
+  SetBootStateResponse response;
+  Keymaster service(*client);
+  request.set_public_key(string(32, '\0'));
+  request.set_boot_hash(string(32, '\0'));
+  ASSERT_NO_ERROR(service.SetBootState(request, &response), "");
+  EXPECT_EQ((ErrorCode)response.error_code(), ErrorCode::OK);
+
+  avb_tools::BootloaderDone(client);
+}
+
 }  // namespace keymaster_tools
diff --git a/tools/keymaster_tools.h b/tools/keymaster_tools.h
index 2b659cd..39715b9 100644
--- a/tools/keymaster_tools.h
+++ b/tools/keymaster_tools.h
@@ -13,6 +13,7 @@
 namespace keymaster_tools {
 
 void SetRootOfTrust(nos::NuggetClientInterface *client);
+void SetBootState(nos::NuggetClientInterface *client);
 
 }  // namespace keymaster_tools
 
diff --git a/tools/nugget_tools.cc b/tools/nugget_tools.cc
index 3a692fc..36466d6 100644
--- a/tools/nugget_tools.cc
+++ b/tools/nugget_tools.cc
@@ -31,6 +31,16 @@
 
 namespace nugget_tools {
 
+bool IsDirectDeviceClient() {
+#ifdef ANDROID
+  nos::NuggetClient client;
+  client.Open();
+  return client.IsOpen();
+#else
+  return true;
+#endif
+}
+
 std::string GetCitadelUSBSerialNo() {
 #ifdef ANDROID
   return "";
@@ -62,6 +72,17 @@
 #endif
 }
 
+std::unique_ptr<nos::NuggetClient> MakeDirectNuggetClient() {
+#ifdef ANDROID
+  std::unique_ptr<nos::NuggetClient> client =
+      std::unique_ptr<nos::NuggetClient>(new nos::NuggetClient());
+  return client;
+#else
+  return std::unique_ptr<nos::NuggetClient>(
+      new nos::NuggetClient(GetCitadelUSBSerialNo()));
+#endif
+}
+
 bool CyclesSinceBoot(nos::NuggetClientInterface *client, uint32_t *cycles) {
   std::vector<uint8_t> buffer;
   buffer.reserve(sizeof(uint32_t));
@@ -95,6 +116,16 @@
          stats.time_spent_in_deep_sleep);
 }
 
+bool RebootNuggetUnchecked(nos::NuggetClientInterface *client) {
+  std::vector<uint8_t> ignored;
+  if (client->CallApp(APP_ID_NUGGET, NUGGET_PARAM_REBOOT, ignored,
+                      nullptr) != app_status::APP_SUCCESS) {
+    LOG(ERROR) << "CallApp(..., NUGGET_PARAM_REBOOT, ...) failed!\n";
+    return false;
+  }
+  return true;
+}
+
 bool RebootNugget(nos::NuggetClientInterface *client) {
   struct nugget_app_low_power_stats stats0;
   struct nugget_app_low_power_stats stats1;
@@ -113,12 +144,7 @@
   auto start = high_resolution_clock::now();
 
   // Tell Nugget OS to reboot
-  std::vector<uint8_t> ignored;
-  if (client->CallApp(APP_ID_NUGGET, NUGGET_PARAM_REBOOT, ignored,
-                      nullptr) != app_status::APP_SUCCESS) {
-    LOG(ERROR) << "CallApp(..., NUGGET_PARAM_REBOOT, ...) failed!\n";
-    return false;
-  }
+  if (!RebootNuggetUnchecked(client)) return false;
 
   // Grab stats after sleeping
   buffer.empty();
diff --git a/tools/nugget_tools.h b/tools/nugget_tools.h
index 1db4c0c..11c46e8 100644
--- a/tools/nugget_tools.h
+++ b/tools/nugget_tools.h
@@ -4,7 +4,7 @@
 #include <app_nugget.h>
 #include <application.h>
 #include <nos/debug.h>
-#include <nos/NuggetClientInterface.h>
+#include <nos/NuggetClient.h>
 
 #include <memory>
 #include <string>
@@ -18,11 +18,17 @@
 
 namespace nugget_tools {
 
+bool IsDirectDeviceClient();
+
 std::string GetCitadelUSBSerialNo();
 
 std::unique_ptr<nos::NuggetClientInterface> MakeNuggetClient();
 
+std::unique_ptr<nos::NuggetClient> MakeDirectNuggetClient();
+
 // Always does a hard reboot. Use WaitForSleep() if you just want deep sleep.
+bool RebootNuggetUnchecked(nos::NuggetClientInterface *client);
+// Does a hard reboot and checks the stats to make sure it happened.
 bool RebootNugget(nos::NuggetClientInterface *client);
 
 // Returns true if Citadel entered deep sleep