[tor-commits] [stegotorus/master] Add ECB support to the crypt.h API.

zwol at torproject.org zwol at torproject.org
Fri Jul 20 23:17:07 UTC 2012


commit 29396e18c427623b582c16ab26f89100f194e86f
Author: Zack Weinberg <zackw at panix.com>
Date:   Tue Mar 6 13:56:45 2012 -0800

    Add ECB support to the crypt.h API.
---
 src/crypt.cc               |  118 +++++++--
 src/crypt.h                |   97 +++++--
 src/protocol/chop.cc       |   12 +-
 src/test/unittest_crypt.cc |  610 +++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 765 insertions(+), 72 deletions(-)

diff --git a/src/crypt.cc b/src/crypt.cc
index 612eeee..402ae58 100644
--- a/src/crypt.cc
+++ b/src/crypt.cc
@@ -36,38 +36,100 @@ public:
   }                                                             \
   return rv /* deliberate absence of semicolon */
 
+// Crypto++ doesn't let us set a key without also setting an IV,
+// even though we will always override the IV later.
+static const uint8_t dummy_iv[16] = {};
+
+namespace {
+  struct ecb_encryptor_impl : ecb_encryptor
+  {
+    CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption ctx;
+    virtual ~ecb_encryptor_impl();
+    virtual void encrypt(uint8_t *out, const uint8_t *in);
+  };
+
+  struct ecb_decryptor_impl : ecb_decryptor
+  {
+    CryptoPP::ECB_Mode<CryptoPP::AES>::Decryption ctx;
+    virtual ~ecb_decryptor_impl();
+    virtual void decrypt(uint8_t *out, const uint8_t *in);
+  };
+}
+
+ecb_encryptor *
+ecb_encryptor::create(const uint8_t *key, size_t keylen)
+{
+  try {
+    ecb_encryptor_impl *enc = new ecb_encryptor_impl;
+    enc->ctx.SetKey(key, keylen);
+    return enc;
+  }
+  CATCH_ALL_EXCEPTIONS(0);
+}
+
+ecb_decryptor *
+ecb_decryptor::create(const uint8_t *key, size_t keylen)
+{
+  try {
+    ecb_decryptor_impl *dec = new ecb_decryptor_impl;
+    dec->ctx.SetKey(key, keylen);
+    return dec;
+  }
+  CATCH_ALL_EXCEPTIONS(0);
+}
+
+ecb_encryptor::~ecb_encryptor() {}
+ecb_encryptor_impl::~ecb_encryptor_impl() {}
+ecb_decryptor::~ecb_decryptor() {}
+ecb_decryptor_impl::~ecb_decryptor_impl() {}
+
+void
+ecb_encryptor_impl::encrypt(uint8_t *out, const uint8_t *in)
+{
+  try {
+    this->ctx.ProcessData(out, in, AES_BLOCK_LEN);
+  }
+  CATCH_ALL_EXCEPTIONS();
+}
+
+void
+ecb_decryptor_impl::decrypt(uint8_t *out, const uint8_t *in)
+{
+  try {
+    this->ctx.ProcessData(out, in, AES_BLOCK_LEN);
+  }
+  CATCH_ALL_EXCEPTIONS();
+}
+
+
 namespace {
-  struct encryptor_impl : encryptor
+  struct gcm_encryptor_impl : gcm_encryptor
   {
     CryptoPP::GCM<CryptoPP::AES>::Encryption ctx;
+    virtual ~gcm_encryptor_impl();
     virtual void encrypt(uint8_t *out, const uint8_t *in, size_t inlen,
                          const uint8_t *nonce, size_t nlen);
-    virtual ~encryptor_impl();
   };
 
-  struct decryptor_impl : decryptor
+  struct gcm_decryptor_impl : gcm_decryptor
   {
     CryptoPP::GCM<CryptoPP::AES>::Decryption ctx;
+    virtual ~gcm_decryptor_impl();
     virtual int decrypt(uint8_t *out, const uint8_t *in, size_t inlen,
                         const uint8_t *nonce, size_t nlen);
     virtual void decrypt_unchecked(uint8_t *out,
                                    const uint8_t *in, size_t inlen,
                                    const uint8_t *nonce, size_t nlen);
-    virtual ~decryptor_impl();
   };
 }
 
-// Crypto++ doesn't let us set a key without also setting an IV,
-// even though we will always override the IV later.
-static const uint8_t dummy_iv[16] = {};
-
-encryptor *
-encryptor::create(const uint8_t *key, size_t keylen)
+gcm_encryptor *
+gcm_encryptor::create(const uint8_t *key, size_t keylen)
 {
   try {
-    encryptor_impl *enc = new encryptor_impl;
+    gcm_encryptor_impl *enc = new gcm_encryptor_impl;
     // sadly, these are not checkable at compile time
-    log_assert(enc->ctx.DigestSize() == 16);
+    log_assert(enc->ctx.DigestSize() == GCM_TAG_LEN);
     log_assert(!enc->ctx.NeedsPrespecifiedDataLengths());
     enc->ctx.SetKeyWithIV(key, keylen, dummy_iv, sizeof dummy_iv);
     return enc;
@@ -75,13 +137,13 @@ encryptor::create(const uint8_t *key, size_t keylen)
   CATCH_ALL_EXCEPTIONS(0);
 }
 
-decryptor *
-decryptor::create(const uint8_t *key, size_t keylen)
+gcm_decryptor *
+gcm_decryptor::create(const uint8_t *key, size_t keylen)
 {
   try {
-    decryptor_impl *dec = new decryptor_impl;
+    gcm_decryptor_impl *dec = new gcm_decryptor_impl;
     // sadly, these are not checkable at compile time
-    log_assert(dec->ctx.DigestSize() == 16);
+    log_assert(dec->ctx.DigestSize() == GCM_TAG_LEN);
     log_assert(!dec->ctx.NeedsPrespecifiedDataLengths());
     dec->ctx.SetKeyWithIV(key, keylen, dummy_iv, sizeof dummy_iv);
     return dec;
@@ -89,14 +151,14 @@ decryptor::create(const uint8_t *key, size_t keylen)
   CATCH_ALL_EXCEPTIONS(0);
 }
 
-encryptor::~encryptor() {}
-encryptor_impl::~encryptor_impl() {}
-decryptor::~decryptor() {}
-decryptor_impl::~decryptor_impl() {}
+gcm_encryptor::~gcm_encryptor() {}
+gcm_encryptor_impl::~gcm_encryptor_impl() {}
+gcm_decryptor::~gcm_decryptor() {}
+gcm_decryptor_impl::~gcm_decryptor_impl() {}
 
 void
-encryptor_impl::encrypt(uint8_t *out, const uint8_t *in, size_t inlen,
-                        const uint8_t *nonce, size_t nlen)
+gcm_encryptor_impl::encrypt(uint8_t *out, const uint8_t *in, size_t inlen,
+                            const uint8_t *nonce, size_t nlen)
 {
   try {
     this->ctx.EncryptAndAuthenticate(out, out + inlen, 16,
@@ -106,8 +168,8 @@ encryptor_impl::encrypt(uint8_t *out, const uint8_t *in, size_t inlen,
 }
 
 int
-decryptor_impl::decrypt(uint8_t *out, const uint8_t *in, size_t inlen,
-                        const uint8_t *nonce, size_t nlen)
+gcm_decryptor_impl::decrypt(uint8_t *out, const uint8_t *in, size_t inlen,
+                            const uint8_t *nonce, size_t nlen)
 {
   try {
     return this->ctx.DecryptAndVerify(out,
@@ -119,9 +181,9 @@ decryptor_impl::decrypt(uint8_t *out, const uint8_t *in, size_t inlen,
 }
 
 void
-decryptor_impl::decrypt_unchecked(uint8_t *out,
-                                  const uint8_t *in, size_t inlen,
-                                  const uint8_t *nonce, size_t nlen)
+gcm_decryptor_impl::decrypt_unchecked(uint8_t *out,
+                                      const uint8_t *in, size_t inlen,
+                                      const uint8_t *nonce, size_t nlen)
 {
   try {
     // there is no convenience function for this
@@ -145,8 +207,8 @@ namespace {
     uint8_t leftover;
     bool dead : 1;
 
-    virtual size_t generate(uint8_t *buf, size_t len);
     virtual ~key_generator_impl();
+    virtual size_t generate(uint8_t *buf, size_t len);
 
     key_generator_impl(const uint8_t *prk,
                        const uint8_t *info, size_t ilen)
diff --git a/src/crypt.h b/src/crypt.h
index e87de0a..c0084e9 100644
--- a/src/crypt.h
+++ b/src/crypt.h
@@ -1,4 +1,4 @@
-/* Copyright 2011 Nick Mathewson, George Kadianakis, Zack Weinberg
+/* Copyright 2011, 2012 Nick Mathewson, George Kadianakis, Zack Weinberg
    See LICENSE for other credits and copying information
 */
 
@@ -8,55 +8,94 @@
 const size_t AES_BLOCK_LEN = 16;
 const size_t GCM_TAG_LEN   = 16;
 
-struct encryptor
+struct ecb_encryptor
 {
+  ecb_encryptor() {}
+  virtual ~ecb_encryptor();
+
+  /** Return a new AES/ECB encryption state using 'key' (of length 'keylen')
+      as the symmetric key.  'keylen' must be 16, 24, or 32 bytes. */
+  static ecb_encryptor *create(const uint8_t *key, size_t keylen);
+
+  /** Encrypt exactly AES_BLOCK_LEN bytes of data in the buffer 'in' and
+      write the result to 'out'.  */
+  virtual void encrypt(uint8_t *out, const uint8_t *in) = 0;
+
+private:
+  ecb_encryptor(const ecb_encryptor&);
+  ecb_encryptor& operator=(const ecb_encryptor&);
+};
+
+struct ecb_decryptor
+{
+  ecb_decryptor() {}
+  virtual ~ecb_decryptor();
+
+  /** Return a new AES/ECB decryption state using 'key' (of length 'keylen')
+      as the symmetric key.  'keylen' must be 16, 24, or 32 bytes. */
+  static ecb_decryptor *create(const uint8_t *key, size_t keylen);
+
+  /** Decrypt exactly AES_BLOCK_LEN bytes of data in the buffer 'in' and
+      write the result to 'out'.  */
+  virtual void decrypt(uint8_t *out, const uint8_t *in) = 0;
+
+private:
+  ecb_decryptor(const ecb_decryptor&) DELETE_METHOD;
+  ecb_decryptor& operator=(const ecb_decryptor&) DELETE_METHOD;
+};
+
+
+struct gcm_encryptor
+{
+  gcm_encryptor() {}
+  virtual ~gcm_encryptor();
+
   /** Return a new AES/GCM encryption state using 'key' (of length 'keylen')
       as the symmetric key.  'keylen' must be 16, 24, or 32 bytes. */
-  static encryptor *create(const uint8_t *key, size_t keylen);
+  static gcm_encryptor *create(const uint8_t *key, size_t keylen);
 
   /** Encrypt 'inlen' bytes of data in the buffer 'in', writing the
-      result plus a MAC to the buffer 'out', whose length must be at
-      least 'inlen'+16 bytes.  Use 'nonce' (of length 'nlen') as the
-      encryption nonce; 'nlen' must be at least 12 bytes.  */
+      result plus an authentication tag to the buffer 'out', whose
+      length must be at least 'inlen'+16 bytes.  Use 'nonce'
+      (of length 'nlen') as the encryption nonce; 'nlen' must be at
+      least 12 bytes.  */
   virtual void encrypt(uint8_t *out, const uint8_t *in, size_t inlen,
                        const uint8_t *nonce, size_t nlen) = 0;
 
-  virtual ~encryptor();
-
-  encryptor() {}
 private:
-  encryptor(const encryptor&) DELETE_METHOD;
-  encryptor& operator=(const encryptor&) DELETE_METHOD;
+  gcm_encryptor(const gcm_encryptor&);
+  gcm_encryptor& operator=(const gcm_encryptor&);
 };
 
-struct decryptor
+struct gcm_decryptor
 {
+  gcm_decryptor() {}
+  virtual ~gcm_decryptor();
+
   /** Return a new AES/GCM decryption state using 'key' (of length 'keylen')
       as the symmetric key.  'keylen' must be 16, 24, or 32 bytes. */
-  static decryptor *create(const uint8_t *key, size_t keylen);
-
-  /** Decrypt 'inlen' bytes of data in the buffer 'in'; the last 16 bytes
-      of this buffer are assumed to be the MAC.  Write the result to the
-      buffer 'out', whose length must be at least 'inlen'-16 bytes.  Use
-      'nonce' (of length 'nlen') as the encryption nonce; as above, 'nlen'
-      must be at least 12 bytes.  Returns 0 if successful, -1 if the MAC
-      did not validate. */
+  static gcm_decryptor *create(const uint8_t *key, size_t keylen);
+
+  /** Decrypt 'inlen' bytes of data in the buffer 'in'; the last 16
+      bytes of this buffer are assumed to be the authentication tag.
+      Write the result to the buffer 'out', whose length must be at
+      least 'inlen'-16 bytes.  Use 'nonce' (of length 'nlen') as the
+      encryption nonce; as above, 'nlen' must be at least 12 bytes.
+      Returns 0 if successful, -1 if the authentication check fails. */
   virtual int decrypt(uint8_t *out, const uint8_t *in, size_t inlen,
                       const uint8_t *nonce, size_t nlen) = 0;
 
-  /** Decrypt 'inlen' bytes of data in the buffer 'in' WITHOUT CHECKING
-      THE MAC.  Arguments same as decrypt().  This should be used only to
-      decode just enough of an incoming block to know how long it's going
-      to be and therefore where the MAC begins. */
+  /** Decrypt 'inlen' bytes of data in the buffer 'in' WITHOUT
+      CHECKING THE AUTHENTICATION TAG.  Arguments same as decrypt().
+      This should be used only to decode just enough of an incoming
+      block to know how long it's going to be and therefore where the
+      tag begins. */
   virtual void decrypt_unchecked(uint8_t *out, const uint8_t *in, size_t inlen,
                                  const uint8_t *nonce, size_t nlen) = 0;
 
-  virtual ~decryptor();
-
-  decryptor() {}
 private:
-  decryptor(const decryptor&) DELETE_METHOD;
-  decryptor& operator=(const decryptor&) DELETE_METHOD;
+  gcm_decryptor(const gcm_decryptor&) DELETE_METHOD;
+  gcm_decryptor& operator=(const gcm_decryptor&) DELETE_METHOD;
 };
 
 /** Generate keying material from an initial key of some kind, a salt
diff --git a/src/protocol/chop.cc b/src/protocol/chop.cc
index 82badde..b4ec692 100644
--- a/src/protocol/chop.cc
+++ b/src/protocol/chop.cc
@@ -92,8 +92,8 @@ namespace {
   {
     chop_reassembly_elt reassembly_queue;
     unordered_set<chop_conn_t *> downstreams;
-    encryptor *send_crypt;
-    decryptor *recv_crypt;
+    gcm_encryptor *send_crypt;
+    gcm_decryptor *recv_crypt;
     chop_config_t *config;
 
     uint64_t circuit_id;
@@ -947,11 +947,11 @@ chop_config_t::circuit_create(size_t)
   ckt->config = this;
 
   if (this->mode == LSN_SIMPLE_SERVER) {
-    ckt->send_crypt = encryptor::create(s2c_key, 16);
-    ckt->recv_crypt = decryptor::create(c2s_key, 16);
+    ckt->send_crypt = gcm_encryptor::create(s2c_key, 16);
+    ckt->recv_crypt = gcm_decryptor::create(c2s_key, 16);
   } else {
-    ckt->send_crypt = encryptor::create(c2s_key, 16);
-    ckt->recv_crypt = decryptor::create(s2c_key, 16);
+    ckt->send_crypt = gcm_encryptor::create(c2s_key, 16);
+    ckt->recv_crypt = gcm_decryptor::create(s2c_key, 16);
     while (!ckt->circuit_id)
       rng_bytes((uint8_t *)&ckt->circuit_id, sizeof(uint64_t));
 
diff --git a/src/test/unittest_crypt.cc b/src/test/unittest_crypt.cc
index 600e207..b903c11 100644
--- a/src/test/unittest_crypt.cc
+++ b/src/test/unittest_crypt.cc
@@ -7,9 +7,599 @@
 #include "crypt.h"
 #include "rng.h"
 
-/* AES/GCM test vectors from
-   http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
-*/
+// AES/ECB test vectors from
+// http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip
+
+static void
+test_crypt_aesecb_varkey128(void *)
+{
+  // ECBVarKey128.rsp -- plaintext is always 16 zero bytes
+  const uint8_t plaintext[] = { 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0 };
+  struct testvec
+  {
+    const char *key;
+    const char *ciphertext;
+  };
+  const struct testvec testvecs[] = {
+    { "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x0e\xdd\x33\xd3\xc6\x21\xe5\x46\x45\x5b\xd8\xba\x14\x18\xbe\xc8" },
+    { "\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x4b\xc3\xf8\x83\x45\x0c\x11\x3c\x64\xca\x42\xe1\x11\x2a\x9e\x87" },
+    { "\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x72\xa1\xda\x77\x0f\x5d\x7a\xc4\xc9\xef\x94\xd8\x22\xaf\xfd\x97" },
+    { "\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x97\x00\x14\xd6\x34\xe2\xb7\x65\x07\x77\xe8\xe8\x4d\x03\xcc\xd8" },
+    { "\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xf1\x7e\x79\xae\xd0\xdb\x7e\x27\x9e\x95\x5b\x5f\x49\x38\x75\xa7" },
+    { "\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x9e\xd5\xa7\x51\x36\xa9\x40\xd0\x96\x3d\xa3\x79\xdb\x4a\xf2\x6a" },
+    { "\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xc4\x29\x5f\x83\x46\x5c\x77\x55\xe8\xfa\x36\x4b\xac\x6a\x7e\xa5" },
+    { "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xb1\xd7\x58\x25\x6b\x28\xfd\x85\x0a\xd4\x94\x42\x08\xcf\x11\x55" },
+    { "\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x42\xff\xb3\x4c\x74\x3d\xe4\xd8\x8c\xa3\x80\x11\xc9\x90\x89\x0b" },
+    { "\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x99\x58\xf0\xec\xea\x8b\x21\x72\xc0\xc1\x99\x5f\x91\x82\xc0\xf3" },
+    { "\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x95\x6d\x77\x98\xfa\xc2\x0f\x82\xa8\x82\x3f\x98\x4d\x06\xf7\xf5" },
+    { "\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xa0\x1b\xf4\x4f\x2d\x16\xbe\x92\x8c\xa4\x4a\xaf\x7b\x9b\x10\x6b" },
+    { "\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xb5\xf1\xa3\x3e\x50\xd4\x0d\x10\x37\x64\xc7\x6b\xd4\xc6\xb6\xf8" },
+    { "\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x26\x37\x05\x0c\x9f\xc0\xd4\x81\x7e\x2d\x69\xde\x87\x8a\xee\x8d" },
+    { "\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x11\x3e\xcb\xe4\xa4\x53\x26\x9a\x0d\xd2\x60\x69\x46\x7f\xb5\xb5" },
+    { "\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x97\xd0\x75\x4f\xe6\x8f\x11\xb9\xe3\x75\xd0\x70\xa6\x08\xc8\x84" },
+    { "\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xc6\xa0\xb3\xe9\x98\xd0\x50\x68\xa5\x39\x97\x78\x40\x52\x00\xb4" },
+    { "\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xdf\x55\x6a\x33\x43\x8d\xb8\x7b\xc4\x1b\x17\x52\xc5\x5e\x5e\x49" },
+    { "\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x90\xfb\x12\x8d\x3a\x1a\xf6\xe5\x48\x52\x1b\xb9\x62\xbf\x1f\x05" },
+    { "\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x26\x29\x8e\x9c\x1d\xb5\x17\xc2\x15\xfa\xdf\xb7\xd2\xa8\xd6\x91" },
+    { "\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xa6\xcb\x76\x1d\x61\xf8\x29\x2d\x0d\xf3\x93\xa2\x79\xad\x03\x80" },
+    { "\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x12\xac\xd8\x9b\x13\xcd\x5f\x87\x26\xe3\x4d\x44\xfd\x48\x61\x08" },
+    { "\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x95\xb1\x70\x3f\xc5\x7b\xa0\x9f\xe0\xc3\x58\x0f\xeb\xdd\x7e\xd4" },
+    { "\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xde\x11\x72\x2d\x89\x3e\x9f\x91\x21\xc3\x81\xbe\xcc\x1d\xa5\x9a" },
+    { "\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x6d\x11\x4c\xcb\x27\xbf\x39\x10\x12\xe8\x97\x4c\x54\x6d\x9b\xf2" },
+    { "\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x5c\xe3\x7e\x17\xeb\x46\x46\xec\xfa\xc2\x9b\x9c\xc3\x8d\x93\x40" },
+    { "\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x18\xc1\xb6\xe2\x15\x71\x22\x05\x6d\x02\x43\xd8\xa1\x65\xcd\xdb" },
+    { "\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x99\x69\x3e\x6a\x59\xd1\x36\x6c\x74\xd8\x23\x56\x2d\x7e\x14\x31" },
+    { "\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x6c\x7c\x64\xdc\x84\xa8\xbb\xa7\x58\xed\x17\xeb\x02\x5a\x57\xe3" },
+    { "\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xe1\x7b\xc7\x9f\x30\xea\xab\x2f\xac\x2c\xbb\xe3\x45\x8d\x68\x7a" },
+    { "\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x11\x14\xbc\x20\x28\x00\x9b\x92\x3f\x0b\x01\x91\x5c\xe5\xe7\xc4" },
+    { "\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x9c\x28\x52\x4a\x16\xa1\xe1\xc1\x45\x29\x71\xca\xa8\xd1\x34\x76" },
+    { "\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xed\x62\xe1\x63\x63\x63\x83\x60\xfd\xd6\xad\x62\x11\x27\x94\xf0" },
+    { "\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x5a\x86\x88\xf0\xb2\xa2\xc1\x62\x24\xc1\x61\x65\x8f\xfd\x40\x44" },
+    { "\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x23\xf7\x10\x84\x2b\x9b\xb9\xc3\x2f\x26\x64\x8c\x78\x68\x07\xca" },
+    { "\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x44\xa9\x8b\xf1\x1e\x16\x3f\x63\x2c\x47\xec\x6a\x49\x68\x3a\x89" },
+    { "\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x0f\x18\xaf\xf9\x42\x74\x69\x6d\x9b\x61\x84\x8b\xd5\x0a\xc5\xe5" },
+    { "\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x82\x40\x85\x71\xc3\xe2\x42\x45\x40\x20\x7f\x83\x3b\x6d\xda\x69" },
+    { "\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x30\x3f\xf9\x96\x94\x7f\x0c\x7d\x1f\x43\xc8\xf3\x02\x7b\x9b\x75" },
+    { "\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x7d\xf4\xda\xf4\xad\x29\xa3\x61\x5a\x9b\x6e\xce\x5c\x99\x51\x8a" },
+    { "\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xc7\x29\x54\xa4\x8d\x07\x74\xdb\x0b\x49\x71\xc5\x26\x26\x04\x15" },
+    { "\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x1d\xf9\xb7\x61\x12\xdc\x65\x31\xe0\x7d\x2c\xfd\xa0\x44\x11\xf0" },
+    { "\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x8e\x4d\x8e\x69\x91\x19\xe1\xfc\x87\x54\x5a\x64\x7f\xb1\xd3\x4f" },
+    { "\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xe6\xc4\x80\x7a\xe1\x1f\x36\xf0\x91\xc5\x7d\x9f\xb6\x85\x48\xd1" },
+    { "\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x8e\xbf\x73\xaa\xd4\x9c\x82\x00\x7f\x77\xa5\xc1\xcc\xec\x6a\xb4" },
+    { "\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x4f\xb2\x88\xcc\x20\x40\x04\x90\x01\xd2\xc7\x58\x5a\xd1\x23\xfc" },
+    { "\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x04\x49\x71\x10\xef\xb9\xdc\xeb\x13\xe2\xb1\x3f\xb4\x46\x55\x64" },
+    { "\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x75\x55\x0e\x6c\xb5\xa8\x8e\x49\x63\x4c\x9a\xb6\x9e\xda\x04\x30" },
+    { "\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xb6\x76\x84\x73\xce\x98\x43\xea\x66\xa8\x14\x05\xdd\x50\xb3\x45" },
+    { "\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xcb\x2f\x43\x03\x83\xf9\x08\x4e\x03\xa6\x53\x57\x1e\x06\x5d\xe6" },
+    { "\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xff\x4e\x66\xc0\x7b\xae\x3e\x79\xfb\x7d\x21\x08\x47\xa3\xb0\xba" },
+    { "\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x7b\x90\x78\x51\x25\x50\x5f\xad\x59\xb1\x3c\x18\x6d\xd6\x6c\xe3" },
+    { "\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x8b\x52\x7a\x6a\xeb\xda\xec\x9e\xae\xf8\xed\xa2\xcb\x77\x83\xe5" },
+    { "\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x43\xfd\xaf\x53\xeb\xbc\x98\x80\xc2\x28\x61\x7d\x6a\x9b\x54\x8b" },
+    { "\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x53\x78\x61\x04\xb9\x74\x4b\x98\xf0\x52\xc4\x6f\x1c\x85\x0d\x0b" },
+    { "\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xb5\xab\x30\x13\xdd\x1e\x61\xdf\x06\xcb\xaf\x34\xca\x2a\xee\x78" },
+    { "\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x74\x70\x46\x9b\xe9\x72\x30\x30\xfd\xcc\x73\xa8\xcd\x4f\xbb\x10" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xa3\x5a\x63\xf5\x34\x3e\xbe\x9e\xf8\x16\x7b\xcb\x48\xad\x12\x2e" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xfd\x86\x87\xf0\x75\x7a\x21\x0e\x9f\xdf\x18\x12\x04\xc3\x08\x63" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x7a\x18\x1e\x84\xbd\x54\x57\xd2\x6a\x88\xfb\xae\x96\x01\x8f\xb0" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x65\x33\x17\xb9\x36\x2b\x6f\x9b\x9e\x1a\x58\x0e\x68\xd4\x94\xb5" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x99\x5c\x9d\xc0\xb6\x89\xf0\x3c\x45\x86\x7b\x5f\xaa\x5c\x18\xd1" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x77\xa4\xd9\x6d\x56\xdd\xa3\x98\xb9\xaa\xbe\xcf\xc7\x57\x29\xfd" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x84\xbe\x19\xe0\x53\x63\x5f\x09\xf2\x66\x5e\x7b\xae\x85\xb4\x2d" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00",
+      "\x32\xcd\x65\x28\x42\x92\x6a\xea\x4a\xa6\x13\x7b\xb2\xbe\x2b\x5e" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00",
+      "\x49\x3d\x4a\x4f\x38\xeb\xb3\x37\xd1\x0a\xa8\x4e\x91\x71\xa5\x54" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00",
+      "\xd9\xbf\xf7\xff\x45\x4b\x0e\xc5\xa4\xa2\xa6\x95\x66\xe2\xcb\x84" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00",
+      "\x35\x35\xd5\x65\xac\xe3\xf3\x1e\xb2\x49\xba\x2c\xc6\x76\x5d\x7a" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00",
+      "\xf6\x0e\x91\xfc\x32\x69\xee\xcf\x32\x31\xc6\xe9\x94\x56\x97\xc6" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00",
+      "\xab\x69\xcf\xad\xf5\x1f\x8e\x60\x4d\x9c\xc3\x71\x82\xf6\x63\x5a" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00",
+      "\x78\x66\x37\x3f\x24\xa0\xb6\xed\x56\xe0\xd9\x6f\xcd\xaf\xb8\x77" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00",
+      "\x1e\xa4\x48\xc2\xaa\xc9\x54\xf5\xd8\x12\xe9\xd7\x84\x94\x44\x6a" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00",
+      "\xac\xc5\x59\x9d\xd8\xac\x02\x23\x9a\x0f\xef\x4a\x36\xdd\x16\x68" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00",
+      "\xd8\x76\x44\x68\xbb\x10\x38\x28\xcf\x7e\x14\x73\xce\x89\x50\x73" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00",
+      "\x1b\x0d\x02\x89\x36\x83\xb9\xf1\x80\x45\x8e\x4a\xa6\xb7\x39\x82" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00",
+      "\x96\xd9\xb0\x17\xd3\x02\xdf\x41\x0a\x93\x7d\xcd\xb8\xbb\x6e\x43" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00",
+      "\xef\x16\x23\xcc\x44\x31\x3c\xff\x44\x0b\x15\x94\xa7\xe2\x1c\xc6" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00",
+      "\x28\x4c\xa2\xfa\x35\x80\x7b\x8b\x0a\xe4\xd1\x9e\x11\xd7\xdb\xd7" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00",
+      "\xf2\xe9\x76\x87\x57\x55\xf9\x40\x1d\x54\xf3\x6e\x2a\x23\xa5\x94" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00",
+      "\xec\x19\x8a\x18\xe1\x0e\x53\x24\x03\xb7\xe2\x08\x87\xc8\xdd\x80" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00",
+      "\x54\x5d\x50\xeb\xd9\x19\xe4\xa6\x94\x9d\x96\xad\x47\xe4\x6a\x80" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00",
+      "\xdb\xdf\xb5\x27\x06\x0e\x0a\x71\x00\x9c\x7b\xb0\xc6\x8f\x1d\x44" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00",
+      "\x9c\xfa\x13\x22\xea\x33\xda\x21\x73\xa0\x24\xf2\xff\x0d\x89\x6d" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00",
+      "\x87\x85\xb1\xa7\x5b\x0f\x3b\xd9\x58\xdc\xd0\xe2\x93\x18\xc5\x21" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00",
+      "\x38\xf6\x7b\x9e\x98\xe4\xa9\x7b\x6d\xf0\x30\xa9\xfc\xdd\x01\x04" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00",
+      "\x19\x2a\xff\xfb\x2c\x88\x0e\x82\xb0\x59\x26\xd0\xfc\x6c\x44\x8b" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00",
+      "\x6a\x79\x80\xce\x7b\x10\x5c\xf5\x30\x95\x2d\x74\xda\xaf\x79\x8c" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00",
+      "\xea\x36\x95\xe1\x35\x1b\x9d\x68\x58\xbd\x95\x8c\xf5\x13\xef\x6c" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00",
+      "\x6d\xa0\x49\x0b\xa0\xba\x03\x43\xb9\x35\x68\x1d\x2c\xce\x5b\xa1" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00",
+      "\xf0\xea\x23\xaf\x08\x53\x40\x11\xc6\x00\x09\xab\x29\xad\xa2\xf1" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00",
+      "\xff\x13\x80\x6c\xf1\x9c\xc3\x87\x21\x55\x4d\x7c\x0f\xcd\xcd\x4b" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00",
+      "\x68\x38\xaf\x1f\x4f\x69\xba\xe9\xd8\x5d\xd1\x88\xdc\xdf\x06\x88" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00",
+      "\x36\xcf\x44\xc9\x2d\x55\x0b\xfb\x1e\xd2\x8e\xf5\x83\xdd\xf5\xd7" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00",
+      "\xd0\x6e\x31\x95\xb5\x37\x6f\x10\x9d\x5c\x4e\xc6\xc5\xd6\x2c\xed" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00",
+      "\xc4\x40\xde\x01\x4d\x3d\x61\x07\x07\x27\x9b\x13\x24\x2a\x5c\x36" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00",
+      "\xf0\xc5\xc6\xff\xa5\xe0\xbd\x3a\x94\xc8\x8f\x6b\x6f\x7c\x16\xb9" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00",
+      "\x3e\x40\xc3\x90\x1c\xd7\xef\xfc\x22\xbf\xfc\x35\xde\xe0\xb4\xd9" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00",
+      "\xb6\x33\x05\xc7\x2b\xed\xfa\xb9\x73\x82\xc4\x06\xd0\xc4\x9b\xc6" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00",
+      "\x36\xbb\xaa\xb2\x2a\x6b\xd4\x92\x5a\x99\xa2\xb4\x08\xd2\xdb\xae" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00",
+      "\x30\x7c\x5b\x8f\xcd\x05\x33\xab\x98\xbc\x51\xe2\x7a\x6c\xe4\x61" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00",
+      "\x82\x9c\x04\xff\x4c\x07\x51\x3c\x0b\x3e\xf0\x5c\x03\xe3\x37\xb5" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00",
+      "\xf1\x7a\xf0\xe8\x95\xdd\xa5\xeb\x98\xef\xc6\x80\x66\xe8\x4c\x54" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00",
+      "\x27\x71\x67\xf3\x81\x2a\xff\xf1\xff\xac\xb4\xa9\x34\x37\x9f\xc3" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00",
+      "\x2c\xb1\xdc\x3a\x9c\x72\x97\x2e\x42\x5a\xe2\xef\x3e\xb5\x97\xcd" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00",
+      "\x36\xae\xaa\x3a\x21\x3e\x96\x8d\x4b\x5b\x67\x9d\x3a\x2c\x97\xfe" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00",
+      "\x92\x41\xda\xca\x4f\xdd\x03\x4a\x82\x37\x2d\xb5\x0e\x1a\x0f\x3f" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00",
+      "\xc1\x45\x74\xd9\xcd\x00\xcf\x2b\x5a\x7f\x77\xe5\x3c\xd5\x78\x85" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00",
+      "\x79\x3d\xe3\x92\x36\x57\x0a\xba\x83\xab\x9b\x73\x7c\xb5\x21\xc9" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00",
+      "\x16\x59\x1c\x0f\x27\xd6\x0e\x29\xb8\x5a\x96\xc3\x38\x61\xa7\xef" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00",
+      "\x44\xfb\x5c\x4d\x4f\x5c\xb7\x9b\xe5\xc1\x74\xa3\xb1\xc9\x73\x48" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00",
+      "\x67\x4d\x2b\x61\x63\x3d\x16\x2b\xe5\x9d\xde\x04\x22\x2f\x47\x40" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00",
+      "\xb4\x75\x0f\xf2\x63\xa6\x5e\x1f\x9e\x92\x4c\xcf\xd9\x8f\x3e\x37" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00",
+      "\x62\xd0\x66\x2d\x6e\xae\xdd\xed\xeb\xae\x7f\x7e\xa3\xa4\xf6\xb6" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00",
+      "\x70\xc4\x6b\xb3\x06\x92\xbe\x65\x7f\x7e\xaa\x93\xeb\xad\x98\x97" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00",
+      "\x32\x39\x94\xcf\xb9\xda\x28\x5a\x5d\x96\x42\xe1\x75\x9b\x22\x4a" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00",
+      "\x1d\xbf\x57\x87\x7b\x7b\x17\x38\x5c\x85\xd0\xb5\x48\x51\xe3\x71" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00",
+      "\xdf\xa5\xc0\x97\xcd\xc1\x53\x2a\xc0\x71\xd5\x7b\x1d\x28\xd1\xbd" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00",
+      "\x3a\x0c\x53\xfa\x37\x31\x1f\xc1\x0b\xd2\xa9\x98\x1f\x51\x31\x74" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00",
+      "\xba\x4f\x97\x0c\x0a\x25\xc4\x18\x14\xbd\xae\x2e\x50\x6b\xe3\xb4" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00",
+      "\x2d\xce\x3a\xcb\x72\x7c\xd1\x3c\xcd\x76\xd4\x25\xea\x56\xe4\xf6" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80",
+      "\x51\x60\x47\x4d\x50\x4b\x9b\x3e\xef\xb6\x8d\x35\xf2\x45\xf4\xb3" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0",
+      "\x41\xa8\xa9\x47\x76\x66\x35\xde\xc3\x75\x53\xd9\xa6\xc0\xcb\xb7" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0",
+      "\x25\xd6\xcf\xe6\x88\x1f\x2b\xf4\x97\xdd\x14\xcd\x4d\xdf\x44\x5b" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0",
+      "\x41\xc7\x8c\x13\x5e\xd9\xe9\x8c\x09\x66\x40\x64\x72\x65\xda\x1e" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8",
+      "\x5a\x4d\x40\x4d\x89\x17\xe3\x53\xe9\x2a\x21\x07\x2c\x3b\x23\x05" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc",
+      "\x02\xbc\x96\x84\x6b\x3f\xdc\x71\x64\x3f\x38\x4c\xd3\xcc\x3e\xaf" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe",
+      "\x9b\xa4\xa9\x14\x3f\x4e\x5d\x40\x48\x52\x1c\x4f\x88\x77\xd8\x8e" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+      "\xa1\xf6\x25\x8c\x87\x7d\x5f\xcd\x89\x64\x48\x45\x38\xbf\xc9\x2c" },
+    { 0, 0 }
+  };
+
+  ecb_encryptor *e;
+  ecb_decryptor *d;
+  uint8_t eout[AES_BLOCK_LEN];
+  uint8_t dout[AES_BLOCK_LEN];
+  int i;
+
+  for (i = 0; testvecs[i].key; i++) {
+    e = ecb_encryptor::create((const uint8_t *)testvecs[i].key, 16);
+    tt_int_op(e, !=, 0);
+    e->encrypt(eout, plaintext);
+    delete e;
+    tt_mem_op(eout, ==, (const uint8_t *)testvecs[i].ciphertext, AES_BLOCK_LEN);
+
+    d = ecb_decryptor::create((const uint8_t *)testvecs[i].key, 16);
+    tt_int_op(d, !=, 0);
+    d->decrypt(dout, eout);
+    delete d;
+    tt_mem_op(dout, ==, plaintext, AES_BLOCK_LEN);
+  }
+
+ end:;
+}
+
+static void
+test_crypt_aesecb_vartxt128(void *)
+{
+  // ECBVarTxt128.rsp -- key is always 16 zero bytes
+  const uint8_t key[] = { 0, 0, 0, 0, 0, 0, 0, 0,
+                          0, 0, 0, 0, 0, 0, 0, 0 };
+  struct testvec
+  {
+    const char *plaintext;
+    const char *ciphertext;
+  };
+  const struct testvec testvecs[] = {
+    { "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x3a\xd7\x8e\x72\x6c\x1e\xc0\x2b\x7e\xbf\xe9\x2b\x23\xd9\xec\x34" },
+    { "\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xaa\xe5\x93\x9c\x8e\xfd\xf2\xf0\x4e\x60\xb9\xfe\x71\x17\xb2\xc2" },
+    { "\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xf0\x31\xd4\xd7\x4f\x5d\xcb\xf3\x9d\xaa\xf8\xca\x3a\xf6\xe5\x27" },
+    { "\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x96\xd9\xfd\x5c\xc4\xf0\x74\x41\x72\x7d\xf0\xf3\x3e\x40\x1a\x36" },
+    { "\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x30\xcc\xdb\x04\x46\x46\xd7\xe1\xf3\xcc\xea\x3d\xca\x08\xb8\xc0" },
+    { "\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x16\xae\x4c\xe5\x04\x2a\x67\xee\x8e\x17\x7b\x7c\x58\x7e\xcc\x82" },
+    { "\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xb6\xda\x0b\xb1\x1a\x23\x85\x5d\x9c\x5c\xb1\xb4\xc6\x41\x2e\x0a" },
+    { "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xdb\x4f\x1a\xa5\x30\x96\x7d\x67\x32\xce\x47\x15\xeb\x0e\xe2\x4b" },
+    { "\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xa8\x17\x38\x25\x26\x21\xdd\x18\x0a\x34\xf3\x45\x5b\x4b\xaa\x2f" },
+    { "\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x77\xe2\xb5\x08\xdb\x7f\xd8\x92\x34\xca\xf7\x93\x9e\xe5\x62\x1a" },
+    { "\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xb8\x49\x9c\x25\x1f\x84\x42\xee\x13\xf0\x93\x3b\x68\x8f\xcd\x19" },
+    { "\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x96\x51\x35\xf8\xa8\x1f\x25\xc9\xd6\x30\xb1\x75\x02\xf6\x8e\x53" },
+    { "\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x8b\x87\x14\x5a\x01\xad\x1c\x6c\xed\xe9\x95\xea\x36\x70\x45\x4f" },
+    { "\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x8e\xae\x3b\x10\xa0\xc8\xca\x6d\x1d\x3b\x0f\xa6\x1e\x56\xb0\xb2" },
+    { "\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x64\xb4\xd6\x29\x81\x0f\xda\x6b\xaf\xdf\x08\xf3\xb0\xd8\xd2\xc5" },
+    { "\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xd7\xe5\xdb\xd3\x32\x45\x95\xf8\xfd\xc7\xd7\xc5\x71\xda\x6c\x2a" },
+    { "\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xf3\xf7\x23\x75\x26\x4e\x16\x7f\xca\x9d\xe2\xc1\x52\x7d\x96\x06" },
+    { "\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x8e\xe7\x9d\xd4\xf4\x01\xff\x9b\x7e\xa9\x45\xd8\x66\x66\xc1\x3b" },
+    { "\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xdd\x35\xce\xa2\x79\x99\x40\xb4\x0d\xb3\xf8\x19\xcb\x94\xc0\x8b" },
+    { "\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x69\x41\xcb\x6b\x3e\x08\xc2\xb7\xaf\xa5\x81\xeb\xdd\x60\x7b\x87" },
+    { "\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x2c\x20\xf4\x39\xf6\xbb\x09\x7b\x29\xb8\xbd\x6d\x99\xaa\xd7\x99" },
+    { "\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x62\x5d\x01\xf0\x58\xe5\x65\xf7\x7a\xe8\x63\x78\xbd\x2c\x49\xb3" },
+    { "\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xc0\xb5\xfd\x98\x19\x0e\xf4\x5f\xbb\x43\x01\x43\x8d\x09\x59\x50" },
+    { "\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x13\x00\x1f\xf5\xd9\x98\x06\xef\xd2\x5d\xa3\x4f\x56\xbe\x85\x4b" },
+    { "\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x3b\x59\x4c\x60\xf5\xc8\x27\x7a\x51\x13\x67\x7f\x94\x20\x8d\x82" },
+    { "\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xe9\xc0\xfc\x18\x18\xe4\xaa\x46\xbd\x2e\x39\xd6\x38\xf8\x9e\x05" },
+    { "\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xf8\x02\x3e\xe9\xc3\xfd\xc4\x5a\x01\x9b\x4e\x98\x5c\x7e\x1a\x54" },
+    { "\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x35\xf4\x01\x82\xab\x46\x62\xf3\x02\x3b\xae\xc1\xee\x79\x6b\x57" },
+    { "\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x3a\xeb\xba\xd7\x30\x36\x49\xb4\x19\x4a\x69\x45\xc6\xcc\x36\x94" },
+    { "\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xa2\x12\x4b\xea\x53\xec\x28\x34\x27\x9b\xed\x7f\x7e\xb0\xf9\x38" },
+    { "\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xb9\xfb\x43\x99\xfa\x4f\xac\xc7\x30\x9e\x14\xec\x98\x36\x0b\x0a" },
+    { "\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xc2\x62\x77\x43\x74\x20\xc5\xd6\x34\xf7\x15\xae\xa8\x1a\x91\x32" },
+    { "\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x17\x1a\x0e\x1b\x2d\xd4\x24\xf0\xe0\x89\xaf\x2c\x4c\x10\xf3\x2f" },
+    { "\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x7c\xad\xbe\x40\x2d\x1b\x20\x8f\xe7\x35\xed\xce\x00\xae\xe7\xce" },
+    { "\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x43\xb0\x2f\xf9\x29\xa1\x48\x5a\xf6\xf5\xc6\xd6\x55\x8b\xaa\x0f" },
+    { "\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x09\x2f\xaa\xcc\x9b\xf4\x35\x08\xbf\x8f\xa8\x61\x3c\xa7\x5d\xea" },
+    { "\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xcb\x2b\xf8\x28\x0f\x3f\x97\x42\xc7\xed\x51\x3f\xe8\x02\x62\x9c" },
+    { "\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x21\x5a\x41\xee\x44\x2f\xa9\x92\xa6\xe3\x23\x98\x6d\xed\x3f\x68" },
+    { "\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xf2\x1e\x99\xcf\x4f\x0f\x77\xce\xa8\x36\xe1\x1a\x2f\xe7\x5f\xb1" },
+    { "\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x95\xe3\xa0\xca\x90\x79\xe6\x46\x33\x1d\xf8\xb4\xe7\x0d\x2c\xd6" },
+    { "\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x4a\xfe\x7f\x12\x0c\xe7\x61\x3f\x74\xfc\x12\xa0\x1a\x82\x80\x73" },
+    { "\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x82\x7f\x00\x0e\x75\xe2\xc8\xb9\xd4\x79\xbe\xed\x91\x3f\xe6\x78" },
+    { "\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x35\x83\x0c\x8e\x7a\xae\xfe\x2d\x30\x31\x0e\xf3\x81\xcb\xf6\x91" },
+    { "\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x19\x1a\xa0\xf2\xc8\x57\x01\x44\xf3\x86\x57\xea\x40\x85\xeb\xe5" },
+    { "\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x85\x06\x2c\x2c\x90\x9f\x15\xd9\x26\x9b\x6c\x18\xce\x99\xc4\xf0" },
+    { "\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x67\x80\x34\xdc\x9e\x41\xb5\xa5\x60\xed\x23\x9e\xea\xb1\xbc\x78" },
+    { "\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xc2\xf9\x3a\x4c\xe5\xab\x6d\x5d\x56\xf1\xb9\x3c\xf1\x99\x11\xc1" },
+    { "\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x1c\x31\x12\xbc\xb0\xc1\xdc\xc7\x49\xd7\x99\x74\x36\x91\xbf\x82" },
+    { "\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x00\xc5\x5b\xd7\x5c\x7f\x9c\x88\x19\x89\xd3\xec\x19\x11\xc0\xd4" },
+    { "\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xea\x2e\x6b\x5e\xf1\x82\xb7\xdf\xf3\x62\x9a\xbd\x6a\x12\x04\x5f" },
+    { "\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x22\x32\x23\x27\xe0\x17\x80\xb1\x73\x97\xf2\x40\x87\xf8\xcc\x6f" },
+    { "\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xc9\xca\xcb\x5c\xd1\x16\x92\xc3\x73\xb2\x41\x17\x68\x14\x9e\xe7" },
+    { "\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xa1\x8e\x3d\xbb\xca\x57\x78\x60\xda\xb6\xb8\x0d\xa3\x13\x92\x56" },
+    { "\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x79\xb6\x1c\x37\xbf\x32\x8e\xcc\xa8\xd7\x43\x26\x5a\x3d\x42\x5c" },
+    { "\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xd2\xd9\x9c\x6b\xcc\x1f\x06\xfd\xa8\xe2\x7e\x8a\xe3\xf1\xcc\xc7" },
+    { "\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x1b\xfd\x4b\x91\xc7\x01\xfd\x6b\x61\xb7\xf9\x97\x82\x9d\x66\x3b" },
+    { "\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x11\x00\x5d\x52\xf2\x5f\x16\xbd\xc9\x54\x5a\x87\x6a\x63\x49\x0a" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x3a\x4d\x35\x4f\x02\xbb\x5a\x5e\x47\xd3\x96\x66\x86\x7f\x24\x6a" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xd4\x51\xb8\xd6\xe1\xe1\xa0\xeb\xb1\x55\xfb\xbf\x6e\x7b\x7d\xc3" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x68\x98\xd4\xf4\x2f\xa7\xba\x6a\x10\xac\x05\xe8\x7b\x9f\x20\x80" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xb6\x11\x29\x5e\x73\x9c\xa7\xd9\xb5\x0f\x8e\x4c\x0e\x75\x4a\x3f" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x7d\x33\xfc\x7d\x8a\xbe\x3c\xa1\x93\x67\x59\xf8\xf5\xde\xaf\x20" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\x3b\x5e\x0f\x56\x6d\xc9\x6c\x29\x8f\x0c\x12\x63\x75\x39\xb2\x5c" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00",
+      "\xf8\x07\xc3\xe7\x98\x5f\xe0\xf5\xa5\x0e\x2c\xdb\x25\xc5\x10\x9e" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00",
+      "\x41\xf9\x92\xa8\x56\xfb\x27\x8b\x38\x9a\x62\xf5\xd2\x74\xd7\xe9" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00",
+      "\x10\xd3\xed\x7a\x6f\xe1\x5a\xb4\xd9\x1a\xcb\xc7\xd0\x76\x7a\xb1" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00",
+      "\x21\xfe\xec\xd4\x5b\x2e\x67\x59\x73\xac\x33\xbf\x0c\x54\x24\xfc" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00",
+      "\x14\x80\xcb\x39\x55\xba\x62\xd0\x9e\xea\x66\x8f\x7c\x70\x88\x17" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00",
+      "\x66\x40\x40\x33\xd6\xb7\x2b\x60\x93\x54\xd5\x49\x6e\x7e\xb5\x11" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00",
+      "\x1c\x31\x7a\x22\x0a\x7d\x70\x0d\xa2\xb1\xe0\x75\xb0\x02\x66\xe1" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00",
+      "\xab\x3b\x89\x54\x22\x33\xf1\x27\x1b\xf8\xfd\x0c\x0f\x40\x35\x45" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00",
+      "\xd9\x3e\xae\x96\x6f\xac\x46\xdc\xa9\x27\xd6\xb1\x14\xfa\x3f\x9e" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00",
+      "\x1b\xde\xc5\x21\x31\x65\x03\xd9\xd5\xee\x65\xdf\x3e\xa9\x4d\xdf" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00",
+      "\xee\xf4\x56\x43\x1d\xea\x8b\x4a\xcf\x83\xbd\xae\x37\x17\xf7\x5f" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00",
+      "\x06\xf2\x51\x9a\x2f\xaf\xaa\x59\x6b\xfe\xf5\xcf\xa1\x5c\x21\xb9" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00",
+      "\x25\x1a\x7e\xac\x7e\x2f\xe8\x09\xe4\xaa\x8d\x0d\x70\x12\x53\x1a" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00",
+      "\x3b\xff\xc1\x6e\x4c\x49\xb2\x68\xa2\x0f\x8d\x96\xa6\x0b\x40\x58" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00",
+      "\xe8\x86\xf9\x28\x19\x99\xc5\xbb\x3b\x3e\x88\x62\xe2\xf7\xc9\x88" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00",
+      "\x56\x3b\xf9\x0d\x61\xbe\xef\x39\xf4\x8d\xd6\x25\xfc\xef\x13\x61" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00",
+      "\x4d\x37\xc8\x50\x64\x45\x63\xc6\x9f\xd0\xac\xd9\xa0\x49\x32\x5b" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00",
+      "\xb8\x7c\x92\x1b\x91\x82\x9e\xf3\xb1\x3c\xa5\x41\xee\x11\x30\xa6" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00",
+      "\x2e\x65\xeb\x6b\x6e\xa3\x83\xe1\x09\xac\xcc\xe8\x32\x6b\x03\x93" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00",
+      "\x9c\xa5\x47\xf7\x43\x9e\xdc\x3e\x25\x5c\x0f\x4d\x49\xaa\x89\x90" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00",
+      "\xa5\xe6\x52\x61\x4c\x93\x00\xf3\x78\x16\xb1\xf9\xfd\x0c\x87\xf9" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00",
+      "\x14\x95\x4f\x0b\x46\x97\x77\x6f\x44\x49\x4f\xe4\x58\xd8\x14\xed" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00",
+      "\x7c\x8d\x9a\xb6\xc2\x76\x17\x23\xfe\x42\xf8\xbb\x50\x6c\xbc\xf7" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00",
+      "\xdb\x7e\x19\x32\x67\x9f\xdd\x99\x74\x2a\xab\x04\xaa\x0d\x5a\x80" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00",
+      "\x4c\x6a\x1c\x83\xe5\x68\xcd\x10\xf2\x7c\x2d\x73\xde\xd1\x9c\x28" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00",
+      "\x90\xec\xbe\x61\x77\xe6\x74\xc9\x8d\xe4\x12\x41\x3f\x7a\xc9\x15" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00",
+      "\x90\x68\x4a\x2a\xc5\x5f\xe1\xec\x2b\x8e\xbd\x56\x22\x52\x0b\x73" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00",
+      "\x74\x72\xf9\xa7\x98\x86\x07\xca\x79\x70\x77\x95\x99\x10\x35\xe6" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00",
+      "\x56\xaf\xf0\x89\x87\x8b\xf3\x35\x2f\x8d\xf1\x72\xa3\xae\x47\xd8" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00",
+      "\x65\xc0\x52\x6c\xbe\x40\x16\x1b\x80\x19\xa2\xa3\x17\x1a\xbd\x23" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00",
+      "\x37\x7b\xe0\xbe\x33\xb4\xe3\xe3\x10\xb4\xaa\xbd\xa1\x73\xf8\x4f" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00",
+      "\x94\x02\xe9\xaa\x6f\x69\xde\x65\x04\xda\x8d\x20\xc4\xfc\xaa\x2f" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00",
+      "\x12\x3c\x1f\x4a\xf3\x13\xad\x8c\x2c\xe6\x48\xb2\xe7\x1f\xb6\xe1" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00",
+      "\x1f\xfc\x62\x6d\x30\x20\x3d\xcd\xb0\x01\x9f\xb8\x0f\x72\x6c\xf4" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00",
+      "\x76\xda\x1f\xbe\x3a\x50\x72\x8c\x50\xfd\x2e\x62\x1b\x5a\xd8\x85" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00",
+      "\x08\x2e\xb8\xbe\x35\xf4\x42\xfb\x52\x66\x8e\x16\xa5\x91\xd1\xd6" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00",
+      "\xe6\x56\xf9\xec\xf5\xfe\x27\xec\x3e\x4a\x73\xd0\x0c\x28\x2f\xb3" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00",
+      "\x2c\xa8\x20\x9d\x63\x27\x4c\xd9\xa2\x9b\xb7\x4b\xcd\x77\x68\x3a" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00",
+      "\x79\xbf\x5d\xce\x14\xbb\x7d\xd7\x3a\x8e\x36\x11\xde\x7c\xe0\x26" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00",
+      "\x3c\x84\x99\x39\xa5\xd2\x93\x99\xf3\x44\xc4\xa0\xec\xa8\xa5\x76" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00",
+      "\xed\x3c\x0a\x94\xd5\x9b\xec\xe9\x88\x35\xda\x7a\xa4\xf0\x7c\xa2" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00",
+      "\x63\x91\x9e\xd4\xce\x10\x19\x64\x38\xb6\xad\x09\xd9\x9c\xd7\x95" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00",
+      "\x76\x78\xf3\xa8\x33\xf1\x9f\xea\x95\xf3\xc6\x02\x9e\x2b\xc6\x10" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00",
+      "\x3a\xa4\x26\x83\x10\x67\xd3\x6b\x92\xbe\x7c\x5f\x81\xc1\x3c\x56" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00",
+      "\x92\x72\xe2\xd2\xcd\xd1\x10\x50\x99\x8c\x84\x50\x77\xa3\x0e\xa0" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00",
+      "\x08\x8c\x4b\x53\xf5\xec\x0f\xf8\x14\xc1\x9a\xda\xe7\xf6\x24\x6c" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00",
+      "\x40\x10\xa5\xe4\x01\xfd\xf0\xa0\x35\x4d\xdb\xcc\x0d\x01\x2b\x17" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00",
+      "\xa8\x7a\x38\x57\x36\xc0\xa6\x18\x9b\xd6\x58\x9b\xd8\x44\x5a\x93" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00",
+      "\x54\x5f\x2b\x83\xd9\x61\x6d\xcc\xf6\x0f\xa9\x83\x0e\x9c\xd2\x87" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00",
+      "\x4b\x70\x6f\x7f\x92\x40\x63\x52\x39\x40\x37\xa6\xd4\xf4\x68\x8d" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00",
+      "\xb7\x97\x2b\x39\x41\xc4\x4b\x90\xaf\xa7\xb2\x64\xbf\xba\x73\x87" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00",
+      "\x6f\x45\x73\x2c\xf1\x08\x81\x54\x6f\x0f\xd2\x38\x96\xd2\xbb\x60" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00",
+      "\x2e\x35\x79\xca\x15\xaf\x27\xf6\x4b\x3c\x95\x5a\x5b\xfc\x30\xba" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00",
+      "\x34\xa2\xc5\xa9\x1a\xe2\xae\xc9\x9b\x7d\x1b\x5f\xa6\x78\x04\x47" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00",
+      "\xa4\xd6\x61\x6b\xd0\x4f\x87\x33\x5b\x0e\x53\x35\x12\x27\xa9\xee" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00",
+      "\x7f\x69\x2b\x03\x94\x58\x67\xd1\x61\x79\xa8\xce\xfc\x83\xea\x3f" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00",
+      "\x3b\xd1\x41\xee\x84\xa0\xe6\x41\x4a\x26\xe7\xa4\xf2\x81\xf8\xa2" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80",
+      "\xd1\x78\x8f\x57\x2d\x98\xb2\xb1\x6e\xc5\xd5\xf3\x92\x2b\x99\xbc" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0",
+      "\x08\x33\xff\x6f\x61\xd9\x8a\x57\xb2\x88\xe8\xc3\x58\x6b\x85\xa6" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0",
+      "\x85\x68\x26\x17\x97\xde\x17\x6b\xf0\xb4\x3b\xec\xc6\x28\x5a\xfb" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0",
+      "\xf9\xb0\xfd\xa0\xc4\xa8\x98\xf5\xb9\xe6\xf6\x61\xc4\xce\x4d\x07" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8",
+      "\x8a\xde\x89\x59\x13\x68\x5c\x67\xc5\x26\x9f\x8a\xae\x42\x98\x3e" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc",
+      "\x39\xbd\xe6\x7d\x5c\x8e\xd8\xa8\xb1\xc3\x7e\xb8\xfa\x9f\x5a\xc0" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe",
+      "\x5c\x00\x5e\x72\xc1\x41\x8c\x44\xf5\x69\xf2\xea\x33\xba\x54\xf3" },
+    { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+      "\x3f\x5b\x8c\xc9\xea\x85\x5a\x0a\xfa\x73\x47\xd2\x3e\x8d\x66\x4e" },
+    { 0, 0 }
+  };
+
+  ecb_encryptor *e = ecb_encryptor::create(key, 16);
+  ecb_decryptor *d = ecb_decryptor::create(key, 16);
+  uint8_t eout[AES_BLOCK_LEN];
+  uint8_t dout[AES_BLOCK_LEN];
+  int i;
+
+  tt_int_op(e, !=, 0);
+  tt_int_op(d, !=, 0);
+
+  for (i = 0; testvecs[i].plaintext; i++) {
+    e->encrypt(eout, (const uint8_t *)testvecs[i].plaintext);
+    tt_mem_op(eout, ==, (const uint8_t *)testvecs[i].ciphertext, AES_BLOCK_LEN);
+
+    d->decrypt(dout, eout);
+    tt_mem_op(dout, ==, (const uint8_t *)testvecs[i].plaintext, AES_BLOCK_LEN);
+  }
+
+ end:
+  delete e;
+  delete d;
+}
+
+
+// AES/GCM test vectors from
+// http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
 
 static void
 test_crypt_aesgcm_enc(void *)
@@ -75,12 +665,12 @@ test_crypt_aesgcm_enc(void *)
     { 0, 0, 0, 0, 0, 0 }
   };
 
-  encryptor *c;
+  gcm_encryptor *c;
   uint8_t obuf[144];
   int i;
 
   for (i = 0; testvecs[i].key; i++) {
-    c = encryptor::create((const uint8_t *)testvecs[i].key, 16);
+    c = gcm_encryptor::create((const uint8_t *)testvecs[i].key, 16);
     tt_int_op(c, !=, 0);
     c->encrypt(obuf,
                (const uint8_t *)testvecs[i].pt, testvecs[i].len,
@@ -158,12 +748,12 @@ test_crypt_aesgcm_good_dec(void *)
     { 0, 0, 0, 0, 0 }
   };
 
-  decryptor *c;
+  gcm_decryptor *c;
   uint8_t obuf[128];
   int i, rv;
 
   for (i = 0; testvecs[i].key; i++) {
-    c = decryptor::create((const uint8_t *)testvecs[i].key, 16);
+    c = gcm_decryptor::create((const uint8_t *)testvecs[i].key, 16);
     tt_int_op(c, !=, 0);
 
     rv = c->decrypt(obuf,
@@ -231,12 +821,12 @@ test_crypt_aesgcm_bad_dec(void *)
     { 0, 0, 0, 0 }
   };
 
-  decryptor *c;
+  gcm_decryptor *c;
   uint8_t obuf[128];
   int i, rv;
 
   for (i = 0; testvecs[i].key; i++) {
-    c = decryptor::create((const uint8_t *)testvecs[i].key, 16);
+    c = gcm_decryptor::create((const uint8_t *)testvecs[i].key, 16);
     tt_int_op(c, !=, 0);
 
     rv = c->decrypt(obuf,
@@ -398,6 +988,8 @@ test_crypt_rng(void *)
   { #name, test_crypt_##name, 0, 0, 0 }
 
 struct testcase_t crypt_tests[] = {
+  T(aesecb_varkey128),
+  T(aesecb_vartxt128),
   T(aesgcm_enc),
   T(aesgcm_good_dec),
   T(aesgcm_bad_dec),





More information about the tor-commits mailing list