grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Crypto Review


From: Michael Gorven
Subject: Crypto Review
Date: Mon, 17 Aug 2009 17:51:42 +0200
User-agent: KMail/1.9.10

Hi

I posted my copyright assignment last weekend, so hopefully that will arrive 
at the FSF soon. In the meantime I have attached some code for review. These 
are the crypto module which manages ciphers and hashes, the SHA1 hash module, 
and the AES cipher module.

The full code is available in a Bazaar repository[1], and I can provide a diff 
or tarball of everything if preferred.

Michael

[1] http://michael.gorven.za.net/bzr/grub/luks

-- 
http://michael.gorven.za.net
PGP Key ID 1E016BE8
S/MIME Key ID AAF09E0E
=== modified file 'conf/common.rmk'
--- conf/common.rmk     2009-08-14 13:31:09 +0000
+++ conf/common.rmk     2009-06-21 10:02:28 +0000
@@ -617,3 +617,9 @@
 setjmp_mod_SOURCES = lib/$(target_cpu)/setjmp.S
 setjmp_mod_ASFLAGS = $(COMMON_ASFLAGS)
 setjmp_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For crypto.mod
+pkglib_MODULES += crypto.mod
+crypto_mod_SOURCES = crypto/crypto.c
+crypto_mod_CFLAGS = $(COMMON_CFLAGS)
+crypto_mod_LDFLAGS = $(COMMON_LDFLAGS)

=== added directory 'crypto'
=== added file 'crypto/crypto.c'
--- crypto/crypto.c     1970-01-01 00:00:00 +0000
+++ crypto/crypto.c     2009-06-21 10:02:28 +0000
@@ -0,0 +1,389 @@
+/*
+ * crypto.c - Strong cryptography API for GRUB
+ *
+ * Copyright (C) 2007 Simon Peter <address@hidden>
+ * Thanks to Raoul Boenisch <address@hidden> for the initial idea.
+ * Modified by Michael Gorven <address@hidden>
+ */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/crypto.h>
+
+#include <grub/normal.h>
+#include <grub/lib/arg.h>
+
+#define MAX(a, b)      (a > b ? a : b)
+
+
+static char *hexchars = "0123456789ABCDEF";
+void print_buffer(char *label, unsigned char *buffer, grub_size_t len)
+{
+       grub_size_t i;
+       grub_printf(label);
+       for (i = 0; i < len; i++)
+               grub_printf("%c%c", hexchars[(buffer[i]>>4)&0xF], 
hexchars[buffer[i]&0xF] );
+       grub_printf("\n");
+}
+
+
+struct cipher_list
+{
+  grub_cipher_t cipher;
+  struct cipher_list *next;
+};
+
+static struct cipher_list *cipher_list = NULL;
+
+grub_err_t
+grub_crypto_hash (grub_cipher_params_t params, char *hash,
+                 const char *payload, unsigned int size)
+{
+  return params->cipher->u.hash.fn (params, hash, payload, size);
+}
+
+static grub_cipher_t
+get_cipher (const char *name, grub_cipher_type_t type)
+{
+  struct cipher_list *i;
+
+  for (i = cipher_list; i != NULL; i = i->next)
+    if (!grub_strcmp (i->cipher->name, name) && i->cipher->type == type)
+      return i->cipher;
+
+  return NULL;
+}
+
+grub_err_t
+grub_crypto_new_cipher (grub_cipher_params_t * params, const char *name,
+                       grub_cipher_type_t type)
+{
+  grub_cipher_t cipher = get_cipher (name, type);
+
+  if (!cipher) {
+    grub_dl_t mod = NULL;
+    mod = grub_dl_load(name);
+    if (mod)
+      cipher = get_cipher(name, type);
+  }
+
+  grub_err_t err;
+
+  if (cipher == NULL)
+    {
+      const char *errstr = "Illegal cipher type";
+
+      switch (type)
+       {
+       case GRUB_CIPHER_TYPE_NONE:
+         break;
+
+       case GRUB_CIPHER_TYPE_CIPHER:
+         errstr = "Unknown cipher";
+         break;
+
+       case GRUB_CIPHER_TYPE_HASH:
+         errstr = "Unknown hash";
+         break;
+       }
+
+      return grub_error (GRUB_ERR_BAD_ARGUMENT, errstr);
+    }
+
+  *params = grub_malloc (sizeof (struct grub_cipher_params));
+  if (*params == NULL)
+    return grub_errno;
+
+  if (cipher->init)
+    {
+      if ((err = cipher->init (*params)) != GRUB_ERR_NONE)
+       {
+         grub_free (*params);
+         return err;
+       }
+    }
+  else
+    {
+      unsigned int i, keysize = 0;
+
+      /* Set keysize to largest */
+      for (i = 0; i < cipher->keysizes_length; i++)
+       keysize = MAX (keysize, cipher->keysizes[i]);
+
+      (*params)->keysize = keysize;
+         (*params)->u.cipher.mode = GRUB_CIPHER_MODE_ECB;
+    }
+
+  (*params)->cipher = cipher;
+  return GRUB_ERR_NONE;
+}
+
+void
+grub_crypto_delete_cipher (grub_cipher_params_t params)
+{
+  if (params->cipher->deinit)
+    params->cipher->deinit (params);
+
+  grub_free (params);
+}
+
+int
+grub_crypto_cipher_iterate (grub_crypto_hook hook, void *data)
+{
+  struct cipher_list *i;
+
+  for (i = cipher_list; i != NULL; i = i->next)
+    if (hook (i->cipher, data))
+      return 1;
+
+  return 0;
+}
+
+void
+grub_crypto_cipher_register (grub_cipher_t cipher)
+{
+  struct cipher_list *newcipher = grub_malloc (sizeof (struct cipher_list));
+
+  if (!newcipher)
+    return;                    /* out of memory! */
+
+  newcipher->cipher = cipher;
+  newcipher->next = cipher_list;
+  cipher_list = newcipher;
+}
+
+void
+grub_crypto_cipher_unregister (grub_cipher_t cipher)
+{
+  struct cipher_list *i, **prev;
+
+  for (i = cipher_list, prev = &cipher_list; i != NULL;
+       prev = &i->next, i = i->next)
+    if (!grub_strcmp (i->cipher->name, cipher->name))
+      break;
+
+  if (!i)
+    {
+      grub_printf ("BUG: Trying to unregister a non-registered cipher!\n");
+      return;
+    }
+
+  /* Remove cipher from list */
+  *prev = i->next;
+  grub_free (i);
+}
+
+grub_err_t
+grub_crypto_set_key (grub_cipher_params_t params, const char *key)
+{
+  if (params->cipher->u.cipher.set_key)
+    return params->cipher->u.cipher.set_key (params, key);
+  else
+    return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_crypto_encrypt (grub_cipher_params_t params, char *out,
+                    char *in, grub_size_t outsize, grub_size_t insize)
+{
+       grub_size_t i;
+
+       if (!params->cipher->u.cipher.encrypt_block)
+               return GRUB_ERR_NOT_IMPLEMENTED_YET;
+
+       if (insize % params->cipher->blocksize != 0)
+               return grub_error(GRUB_ERR_BAD_ARGUMENT, "Size must be multiple 
of cipher block size");
+
+       switch (params->u.cipher.mode) {
+
+               case GRUB_CIPHER_MODE_ECB:
+                       for (i = 0; i < insize; i += params->cipher->blocksize)
+                               params->cipher->u.cipher.encrypt_block(params, 
(char*) out + i, (char*) in + i);
+                       return GRUB_ERR_NONE;
+
+               default:
+                       return GRUB_ERR_NOT_IMPLEMENTED_YET;
+       }
+}
+
+grub_err_t
+grub_crypto_decrypt (grub_cipher_params_t params, char *out,
+                    char *in, grub_size_t outsize, grub_size_t insize)
+{
+       grub_size_t i, j;
+                       unsigned char temp[params->cipher->blocksize];
+                       unsigned char prevcipher[params->cipher->blocksize];
+
+       if (!params->cipher->u.cipher.decrypt_block)
+               return GRUB_ERR_NOT_IMPLEMENTED_YET;
+
+       if (insize % params->cipher->blocksize != 0)
+               return grub_error(GRUB_ERR_BAD_ARGUMENT, "Size must be multiple 
of cipher block size");
+
+       switch (params->u.cipher.mode) {
+
+               case GRUB_CIPHER_MODE_ECB:
+                       for (i = 0; i < insize; i += params->cipher->blocksize) 
{
+                               params->cipher->u.cipher.decrypt_block(params, 
(char*) out + i, (char*) in + i);
+                       }
+                       return 0;
+
+               case GRUB_CIPHER_MODE_CBC_PLAIN:
+               case GRUB_CIPHER_MODE_CBC_ESSIV:
+                       if (!params->u.cipher.iv)
+                               return grub_error(GRUB_ERR_BAD_ARGUMENT, 
"Initialisation vector not specified");
+
+                       grub_memcpy(prevcipher, params->u.cipher.iv, 
params->cipher->blocksize);
+
+                       for (i = 0; i < insize; i += params->cipher->blocksize) 
{
+                               params->cipher->u.cipher.decrypt_block(params, 
(char*) temp, (char*) in+i);
+                               for (j = 0; j < params->cipher->blocksize; j++)
+                                       temp[j] = temp[j] ^ prevcipher[j];
+
+                               grub_memcpy(prevcipher, in+i, 
params->cipher->blocksize);
+                               grub_memcpy(out+i, temp, 
params->cipher->blocksize);
+                       }
+
+                       break;
+       }
+
+       return 0;
+}
+
+grub_err_t
+grub_crypto_decrypt_inplace (grub_cipher_params_t params, char *buf,
+                            grub_size_t size)
+{
+       return grub_crypto_decrypt(params, buf, buf, size, size);
+}
+
+grub_err_t
+grub_crypto_encrypt_inplace (grub_cipher_params_t params, char *buf,
+                            grub_size_t size)
+{
+  if (params->cipher->u.cipher.encrypt_inplace)
+    return params->cipher->u.cipher.encrypt_inplace (params, buf, size);
+  else
+    return GRUB_ERR_NOT_IMPLEMENTED_YET;
+}
+
+/***** None cipher interface ***********************************************/
+
+static grub_err_t
+cipher_none_crypt (grub_cipher_params_t unused, char **out, const char *in,
+                  grub_size_t * outsize, grub_size_t insize)
+{
+  (void) unused;
+  if (!(*out = grub_malloc (insize)))
+    return grub_errno;
+  *out = grub_memcpy (*out, in, insize);
+  *outsize = insize;
+  return 0;
+}
+
+static grub_err_t
+cipher_none_crypt_inplace (grub_cipher_params_t unused, char *buf,
+                          grub_size_t size)
+{
+  (void) unused;
+  (void) buf;
+  (void) size;
+  return 0;
+}
+
+static grub_err_t
+hash_none_fn (grub_cipher_params_t params, char *out, const char *in,
+             grub_size_t insize)
+{
+  params->keysize = insize;
+  grub_memcpy (out, in, insize);
+  return 0;
+}
+
+static struct grub_cipher grub_cipher_none = {
+  .name = "none",
+  .type = GRUB_CIPHER_TYPE_CIPHER,
+  .keysizes_length = 0,
+
+  .u.cipher = {
+              .encrypt = cipher_none_crypt,
+              .decrypt = cipher_none_crypt,
+              .decrypt_inplace = cipher_none_crypt_inplace,
+              .encrypt_inplace = cipher_none_crypt_inplace}
+};
+
+static struct grub_cipher grub_hash_none = {
+  .name = "none",
+  .type = GRUB_CIPHER_TYPE_HASH,
+  .keysizes_length = 0,
+  .u.hash.fn = hash_none_fn
+};
+
+static const struct grub_arg_option options[] = {};
+
+
+static grub_err_t
+grub_cmd_hash(struct grub_arg_list *state, int argc, char **args)
+{
+  char digest[64];
+  grub_cipher_params_t hash;
+  grub_err_t err;
+  int i;
+
+  if (argc < 2)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Hash and data required");
+
+  hash=grub_malloc(sizeof(struct grub_cipher_params));
+
+  err = grub_crypto_new_cipher(&hash, args[0], GRUB_CIPHER_TYPE_HASH);
+  if (err)
+    return grub_error(GRUB_ERR_BAD_ARGUMENT, "Hash doesn't exist");
+
+  err = grub_crypto_hash(hash, digest, args[1], grub_strlen(args[1]));
+
+  for (i = 0; i < hash->keysize; i++)
+    grub_printf("%c%c", hexchars[(digest[i]>>4)&0xF], hexchars[digest[i]&0xF] 
);
+  grub_printf("\n");
+
+  return GRUB_ERR_NONE;
+}
+
+
+/***** GRUB module (de-)initialization *************************************/
+
+GRUB_MOD_INIT (crypto)
+{
+  grub_crypto_cipher_register (&grub_cipher_none);
+  grub_crypto_cipher_register (&grub_hash_none);
+  grub_register_command("hash", grub_cmd_hash,
+                                               "hash [HASH] [STRING]", 
"Computes a hash");
+}
+
+GRUB_MOD_FINI (crypto)
+{
+  grub_crypto_cipher_unregister (&grub_hash_none);
+  grub_crypto_cipher_unregister (&grub_cipher_none);
+  grub_unregister_command("hash");
+}
+
+/* vi: set et sw=2 sts=2: */

=== added file 'include/grub/crypto.h'
--- include/grub/crypto.h       1970-01-01 00:00:00 +0000
+++ include/grub/crypto.h       2009-06-21 10:02:28 +0000
@@ -0,0 +1,137 @@
+/*
+ * crypto.h - GRUB cryptographic API
+ *
+ * Copyright (C) 2007 Simon Peter <address@hidden>
+ */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CRYPTO_H
+#define CRYPTO_H
+
+#include <grub/types.h>
+
+enum grub_cipher_type
+{
+  GRUB_CIPHER_TYPE_NONE = 0,
+  GRUB_CIPHER_TYPE_CIPHER,
+  GRUB_CIPHER_TYPE_HASH
+};
+
+enum grub_cipher_mode
+{
+       GRUB_CIPHER_MODE_ECB = 0,
+       GRUB_CIPHER_MODE_CBC_PLAIN,
+       GRUB_CIPHER_MODE_CBC_ESSIV
+};
+
+typedef enum grub_cipher_type grub_cipher_type_t;
+typedef enum grub_cipher_mode grub_cipher_mode_t;
+
+struct grub_cipher_params;
+typedef struct grub_cipher_params *grub_cipher_params_t;
+
+struct grub_cipher
+{
+  const char *name;
+  grub_cipher_type_t type;
+  const unsigned int *keysizes, keysizes_length;
+  const unsigned int blocksize;
+
+    grub_err_t (*init) (grub_cipher_params_t);
+  void (*deinit) (grub_cipher_params_t);
+
+  union
+  {
+    struct
+    {
+      const unsigned int *ivsizes, ivsizes_length;
+
+        grub_err_t (*set_key) (grub_cipher_params_t, const char *key);
+        grub_err_t (*encrypt) (grub_cipher_params_t, char **out,
+                              const char *in, grub_size_t * outsize,
+                              grub_size_t insize);
+        grub_err_t (*decrypt) (grub_cipher_params_t, char **out,
+                              const char *in, grub_size_t * outsize,
+                              grub_size_t insize);
+               grub_err_t (*decrypt_block) (grub_cipher_params_t, char *out, 
char *in);
+               grub_err_t (*encrypt_block) (grub_cipher_params_t, char *out, 
char *in);
+        grub_err_t (*decrypt_inplace) (grub_cipher_params_t, char *buf,
+                                      grub_size_t size);
+        grub_err_t (*encrypt_inplace) (grub_cipher_params_t, char *buf,
+                                      grub_size_t size);
+    } cipher;
+
+    struct
+    {
+      grub_err_t (*fn) (grub_cipher_params_t, char *out, const char *in,
+                       grub_size_t insize);
+    } hash;
+  } u;
+};
+
+typedef struct grub_cipher *grub_cipher_t;
+
+struct grub_cipher_params
+{
+  grub_cipher_t cipher;
+  void *private;
+  unsigned int keysize;
+
+  union
+  {
+    struct
+    {
+      unsigned char *iv;
+      unsigned int iv_length;
+         grub_cipher_mode_t mode;
+    } cipher;
+  } u;
+};
+
+typedef int (*grub_crypto_hook) (grub_cipher_t, void *);
+
+grub_err_t EXPORT_FUNC (grub_crypto_encrypt) (grub_cipher_params_t params,
+                                             char *out, char *in,
+                                             grub_size_t outsize,
+                                             grub_size_t insize);
+grub_err_t EXPORT_FUNC (grub_crypto_decrypt) (grub_cipher_params_t params,
+                                             char *out, char *in,
+                                             grub_size_t outsize,
+                                             grub_size_t insize);
+grub_err_t EXPORT_FUNC (grub_crypto_decrypt_inplace) (grub_cipher_params_t
+                                                     params, char *buf,
+                                                     grub_size_t size);
+grub_err_t EXPORT_FUNC (grub_crypto_encrypt_inplace) (grub_cipher_params_t
+                                                     params, char *buf,
+                                                     grub_size_t size);
+grub_err_t EXPORT_FUNC (grub_crypto_set_key) (grub_cipher_params_t params,
+                                             const char *key);
+int EXPORT_FUNC (grub_crypto_cipher_iterate) (grub_crypto_hook hook,
+                                             void *data);
+grub_err_t EXPORT_FUNC (grub_crypto_hash) (grub_cipher_params_t params,
+                                          char *hash, const char *payload,
+                                          unsigned int size);
+grub_err_t EXPORT_FUNC (grub_crypto_new_cipher) (grub_cipher_params_t *
+                                                params, const char *name,
+                                                grub_cipher_type_t type);
+void EXPORT_FUNC (grub_crypto_delete_cipher) (grub_cipher_params_t params);
+void EXPORT_FUNC (grub_crypto_cipher_register) (grub_cipher_t cipher);
+void EXPORT_FUNC (grub_crypto_cipher_unregister) (grub_cipher_t cipher);
+
+#endif

=== modified file 'conf/common.rmk'
--- conf/common.rmk     2009-06-21 10:11:34 +0000
+++ conf/common.rmk     2009-06-21 10:16:08 +0000
@@ -653,3 +653,9 @@
 sha512_mod_SOURCES = crypto/sha512.c
 sha512_mod_CFLAGS = $(COMMON_CFLAGS)
 sha512_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For aes.mod
+pkglib_MODULES += aes.mod
+aes_mod_SOURCES = crypto/aes.c
+aes_mod_CFLAGS = $(COMMON_CFLAGS)
+aes_mod_LDFLAGS = $(COMMON_LDFLAGS)

=== added file 'crypto/aes.c'
--- crypto/aes.c        1970-01-01 00:00:00 +0000
+++ crypto/aes.c        2009-06-21 10:16:08 +0000
@@ -0,0 +1,762 @@
+/* Rijndael (AES) for GnuPG
+ * Copyright (C) 2000, 2001, 2002, 2003, 2007,
+ *               2008 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *******************************************************************
+ * The code here is based on the optimized implementation taken from
+ * http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ on Oct 2, 2000,
+ * which carries this notice:
+ *------------------------------------------
+ * rijndael-alg-fst.c   v2.3   April '2000
+ *
+ * Optimised ANSI C code
+ *
+ * authors: v1.0: Antoon Bosselaers
+ *          v2.0: Vincent Rijmen
+ *          v2.3: Paulo Barreto
+ *
+ * This code is placed in the public domain.
+ *------------------------------------------
+ */
+
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/crypto.h>
+#include <grub/dl.h>
+#include <grub/err.h>
+
+#define MAXKC                  (256/32)
+#define MAXROUNDS              14
+#define BLOCKSIZE               (128/8)
+
+typedef union {
+  int a;
+  short b;
+  char c[1];
+  long d;
+#ifdef HAVE_U64_TYPEDEF
+  u64 e;
+#endif
+  float f;
+  double g;
+} PROPERLY_ALIGNED_TYPE;
+
+/* USE_PADLOCK indicates whether to compile the padlock specific
+   code.  */
+#undef USE_PADLOCK
+#ifdef ENABLE_PADLOCK_SUPPORT
+# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__)
+# define USE_PADLOCK
+# endif
+#endif /*ENABLE_PADLOCK_SUPPORT*/
+
+static const char *selftest(void);
+
+typedef struct 
+{
+  int   ROUNDS;             /* Key-length-dependent number of rounds.  */
+  int decryption_prepared;  /* The decryption key schedule is available.  */
+#ifdef USE_PADLOCK
+  int use_padlock;          /* Padlock shall be used.  */
+  /* The key as passed to the padlock engine.  */
+  unsigned char padlock_key[16] __attribute__ ((aligned (16)));
+#endif
+  union
+  {
+    PROPERLY_ALIGNED_TYPE dummy;
+    grub_uint8_t keyschedule[MAXROUNDS+1][4][4];
+  } u1;
+  union
+  {
+    PROPERLY_ALIGNED_TYPE dummy;
+    grub_uint8_t keyschedule[MAXROUNDS+1][4][4];       
+  } u2;
+} RIJNDAEL_context;
+
+#define keySched  u1.keyschedule
+#define keySched2 u2.keyschedule
+
+/* All the numbers.  */
+#include "rijndael-tables.h"
+
+
+/* Perform the key setup.  */  
+static grub_err_t
+do_setkey (RIJNDAEL_context *ctx, const grub_uint8_t *key, const unsigned 
keylen)
+{
+  static int initialized = 0;
+  static const char *selftest_failed=0;
+  int ROUNDS;
+  grub_uint8_t k[MAXKC][4];
+  int i,j, r, t, rconpointer = 0;
+  grub_uint8_t tk[MAXKC][4];
+  int KC;
+
+  if (!initialized)
+  {
+    initialized = 1;
+    selftest_failed = selftest ();
+    if( selftest_failed )
+      grub_dprintf("aes", "%s\n", selftest_failed );
+  }
+  if( selftest_failed )
+    return GRUB_ERR_TEST_FAILURE;
+
+  ctx->decryption_prepared = 0;
+#ifdef USE_PADLOCK
+  ctx->use_padlock = 0;
+#endif
+
+  if( keylen == 128/8 )
+  {
+    ROUNDS = 10;
+    KC = 4;
+#ifdef USE_PADLOCK
+    if ((_gcry_get_hw_features () & HWF_PADLOCK_AES))
+    {
+      ctx->use_padlock = 1;
+      memcpy (ctx->padlock_key, key, keylen);
+    }
+#endif
+  }
+  else if ( keylen == 192/8 )
+  {
+    ROUNDS = 12;
+    KC = 6;
+  }
+  else if ( keylen == 256/8 )
+  {
+    ROUNDS = 14;
+    KC = 8;
+  }
+  else
+    return GRUB_ERR_BAD_ARGUMENT;
+
+  ctx->ROUNDS = ROUNDS;
+
+#ifdef USE_PADLOCK
+  if (ctx->use_padlock)
+  {
+    /* Nothing to do as we support only hardware key generation for
+       now.  */
+  }
+  else
+#endif /*USE_PADLOCK*/
+  {
+#define W (ctx->keySched)
+    for (i = 0; i < keylen; i++) 
+    {
+      k[i >> 2][i & 3] = key[i]; 
+    }
+
+    for (j = KC-1; j >= 0; j--) 
+    {
+      *((grub_uint32_t*)tk[j]) = *((grub_uint32_t*)k[j]);
+    }
+    r = 0;
+    t = 0;
+    /* Copy values into round key array.  */
+    for (j = 0; (j < KC) && (r < ROUNDS + 1); )
+    {
+      for (; (j < KC) && (t < 4); j++, t++)
+      {
+        *((grub_uint32_t*)W[r][t]) = *((grub_uint32_t*)tk[j]);
+      }
+      if (t == 4)
+      {
+        r++;
+        t = 0;
+      }
+    }
+
+    while (r < ROUNDS + 1)
+    {
+      /* While not enough round key material calculated calculate
+         new values.  */
+      tk[0][0] ^= S[tk[KC-1][1]];
+      tk[0][1] ^= S[tk[KC-1][2]];
+      tk[0][2] ^= S[tk[KC-1][3]];
+      tk[0][3] ^= S[tk[KC-1][0]];
+      tk[0][0] ^= rcon[rconpointer++];
+
+      if (KC != 8)
+      {
+        for (j = 1; j < KC; j++) 
+        {
+          *((grub_uint32_t*)tk[j]) ^= *((grub_uint32_t*)tk[j-1]);
+        }
+      } 
+      else 
+      {
+        for (j = 1; j < KC/2; j++)
+        {
+          *((grub_uint32_t*)tk[j]) ^= *((grub_uint32_t*)tk[j-1]);
+        }
+        tk[KC/2][0] ^= S[tk[KC/2 - 1][0]];
+        tk[KC/2][1] ^= S[tk[KC/2 - 1][1]];
+        tk[KC/2][2] ^= S[tk[KC/2 - 1][2]];
+        tk[KC/2][3] ^= S[tk[KC/2 - 1][3]];
+        for (j = KC/2 + 1; j < KC; j++)
+        {
+          *((grub_uint32_t*)tk[j]) ^= *((grub_uint32_t*)tk[j-1]);
+        }
+      }
+
+      /* Copy values into round key array.  */
+      for (j = 0; (j < KC) && (r < ROUNDS + 1); )
+      {
+        for (; (j < KC) && (t < 4); j++, t++)
+        {
+          *((grub_uint32_t*)W[r][t]) = *((grub_uint32_t*)tk[j]);
+        }
+        if (t == 4)
+        {
+          r++;
+          t = 0;
+        }
+      }
+    }          
+#undef W    
+  }
+
+  return 0;
+}
+
+
+static grub_err_t
+rijndael_setkey (void *context, const grub_uint8_t *key, const unsigned keylen)
+{
+  RIJNDAEL_context *ctx = context;
+
+  int rc = do_setkey (ctx, key, keylen);
+  //  _gcry_burn_stack ( 100 + 16*sizeof(int));
+  return rc;
+}
+
+
+/* Make a decryption key from an encryption key. */
+static void
+prepare_decryption( RIJNDAEL_context *ctx )
+{
+  int r;
+  grub_uint8_t *w;
+
+  for (r=0; r < MAXROUNDS+1; r++ )
+  {
+    *((grub_uint32_t*)ctx->keySched2[r][0]) = 
*((grub_uint32_t*)ctx->keySched[r][0]);
+    *((grub_uint32_t*)ctx->keySched2[r][1]) = 
*((grub_uint32_t*)ctx->keySched[r][1]);
+    *((grub_uint32_t*)ctx->keySched2[r][2]) = 
*((grub_uint32_t*)ctx->keySched[r][2]);
+    *((grub_uint32_t*)ctx->keySched2[r][3]) = 
*((grub_uint32_t*)ctx->keySched[r][3]);
+  }
+#define W (ctx->keySched2)
+  for (r = 1; r < ctx->ROUNDS; r++)
+  {
+    w = W[r][0];
+    *((grub_uint32_t*)w) = *((grub_uint32_t*)U1[w[0]]) ^ 
*((grub_uint32_t*)U2[w[1]])
+      ^ *((grub_uint32_t*)U3[w[2]]) ^ *((grub_uint32_t*)U4[w[3]]);
+
+    w = W[r][1];
+    *((grub_uint32_t*)w) = *((grub_uint32_t*)U1[w[0]]) ^ 
*((grub_uint32_t*)U2[w[1]])
+      ^ *((grub_uint32_t*)U3[w[2]]) ^ *((grub_uint32_t*)U4[w[3]]);
+
+    w = W[r][2];
+    *((grub_uint32_t*)w) = *((grub_uint32_t*)U1[w[0]]) ^ 
*((grub_uint32_t*)U2[w[1]])
+      ^ *((grub_uint32_t*)U3[w[2]]) ^ *((grub_uint32_t*)U4[w[3]]);
+
+    w = W[r][3];
+    *((grub_uint32_t*)w) = *((grub_uint32_t*)U1[w[0]]) ^ 
*((grub_uint32_t*)U2[w[1]])
+      ^ *((grub_uint32_t*)U3[w[2]]) ^ *((grub_uint32_t*)U4[w[3]]);
+  }
+#undef W
+}      
+
+
+
+/* Encrypt one block.  A and B need to be aligned on a 4 grub_uint8_t
+   boundary.  A and B may be the same. */
+static void
+do_encrypt_aligned (const RIJNDAEL_context *ctx, 
+    unsigned char *b, const unsigned char *a)
+{
+#define rk (ctx->keySched)
+  int ROUNDS = ctx->ROUNDS;
+  int r;
+  union
+  {
+    grub_uint32_t  tempgrub_uint32_t[4];  /* Force correct alignment. */
+    grub_uint8_t temp[4][4];
+  } u;
+
+  *((grub_uint32_t*)u.temp[0]) = *((grub_uint32_t*)(a   )) ^ 
*((grub_uint32_t*)rk[0][0]);
+  *((grub_uint32_t*)u.temp[1]) = *((grub_uint32_t*)(a+ 4)) ^ 
*((grub_uint32_t*)rk[0][1]);
+  *((grub_uint32_t*)u.temp[2]) = *((grub_uint32_t*)(a+ 8)) ^ 
*((grub_uint32_t*)rk[0][2]);
+  *((grub_uint32_t*)u.temp[3]) = *((grub_uint32_t*)(a+12)) ^ 
*((grub_uint32_t*)rk[0][3]);
+  *((grub_uint32_t*)(b    ))   = (*((grub_uint32_t*)T1[u.temp[0][0]])
+      ^ *((grub_uint32_t*)T2[u.temp[1][1]])
+      ^ *((grub_uint32_t*)T3[u.temp[2][2]]) 
+      ^ *((grub_uint32_t*)T4[u.temp[3][3]]));
+  *((grub_uint32_t*)(b + 4))   = (*((grub_uint32_t*)T1[u.temp[1][0]])
+      ^ *((grub_uint32_t*)T2[u.temp[2][1]])
+      ^ *((grub_uint32_t*)T3[u.temp[3][2]]) 
+      ^ *((grub_uint32_t*)T4[u.temp[0][3]]));
+  *((grub_uint32_t*)(b + 8))   = (*((grub_uint32_t*)T1[u.temp[2][0]])
+      ^ *((grub_uint32_t*)T2[u.temp[3][1]])
+      ^ *((grub_uint32_t*)T3[u.temp[0][2]]) 
+      ^ *((grub_uint32_t*)T4[u.temp[1][3]]));
+  *((grub_uint32_t*)(b +12))   = (*((grub_uint32_t*)T1[u.temp[3][0]])
+      ^ *((grub_uint32_t*)T2[u.temp[0][1]])
+      ^ *((grub_uint32_t*)T3[u.temp[1][2]]) 
+      ^ *((grub_uint32_t*)T4[u.temp[2][3]]));
+
+  for (r = 1; r < ROUNDS-1; r++)
+  {
+    *((grub_uint32_t*)u.temp[0]) = *((grub_uint32_t*)(b   )) ^ 
*((grub_uint32_t*)rk[r][0]);
+    *((grub_uint32_t*)u.temp[1]) = *((grub_uint32_t*)(b+ 4)) ^ 
*((grub_uint32_t*)rk[r][1]);
+    *((grub_uint32_t*)u.temp[2]) = *((grub_uint32_t*)(b+ 8)) ^ 
*((grub_uint32_t*)rk[r][2]);
+    *((grub_uint32_t*)u.temp[3]) = *((grub_uint32_t*)(b+12)) ^ 
*((grub_uint32_t*)rk[r][3]);
+
+    *((grub_uint32_t*)(b    ))   = (*((grub_uint32_t*)T1[u.temp[0][0]])
+        ^ *((grub_uint32_t*)T2[u.temp[1][1]])
+        ^ *((grub_uint32_t*)T3[u.temp[2][2]]) 
+        ^ *((grub_uint32_t*)T4[u.temp[3][3]]));
+    *((grub_uint32_t*)(b + 4))   = (*((grub_uint32_t*)T1[u.temp[1][0]])
+        ^ *((grub_uint32_t*)T2[u.temp[2][1]])
+        ^ *((grub_uint32_t*)T3[u.temp[3][2]]) 
+        ^ *((grub_uint32_t*)T4[u.temp[0][3]]));
+    *((grub_uint32_t*)(b + 8))   = (*((grub_uint32_t*)T1[u.temp[2][0]])
+        ^ *((grub_uint32_t*)T2[u.temp[3][1]])
+        ^ *((grub_uint32_t*)T3[u.temp[0][2]]) 
+        ^ *((grub_uint32_t*)T4[u.temp[1][3]]));
+    *((grub_uint32_t*)(b +12))   = (*((grub_uint32_t*)T1[u.temp[3][0]])
+        ^ *((grub_uint32_t*)T2[u.temp[0][1]])
+        ^ *((grub_uint32_t*)T3[u.temp[1][2]]) 
+        ^ *((grub_uint32_t*)T4[u.temp[2][3]]));
+  }
+
+  /* Last round is special. */   
+  *((grub_uint32_t*)u.temp[0]) = *((grub_uint32_t*)(b   )) ^ 
*((grub_uint32_t*)rk[ROUNDS-1][0]);
+  *((grub_uint32_t*)u.temp[1]) = *((grub_uint32_t*)(b+ 4)) ^ 
*((grub_uint32_t*)rk[ROUNDS-1][1]);
+  *((grub_uint32_t*)u.temp[2]) = *((grub_uint32_t*)(b+ 8)) ^ 
*((grub_uint32_t*)rk[ROUNDS-1][2]);
+  *((grub_uint32_t*)u.temp[3]) = *((grub_uint32_t*)(b+12)) ^ 
*((grub_uint32_t*)rk[ROUNDS-1][3]);
+  b[ 0] = T1[u.temp[0][0]][1];
+  b[ 1] = T1[u.temp[1][1]][1];
+  b[ 2] = T1[u.temp[2][2]][1];
+  b[ 3] = T1[u.temp[3][3]][1];
+  b[ 4] = T1[u.temp[1][0]][1];
+  b[ 5] = T1[u.temp[2][1]][1];
+  b[ 6] = T1[u.temp[3][2]][1];
+  b[ 7] = T1[u.temp[0][3]][1];
+  b[ 8] = T1[u.temp[2][0]][1];
+  b[ 9] = T1[u.temp[3][1]][1];
+  b[10] = T1[u.temp[0][2]][1];
+  b[11] = T1[u.temp[1][3]][1];
+  b[12] = T1[u.temp[3][0]][1];
+  b[13] = T1[u.temp[0][1]][1];
+  b[14] = T1[u.temp[1][2]][1];
+  b[15] = T1[u.temp[2][3]][1];
+  *((grub_uint32_t*)(b   )) ^= *((grub_uint32_t*)rk[ROUNDS][0]);
+  *((grub_uint32_t*)(b+ 4)) ^= *((grub_uint32_t*)rk[ROUNDS][1]);
+  *((grub_uint32_t*)(b+ 8)) ^= *((grub_uint32_t*)rk[ROUNDS][2]);
+  *((grub_uint32_t*)(b+12)) ^= *((grub_uint32_t*)rk[ROUNDS][3]);
+#undef rk
+}
+
+static void
+do_encrypt (const RIJNDAEL_context *ctx,
+    unsigned char *bx, const unsigned char *ax)
+{
+  /* BX and AX are not necessary correctly aligned.  Thus we need to
+     copy them here. */
+  union
+  {
+    grub_uint32_t  dummy[4]; 
+    grub_uint8_t a[16];
+  } a;
+  union
+  {
+    grub_uint32_t  dummy[4]; 
+    grub_uint8_t b[16];
+  } b;
+
+  memcpy (a.a, ax, 16);
+  do_encrypt_aligned (ctx, b.b, a.a);
+  memcpy (bx, b.b, 16);
+}
+
+
+/* Encrypt or decrypt one block using the padlock engine.  A and B may
+   be the same. */
+#ifdef USE_PADLOCK
+static void
+do_padlock (const RIJNDAEL_context *ctx, int decrypt_flag,
+    unsigned char *bx, const unsigned char *ax)
+{
+  /* BX and AX are not necessary correctly aligned.  Thus we need to
+     copy them here. */
+  unsigned char a[16] __attribute__ ((aligned (16)));
+  unsigned char b[16] __attribute__ ((aligned (16)));
+  unsigned int cword[4] __attribute__ ((aligned (16)));
+
+  /* The control word fields are:
+127:12   11:10 9     8     7     6     5     4     3:0
+RESERVED KSIZE CRYPT INTER KEYGN CIPHR ALIGN DGEST ROUND  */
+  cword[0] = (ctx->ROUNDS & 15);  /* (The mask is just a safeguard.)  */
+  cword[1] = 0;
+  cword[2] = 0;
+  cword[3] = 0;
+  if (decrypt_flag)
+    cword[0] |= 0x00000200;
+
+  memcpy (a, ax, 16);
+
+  asm volatile 
+    ("pushfl\n\t"          /* Force key reload.  */            
+     "popfl\n\t"
+     "xchg %3, %%ebx\n\t"  /* Load key.  */
+     "movl $1, %%ecx\n\t"  /* Init counter for just one block.  */
+     ".grub_uint8_t 0xf3, 0x0f, 0xa7, 0xc8\n\t" /* REP XSTORE ECB. */
+     "xchg %3, %%ebx\n"    /* Restore GOT register.  */
+     : /* No output */
+     : "S" (a), "D" (b), "d" (cword), "r" (ctx->padlock_key)
+     : "%ecx", "cc", "memory"
+    );
+
+  memcpy (bx, b, 16);
+
+}
+#endif /*USE_PADLOCK*/
+
+
+static void
+rijndael_encrypt (void *context, grub_uint8_t *b, const grub_uint8_t *a)
+{
+  RIJNDAEL_context *ctx = context;
+
+#ifdef USE_PADLOCK
+  if (ctx->use_padlock)
+  {
+    do_padlock (ctx, 0, b, a);
+    //      _gcry_burn_stack (48 + 15 /* possible padding for alignment */);
+  }
+  else
+#endif /*USE_PADLOCK*/
+  {
+    do_encrypt (ctx, b, a);
+    //      _gcry_burn_stack (48 + 2*sizeof(int));
+  }
+}
+
+
+/* Decrypt one block.  A and B need to be aligned on a 4 grub_uint8_t boundary
+   and the decryption must have been prepared.  A and B may be the
+   same. */
+static void
+do_decrypt_aligned (RIJNDAEL_context *ctx, 
+    unsigned char *b, const unsigned char *a)
+{
+#define rk  (ctx->keySched2)
+  int ROUNDS = ctx->ROUNDS; 
+  int r;
+  union 
+  {
+    grub_uint32_t  tempgrub_uint32_t[4];  /* Force correct alignment. */
+    grub_uint8_t temp[4][4];
+  } u;
+
+
+  *((grub_uint32_t*)u.temp[0]) = *((grub_uint32_t*)(a   )) ^ 
*((grub_uint32_t*)rk[ROUNDS][0]);
+  *((grub_uint32_t*)u.temp[1]) = *((grub_uint32_t*)(a+ 4)) ^ 
*((grub_uint32_t*)rk[ROUNDS][1]);
+  *((grub_uint32_t*)u.temp[2]) = *((grub_uint32_t*)(a+ 8)) ^ 
*((grub_uint32_t*)rk[ROUNDS][2]);
+  *((grub_uint32_t*)u.temp[3]) = *((grub_uint32_t*)(a+12)) ^ 
*((grub_uint32_t*)rk[ROUNDS][3]);
+
+  *((grub_uint32_t*)(b   ))    = (*((grub_uint32_t*)T5[u.temp[0][0]])
+      ^ *((grub_uint32_t*)T6[u.temp[3][1]])
+      ^ *((grub_uint32_t*)T7[u.temp[2][2]]) 
+      ^ *((grub_uint32_t*)T8[u.temp[1][3]]));
+  *((grub_uint32_t*)(b+ 4))    = (*((grub_uint32_t*)T5[u.temp[1][0]])
+      ^ *((grub_uint32_t*)T6[u.temp[0][1]])
+      ^ *((grub_uint32_t*)T7[u.temp[3][2]]) 
+      ^ *((grub_uint32_t*)T8[u.temp[2][3]]));
+  *((grub_uint32_t*)(b+ 8))    = (*((grub_uint32_t*)T5[u.temp[2][0]])
+      ^ *((grub_uint32_t*)T6[u.temp[1][1]])
+      ^ *((grub_uint32_t*)T7[u.temp[0][2]]) 
+      ^ *((grub_uint32_t*)T8[u.temp[3][3]]));
+  *((grub_uint32_t*)(b+12))    = (*((grub_uint32_t*)T5[u.temp[3][0]])
+      ^ *((grub_uint32_t*)T6[u.temp[2][1]])
+      ^ *((grub_uint32_t*)T7[u.temp[1][2]]) 
+      ^ *((grub_uint32_t*)T8[u.temp[0][3]]));
+
+  for (r = ROUNDS-1; r > 1; r--)
+  {
+    *((grub_uint32_t*)u.temp[0]) = *((grub_uint32_t*)(b   )) ^ 
*((grub_uint32_t*)rk[r][0]);
+    *((grub_uint32_t*)u.temp[1]) = *((grub_uint32_t*)(b+ 4)) ^ 
*((grub_uint32_t*)rk[r][1]);
+    *((grub_uint32_t*)u.temp[2]) = *((grub_uint32_t*)(b+ 8)) ^ 
*((grub_uint32_t*)rk[r][2]);
+    *((grub_uint32_t*)u.temp[3]) = *((grub_uint32_t*)(b+12)) ^ 
*((grub_uint32_t*)rk[r][3]);
+    *((grub_uint32_t*)(b   ))    = (*((grub_uint32_t*)T5[u.temp[0][0]])
+        ^ *((grub_uint32_t*)T6[u.temp[3][1]])
+        ^ *((grub_uint32_t*)T7[u.temp[2][2]]) 
+        ^ *((grub_uint32_t*)T8[u.temp[1][3]]));
+    *((grub_uint32_t*)(b+ 4))    = (*((grub_uint32_t*)T5[u.temp[1][0]])
+        ^ *((grub_uint32_t*)T6[u.temp[0][1]])
+        ^ *((grub_uint32_t*)T7[u.temp[3][2]]) 
+        ^ *((grub_uint32_t*)T8[u.temp[2][3]]));
+    *((grub_uint32_t*)(b+ 8))    = (*((grub_uint32_t*)T5[u.temp[2][0]])
+        ^ *((grub_uint32_t*)T6[u.temp[1][1]])
+        ^ *((grub_uint32_t*)T7[u.temp[0][2]]) 
+        ^ *((grub_uint32_t*)T8[u.temp[3][3]]));
+    *((grub_uint32_t*)(b+12))    = (*((grub_uint32_t*)T5[u.temp[3][0]])
+        ^ *((grub_uint32_t*)T6[u.temp[2][1]])
+        ^ *((grub_uint32_t*)T7[u.temp[1][2]]) 
+        ^ *((grub_uint32_t*)T8[u.temp[0][3]]));
+  }
+
+  /* Last round is special. */   
+  *((grub_uint32_t*)u.temp[0]) = *((grub_uint32_t*)(b   )) ^ 
*((grub_uint32_t*)rk[1][0]);
+  *((grub_uint32_t*)u.temp[1]) = *((grub_uint32_t*)(b+ 4)) ^ 
*((grub_uint32_t*)rk[1][1]);
+  *((grub_uint32_t*)u.temp[2]) = *((grub_uint32_t*)(b+ 8)) ^ 
*((grub_uint32_t*)rk[1][2]);
+  *((grub_uint32_t*)u.temp[3]) = *((grub_uint32_t*)(b+12)) ^ 
*((grub_uint32_t*)rk[1][3]);
+  b[ 0] = S5[u.temp[0][0]];
+  b[ 1] = S5[u.temp[3][1]];
+  b[ 2] = S5[u.temp[2][2]];
+  b[ 3] = S5[u.temp[1][3]];
+  b[ 4] = S5[u.temp[1][0]];
+  b[ 5] = S5[u.temp[0][1]];
+  b[ 6] = S5[u.temp[3][2]];
+  b[ 7] = S5[u.temp[2][3]];
+  b[ 8] = S5[u.temp[2][0]];
+  b[ 9] = S5[u.temp[1][1]];
+  b[10] = S5[u.temp[0][2]];
+  b[11] = S5[u.temp[3][3]];
+  b[12] = S5[u.temp[3][0]];
+  b[13] = S5[u.temp[2][1]];
+  b[14] = S5[u.temp[1][2]];
+  b[15] = S5[u.temp[0][3]];
+  *((grub_uint32_t*)(b   )) ^= *((grub_uint32_t*)rk[0][0]);
+  *((grub_uint32_t*)(b+ 4)) ^= *((grub_uint32_t*)rk[0][1]);
+  *((grub_uint32_t*)(b+ 8)) ^= *((grub_uint32_t*)rk[0][2]);
+  *((grub_uint32_t*)(b+12)) ^= *((grub_uint32_t*)rk[0][3]);
+#undef rk
+}
+
+
+/* Decrypt one block.  AX and BX may be the same. */
+static void
+do_decrypt (RIJNDAEL_context *ctx, grub_uint8_t *bx, const grub_uint8_t *ax)
+{
+  /* BX and AX are not necessary correctly aligned.  Thus we need to
+     copy them here. */
+  union
+  {
+    grub_uint32_t  dummy[4]; 
+    grub_uint8_t a[16];
+  } a;
+  union
+  {
+    grub_uint32_t  dummy[4]; 
+    grub_uint8_t b[16];
+  } b;
+
+  if ( !ctx->decryption_prepared )
+  {
+    prepare_decryption ( ctx );
+    //      _gcry_burn_stack (64);
+    ctx->decryption_prepared = 1;
+  }
+
+  memcpy (a.a, ax, 16);
+  do_decrypt_aligned (ctx, b.b, a.a);
+  memcpy (bx, b.b, 16);
+#undef rk
+}
+
+static void
+rijndael_decrypt (void *context, grub_uint8_t *b, const grub_uint8_t *a)
+{
+  RIJNDAEL_context *ctx = context;
+
+#ifdef USE_PADLOCK
+  if (ctx->use_padlock)
+  {
+    do_padlock (ctx, 1, b, a);
+    //      _gcry_burn_stack (48 + 2*sizeof(int) /* FIXME */);
+  }
+  else
+#endif /*USE_PADLOCK*/
+  {
+    do_decrypt (ctx, b, a);
+    //      _gcry_burn_stack (48+2*sizeof(int));
+  }
+}
+
+
+/* Test a single encryption and decryption with each key size. */
+static const char*
+selftest (void)
+{
+  RIJNDAEL_context ctx;
+  grub_uint8_t scratch[16];       
+
+  /* The test vectors are from the AES supplied ones; more or less 
+   * randomly taken from ecb_tbl.txt (I=42,81,14)
+   */
+  static grub_uint8_t plaintext[16] = {
+    0x01,0x4B,0xAF,0x22,0x78,0xA6,0x9D,0x33,
+    0x1D,0x51,0x80,0x10,0x36,0x43,0xE9,0x9A
+  };
+  static grub_uint8_t key[16] = {
+    0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,0xF0,
+    0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA
+  };
+  static const grub_uint8_t ciphertext[16] = {
+    0x67,0x43,0xC3,0xD1,0x51,0x9A,0xB4,0xF2,
+    0xCD,0x9A,0x78,0xAB,0x09,0xA5,0x11,0xBD
+  };
+
+  static grub_uint8_t plaintext_192[16] = {
+    0x76,0x77,0x74,0x75,0xF1,0xF2,0xF3,0xF4,
+    0xF8,0xF9,0xE6,0xE7,0x77,0x70,0x71,0x72
+  };
+  static grub_uint8_t key_192[24] = {
+    0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C,
+    0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16,
+    0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20
+  };
+  static const grub_uint8_t ciphertext_192[16] = {
+    0x5D,0x1E,0xF2,0x0D,0xCE,0xD6,0xBC,0xBC,
+    0x12,0x13,0x1A,0xC7,0xC5,0x47,0x88,0xAA
+  };
+
+  static grub_uint8_t plaintext_256[16] = {
+    0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
+    0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21
+  };
+  static grub_uint8_t key_256[32] = {
+    0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10,
+    0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A,
+    0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24,
+    0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E
+  };
+  static const grub_uint8_t ciphertext_256[16] = {
+    0x08,0x0E,0x95,0x17,0xEB,0x16,0x77,0x71,
+    0x9A,0xCF,0x72,0x80,0x86,0x04,0x0A,0xE3
+  };
+
+  rijndael_setkey (&ctx, key, sizeof(key));
+  rijndael_encrypt (&ctx, scratch, plaintext);
+  if (grub_memcmp (scratch, ciphertext, sizeof (ciphertext)))
+    return "Rijndael-128 test encryption failed.";
+  rijndael_decrypt (&ctx, scratch, scratch);
+  if (grub_memcmp (scratch, plaintext, sizeof (plaintext)))
+    return "Rijndael-128 test decryption failed.";
+
+  rijndael_setkey (&ctx, key_192, sizeof(key_192));
+  rijndael_encrypt (&ctx, scratch, plaintext_192);
+  if (grub_memcmp (scratch, ciphertext_192, sizeof (ciphertext_192)))
+    return "Rijndael-192 test encryption failed.";
+  rijndael_decrypt (&ctx, scratch, scratch);
+  if (grub_memcmp (scratch, plaintext_192, sizeof (plaintext_192)))
+    return "Rijndael-192 test decryption failed.";
+
+  rijndael_setkey (&ctx, key_256, sizeof(key_256));
+  rijndael_encrypt (&ctx, scratch, plaintext_256);
+  if (grub_memcmp (scratch, ciphertext_256, sizeof (ciphertext_256)))
+    return "Rijndael-256 test encryption failed.";
+  rijndael_decrypt (&ctx, scratch, scratch);
+  if (grub_memcmp (scratch, plaintext_256, sizeof (plaintext_256)))
+    return "Rijndael-256 test decryption failed.";
+
+  return NULL;
+}
+
+/**
+ * GRUB2 Crypto Interface
+ * Written by Michael Gorven
+ */
+
+static grub_err_t
+grub_cipher_aes_init (grub_cipher_params_t params)
+{
+  if (!(params->private = grub_malloc(sizeof(RIJNDAEL_context))))
+    return GRUB_ERR_OUT_OF_MEMORY;
+
+  params->keysize = 32;
+
+  return GRUB_ERR_NONE;
+}
+
+static void
+grub_cipher_aes_deinit (grub_cipher_params_t params)
+{
+  grub_free(params->private);
+}
+
+static grub_err_t
+grub_cipher_aes_set_key(grub_cipher_params_t params, const char *key)
+{
+  rijndael_setkey(params->private, (unsigned char*) key, params->keysize);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cipher_aes_decrypt_block(grub_cipher_params_t params, char *out, char*in)
+{
+  rijndael_decrypt(params->private, (grub_uint32_t *) out, (grub_uint32_t *) 
in);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cipher_aes_encrypt_block(grub_cipher_params_t params, char *out, char*in)
+{
+  rijndael_encrypt(params->private, (grub_uint32_t *) out, (grub_uint32_t *) 
in);
+  return GRUB_ERR_NONE;
+}
+
+#define FIELDSOF(a)    (sizeof(a) / sizeof(a[0]))
+static const unsigned int aes_keysizes[] = { 16, 24, 32 };
+
+static struct grub_cipher grub_cipher_aes = {
+  .name = "aes",
+  .type = GRUB_CIPHER_TYPE_CIPHER,
+  .keysizes = aes_keysizes,
+  .keysizes_length = FIELDSOF(aes_keysizes),
+  .blocksize = 16,
+
+  .init = grub_cipher_aes_init,
+  .deinit = grub_cipher_aes_deinit,
+  .u.cipher = {
+    .set_key = grub_cipher_aes_set_key,
+    .encrypt = NULL,
+    .decrypt = NULL,
+    .encrypt_block = grub_cipher_aes_encrypt_block,
+    .decrypt_block = grub_cipher_aes_decrypt_block,
+    .encrypt_inplace = NULL,
+    .decrypt_inplace = NULL,
+  }
+};
+
+GRUB_MOD_INIT (aes)
+{
+  grub_crypto_cipher_register (&grub_cipher_aes);
+}
+
+GRUB_MOD_FINI (aes)
+{
+  grub_crypto_cipher_unregister (&grub_cipher_aes);
+}
+
+/* vi: set et sw=2 sts=2: */

=== added file 'crypto/rijndael-tables.h'
--- crypto/rijndael-tables.h    1970-01-01 00:00:00 +0000
+++ crypto/rijndael-tables.h    2009-06-21 10:16:08 +0000
@@ -0,0 +1,1687 @@
+/* rijndael-tables.h - Rijndael (AES) for GnuPG, 
+ * Copyright (C) 2000, 2001, 2002, 2003, 2007,
+ *               2008 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* To keep the actual implementation at a readable size we use this
+   include file to define the tables.  */
+
+static const unsigned char S[256] = 
+  {
+     99, 124, 119, 123, 242, 107, 111, 197,
+     48,   1, 103,  43, 254, 215, 171, 118, 
+    202, 130, 201, 125, 250,  89,  71, 240,
+    173, 212, 162, 175, 156, 164, 114, 192, 
+    183, 253, 147,  38,  54,  63, 247, 204,
+     52, 165, 229, 241, 113, 216,  49,  21, 
+      4, 199,  35, 195,  24, 150,   5, 154,
+      7,  18, 128, 226, 235,  39, 178, 117, 
+      9, 131,  44,  26,  27, 110,  90, 160, 
+     82,  59, 214, 179,  41, 227,  47, 132, 
+     83, 209,   0, 237,  32, 252, 177,  91,
+    106, 203, 190,  57,  74,  76,  88, 207, 
+    208, 239, 170, 251,  67,  77,  51, 133,
+     69, 249,   2, 127,  80,  60, 159, 168, 
+     81, 163,  64, 143, 146, 157,  56, 245,
+    188, 182, 218,  33,  16, 255, 243, 210, 
+    205,  12,  19, 236,  95, 151,  68,  23,
+    196, 167, 126,  61, 100,  93,  25, 115, 
+     96, 129,  79, 220,  34,  42, 144, 136,
+     70, 238, 184,  20, 222,  94,  11, 219, 
+    224,  50,  58,  10,  73,   6,  36,  92,
+    194, 211, 172,  98, 145, 149, 228, 121, 
+    231, 200,  55, 109, 141, 213,  78, 169, 
+    108,  86, 244, 234, 101, 122, 174,   8, 
+    186, 120,  37,  46,  28, 166, 180, 198, 
+    232, 221, 116,  31,  75, 189, 139, 138, 
+    112,  62, 181, 102,  72,   3, 246,  14,
+     97,  53,  87, 185, 134, 193,  29, 158, 
+    225, 248, 152,  17, 105, 217, 142, 148,
+    155,  30, 135, 233, 206,  85,  40, 223, 
+    140, 161, 137,  13, 191, 230,  66, 104, 
+     65, 153,  45,  15, 176,  84, 187,  22
+  };
+
+
+static const unsigned char T1[256][4] = 
+  {
+    { 0xc6,0x63,0x63,0xa5 }, { 0xf8,0x7c,0x7c,0x84 },
+    { 0xee,0x77,0x77,0x99 }, { 0xf6,0x7b,0x7b,0x8d }, 
+    { 0xff,0xf2,0xf2,0x0d }, { 0xd6,0x6b,0x6b,0xbd },
+    { 0xde,0x6f,0x6f,0xb1 }, { 0x91,0xc5,0xc5,0x54 }, 
+    { 0x60,0x30,0x30,0x50 }, { 0x02,0x01,0x01,0x03 },
+    { 0xce,0x67,0x67,0xa9 }, { 0x56,0x2b,0x2b,0x7d }, 
+    { 0xe7,0xfe,0xfe,0x19 }, { 0xb5,0xd7,0xd7,0x62 },
+    { 0x4d,0xab,0xab,0xe6 }, { 0xec,0x76,0x76,0x9a }, 
+    { 0x8f,0xca,0xca,0x45 }, { 0x1f,0x82,0x82,0x9d },
+    { 0x89,0xc9,0xc9,0x40 }, { 0xfa,0x7d,0x7d,0x87 }, 
+    { 0xef,0xfa,0xfa,0x15 }, { 0xb2,0x59,0x59,0xeb }, 
+    { 0x8e,0x47,0x47,0xc9 }, { 0xfb,0xf0,0xf0,0x0b }, 
+    { 0x41,0xad,0xad,0xec }, { 0xb3,0xd4,0xd4,0x67 },
+    { 0x5f,0xa2,0xa2,0xfd }, { 0x45,0xaf,0xaf,0xea }, 
+    { 0x23,0x9c,0x9c,0xbf }, { 0x53,0xa4,0xa4,0xf7 },
+    { 0xe4,0x72,0x72,0x96 }, { 0x9b,0xc0,0xc0,0x5b }, 
+    { 0x75,0xb7,0xb7,0xc2 }, { 0xe1,0xfd,0xfd,0x1c },
+    { 0x3d,0x93,0x93,0xae }, { 0x4c,0x26,0x26,0x6a }, 
+    { 0x6c,0x36,0x36,0x5a }, { 0x7e,0x3f,0x3f,0x41 },
+    { 0xf5,0xf7,0xf7,0x02 }, { 0x83,0xcc,0xcc,0x4f }, 
+    { 0x68,0x34,0x34,0x5c }, { 0x51,0xa5,0xa5,0xf4 }, 
+    { 0xd1,0xe5,0xe5,0x34 }, { 0xf9,0xf1,0xf1,0x08 }, 
+    { 0xe2,0x71,0x71,0x93 }, { 0xab,0xd8,0xd8,0x73 },
+    { 0x62,0x31,0x31,0x53 }, { 0x2a,0x15,0x15,0x3f }, 
+    { 0x08,0x04,0x04,0x0c }, { 0x95,0xc7,0xc7,0x52 },
+    { 0x46,0x23,0x23,0x65 }, { 0x9d,0xc3,0xc3,0x5e }, 
+    { 0x30,0x18,0x18,0x28 }, { 0x37,0x96,0x96,0xa1 },
+    { 0x0a,0x05,0x05,0x0f }, { 0x2f,0x9a,0x9a,0xb5 }, 
+    { 0x0e,0x07,0x07,0x09 }, { 0x24,0x12,0x12,0x36 },
+    { 0x1b,0x80,0x80,0x9b }, { 0xdf,0xe2,0xe2,0x3d }, 
+    { 0xcd,0xeb,0xeb,0x26 }, { 0x4e,0x27,0x27,0x69 },
+    { 0x7f,0xb2,0xb2,0xcd }, { 0xea,0x75,0x75,0x9f }, 
+    { 0x12,0x09,0x09,0x1b }, { 0x1d,0x83,0x83,0x9e },
+    { 0x58,0x2c,0x2c,0x74 }, { 0x34,0x1a,0x1a,0x2e }, 
+    { 0x36,0x1b,0x1b,0x2d }, { 0xdc,0x6e,0x6e,0xb2 }, 
+    { 0xb4,0x5a,0x5a,0xee }, { 0x5b,0xa0,0xa0,0xfb }, 
+    { 0xa4,0x52,0x52,0xf6 }, { 0x76,0x3b,0x3b,0x4d },
+    { 0xb7,0xd6,0xd6,0x61 }, { 0x7d,0xb3,0xb3,0xce }, 
+    { 0x52,0x29,0x29,0x7b }, { 0xdd,0xe3,0xe3,0x3e }, 
+    { 0x5e,0x2f,0x2f,0x71 }, { 0x13,0x84,0x84,0x97 }, 
+    { 0xa6,0x53,0x53,0xf5 }, { 0xb9,0xd1,0xd1,0x68 }, 
+    { 0x00,0x00,0x00,0x00 }, { 0xc1,0xed,0xed,0x2c }, 
+    { 0x40,0x20,0x20,0x60 }, { 0xe3,0xfc,0xfc,0x1f },
+    { 0x79,0xb1,0xb1,0xc8 }, { 0xb6,0x5b,0x5b,0xed }, 
+    { 0xd4,0x6a,0x6a,0xbe }, { 0x8d,0xcb,0xcb,0x46 },
+    { 0x67,0xbe,0xbe,0xd9 }, { 0x72,0x39,0x39,0x4b }, 
+    { 0x94,0x4a,0x4a,0xde }, { 0x98,0x4c,0x4c,0xd4 },
+    { 0xb0,0x58,0x58,0xe8 }, { 0x85,0xcf,0xcf,0x4a }, 
+    { 0xbb,0xd0,0xd0,0x6b }, { 0xc5,0xef,0xef,0x2a },
+    { 0x4f,0xaa,0xaa,0xe5 }, { 0xed,0xfb,0xfb,0x16 }, 
+    { 0x86,0x43,0x43,0xc5 }, { 0x9a,0x4d,0x4d,0xd7 },
+    { 0x66,0x33,0x33,0x55 }, { 0x11,0x85,0x85,0x94 }, 
+    { 0x8a,0x45,0x45,0xcf }, { 0xe9,0xf9,0xf9,0x10 },
+    { 0x04,0x02,0x02,0x06 }, { 0xfe,0x7f,0x7f,0x81 }, 
+    { 0xa0,0x50,0x50,0xf0 }, { 0x78,0x3c,0x3c,0x44 },
+    { 0x25,0x9f,0x9f,0xba }, { 0x4b,0xa8,0xa8,0xe3 }, 
+    { 0xa2,0x51,0x51,0xf3 }, { 0x5d,0xa3,0xa3,0xfe },
+    { 0x80,0x40,0x40,0xc0 }, { 0x05,0x8f,0x8f,0x8a }, 
+    { 0x3f,0x92,0x92,0xad }, { 0x21,0x9d,0x9d,0xbc },
+    { 0x70,0x38,0x38,0x48 }, { 0xf1,0xf5,0xf5,0x04 }, 
+    { 0x63,0xbc,0xbc,0xdf }, { 0x77,0xb6,0xb6,0xc1 },
+    { 0xaf,0xda,0xda,0x75 }, { 0x42,0x21,0x21,0x63 }, 
+    { 0x20,0x10,0x10,0x30 }, { 0xe5,0xff,0xff,0x1a },
+    { 0xfd,0xf3,0xf3,0x0e }, { 0xbf,0xd2,0xd2,0x6d }, 
+    { 0x81,0xcd,0xcd,0x4c }, { 0x18,0x0c,0x0c,0x14 },
+    { 0x26,0x13,0x13,0x35 }, { 0xc3,0xec,0xec,0x2f }, 
+    { 0xbe,0x5f,0x5f,0xe1 }, { 0x35,0x97,0x97,0xa2 },
+    { 0x88,0x44,0x44,0xcc }, { 0x2e,0x17,0x17,0x39 }, 
+    { 0x93,0xc4,0xc4,0x57 }, { 0x55,0xa7,0xa7,0xf2 },
+    { 0xfc,0x7e,0x7e,0x82 }, { 0x7a,0x3d,0x3d,0x47 }, 
+    { 0xc8,0x64,0x64,0xac }, { 0xba,0x5d,0x5d,0xe7 },
+    { 0x32,0x19,0x19,0x2b }, { 0xe6,0x73,0x73,0x95 }, 
+    { 0xc0,0x60,0x60,0xa0 }, { 0x19,0x81,0x81,0x98 },
+    { 0x9e,0x4f,0x4f,0xd1 }, { 0xa3,0xdc,0xdc,0x7f }, 
+    { 0x44,0x22,0x22,0x66 }, { 0x54,0x2a,0x2a,0x7e },
+    { 0x3b,0x90,0x90,0xab }, { 0x0b,0x88,0x88,0x83 }, 
+    { 0x8c,0x46,0x46,0xca }, { 0xc7,0xee,0xee,0x29 },
+    { 0x6b,0xb8,0xb8,0xd3 }, { 0x28,0x14,0x14,0x3c }, 
+    { 0xa7,0xde,0xde,0x79 }, { 0xbc,0x5e,0x5e,0xe2 },
+    { 0x16,0x0b,0x0b,0x1d }, { 0xad,0xdb,0xdb,0x76 }, 
+    { 0xdb,0xe0,0xe0,0x3b }, { 0x64,0x32,0x32,0x56 },
+    { 0x74,0x3a,0x3a,0x4e }, { 0x14,0x0a,0x0a,0x1e }, 
+    { 0x92,0x49,0x49,0xdb }, { 0x0c,0x06,0x06,0x0a },
+    { 0x48,0x24,0x24,0x6c }, { 0xb8,0x5c,0x5c,0xe4 }, 
+    { 0x9f,0xc2,0xc2,0x5d }, { 0xbd,0xd3,0xd3,0x6e },
+    { 0x43,0xac,0xac,0xef }, { 0xc4,0x62,0x62,0xa6 }, 
+    { 0x39,0x91,0x91,0xa8 }, { 0x31,0x95,0x95,0xa4 },
+    { 0xd3,0xe4,0xe4,0x37 }, { 0xf2,0x79,0x79,0x8b }, 
+    { 0xd5,0xe7,0xe7,0x32 }, { 0x8b,0xc8,0xc8,0x43 },
+    { 0x6e,0x37,0x37,0x59 }, { 0xda,0x6d,0x6d,0xb7 }, 
+    { 0x01,0x8d,0x8d,0x8c }, { 0xb1,0xd5,0xd5,0x64 },
+    { 0x9c,0x4e,0x4e,0xd2 }, { 0x49,0xa9,0xa9,0xe0 }, 
+    { 0xd8,0x6c,0x6c,0xb4 }, { 0xac,0x56,0x56,0xfa },
+    { 0xf3,0xf4,0xf4,0x07 }, { 0xcf,0xea,0xea,0x25 }, 
+    { 0xca,0x65,0x65,0xaf }, { 0xf4,0x7a,0x7a,0x8e },
+    { 0x47,0xae,0xae,0xe9 }, { 0x10,0x08,0x08,0x18 }, 
+    { 0x6f,0xba,0xba,0xd5 }, { 0xf0,0x78,0x78,0x88 },
+    { 0x4a,0x25,0x25,0x6f }, { 0x5c,0x2e,0x2e,0x72 }, 
+    { 0x38,0x1c,0x1c,0x24 }, { 0x57,0xa6,0xa6,0xf1 },
+    { 0x73,0xb4,0xb4,0xc7 }, { 0x97,0xc6,0xc6,0x51 }, 
+    { 0xcb,0xe8,0xe8,0x23 }, { 0xa1,0xdd,0xdd,0x7c },
+    { 0xe8,0x74,0x74,0x9c }, { 0x3e,0x1f,0x1f,0x21 }, 
+    { 0x96,0x4b,0x4b,0xdd }, { 0x61,0xbd,0xbd,0xdc }, 
+    { 0x0d,0x8b,0x8b,0x86 }, { 0x0f,0x8a,0x8a,0x85 }, 
+    { 0xe0,0x70,0x70,0x90 }, { 0x7c,0x3e,0x3e,0x42 },
+    { 0x71,0xb5,0xb5,0xc4 }, { 0xcc,0x66,0x66,0xaa }, 
+    { 0x90,0x48,0x48,0xd8 }, { 0x06,0x03,0x03,0x05 },
+    { 0xf7,0xf6,0xf6,0x01 }, { 0x1c,0x0e,0x0e,0x12 }, 
+    { 0xc2,0x61,0x61,0xa3 }, { 0x6a,0x35,0x35,0x5f },
+    { 0xae,0x57,0x57,0xf9 }, { 0x69,0xb9,0xb9,0xd0 }, 
+    { 0x17,0x86,0x86,0x91 }, { 0x99,0xc1,0xc1,0x58 },
+    { 0x3a,0x1d,0x1d,0x27 }, { 0x27,0x9e,0x9e,0xb9 }, 
+    { 0xd9,0xe1,0xe1,0x38 }, { 0xeb,0xf8,0xf8,0x13 },
+    { 0x2b,0x98,0x98,0xb3 }, { 0x22,0x11,0x11,0x33 }, 
+    { 0xd2,0x69,0x69,0xbb }, { 0xa9,0xd9,0xd9,0x70 },
+    { 0x07,0x8e,0x8e,0x89 }, { 0x33,0x94,0x94,0xa7 }, 
+    { 0x2d,0x9b,0x9b,0xb6 }, { 0x3c,0x1e,0x1e,0x22 },
+    { 0x15,0x87,0x87,0x92 }, { 0xc9,0xe9,0xe9,0x20 }, 
+    { 0x87,0xce,0xce,0x49 }, { 0xaa,0x55,0x55,0xff },
+    { 0x50,0x28,0x28,0x78 }, { 0xa5,0xdf,0xdf,0x7a }, 
+    { 0x03,0x8c,0x8c,0x8f }, { 0x59,0xa1,0xa1,0xf8 },
+    { 0x09,0x89,0x89,0x80 }, { 0x1a,0x0d,0x0d,0x17 }, 
+    { 0x65,0xbf,0xbf,0xda }, { 0xd7,0xe6,0xe6,0x31 },
+    { 0x84,0x42,0x42,0xc6 }, { 0xd0,0x68,0x68,0xb8 }, 
+    { 0x82,0x41,0x41,0xc3 }, { 0x29,0x99,0x99,0xb0 },
+    { 0x5a,0x2d,0x2d,0x77 }, { 0x1e,0x0f,0x0f,0x11 }, 
+    { 0x7b,0xb0,0xb0,0xcb }, { 0xa8,0x54,0x54,0xfc },
+    { 0x6d,0xbb,0xbb,0xd6 }, { 0x2c,0x16,0x16,0x3a }
+  };
+
+static const unsigned char T2[256][4] = 
+  {
+    { 0xa5,0xc6,0x63,0x63 }, { 0x84,0xf8,0x7c,0x7c },
+    { 0x99,0xee,0x77,0x77 }, { 0x8d,0xf6,0x7b,0x7b }, 
+    { 0x0d,0xff,0xf2,0xf2 }, { 0xbd,0xd6,0x6b,0x6b },
+    { 0xb1,0xde,0x6f,0x6f }, { 0x54,0x91,0xc5,0xc5 }, 
+    { 0x50,0x60,0x30,0x30 }, { 0x03,0x02,0x01,0x01 },
+    { 0xa9,0xce,0x67,0x67 }, { 0x7d,0x56,0x2b,0x2b }, 
+    { 0x19,0xe7,0xfe,0xfe }, { 0x62,0xb5,0xd7,0xd7 }, 
+    { 0xe6,0x4d,0xab,0xab }, { 0x9a,0xec,0x76,0x76 }, 
+    { 0x45,0x8f,0xca,0xca }, { 0x9d,0x1f,0x82,0x82 }, 
+    { 0x40,0x89,0xc9,0xc9 }, { 0x87,0xfa,0x7d,0x7d }, 
+    { 0x15,0xef,0xfa,0xfa }, { 0xeb,0xb2,0x59,0x59 }, 
+    { 0xc9,0x8e,0x47,0x47 }, { 0x0b,0xfb,0xf0,0xf0 }, 
+    { 0xec,0x41,0xad,0xad }, { 0x67,0xb3,0xd4,0xd4 }, 
+    { 0xfd,0x5f,0xa2,0xa2 }, { 0xea,0x45,0xaf,0xaf }, 
+    { 0xbf,0x23,0x9c,0x9c }, { 0xf7,0x53,0xa4,0xa4 }, 
+    { 0x96,0xe4,0x72,0x72 }, { 0x5b,0x9b,0xc0,0xc0 }, 
+    { 0xc2,0x75,0xb7,0xb7 }, { 0x1c,0xe1,0xfd,0xfd }, 
+    { 0xae,0x3d,0x93,0x93 }, { 0x6a,0x4c,0x26,0x26 }, 
+    { 0x5a,0x6c,0x36,0x36 }, { 0x41,0x7e,0x3f,0x3f },
+    { 0x02,0xf5,0xf7,0xf7 }, { 0x4f,0x83,0xcc,0xcc }, 
+    { 0x5c,0x68,0x34,0x34 }, { 0xf4,0x51,0xa5,0xa5 },
+    { 0x34,0xd1,0xe5,0xe5 }, { 0x08,0xf9,0xf1,0xf1 }, 
+    { 0x93,0xe2,0x71,0x71 }, { 0x73,0xab,0xd8,0xd8 },
+    { 0x53,0x62,0x31,0x31 }, { 0x3f,0x2a,0x15,0x15 }, 
+    { 0x0c,0x08,0x04,0x04 }, { 0x52,0x95,0xc7,0xc7 }, 
+    { 0x65,0x46,0x23,0x23 }, { 0x5e,0x9d,0xc3,0xc3 }, 
+    { 0x28,0x30,0x18,0x18 }, { 0xa1,0x37,0x96,0x96 }, 
+    { 0x0f,0x0a,0x05,0x05 }, { 0xb5,0x2f,0x9a,0x9a }, 
+    { 0x09,0x0e,0x07,0x07 }, { 0x36,0x24,0x12,0x12 },
+    { 0x9b,0x1b,0x80,0x80 }, { 0x3d,0xdf,0xe2,0xe2 }, 
+    { 0x26,0xcd,0xeb,0xeb }, { 0x69,0x4e,0x27,0x27 }, 
+    { 0xcd,0x7f,0xb2,0xb2 }, { 0x9f,0xea,0x75,0x75 }, 
+    { 0x1b,0x12,0x09,0x09 }, { 0x9e,0x1d,0x83,0x83 },
+    { 0x74,0x58,0x2c,0x2c }, { 0x2e,0x34,0x1a,0x1a }, 
+    { 0x2d,0x36,0x1b,0x1b }, { 0xb2,0xdc,0x6e,0x6e },
+    { 0xee,0xb4,0x5a,0x5a }, { 0xfb,0x5b,0xa0,0xa0 }, 
+    { 0xf6,0xa4,0x52,0x52 }, { 0x4d,0x76,0x3b,0x3b },
+    { 0x61,0xb7,0xd6,0xd6 }, { 0xce,0x7d,0xb3,0xb3 }, 
+    { 0x7b,0x52,0x29,0x29 }, { 0x3e,0xdd,0xe3,0xe3 }, 
+    { 0x71,0x5e,0x2f,0x2f }, { 0x97,0x13,0x84,0x84 }, 
+    { 0xf5,0xa6,0x53,0x53 }, { 0x68,0xb9,0xd1,0xd1 }, 
+    { 0x00,0x00,0x00,0x00 }, { 0x2c,0xc1,0xed,0xed }, 
+    { 0x60,0x40,0x20,0x20 }, { 0x1f,0xe3,0xfc,0xfc }, 
+    { 0xc8,0x79,0xb1,0xb1 }, { 0xed,0xb6,0x5b,0x5b }, 
+    { 0xbe,0xd4,0x6a,0x6a }, { 0x46,0x8d,0xcb,0xcb }, 
+    { 0xd9,0x67,0xbe,0xbe }, { 0x4b,0x72,0x39,0x39 }, 
+    { 0xde,0x94,0x4a,0x4a }, { 0xd4,0x98,0x4c,0x4c }, 
+    { 0xe8,0xb0,0x58,0x58 }, { 0x4a,0x85,0xcf,0xcf }, 
+    { 0x6b,0xbb,0xd0,0xd0 }, { 0x2a,0xc5,0xef,0xef },
+    { 0xe5,0x4f,0xaa,0xaa }, { 0x16,0xed,0xfb,0xfb }, 
+    { 0xc5,0x86,0x43,0x43 }, { 0xd7,0x9a,0x4d,0x4d }, 
+    { 0x55,0x66,0x33,0x33 }, { 0x94,0x11,0x85,0x85 }, 
+    { 0xcf,0x8a,0x45,0x45 }, { 0x10,0xe9,0xf9,0xf9 }, 
+    { 0x06,0x04,0x02,0x02 }, { 0x81,0xfe,0x7f,0x7f }, 
+    { 0xf0,0xa0,0x50,0x50 }, { 0x44,0x78,0x3c,0x3c },
+    { 0xba,0x25,0x9f,0x9f }, { 0xe3,0x4b,0xa8,0xa8 }, 
+    { 0xf3,0xa2,0x51,0x51 }, { 0xfe,0x5d,0xa3,0xa3 },
+    { 0xc0,0x80,0x40,0x40 }, { 0x8a,0x05,0x8f,0x8f }, 
+    { 0xad,0x3f,0x92,0x92 }, { 0xbc,0x21,0x9d,0x9d },
+    { 0x48,0x70,0x38,0x38 }, { 0x04,0xf1,0xf5,0xf5 }, 
+    { 0xdf,0x63,0xbc,0xbc }, { 0xc1,0x77,0xb6,0xb6 },
+    { 0x75,0xaf,0xda,0xda }, { 0x63,0x42,0x21,0x21 }, 
+    { 0x30,0x20,0x10,0x10 }, { 0x1a,0xe5,0xff,0xff },
+    { 0x0e,0xfd,0xf3,0xf3 }, { 0x6d,0xbf,0xd2,0xd2 }, 
+    { 0x4c,0x81,0xcd,0xcd }, { 0x14,0x18,0x0c,0x0c },
+    { 0x35,0x26,0x13,0x13 }, { 0x2f,0xc3,0xec,0xec }, 
+    { 0xe1,0xbe,0x5f,0x5f }, { 0xa2,0x35,0x97,0x97 },
+    { 0xcc,0x88,0x44,0x44 }, { 0x39,0x2e,0x17,0x17 }, 
+    { 0x57,0x93,0xc4,0xc4 }, { 0xf2,0x55,0xa7,0xa7 },
+    { 0x82,0xfc,0x7e,0x7e }, { 0x47,0x7a,0x3d,0x3d }, 
+    { 0xac,0xc8,0x64,0x64 }, { 0xe7,0xba,0x5d,0x5d },
+    { 0x2b,0x32,0x19,0x19 }, { 0x95,0xe6,0x73,0x73 }, 
+    { 0xa0,0xc0,0x60,0x60 }, { 0x98,0x19,0x81,0x81 }, 
+    { 0xd1,0x9e,0x4f,0x4f }, { 0x7f,0xa3,0xdc,0xdc }, 
+    { 0x66,0x44,0x22,0x22 }, { 0x7e,0x54,0x2a,0x2a }, 
+    { 0xab,0x3b,0x90,0x90 }, { 0x83,0x0b,0x88,0x88 }, 
+    { 0xca,0x8c,0x46,0x46 }, { 0x29,0xc7,0xee,0xee },
+    { 0xd3,0x6b,0xb8,0xb8 }, { 0x3c,0x28,0x14,0x14 }, 
+    { 0x79,0xa7,0xde,0xde }, { 0xe2,0xbc,0x5e,0x5e },
+    { 0x1d,0x16,0x0b,0x0b }, { 0x76,0xad,0xdb,0xdb }, 
+    { 0x3b,0xdb,0xe0,0xe0 }, { 0x56,0x64,0x32,0x32 },
+    { 0x4e,0x74,0x3a,0x3a }, { 0x1e,0x14,0x0a,0x0a }, 
+    { 0xdb,0x92,0x49,0x49 }, { 0x0a,0x0c,0x06,0x06 },
+    { 0x6c,0x48,0x24,0x24 }, { 0xe4,0xb8,0x5c,0x5c }, 
+    { 0x5d,0x9f,0xc2,0xc2 }, { 0x6e,0xbd,0xd3,0xd3 }, 
+    { 0xef,0x43,0xac,0xac }, { 0xa6,0xc4,0x62,0x62 }, 
+    { 0xa8,0x39,0x91,0x91 }, { 0xa4,0x31,0x95,0x95 },
+    { 0x37,0xd3,0xe4,0xe4 }, { 0x8b,0xf2,0x79,0x79 }, 
+    { 0x32,0xd5,0xe7,0xe7 }, { 0x43,0x8b,0xc8,0xc8 },
+    { 0x59,0x6e,0x37,0x37 }, { 0xb7,0xda,0x6d,0x6d }, 
+    { 0x8c,0x01,0x8d,0x8d }, { 0x64,0xb1,0xd5,0xd5 },
+    { 0xd2,0x9c,0x4e,0x4e }, { 0xe0,0x49,0xa9,0xa9 }, 
+    { 0xb4,0xd8,0x6c,0x6c }, { 0xfa,0xac,0x56,0x56 },
+    { 0x07,0xf3,0xf4,0xf4 }, { 0x25,0xcf,0xea,0xea }, 
+    { 0xaf,0xca,0x65,0x65 }, { 0x8e,0xf4,0x7a,0x7a },
+    { 0xe9,0x47,0xae,0xae }, { 0x18,0x10,0x08,0x08 }, 
+    { 0xd5,0x6f,0xba,0xba }, { 0x88,0xf0,0x78,0x78 }, 
+    { 0x6f,0x4a,0x25,0x25 }, { 0x72,0x5c,0x2e,0x2e }, 
+    { 0x24,0x38,0x1c,0x1c }, { 0xf1,0x57,0xa6,0xa6 }, 
+    { 0xc7,0x73,0xb4,0xb4 }, { 0x51,0x97,0xc6,0xc6 }, 
+    { 0x23,0xcb,0xe8,0xe8 }, { 0x7c,0xa1,0xdd,0xdd },
+    { 0x9c,0xe8,0x74,0x74 }, { 0x21,0x3e,0x1f,0x1f }, 
+    { 0xdd,0x96,0x4b,0x4b }, { 0xdc,0x61,0xbd,0xbd },
+    { 0x86,0x0d,0x8b,0x8b }, { 0x85,0x0f,0x8a,0x8a }, 
+    { 0x90,0xe0,0x70,0x70 }, { 0x42,0x7c,0x3e,0x3e }, 
+    { 0xc4,0x71,0xb5,0xb5 }, { 0xaa,0xcc,0x66,0x66 }, 
+    { 0xd8,0x90,0x48,0x48 }, { 0x05,0x06,0x03,0x03 },
+    { 0x01,0xf7,0xf6,0xf6 }, { 0x12,0x1c,0x0e,0x0e }, 
+    { 0xa3,0xc2,0x61,0x61 }, { 0x5f,0x6a,0x35,0x35 },
+    { 0xf9,0xae,0x57,0x57 }, { 0xd0,0x69,0xb9,0xb9 }, 
+    { 0x91,0x17,0x86,0x86 }, { 0x58,0x99,0xc1,0xc1 }, 
+    { 0x27,0x3a,0x1d,0x1d }, { 0xb9,0x27,0x9e,0x9e }, 
+    { 0x38,0xd9,0xe1,0xe1 }, { 0x13,0xeb,0xf8,0xf8 },
+    { 0xb3,0x2b,0x98,0x98 }, { 0x33,0x22,0x11,0x11 }, 
+    { 0xbb,0xd2,0x69,0x69 }, { 0x70,0xa9,0xd9,0xd9 },
+    { 0x89,0x07,0x8e,0x8e }, { 0xa7,0x33,0x94,0x94 }, 
+    { 0xb6,0x2d,0x9b,0x9b }, { 0x22,0x3c,0x1e,0x1e },
+    { 0x92,0x15,0x87,0x87 }, { 0x20,0xc9,0xe9,0xe9 }, 
+    { 0x49,0x87,0xce,0xce }, { 0xff,0xaa,0x55,0x55 },
+    { 0x78,0x50,0x28,0x28 }, { 0x7a,0xa5,0xdf,0xdf }, 
+    { 0x8f,0x03,0x8c,0x8c }, { 0xf8,0x59,0xa1,0xa1 }, 
+    { 0x80,0x09,0x89,0x89 }, { 0x17,0x1a,0x0d,0x0d }, 
+    { 0xda,0x65,0xbf,0xbf }, { 0x31,0xd7,0xe6,0xe6 },
+    { 0xc6,0x84,0x42,0x42 }, { 0xb8,0xd0,0x68,0x68 }, 
+    { 0xc3,0x82,0x41,0x41 }, { 0xb0,0x29,0x99,0x99 }, 
+    { 0x77,0x5a,0x2d,0x2d }, { 0x11,0x1e,0x0f,0x0f }, 
+    { 0xcb,0x7b,0xb0,0xb0 }, { 0xfc,0xa8,0x54,0x54 }, 
+    { 0xd6,0x6d,0xbb,0xbb }, { 0x3a,0x2c,0x16,0x16 }
+  };
+
+static const unsigned char T3[256][4] = 
+  {
+    { 0x63,0xa5,0xc6,0x63 }, { 0x7c,0x84,0xf8,0x7c },
+    { 0x77,0x99,0xee,0x77 }, { 0x7b,0x8d,0xf6,0x7b }, 
+    { 0xf2,0x0d,0xff,0xf2 }, { 0x6b,0xbd,0xd6,0x6b },
+    { 0x6f,0xb1,0xde,0x6f }, { 0xc5,0x54,0x91,0xc5 }, 
+    { 0x30,0x50,0x60,0x30 }, { 0x01,0x03,0x02,0x01 },
+    { 0x67,0xa9,0xce,0x67 }, { 0x2b,0x7d,0x56,0x2b }, 
+    { 0xfe,0x19,0xe7,0xfe }, { 0xd7,0x62,0xb5,0xd7 }, 
+    { 0xab,0xe6,0x4d,0xab }, { 0x76,0x9a,0xec,0x76 }, 
+    { 0xca,0x45,0x8f,0xca }, { 0x82,0x9d,0x1f,0x82 },
+    { 0xc9,0x40,0x89,0xc9 }, { 0x7d,0x87,0xfa,0x7d }, 
+    { 0xfa,0x15,0xef,0xfa }, { 0x59,0xeb,0xb2,0x59 }, 
+    { 0x47,0xc9,0x8e,0x47 }, { 0xf0,0x0b,0xfb,0xf0 }, 
+    { 0xad,0xec,0x41,0xad }, { 0xd4,0x67,0xb3,0xd4 }, 
+    { 0xa2,0xfd,0x5f,0xa2 }, { 0xaf,0xea,0x45,0xaf }, 
+    { 0x9c,0xbf,0x23,0x9c }, { 0xa4,0xf7,0x53,0xa4 },
+    { 0x72,0x96,0xe4,0x72 }, { 0xc0,0x5b,0x9b,0xc0 }, 
+    { 0xb7,0xc2,0x75,0xb7 }, { 0xfd,0x1c,0xe1,0xfd }, 
+    { 0x93,0xae,0x3d,0x93 }, { 0x26,0x6a,0x4c,0x26 }, 
+    { 0x36,0x5a,0x6c,0x36 }, { 0x3f,0x41,0x7e,0x3f },
+    { 0xf7,0x02,0xf5,0xf7 }, { 0xcc,0x4f,0x83,0xcc }, 
+    { 0x34,0x5c,0x68,0x34 }, { 0xa5,0xf4,0x51,0xa5 },
+    { 0xe5,0x34,0xd1,0xe5 }, { 0xf1,0x08,0xf9,0xf1 }, 
+    { 0x71,0x93,0xe2,0x71 }, { 0xd8,0x73,0xab,0xd8 },
+    { 0x31,0x53,0x62,0x31 }, { 0x15,0x3f,0x2a,0x15 }, 
+    { 0x04,0x0c,0x08,0x04 }, { 0xc7,0x52,0x95,0xc7 }, 
+    { 0x23,0x65,0x46,0x23 }, { 0xc3,0x5e,0x9d,0xc3 }, 
+    { 0x18,0x28,0x30,0x18 }, { 0x96,0xa1,0x37,0x96 },
+    { 0x05,0x0f,0x0a,0x05 }, { 0x9a,0xb5,0x2f,0x9a }, 
+    { 0x07,0x09,0x0e,0x07 }, { 0x12,0x36,0x24,0x12 }, 
+    { 0x80,0x9b,0x1b,0x80 }, { 0xe2,0x3d,0xdf,0xe2 }, 
+    { 0xeb,0x26,0xcd,0xeb }, { 0x27,0x69,0x4e,0x27 },
+    { 0xb2,0xcd,0x7f,0xb2 }, { 0x75,0x9f,0xea,0x75 }, 
+    { 0x09,0x1b,0x12,0x09 }, { 0x83,0x9e,0x1d,0x83 },
+    { 0x2c,0x74,0x58,0x2c }, { 0x1a,0x2e,0x34,0x1a }, 
+    { 0x1b,0x2d,0x36,0x1b }, { 0x6e,0xb2,0xdc,0x6e },
+    { 0x5a,0xee,0xb4,0x5a }, { 0xa0,0xfb,0x5b,0xa0 }, 
+    { 0x52,0xf6,0xa4,0x52 }, { 0x3b,0x4d,0x76,0x3b },
+    { 0xd6,0x61,0xb7,0xd6 }, { 0xb3,0xce,0x7d,0xb3 }, 
+    { 0x29,0x7b,0x52,0x29 }, { 0xe3,0x3e,0xdd,0xe3 }, 
+    { 0x2f,0x71,0x5e,0x2f }, { 0x84,0x97,0x13,0x84 }, 
+    { 0x53,0xf5,0xa6,0x53 }, { 0xd1,0x68,0xb9,0xd1 },
+    { 0x00,0x00,0x00,0x00 }, { 0xed,0x2c,0xc1,0xed }, 
+    { 0x20,0x60,0x40,0x20 }, { 0xfc,0x1f,0xe3,0xfc },
+    { 0xb1,0xc8,0x79,0xb1 }, { 0x5b,0xed,0xb6,0x5b }, 
+    { 0x6a,0xbe,0xd4,0x6a }, { 0xcb,0x46,0x8d,0xcb },
+    { 0xbe,0xd9,0x67,0xbe }, { 0x39,0x4b,0x72,0x39 }, 
+    { 0x4a,0xde,0x94,0x4a }, { 0x4c,0xd4,0x98,0x4c },
+    { 0x58,0xe8,0xb0,0x58 }, { 0xcf,0x4a,0x85,0xcf }, 
+    { 0xd0,0x6b,0xbb,0xd0 }, { 0xef,0x2a,0xc5,0xef },
+    { 0xaa,0xe5,0x4f,0xaa }, { 0xfb,0x16,0xed,0xfb }, 
+    { 0x43,0xc5,0x86,0x43 }, { 0x4d,0xd7,0x9a,0x4d },
+    { 0x33,0x55,0x66,0x33 }, { 0x85,0x94,0x11,0x85 }, 
+    { 0x45,0xcf,0x8a,0x45 }, { 0xf9,0x10,0xe9,0xf9 },
+    { 0x02,0x06,0x04,0x02 }, { 0x7f,0x81,0xfe,0x7f }, 
+    { 0x50,0xf0,0xa0,0x50 }, { 0x3c,0x44,0x78,0x3c },
+    { 0x9f,0xba,0x25,0x9f }, { 0xa8,0xe3,0x4b,0xa8 }, 
+    { 0x51,0xf3,0xa2,0x51 }, { 0xa3,0xfe,0x5d,0xa3 },
+    { 0x40,0xc0,0x80,0x40 }, { 0x8f,0x8a,0x05,0x8f }, 
+    { 0x92,0xad,0x3f,0x92 }, { 0x9d,0xbc,0x21,0x9d },
+    { 0x38,0x48,0x70,0x38 }, { 0xf5,0x04,0xf1,0xf5 }, 
+    { 0xbc,0xdf,0x63,0xbc }, { 0xb6,0xc1,0x77,0xb6 },
+    { 0xda,0x75,0xaf,0xda }, { 0x21,0x63,0x42,0x21 }, 
+    { 0x10,0x30,0x20,0x10 }, { 0xff,0x1a,0xe5,0xff },
+    { 0xf3,0x0e,0xfd,0xf3 }, { 0xd2,0x6d,0xbf,0xd2 }, 
+    { 0xcd,0x4c,0x81,0xcd }, { 0x0c,0x14,0x18,0x0c }, 
+    { 0x13,0x35,0x26,0x13 }, { 0xec,0x2f,0xc3,0xec }, 
+    { 0x5f,0xe1,0xbe,0x5f }, { 0x97,0xa2,0x35,0x97 },
+    { 0x44,0xcc,0x88,0x44 }, { 0x17,0x39,0x2e,0x17 }, 
+    { 0xc4,0x57,0x93,0xc4 }, { 0xa7,0xf2,0x55,0xa7 },
+    { 0x7e,0x82,0xfc,0x7e }, { 0x3d,0x47,0x7a,0x3d }, 
+    { 0x64,0xac,0xc8,0x64 }, { 0x5d,0xe7,0xba,0x5d },
+    { 0x19,0x2b,0x32,0x19 }, { 0x73,0x95,0xe6,0x73 }, 
+    { 0x60,0xa0,0xc0,0x60 }, { 0x81,0x98,0x19,0x81 },
+    { 0x4f,0xd1,0x9e,0x4f }, { 0xdc,0x7f,0xa3,0xdc }, 
+    { 0x22,0x66,0x44,0x22 }, { 0x2a,0x7e,0x54,0x2a },
+    { 0x90,0xab,0x3b,0x90 }, { 0x88,0x83,0x0b,0x88 }, 
+    { 0x46,0xca,0x8c,0x46 }, { 0xee,0x29,0xc7,0xee },
+    { 0xb8,0xd3,0x6b,0xb8 }, { 0x14,0x3c,0x28,0x14 }, 
+    { 0xde,0x79,0xa7,0xde }, { 0x5e,0xe2,0xbc,0x5e }, 
+    { 0x0b,0x1d,0x16,0x0b }, { 0xdb,0x76,0xad,0xdb }, 
+    { 0xe0,0x3b,0xdb,0xe0 }, { 0x32,0x56,0x64,0x32 },
+    { 0x3a,0x4e,0x74,0x3a }, { 0x0a,0x1e,0x14,0x0a }, 
+    { 0x49,0xdb,0x92,0x49 }, { 0x06,0x0a,0x0c,0x06 },
+    { 0x24,0x6c,0x48,0x24 }, { 0x5c,0xe4,0xb8,0x5c }, 
+    { 0xc2,0x5d,0x9f,0xc2 }, { 0xd3,0x6e,0xbd,0xd3 },
+    { 0xac,0xef,0x43,0xac }, { 0x62,0xa6,0xc4,0x62 }, 
+    { 0x91,0xa8,0x39,0x91 }, { 0x95,0xa4,0x31,0x95 },
+    { 0xe4,0x37,0xd3,0xe4 }, { 0x79,0x8b,0xf2,0x79 }, 
+    { 0xe7,0x32,0xd5,0xe7 }, { 0xc8,0x43,0x8b,0xc8 }, 
+    { 0x37,0x59,0x6e,0x37 }, { 0x6d,0xb7,0xda,0x6d }, 
+    { 0x8d,0x8c,0x01,0x8d }, { 0xd5,0x64,0xb1,0xd5 }, 
+    { 0x4e,0xd2,0x9c,0x4e }, { 0xa9,0xe0,0x49,0xa9 }, 
+    { 0x6c,0xb4,0xd8,0x6c }, { 0x56,0xfa,0xac,0x56 },
+    { 0xf4,0x07,0xf3,0xf4 }, { 0xea,0x25,0xcf,0xea }, 
+    { 0x65,0xaf,0xca,0x65 }, { 0x7a,0x8e,0xf4,0x7a }, 
+    { 0xae,0xe9,0x47,0xae }, { 0x08,0x18,0x10,0x08 }, 
+    { 0xba,0xd5,0x6f,0xba }, { 0x78,0x88,0xf0,0x78 }, 
+    { 0x25,0x6f,0x4a,0x25 }, { 0x2e,0x72,0x5c,0x2e }, 
+    { 0x1c,0x24,0x38,0x1c }, { 0xa6,0xf1,0x57,0xa6 }, 
+    { 0xb4,0xc7,0x73,0xb4 }, { 0xc6,0x51,0x97,0xc6 }, 
+    { 0xe8,0x23,0xcb,0xe8 }, { 0xdd,0x7c,0xa1,0xdd },
+    { 0x74,0x9c,0xe8,0x74 }, { 0x1f,0x21,0x3e,0x1f }, 
+    { 0x4b,0xdd,0x96,0x4b }, { 0xbd,0xdc,0x61,0xbd },
+    { 0x8b,0x86,0x0d,0x8b }, { 0x8a,0x85,0x0f,0x8a }, 
+    { 0x70,0x90,0xe0,0x70 }, { 0x3e,0x42,0x7c,0x3e },
+    { 0xb5,0xc4,0x71,0xb5 }, { 0x66,0xaa,0xcc,0x66 }, 
+    { 0x48,0xd8,0x90,0x48 }, { 0x03,0x05,0x06,0x03 },
+    { 0xf6,0x01,0xf7,0xf6 }, { 0x0e,0x12,0x1c,0x0e }, 
+    { 0x61,0xa3,0xc2,0x61 }, { 0x35,0x5f,0x6a,0x35 },
+    { 0x57,0xf9,0xae,0x57 }, { 0xb9,0xd0,0x69,0xb9 }, 
+    { 0x86,0x91,0x17,0x86 }, { 0xc1,0x58,0x99,0xc1 }, 
+    { 0x1d,0x27,0x3a,0x1d }, { 0x9e,0xb9,0x27,0x9e }, 
+    { 0xe1,0x38,0xd9,0xe1 }, { 0xf8,0x13,0xeb,0xf8 },
+    { 0x98,0xb3,0x2b,0x98 }, { 0x11,0x33,0x22,0x11 }, 
+    { 0x69,0xbb,0xd2,0x69 }, { 0xd9,0x70,0xa9,0xd9 },
+    { 0x8e,0x89,0x07,0x8e }, { 0x94,0xa7,0x33,0x94 }, 
+    { 0x9b,0xb6,0x2d,0x9b }, { 0x1e,0x22,0x3c,0x1e },
+    { 0x87,0x92,0x15,0x87 }, { 0xe9,0x20,0xc9,0xe9 }, 
+    { 0xce,0x49,0x87,0xce }, { 0x55,0xff,0xaa,0x55 },
+    { 0x28,0x78,0x50,0x28 }, { 0xdf,0x7a,0xa5,0xdf }, 
+    { 0x8c,0x8f,0x03,0x8c }, { 0xa1,0xf8,0x59,0xa1 },
+    { 0x89,0x80,0x09,0x89 }, { 0x0d,0x17,0x1a,0x0d }, 
+    { 0xbf,0xda,0x65,0xbf }, { 0xe6,0x31,0xd7,0xe6 },
+    { 0x42,0xc6,0x84,0x42 }, { 0x68,0xb8,0xd0,0x68 }, 
+    { 0x41,0xc3,0x82,0x41 }, { 0x99,0xb0,0x29,0x99 },
+    { 0x2d,0x77,0x5a,0x2d }, { 0x0f,0x11,0x1e,0x0f }, 
+    { 0xb0,0xcb,0x7b,0xb0 }, { 0x54,0xfc,0xa8,0x54 },
+    { 0xbb,0xd6,0x6d,0xbb }, { 0x16,0x3a,0x2c,0x16 }
+  };
+
+static const unsigned char T4[256][4] = 
+  {
+    { 0x63,0x63,0xa5,0xc6 }, { 0x7c,0x7c,0x84,0xf8 },
+    { 0x77,0x77,0x99,0xee }, { 0x7b,0x7b,0x8d,0xf6 }, 
+    { 0xf2,0xf2,0x0d,0xff }, { 0x6b,0x6b,0xbd,0xd6 }, 
+    { 0x6f,0x6f,0xb1,0xde }, { 0xc5,0xc5,0x54,0x91 }, 
+    { 0x30,0x30,0x50,0x60 }, { 0x01,0x01,0x03,0x02 },
+    { 0x67,0x67,0xa9,0xce }, { 0x2b,0x2b,0x7d,0x56 }, 
+    { 0xfe,0xfe,0x19,0xe7 }, { 0xd7,0xd7,0x62,0xb5 },
+    { 0xab,0xab,0xe6,0x4d }, { 0x76,0x76,0x9a,0xec }, 
+    { 0xca,0xca,0x45,0x8f }, { 0x82,0x82,0x9d,0x1f },
+    { 0xc9,0xc9,0x40,0x89 }, { 0x7d,0x7d,0x87,0xfa }, 
+    { 0xfa,0xfa,0x15,0xef }, { 0x59,0x59,0xeb,0xb2 },
+    { 0x47,0x47,0xc9,0x8e }, { 0xf0,0xf0,0x0b,0xfb }, 
+    { 0xad,0xad,0xec,0x41 }, { 0xd4,0xd4,0x67,0xb3 },
+    { 0xa2,0xa2,0xfd,0x5f }, { 0xaf,0xaf,0xea,0x45 }, 
+    { 0x9c,0x9c,0xbf,0x23 }, { 0xa4,0xa4,0xf7,0x53 },
+    { 0x72,0x72,0x96,0xe4 }, { 0xc0,0xc0,0x5b,0x9b }, 
+    { 0xb7,0xb7,0xc2,0x75 }, { 0xfd,0xfd,0x1c,0xe1 },
+    { 0x93,0x93,0xae,0x3d }, { 0x26,0x26,0x6a,0x4c }, 
+    { 0x36,0x36,0x5a,0x6c }, { 0x3f,0x3f,0x41,0x7e },
+    { 0xf7,0xf7,0x02,0xf5 }, { 0xcc,0xcc,0x4f,0x83 }, 
+    { 0x34,0x34,0x5c,0x68 }, { 0xa5,0xa5,0xf4,0x51 },
+    { 0xe5,0xe5,0x34,0xd1 }, { 0xf1,0xf1,0x08,0xf9 }, 
+    { 0x71,0x71,0x93,0xe2 }, { 0xd8,0xd8,0x73,0xab },
+    { 0x31,0x31,0x53,0x62 }, { 0x15,0x15,0x3f,0x2a }, 
+    { 0x04,0x04,0x0c,0x08 }, { 0xc7,0xc7,0x52,0x95 },
+    { 0x23,0x23,0x65,0x46 }, { 0xc3,0xc3,0x5e,0x9d }, 
+    { 0x18,0x18,0x28,0x30 }, { 0x96,0x96,0xa1,0x37 },
+    { 0x05,0x05,0x0f,0x0a }, { 0x9a,0x9a,0xb5,0x2f }, 
+    { 0x07,0x07,0x09,0x0e }, { 0x12,0x12,0x36,0x24 },
+    { 0x80,0x80,0x9b,0x1b }, { 0xe2,0xe2,0x3d,0xdf }, 
+    { 0xeb,0xeb,0x26,0xcd }, { 0x27,0x27,0x69,0x4e },
+    { 0xb2,0xb2,0xcd,0x7f }, { 0x75,0x75,0x9f,0xea }, 
+    { 0x09,0x09,0x1b,0x12 }, { 0x83,0x83,0x9e,0x1d },
+    { 0x2c,0x2c,0x74,0x58 }, { 0x1a,0x1a,0x2e,0x34 }, 
+    { 0x1b,0x1b,0x2d,0x36 }, { 0x6e,0x6e,0xb2,0xdc },
+    { 0x5a,0x5a,0xee,0xb4 }, { 0xa0,0xa0,0xfb,0x5b }, 
+    { 0x52,0x52,0xf6,0xa4 }, { 0x3b,0x3b,0x4d,0x76 },
+    { 0xd6,0xd6,0x61,0xb7 }, { 0xb3,0xb3,0xce,0x7d }, 
+    { 0x29,0x29,0x7b,0x52 }, { 0xe3,0xe3,0x3e,0xdd },
+    { 0x2f,0x2f,0x71,0x5e }, { 0x84,0x84,0x97,0x13 }, 
+    { 0x53,0x53,0xf5,0xa6 }, { 0xd1,0xd1,0x68,0xb9 },
+    { 0x00,0x00,0x00,0x00 }, { 0xed,0xed,0x2c,0xc1 }, 
+    { 0x20,0x20,0x60,0x40 }, { 0xfc,0xfc,0x1f,0xe3 },
+    { 0xb1,0xb1,0xc8,0x79 }, { 0x5b,0x5b,0xed,0xb6 }, 
+    { 0x6a,0x6a,0xbe,0xd4 }, { 0xcb,0xcb,0x46,0x8d },
+    { 0xbe,0xbe,0xd9,0x67 }, { 0x39,0x39,0x4b,0x72 }, 
+    { 0x4a,0x4a,0xde,0x94 }, { 0x4c,0x4c,0xd4,0x98 },
+    { 0x58,0x58,0xe8,0xb0 }, { 0xcf,0xcf,0x4a,0x85 }, 
+    { 0xd0,0xd0,0x6b,0xbb }, { 0xef,0xef,0x2a,0xc5 },
+    { 0xaa,0xaa,0xe5,0x4f }, { 0xfb,0xfb,0x16,0xed }, 
+    { 0x43,0x43,0xc5,0x86 }, { 0x4d,0x4d,0xd7,0x9a },
+    { 0x33,0x33,0x55,0x66 }, { 0x85,0x85,0x94,0x11 }, 
+    { 0x45,0x45,0xcf,0x8a }, { 0xf9,0xf9,0x10,0xe9 },
+    { 0x02,0x02,0x06,0x04 }, { 0x7f,0x7f,0x81,0xfe }, 
+    { 0x50,0x50,0xf0,0xa0 }, { 0x3c,0x3c,0x44,0x78 },
+    { 0x9f,0x9f,0xba,0x25 }, { 0xa8,0xa8,0xe3,0x4b }, 
+    { 0x51,0x51,0xf3,0xa2 }, { 0xa3,0xa3,0xfe,0x5d },
+    { 0x40,0x40,0xc0,0x80 }, { 0x8f,0x8f,0x8a,0x05 }, 
+    { 0x92,0x92,0xad,0x3f }, { 0x9d,0x9d,0xbc,0x21 },
+    { 0x38,0x38,0x48,0x70 }, { 0xf5,0xf5,0x04,0xf1 }, 
+    { 0xbc,0xbc,0xdf,0x63 }, { 0xb6,0xb6,0xc1,0x77 },
+    { 0xda,0xda,0x75,0xaf }, { 0x21,0x21,0x63,0x42 }, 
+    { 0x10,0x10,0x30,0x20 }, { 0xff,0xff,0x1a,0xe5 },
+    { 0xf3,0xf3,0x0e,0xfd }, { 0xd2,0xd2,0x6d,0xbf }, 
+    { 0xcd,0xcd,0x4c,0x81 }, { 0x0c,0x0c,0x14,0x18 },
+    { 0x13,0x13,0x35,0x26 }, { 0xec,0xec,0x2f,0xc3 }, 
+    { 0x5f,0x5f,0xe1,0xbe }, { 0x97,0x97,0xa2,0x35 },
+    { 0x44,0x44,0xcc,0x88 }, { 0x17,0x17,0x39,0x2e }, 
+    { 0xc4,0xc4,0x57,0x93 }, { 0xa7,0xa7,0xf2,0x55 },
+    { 0x7e,0x7e,0x82,0xfc }, { 0x3d,0x3d,0x47,0x7a }, 
+    { 0x64,0x64,0xac,0xc8 }, { 0x5d,0x5d,0xe7,0xba },
+    { 0x19,0x19,0x2b,0x32 }, { 0x73,0x73,0x95,0xe6 }, 
+    { 0x60,0x60,0xa0,0xc0 }, { 0x81,0x81,0x98,0x19 },
+    { 0x4f,0x4f,0xd1,0x9e }, { 0xdc,0xdc,0x7f,0xa3 }, 
+    { 0x22,0x22,0x66,0x44 }, { 0x2a,0x2a,0x7e,0x54 },
+    { 0x90,0x90,0xab,0x3b }, { 0x88,0x88,0x83,0x0b }, 
+    { 0x46,0x46,0xca,0x8c }, { 0xee,0xee,0x29,0xc7 },
+    { 0xb8,0xb8,0xd3,0x6b }, { 0x14,0x14,0x3c,0x28 }, 
+    { 0xde,0xde,0x79,0xa7 }, { 0x5e,0x5e,0xe2,0xbc },
+    { 0x0b,0x0b,0x1d,0x16 }, { 0xdb,0xdb,0x76,0xad }, 
+    { 0xe0,0xe0,0x3b,0xdb }, { 0x32,0x32,0x56,0x64 },
+    { 0x3a,0x3a,0x4e,0x74 }, { 0x0a,0x0a,0x1e,0x14 }, 
+    { 0x49,0x49,0xdb,0x92 }, { 0x06,0x06,0x0a,0x0c },
+    { 0x24,0x24,0x6c,0x48 }, { 0x5c,0x5c,0xe4,0xb8 }, 
+    { 0xc2,0xc2,0x5d,0x9f }, { 0xd3,0xd3,0x6e,0xbd },
+    { 0xac,0xac,0xef,0x43 }, { 0x62,0x62,0xa6,0xc4 }, 
+    { 0x91,0x91,0xa8,0x39 }, { 0x95,0x95,0xa4,0x31 },
+    { 0xe4,0xe4,0x37,0xd3 }, { 0x79,0x79,0x8b,0xf2 }, 
+    { 0xe7,0xe7,0x32,0xd5 }, { 0xc8,0xc8,0x43,0x8b },
+    { 0x37,0x37,0x59,0x6e }, { 0x6d,0x6d,0xb7,0xda }, 
+    { 0x8d,0x8d,0x8c,0x01 }, { 0xd5,0xd5,0x64,0xb1 }, 
+    { 0x4e,0x4e,0xd2,0x9c }, { 0xa9,0xa9,0xe0,0x49 }, 
+    { 0x6c,0x6c,0xb4,0xd8 }, { 0x56,0x56,0xfa,0xac }, 
+    { 0xf4,0xf4,0x07,0xf3 }, { 0xea,0xea,0x25,0xcf }, 
+    { 0x65,0x65,0xaf,0xca }, { 0x7a,0x7a,0x8e,0xf4 }, 
+    { 0xae,0xae,0xe9,0x47 }, { 0x08,0x08,0x18,0x10 }, 
+    { 0xba,0xba,0xd5,0x6f }, { 0x78,0x78,0x88,0xf0 }, 
+    { 0x25,0x25,0x6f,0x4a }, { 0x2e,0x2e,0x72,0x5c }, 
+    { 0x1c,0x1c,0x24,0x38 }, { 0xa6,0xa6,0xf1,0x57 },
+    { 0xb4,0xb4,0xc7,0x73 }, { 0xc6,0xc6,0x51,0x97 }, 
+    { 0xe8,0xe8,0x23,0xcb }, { 0xdd,0xdd,0x7c,0xa1 },
+    { 0x74,0x74,0x9c,0xe8 }, { 0x1f,0x1f,0x21,0x3e }, 
+    { 0x4b,0x4b,0xdd,0x96 }, { 0xbd,0xbd,0xdc,0x61 },
+    { 0x8b,0x8b,0x86,0x0d }, { 0x8a,0x8a,0x85,0x0f }, 
+    { 0x70,0x70,0x90,0xe0 }, { 0x3e,0x3e,0x42,0x7c },
+    { 0xb5,0xb5,0xc4,0x71 }, { 0x66,0x66,0xaa,0xcc }, 
+    { 0x48,0x48,0xd8,0x90 }, { 0x03,0x03,0x05,0x06 },
+    { 0xf6,0xf6,0x01,0xf7 }, { 0x0e,0x0e,0x12,0x1c }, 
+    { 0x61,0x61,0xa3,0xc2 }, { 0x35,0x35,0x5f,0x6a },
+    { 0x57,0x57,0xf9,0xae }, { 0xb9,0xb9,0xd0,0x69 }, 
+    { 0x86,0x86,0x91,0x17 }, { 0xc1,0xc1,0x58,0x99 },
+    { 0x1d,0x1d,0x27,0x3a }, { 0x9e,0x9e,0xb9,0x27 }, 
+    { 0xe1,0xe1,0x38,0xd9 }, { 0xf8,0xf8,0x13,0xeb },
+    { 0x98,0x98,0xb3,0x2b }, { 0x11,0x11,0x33,0x22 }, 
+    { 0x69,0x69,0xbb,0xd2 }, { 0xd9,0xd9,0x70,0xa9 },
+    { 0x8e,0x8e,0x89,0x07 }, { 0x94,0x94,0xa7,0x33 }, 
+    { 0x9b,0x9b,0xb6,0x2d }, { 0x1e,0x1e,0x22,0x3c },
+    { 0x87,0x87,0x92,0x15 }, { 0xe9,0xe9,0x20,0xc9 }, 
+    { 0xce,0xce,0x49,0x87 }, { 0x55,0x55,0xff,0xaa },
+    { 0x28,0x28,0x78,0x50 }, { 0xdf,0xdf,0x7a,0xa5 }, 
+    { 0x8c,0x8c,0x8f,0x03 }, { 0xa1,0xa1,0xf8,0x59 },
+    { 0x89,0x89,0x80,0x09 }, { 0x0d,0x0d,0x17,0x1a }, 
+    { 0xbf,0xbf,0xda,0x65 }, { 0xe6,0xe6,0x31,0xd7 }, 
+    { 0x42,0x42,0xc6,0x84 }, { 0x68,0x68,0xb8,0xd0 }, 
+    { 0x41,0x41,0xc3,0x82 }, { 0x99,0x99,0xb0,0x29 },
+    { 0x2d,0x2d,0x77,0x5a }, { 0x0f,0x0f,0x11,0x1e }, 
+    { 0xb0,0xb0,0xcb,0x7b }, { 0x54,0x54,0xfc,0xa8 },
+    { 0xbb,0xbb,0xd6,0x6d }, { 0x16,0x16,0x3a,0x2c }
+  };
+
+static const unsigned char T5[256][4] = 
+  {
+    { 0x51,0xf4,0xa7,0x50 }, { 0x7e,0x41,0x65,0x53 }, 
+    { 0x1a,0x17,0xa4,0xc3 }, { 0x3a,0x27,0x5e,0x96 }, 
+    { 0x3b,0xab,0x6b,0xcb }, { 0x1f,0x9d,0x45,0xf1 },
+    { 0xac,0xfa,0x58,0xab }, { 0x4b,0xe3,0x03,0x93 }, 
+    { 0x20,0x30,0xfa,0x55 }, { 0xad,0x76,0x6d,0xf6 },
+    { 0x88,0xcc,0x76,0x91 }, { 0xf5,0x02,0x4c,0x25 }, 
+    { 0x4f,0xe5,0xd7,0xfc }, { 0xc5,0x2a,0xcb,0xd7 },
+    { 0x26,0x35,0x44,0x80 }, { 0xb5,0x62,0xa3,0x8f }, 
+    { 0xde,0xb1,0x5a,0x49 }, { 0x25,0xba,0x1b,0x67 },
+    { 0x45,0xea,0x0e,0x98 }, { 0x5d,0xfe,0xc0,0xe1 }, 
+    { 0xc3,0x2f,0x75,0x02 }, { 0x81,0x4c,0xf0,0x12 },
+    { 0x8d,0x46,0x97,0xa3 }, { 0x6b,0xd3,0xf9,0xc6 }, 
+    { 0x03,0x8f,0x5f,0xe7 }, { 0x15,0x92,0x9c,0x95 },
+    { 0xbf,0x6d,0x7a,0xeb }, { 0x95,0x52,0x59,0xda }, 
+    { 0xd4,0xbe,0x83,0x2d }, { 0x58,0x74,0x21,0xd3 },
+    { 0x49,0xe0,0x69,0x29 }, { 0x8e,0xc9,0xc8,0x44 }, 
+    { 0x75,0xc2,0x89,0x6a }, { 0xf4,0x8e,0x79,0x78 },
+    { 0x99,0x58,0x3e,0x6b }, { 0x27,0xb9,0x71,0xdd }, 
+    { 0xbe,0xe1,0x4f,0xb6 }, { 0xf0,0x88,0xad,0x17 },
+    { 0xc9,0x20,0xac,0x66 }, { 0x7d,0xce,0x3a,0xb4 }, 
+    { 0x63,0xdf,0x4a,0x18 }, { 0xe5,0x1a,0x31,0x82 },
+    { 0x97,0x51,0x33,0x60 }, { 0x62,0x53,0x7f,0x45 }, 
+    { 0xb1,0x64,0x77,0xe0 }, { 0xbb,0x6b,0xae,0x84 }, 
+    { 0xfe,0x81,0xa0,0x1c }, { 0xf9,0x08,0x2b,0x94 }, 
+    { 0x70,0x48,0x68,0x58 }, { 0x8f,0x45,0xfd,0x19 }, 
+    { 0x94,0xde,0x6c,0x87 }, { 0x52,0x7b,0xf8,0xb7 }, 
+    { 0xab,0x73,0xd3,0x23 }, { 0x72,0x4b,0x02,0xe2 },
+    { 0xe3,0x1f,0x8f,0x57 }, { 0x66,0x55,0xab,0x2a }, 
+    { 0xb2,0xeb,0x28,0x07 }, { 0x2f,0xb5,0xc2,0x03 },
+    { 0x86,0xc5,0x7b,0x9a }, { 0xd3,0x37,0x08,0xa5 }, 
+    { 0x30,0x28,0x87,0xf2 }, { 0x23,0xbf,0xa5,0xb2 },
+    { 0x02,0x03,0x6a,0xba }, { 0xed,0x16,0x82,0x5c }, 
+    { 0x8a,0xcf,0x1c,0x2b }, { 0xa7,0x79,0xb4,0x92 },
+    { 0xf3,0x07,0xf2,0xf0 }, { 0x4e,0x69,0xe2,0xa1 }, 
+    { 0x65,0xda,0xf4,0xcd }, { 0x06,0x05,0xbe,0xd5 },
+    { 0xd1,0x34,0x62,0x1f }, { 0xc4,0xa6,0xfe,0x8a }, 
+    { 0x34,0x2e,0x53,0x9d }, { 0xa2,0xf3,0x55,0xa0 },
+    { 0x05,0x8a,0xe1,0x32 }, { 0xa4,0xf6,0xeb,0x75 }, 
+    { 0x0b,0x83,0xec,0x39 }, { 0x40,0x60,0xef,0xaa },
+    { 0x5e,0x71,0x9f,0x06 }, { 0xbd,0x6e,0x10,0x51 }, 
+    { 0x3e,0x21,0x8a,0xf9 }, { 0x96,0xdd,0x06,0x3d }, 
+    { 0xdd,0x3e,0x05,0xae }, { 0x4d,0xe6,0xbd,0x46 }, 
+    { 0x91,0x54,0x8d,0xb5 }, { 0x71,0xc4,0x5d,0x05 }, 
+    { 0x04,0x06,0xd4,0x6f }, { 0x60,0x50,0x15,0xff }, 
+    { 0x19,0x98,0xfb,0x24 }, { 0xd6,0xbd,0xe9,0x97 },
+    { 0x89,0x40,0x43,0xcc }, { 0x67,0xd9,0x9e,0x77 }, 
+    { 0xb0,0xe8,0x42,0xbd }, { 0x07,0x89,0x8b,0x88 },
+    { 0xe7,0x19,0x5b,0x38 }, { 0x79,0xc8,0xee,0xdb }, 
+    { 0xa1,0x7c,0x0a,0x47 }, { 0x7c,0x42,0x0f,0xe9 },
+    { 0xf8,0x84,0x1e,0xc9 }, { 0x00,0x00,0x00,0x00 }, 
+    { 0x09,0x80,0x86,0x83 }, { 0x32,0x2b,0xed,0x48 },
+    { 0x1e,0x11,0x70,0xac }, { 0x6c,0x5a,0x72,0x4e }, 
+    { 0xfd,0x0e,0xff,0xfb }, { 0x0f,0x85,0x38,0x56 },
+    { 0x3d,0xae,0xd5,0x1e }, { 0x36,0x2d,0x39,0x27 }, 
+    { 0x0a,0x0f,0xd9,0x64 }, { 0x68,0x5c,0xa6,0x21 },
+    { 0x9b,0x5b,0x54,0xd1 }, { 0x24,0x36,0x2e,0x3a }, 
+    { 0x0c,0x0a,0x67,0xb1 }, { 0x93,0x57,0xe7,0x0f },
+    { 0xb4,0xee,0x96,0xd2 }, { 0x1b,0x9b,0x91,0x9e }, 
+    { 0x80,0xc0,0xc5,0x4f }, { 0x61,0xdc,0x20,0xa2 },
+    { 0x5a,0x77,0x4b,0x69 }, { 0x1c,0x12,0x1a,0x16 }, 
+    { 0xe2,0x93,0xba,0x0a }, { 0xc0,0xa0,0x2a,0xe5 }, 
+    { 0x3c,0x22,0xe0,0x43 }, { 0x12,0x1b,0x17,0x1d }, 
+    { 0x0e,0x09,0x0d,0x0b }, { 0xf2,0x8b,0xc7,0xad }, 
+    { 0x2d,0xb6,0xa8,0xb9 }, { 0x14,0x1e,0xa9,0xc8 }, 
+    { 0x57,0xf1,0x19,0x85 }, { 0xaf,0x75,0x07,0x4c }, 
+    { 0xee,0x99,0xdd,0xbb }, { 0xa3,0x7f,0x60,0xfd }, 
+    { 0xf7,0x01,0x26,0x9f }, { 0x5c,0x72,0xf5,0xbc },
+    { 0x44,0x66,0x3b,0xc5 }, { 0x5b,0xfb,0x7e,0x34 }, 
+    { 0x8b,0x43,0x29,0x76 }, { 0xcb,0x23,0xc6,0xdc },
+    { 0xb6,0xed,0xfc,0x68 }, { 0xb8,0xe4,0xf1,0x63 }, 
+    { 0xd7,0x31,0xdc,0xca }, { 0x42,0x63,0x85,0x10 },
+    { 0x13,0x97,0x22,0x40 }, { 0x84,0xc6,0x11,0x20 }, 
+    { 0x85,0x4a,0x24,0x7d }, { 0xd2,0xbb,0x3d,0xf8 }, 
+    { 0xae,0xf9,0x32,0x11 }, { 0xc7,0x29,0xa1,0x6d }, 
+    { 0x1d,0x9e,0x2f,0x4b }, { 0xdc,0xb2,0x30,0xf3 },
+    { 0x0d,0x86,0x52,0xec }, { 0x77,0xc1,0xe3,0xd0 }, 
+    { 0x2b,0xb3,0x16,0x6c }, { 0xa9,0x70,0xb9,0x99 },
+    { 0x11,0x94,0x48,0xfa }, { 0x47,0xe9,0x64,0x22 }, 
+    { 0xa8,0xfc,0x8c,0xc4 }, { 0xa0,0xf0,0x3f,0x1a },
+    { 0x56,0x7d,0x2c,0xd8 }, { 0x22,0x33,0x90,0xef }, 
+    { 0x87,0x49,0x4e,0xc7 }, { 0xd9,0x38,0xd1,0xc1 }, 
+    { 0x8c,0xca,0xa2,0xfe }, { 0x98,0xd4,0x0b,0x36 }, 
+    { 0xa6,0xf5,0x81,0xcf }, { 0xa5,0x7a,0xde,0x28 }, 
+    { 0xda,0xb7,0x8e,0x26 }, { 0x3f,0xad,0xbf,0xa4 }, 
+    { 0x2c,0x3a,0x9d,0xe4 }, { 0x50,0x78,0x92,0x0d }, 
+    { 0x6a,0x5f,0xcc,0x9b }, { 0x54,0x7e,0x46,0x62 }, 
+    { 0xf6,0x8d,0x13,0xc2 }, { 0x90,0xd8,0xb8,0xe8 }, 
+    { 0x2e,0x39,0xf7,0x5e }, { 0x82,0xc3,0xaf,0xf5 }, 
+    { 0x9f,0x5d,0x80,0xbe }, { 0x69,0xd0,0x93,0x7c },
+    { 0x6f,0xd5,0x2d,0xa9 }, { 0xcf,0x25,0x12,0xb3 }, 
+    { 0xc8,0xac,0x99,0x3b }, { 0x10,0x18,0x7d,0xa7 },
+    { 0xe8,0x9c,0x63,0x6e }, { 0xdb,0x3b,0xbb,0x7b }, 
+    { 0xcd,0x26,0x78,0x09 }, { 0x6e,0x59,0x18,0xf4 },
+    { 0xec,0x9a,0xb7,0x01 }, { 0x83,0x4f,0x9a,0xa8 }, 
+    { 0xe6,0x95,0x6e,0x65 }, { 0xaa,0xff,0xe6,0x7e }, 
+    { 0x21,0xbc,0xcf,0x08 }, { 0xef,0x15,0xe8,0xe6 }, 
+    { 0xba,0xe7,0x9b,0xd9 }, { 0x4a,0x6f,0x36,0xce }, 
+    { 0xea,0x9f,0x09,0xd4 }, { 0x29,0xb0,0x7c,0xd6 }, 
+    { 0x31,0xa4,0xb2,0xaf }, { 0x2a,0x3f,0x23,0x31 }, 
+    { 0xc6,0xa5,0x94,0x30 }, { 0x35,0xa2,0x66,0xc0 }, 
+    { 0x74,0x4e,0xbc,0x37 }, { 0xfc,0x82,0xca,0xa6 }, 
+    { 0xe0,0x90,0xd0,0xb0 }, { 0x33,0xa7,0xd8,0x15 }, 
+    { 0xf1,0x04,0x98,0x4a }, { 0x41,0xec,0xda,0xf7 },
+    { 0x7f,0xcd,0x50,0x0e }, { 0x17,0x91,0xf6,0x2f }, 
+    { 0x76,0x4d,0xd6,0x8d }, { 0x43,0xef,0xb0,0x4d },
+    { 0xcc,0xaa,0x4d,0x54 }, { 0xe4,0x96,0x04,0xdf }, 
+    { 0x9e,0xd1,0xb5,0xe3 }, { 0x4c,0x6a,0x88,0x1b },
+    { 0xc1,0x2c,0x1f,0xb8 }, { 0x46,0x65,0x51,0x7f }, 
+    { 0x9d,0x5e,0xea,0x04 }, { 0x01,0x8c,0x35,0x5d },
+    { 0xfa,0x87,0x74,0x73 }, { 0xfb,0x0b,0x41,0x2e }, 
+    { 0xb3,0x67,0x1d,0x5a }, { 0x92,0xdb,0xd2,0x52 },
+    { 0xe9,0x10,0x56,0x33 }, { 0x6d,0xd6,0x47,0x13 }, 
+    { 0x9a,0xd7,0x61,0x8c }, { 0x37,0xa1,0x0c,0x7a },
+    { 0x59,0xf8,0x14,0x8e }, { 0xeb,0x13,0x3c,0x89 }, 
+    { 0xce,0xa9,0x27,0xee }, { 0xb7,0x61,0xc9,0x35 },
+    { 0xe1,0x1c,0xe5,0xed }, { 0x7a,0x47,0xb1,0x3c }, 
+    { 0x9c,0xd2,0xdf,0x59 }, { 0x55,0xf2,0x73,0x3f }, 
+    { 0x18,0x14,0xce,0x79 }, { 0x73,0xc7,0x37,0xbf }, 
+    { 0x53,0xf7,0xcd,0xea }, { 0x5f,0xfd,0xaa,0x5b },
+    { 0xdf,0x3d,0x6f,0x14 }, { 0x78,0x44,0xdb,0x86 }, 
+    { 0xca,0xaf,0xf3,0x81 }, { 0xb9,0x68,0xc4,0x3e }, 
+    { 0x38,0x24,0x34,0x2c }, { 0xc2,0xa3,0x40,0x5f }, 
+    { 0x16,0x1d,0xc3,0x72 }, { 0xbc,0xe2,0x25,0x0c }, 
+    { 0x28,0x3c,0x49,0x8b }, { 0xff,0x0d,0x95,0x41 }, 
+    { 0x39,0xa8,0x01,0x71 }, { 0x08,0x0c,0xb3,0xde }, 
+    { 0xd8,0xb4,0xe4,0x9c }, { 0x64,0x56,0xc1,0x90 }, 
+    { 0x7b,0xcb,0x84,0x61 }, { 0xd5,0x32,0xb6,0x70 },
+    { 0x48,0x6c,0x5c,0x74 }, { 0xd0,0xb8,0x57,0x42 }
+  };
+
+static const unsigned char T6[256][4] = 
+  {
+    { 0x50,0x51,0xf4,0xa7 }, { 0x53,0x7e,0x41,0x65 }, 
+    { 0xc3,0x1a,0x17,0xa4 }, { 0x96,0x3a,0x27,0x5e }, 
+    { 0xcb,0x3b,0xab,0x6b }, { 0xf1,0x1f,0x9d,0x45 },
+    { 0xab,0xac,0xfa,0x58 }, { 0x93,0x4b,0xe3,0x03 }, 
+    { 0x55,0x20,0x30,0xfa }, { 0xf6,0xad,0x76,0x6d },
+    { 0x91,0x88,0xcc,0x76 }, { 0x25,0xf5,0x02,0x4c }, 
+    { 0xfc,0x4f,0xe5,0xd7 }, { 0xd7,0xc5,0x2a,0xcb },
+    { 0x80,0x26,0x35,0x44 }, { 0x8f,0xb5,0x62,0xa3 }, 
+    { 0x49,0xde,0xb1,0x5a }, { 0x67,0x25,0xba,0x1b }, 
+    { 0x98,0x45,0xea,0x0e }, { 0xe1,0x5d,0xfe,0xc0 }, 
+    { 0x02,0xc3,0x2f,0x75 }, { 0x12,0x81,0x4c,0xf0 },
+    { 0xa3,0x8d,0x46,0x97 }, { 0xc6,0x6b,0xd3,0xf9 }, 
+    { 0xe7,0x03,0x8f,0x5f }, { 0x95,0x15,0x92,0x9c },
+    { 0xeb,0xbf,0x6d,0x7a }, { 0xda,0x95,0x52,0x59 }, 
+    { 0x2d,0xd4,0xbe,0x83 }, { 0xd3,0x58,0x74,0x21 },
+    { 0x29,0x49,0xe0,0x69 }, { 0x44,0x8e,0xc9,0xc8 }, 
+    { 0x6a,0x75,0xc2,0x89 }, { 0x78,0xf4,0x8e,0x79 },
+    { 0x6b,0x99,0x58,0x3e }, { 0xdd,0x27,0xb9,0x71 }, 
+    { 0xb6,0xbe,0xe1,0x4f }, { 0x17,0xf0,0x88,0xad },
+    { 0x66,0xc9,0x20,0xac }, { 0xb4,0x7d,0xce,0x3a }, 
+    { 0x18,0x63,0xdf,0x4a }, { 0x82,0xe5,0x1a,0x31 },
+    { 0x60,0x97,0x51,0x33 }, { 0x45,0x62,0x53,0x7f }, 
+    { 0xe0,0xb1,0x64,0x77 }, { 0x84,0xbb,0x6b,0xae },
+    { 0x1c,0xfe,0x81,0xa0 }, { 0x94,0xf9,0x08,0x2b }, 
+    { 0x58,0x70,0x48,0x68 }, { 0x19,0x8f,0x45,0xfd },
+    { 0x87,0x94,0xde,0x6c }, { 0xb7,0x52,0x7b,0xf8 }, 
+    { 0x23,0xab,0x73,0xd3 }, { 0xe2,0x72,0x4b,0x02 },
+    { 0x57,0xe3,0x1f,0x8f }, { 0x2a,0x66,0x55,0xab }, 
+    { 0x07,0xb2,0xeb,0x28 }, { 0x03,0x2f,0xb5,0xc2 },
+    { 0x9a,0x86,0xc5,0x7b }, { 0xa5,0xd3,0x37,0x08 }, 
+    { 0xf2,0x30,0x28,0x87 }, { 0xb2,0x23,0xbf,0xa5 },
+    { 0xba,0x02,0x03,0x6a }, { 0x5c,0xed,0x16,0x82 }, 
+    { 0x2b,0x8a,0xcf,0x1c }, { 0x92,0xa7,0x79,0xb4 },
+    { 0xf0,0xf3,0x07,0xf2 }, { 0xa1,0x4e,0x69,0xe2 }, 
+    { 0xcd,0x65,0xda,0xf4 }, { 0xd5,0x06,0x05,0xbe },
+    { 0x1f,0xd1,0x34,0x62 }, { 0x8a,0xc4,0xa6,0xfe }, 
+    { 0x9d,0x34,0x2e,0x53 }, { 0xa0,0xa2,0xf3,0x55 },
+    { 0x32,0x05,0x8a,0xe1 }, { 0x75,0xa4,0xf6,0xeb }, 
+    { 0x39,0x0b,0x83,0xec }, { 0xaa,0x40,0x60,0xef },
+    { 0x06,0x5e,0x71,0x9f }, { 0x51,0xbd,0x6e,0x10 }, 
+    { 0xf9,0x3e,0x21,0x8a }, { 0x3d,0x96,0xdd,0x06 },
+    { 0xae,0xdd,0x3e,0x05 }, { 0x46,0x4d,0xe6,0xbd }, 
+    { 0xb5,0x91,0x54,0x8d }, { 0x05,0x71,0xc4,0x5d },
+    { 0x6f,0x04,0x06,0xd4 }, { 0xff,0x60,0x50,0x15 }, 
+    { 0x24,0x19,0x98,0xfb }, { 0x97,0xd6,0xbd,0xe9 },
+    { 0xcc,0x89,0x40,0x43 }, { 0x77,0x67,0xd9,0x9e }, 
+    { 0xbd,0xb0,0xe8,0x42 }, { 0x88,0x07,0x89,0x8b },
+    { 0x38,0xe7,0x19,0x5b }, { 0xdb,0x79,0xc8,0xee }, 
+    { 0x47,0xa1,0x7c,0x0a }, { 0xe9,0x7c,0x42,0x0f },
+    { 0xc9,0xf8,0x84,0x1e }, { 0x00,0x00,0x00,0x00 }, 
+    { 0x83,0x09,0x80,0x86 }, { 0x48,0x32,0x2b,0xed },
+    { 0xac,0x1e,0x11,0x70 }, { 0x4e,0x6c,0x5a,0x72 }, 
+    { 0xfb,0xfd,0x0e,0xff }, { 0x56,0x0f,0x85,0x38 },
+    { 0x1e,0x3d,0xae,0xd5 }, { 0x27,0x36,0x2d,0x39 }, 
+    { 0x64,0x0a,0x0f,0xd9 }, { 0x21,0x68,0x5c,0xa6 },
+    { 0xd1,0x9b,0x5b,0x54 }, { 0x3a,0x24,0x36,0x2e }, 
+    { 0xb1,0x0c,0x0a,0x67 }, { 0x0f,0x93,0x57,0xe7 },
+    { 0xd2,0xb4,0xee,0x96 }, { 0x9e,0x1b,0x9b,0x91 }, 
+    { 0x4f,0x80,0xc0,0xc5 }, { 0xa2,0x61,0xdc,0x20 }, 
+    { 0x69,0x5a,0x77,0x4b }, { 0x16,0x1c,0x12,0x1a }, 
+    { 0x0a,0xe2,0x93,0xba }, { 0xe5,0xc0,0xa0,0x2a },
+    { 0x43,0x3c,0x22,0xe0 }, { 0x1d,0x12,0x1b,0x17 }, 
+    { 0x0b,0x0e,0x09,0x0d }, { 0xad,0xf2,0x8b,0xc7 },
+    { 0xb9,0x2d,0xb6,0xa8 }, { 0xc8,0x14,0x1e,0xa9 }, 
+    { 0x85,0x57,0xf1,0x19 }, { 0x4c,0xaf,0x75,0x07 },
+    { 0xbb,0xee,0x99,0xdd }, { 0xfd,0xa3,0x7f,0x60 }, 
+    { 0x9f,0xf7,0x01,0x26 }, { 0xbc,0x5c,0x72,0xf5 },
+    { 0xc5,0x44,0x66,0x3b }, { 0x34,0x5b,0xfb,0x7e }, 
+    { 0x76,0x8b,0x43,0x29 }, { 0xdc,0xcb,0x23,0xc6 },
+    { 0x68,0xb6,0xed,0xfc }, { 0x63,0xb8,0xe4,0xf1 }, 
+    { 0xca,0xd7,0x31,0xdc }, { 0x10,0x42,0x63,0x85 },
+    { 0x40,0x13,0x97,0x22 }, { 0x20,0x84,0xc6,0x11 }, 
+    { 0x7d,0x85,0x4a,0x24 }, { 0xf8,0xd2,0xbb,0x3d },
+    { 0x11,0xae,0xf9,0x32 }, { 0x6d,0xc7,0x29,0xa1 }, 
+    { 0x4b,0x1d,0x9e,0x2f }, { 0xf3,0xdc,0xb2,0x30 },
+    { 0xec,0x0d,0x86,0x52 }, { 0xd0,0x77,0xc1,0xe3 }, 
+    { 0x6c,0x2b,0xb3,0x16 }, { 0x99,0xa9,0x70,0xb9 }, 
+    { 0xfa,0x11,0x94,0x48 }, { 0x22,0x47,0xe9,0x64 }, 
+    { 0xc4,0xa8,0xfc,0x8c }, { 0x1a,0xa0,0xf0,0x3f }, 
+    { 0xd8,0x56,0x7d,0x2c }, { 0xef,0x22,0x33,0x90 }, 
+    { 0xc7,0x87,0x49,0x4e }, { 0xc1,0xd9,0x38,0xd1 },
+    { 0xfe,0x8c,0xca,0xa2 }, { 0x36,0x98,0xd4,0x0b }, 
+    { 0xcf,0xa6,0xf5,0x81 }, { 0x28,0xa5,0x7a,0xde }, 
+    { 0x26,0xda,0xb7,0x8e }, { 0xa4,0x3f,0xad,0xbf }, 
+    { 0xe4,0x2c,0x3a,0x9d }, { 0x0d,0x50,0x78,0x92 }, 
+    { 0x9b,0x6a,0x5f,0xcc }, { 0x62,0x54,0x7e,0x46 }, 
+    { 0xc2,0xf6,0x8d,0x13 }, { 0xe8,0x90,0xd8,0xb8 }, 
+    { 0x5e,0x2e,0x39,0xf7 }, { 0xf5,0x82,0xc3,0xaf }, 
+    { 0xbe,0x9f,0x5d,0x80 }, { 0x7c,0x69,0xd0,0x93 },
+    { 0xa9,0x6f,0xd5,0x2d }, { 0xb3,0xcf,0x25,0x12 }, 
+    { 0x3b,0xc8,0xac,0x99 }, { 0xa7,0x10,0x18,0x7d }, 
+    { 0x6e,0xe8,0x9c,0x63 }, { 0x7b,0xdb,0x3b,0xbb }, 
+    { 0x09,0xcd,0x26,0x78 }, { 0xf4,0x6e,0x59,0x18 },
+    { 0x01,0xec,0x9a,0xb7 }, { 0xa8,0x83,0x4f,0x9a }, 
+    { 0x65,0xe6,0x95,0x6e }, { 0x7e,0xaa,0xff,0xe6 }, 
+    { 0x08,0x21,0xbc,0xcf }, { 0xe6,0xef,0x15,0xe8 }, 
+    { 0xd9,0xba,0xe7,0x9b }, { 0xce,0x4a,0x6f,0x36 },
+    { 0xd4,0xea,0x9f,0x09 }, { 0xd6,0x29,0xb0,0x7c }, 
+    { 0xaf,0x31,0xa4,0xb2 }, { 0x31,0x2a,0x3f,0x23 },
+    { 0x30,0xc6,0xa5,0x94 }, { 0xc0,0x35,0xa2,0x66 }, 
+    { 0x37,0x74,0x4e,0xbc }, { 0xa6,0xfc,0x82,0xca }, 
+    { 0xb0,0xe0,0x90,0xd0 }, { 0x15,0x33,0xa7,0xd8 }, 
+    { 0x4a,0xf1,0x04,0x98 }, { 0xf7,0x41,0xec,0xda },
+    { 0x0e,0x7f,0xcd,0x50 }, { 0x2f,0x17,0x91,0xf6 }, 
+    { 0x8d,0x76,0x4d,0xd6 }, { 0x4d,0x43,0xef,0xb0 },
+    { 0x54,0xcc,0xaa,0x4d }, { 0xdf,0xe4,0x96,0x04 }, 
+    { 0xe3,0x9e,0xd1,0xb5 }, { 0x1b,0x4c,0x6a,0x88 },
+    { 0xb8,0xc1,0x2c,0x1f }, { 0x7f,0x46,0x65,0x51 }, 
+    { 0x04,0x9d,0x5e,0xea }, { 0x5d,0x01,0x8c,0x35 },
+    { 0x73,0xfa,0x87,0x74 }, { 0x2e,0xfb,0x0b,0x41 }, 
+    { 0x5a,0xb3,0x67,0x1d }, { 0x52,0x92,0xdb,0xd2 },
+    { 0x33,0xe9,0x10,0x56 }, { 0x13,0x6d,0xd6,0x47 }, 
+    { 0x8c,0x9a,0xd7,0x61 }, { 0x7a,0x37,0xa1,0x0c }, 
+    { 0x8e,0x59,0xf8,0x14 }, { 0x89,0xeb,0x13,0x3c }, 
+    { 0xee,0xce,0xa9,0x27 }, { 0x35,0xb7,0x61,0xc9 },
+    { 0xed,0xe1,0x1c,0xe5 }, { 0x3c,0x7a,0x47,0xb1 }, 
+    { 0x59,0x9c,0xd2,0xdf }, { 0x3f,0x55,0xf2,0x73 },
+    { 0x79,0x18,0x14,0xce }, { 0xbf,0x73,0xc7,0x37 }, 
+    { 0xea,0x53,0xf7,0xcd }, { 0x5b,0x5f,0xfd,0xaa },
+    { 0x14,0xdf,0x3d,0x6f }, { 0x86,0x78,0x44,0xdb }, 
+    { 0x81,0xca,0xaf,0xf3 }, { 0x3e,0xb9,0x68,0xc4 },
+    { 0x2c,0x38,0x24,0x34 }, { 0x5f,0xc2,0xa3,0x40 }, 
+    { 0x72,0x16,0x1d,0xc3 }, { 0x0c,0xbc,0xe2,0x25 },
+    { 0x8b,0x28,0x3c,0x49 }, { 0x41,0xff,0x0d,0x95 }, 
+    { 0x71,0x39,0xa8,0x01 }, { 0xde,0x08,0x0c,0xb3 },
+    { 0x9c,0xd8,0xb4,0xe4 }, { 0x90,0x64,0x56,0xc1 }, 
+    { 0x61,0x7b,0xcb,0x84 }, { 0x70,0xd5,0x32,0xb6 },
+    { 0x74,0x48,0x6c,0x5c }, { 0x42,0xd0,0xb8,0x57 }
+  };
+
+static const unsigned char T7[256][4] = 
+  {
+    { 0xa7,0x50,0x51,0xf4 }, { 0x65,0x53,0x7e,0x41 },
+    { 0xa4,0xc3,0x1a,0x17 }, { 0x5e,0x96,0x3a,0x27 }, 
+    { 0x6b,0xcb,0x3b,0xab }, { 0x45,0xf1,0x1f,0x9d },
+    { 0x58,0xab,0xac,0xfa }, { 0x03,0x93,0x4b,0xe3 }, 
+    { 0xfa,0x55,0x20,0x30 }, { 0x6d,0xf6,0xad,0x76 },
+    { 0x76,0x91,0x88,0xcc }, { 0x4c,0x25,0xf5,0x02 }, 
+    { 0xd7,0xfc,0x4f,0xe5 }, { 0xcb,0xd7,0xc5,0x2a },
+    { 0x44,0x80,0x26,0x35 }, { 0xa3,0x8f,0xb5,0x62 }, 
+    { 0x5a,0x49,0xde,0xb1 }, { 0x1b,0x67,0x25,0xba }, 
+    { 0x0e,0x98,0x45,0xea }, { 0xc0,0xe1,0x5d,0xfe }, 
+    { 0x75,0x02,0xc3,0x2f }, { 0xf0,0x12,0x81,0x4c },
+    { 0x97,0xa3,0x8d,0x46 }, { 0xf9,0xc6,0x6b,0xd3 }, 
+    { 0x5f,0xe7,0x03,0x8f }, { 0x9c,0x95,0x15,0x92 },
+    { 0x7a,0xeb,0xbf,0x6d }, { 0x59,0xda,0x95,0x52 }, 
+    { 0x83,0x2d,0xd4,0xbe }, { 0x21,0xd3,0x58,0x74 },
+    { 0x69,0x29,0x49,0xe0 }, { 0xc8,0x44,0x8e,0xc9 }, 
+    { 0x89,0x6a,0x75,0xc2 }, { 0x79,0x78,0xf4,0x8e }, 
+    { 0x3e,0x6b,0x99,0x58 }, { 0x71,0xdd,0x27,0xb9 }, 
+    { 0x4f,0xb6,0xbe,0xe1 }, { 0xad,0x17,0xf0,0x88 },
+    { 0xac,0x66,0xc9,0x20 }, { 0x3a,0xb4,0x7d,0xce }, 
+    { 0x4a,0x18,0x63,0xdf }, { 0x31,0x82,0xe5,0x1a },
+    { 0x33,0x60,0x97,0x51 }, { 0x7f,0x45,0x62,0x53 }, 
+    { 0x77,0xe0,0xb1,0x64 }, { 0xae,0x84,0xbb,0x6b },
+    { 0xa0,0x1c,0xfe,0x81 }, { 0x2b,0x94,0xf9,0x08 }, 
+    { 0x68,0x58,0x70,0x48 }, { 0xfd,0x19,0x8f,0x45 },
+    { 0x6c,0x87,0x94,0xde }, { 0xf8,0xb7,0x52,0x7b }, 
+    { 0xd3,0x23,0xab,0x73 }, { 0x02,0xe2,0x72,0x4b },
+    { 0x8f,0x57,0xe3,0x1f }, { 0xab,0x2a,0x66,0x55 }, 
+    { 0x28,0x07,0xb2,0xeb }, { 0xc2,0x03,0x2f,0xb5 },
+    { 0x7b,0x9a,0x86,0xc5 }, { 0x08,0xa5,0xd3,0x37 }, 
+    { 0x87,0xf2,0x30,0x28 }, { 0xa5,0xb2,0x23,0xbf },
+    { 0x6a,0xba,0x02,0x03 }, { 0x82,0x5c,0xed,0x16 }, 
+    { 0x1c,0x2b,0x8a,0xcf }, { 0xb4,0x92,0xa7,0x79 }, 
+    { 0xf2,0xf0,0xf3,0x07 }, { 0xe2,0xa1,0x4e,0x69 }, 
+    { 0xf4,0xcd,0x65,0xda }, { 0xbe,0xd5,0x06,0x05 },
+    { 0x62,0x1f,0xd1,0x34 }, { 0xfe,0x8a,0xc4,0xa6 }, 
+    { 0x53,0x9d,0x34,0x2e }, { 0x55,0xa0,0xa2,0xf3 },
+    { 0xe1,0x32,0x05,0x8a }, { 0xeb,0x75,0xa4,0xf6 }, 
+    { 0xec,0x39,0x0b,0x83 }, { 0xef,0xaa,0x40,0x60 },
+    { 0x9f,0x06,0x5e,0x71 }, { 0x10,0x51,0xbd,0x6e }, 
+    { 0x8a,0xf9,0x3e,0x21 }, { 0x06,0x3d,0x96,0xdd },
+    { 0x05,0xae,0xdd,0x3e }, { 0xbd,0x46,0x4d,0xe6 }, 
+    { 0x8d,0xb5,0x91,0x54 }, { 0x5d,0x05,0x71,0xc4 },
+    { 0xd4,0x6f,0x04,0x06 }, { 0x15,0xff,0x60,0x50 }, 
+    { 0xfb,0x24,0x19,0x98 }, { 0xe9,0x97,0xd6,0xbd }, 
+    { 0x43,0xcc,0x89,0x40 }, { 0x9e,0x77,0x67,0xd9 }, 
+    { 0x42,0xbd,0xb0,0xe8 }, { 0x8b,0x88,0x07,0x89 },
+    { 0x5b,0x38,0xe7,0x19 }, { 0xee,0xdb,0x79,0xc8 }, 
+    { 0x0a,0x47,0xa1,0x7c }, { 0x0f,0xe9,0x7c,0x42 },
+    { 0x1e,0xc9,0xf8,0x84 }, { 0x00,0x00,0x00,0x00 }, 
+    { 0x86,0x83,0x09,0x80 }, { 0xed,0x48,0x32,0x2b },
+    { 0x70,0xac,0x1e,0x11 }, { 0x72,0x4e,0x6c,0x5a }, 
+    { 0xff,0xfb,0xfd,0x0e }, { 0x38,0x56,0x0f,0x85 },
+    { 0xd5,0x1e,0x3d,0xae }, { 0x39,0x27,0x36,0x2d }, 
+    { 0xd9,0x64,0x0a,0x0f }, { 0xa6,0x21,0x68,0x5c },
+    { 0x54,0xd1,0x9b,0x5b }, { 0x2e,0x3a,0x24,0x36 }, 
+    { 0x67,0xb1,0x0c,0x0a }, { 0xe7,0x0f,0x93,0x57 },
+    { 0x96,0xd2,0xb4,0xee }, { 0x91,0x9e,0x1b,0x9b }, 
+    { 0xc5,0x4f,0x80,0xc0 }, { 0x20,0xa2,0x61,0xdc },
+    { 0x4b,0x69,0x5a,0x77 }, { 0x1a,0x16,0x1c,0x12 }, 
+    { 0xba,0x0a,0xe2,0x93 }, { 0x2a,0xe5,0xc0,0xa0 },
+    { 0xe0,0x43,0x3c,0x22 }, { 0x17,0x1d,0x12,0x1b }, 
+    { 0x0d,0x0b,0x0e,0x09 }, { 0xc7,0xad,0xf2,0x8b },
+    { 0xa8,0xb9,0x2d,0xb6 }, { 0xa9,0xc8,0x14,0x1e }, 
+    { 0x19,0x85,0x57,0xf1 }, { 0x07,0x4c,0xaf,0x75 },
+    { 0xdd,0xbb,0xee,0x99 }, { 0x60,0xfd,0xa3,0x7f }, 
+    { 0x26,0x9f,0xf7,0x01 }, { 0xf5,0xbc,0x5c,0x72 },
+    { 0x3b,0xc5,0x44,0x66 }, { 0x7e,0x34,0x5b,0xfb }, 
+    { 0x29,0x76,0x8b,0x43 }, { 0xc6,0xdc,0xcb,0x23 },
+    { 0xfc,0x68,0xb6,0xed }, { 0xf1,0x63,0xb8,0xe4 }, 
+    { 0xdc,0xca,0xd7,0x31 }, { 0x85,0x10,0x42,0x63 },
+    { 0x22,0x40,0x13,0x97 }, { 0x11,0x20,0x84,0xc6 }, 
+    { 0x24,0x7d,0x85,0x4a }, { 0x3d,0xf8,0xd2,0xbb },
+    { 0x32,0x11,0xae,0xf9 }, { 0xa1,0x6d,0xc7,0x29 }, 
+    { 0x2f,0x4b,0x1d,0x9e }, { 0x30,0xf3,0xdc,0xb2 },
+    { 0x52,0xec,0x0d,0x86 }, { 0xe3,0xd0,0x77,0xc1 }, 
+    { 0x16,0x6c,0x2b,0xb3 }, { 0xb9,0x99,0xa9,0x70 },
+    { 0x48,0xfa,0x11,0x94 }, { 0x64,0x22,0x47,0xe9 }, 
+    { 0x8c,0xc4,0xa8,0xfc }, { 0x3f,0x1a,0xa0,0xf0 },
+    { 0x2c,0xd8,0x56,0x7d }, { 0x90,0xef,0x22,0x33 }, 
+    { 0x4e,0xc7,0x87,0x49 }, { 0xd1,0xc1,0xd9,0x38 },
+    { 0xa2,0xfe,0x8c,0xca }, { 0x0b,0x36,0x98,0xd4 }, 
+    { 0x81,0xcf,0xa6,0xf5 }, { 0xde,0x28,0xa5,0x7a },
+    { 0x8e,0x26,0xda,0xb7 }, { 0xbf,0xa4,0x3f,0xad }, 
+    { 0x9d,0xe4,0x2c,0x3a }, { 0x92,0x0d,0x50,0x78 },
+    { 0xcc,0x9b,0x6a,0x5f }, { 0x46,0x62,0x54,0x7e }, 
+    { 0x13,0xc2,0xf6,0x8d }, { 0xb8,0xe8,0x90,0xd8 },
+    { 0xf7,0x5e,0x2e,0x39 }, { 0xaf,0xf5,0x82,0xc3 }, 
+    { 0x80,0xbe,0x9f,0x5d }, { 0x93,0x7c,0x69,0xd0 },
+    { 0x2d,0xa9,0x6f,0xd5 }, { 0x12,0xb3,0xcf,0x25 }, 
+    { 0x99,0x3b,0xc8,0xac }, { 0x7d,0xa7,0x10,0x18 },
+    { 0x63,0x6e,0xe8,0x9c }, { 0xbb,0x7b,0xdb,0x3b }, 
+    { 0x78,0x09,0xcd,0x26 }, { 0x18,0xf4,0x6e,0x59 }, 
+    { 0xb7,0x01,0xec,0x9a }, { 0x9a,0xa8,0x83,0x4f }, 
+    { 0x6e,0x65,0xe6,0x95 }, { 0xe6,0x7e,0xaa,0xff },
+    { 0xcf,0x08,0x21,0xbc }, { 0xe8,0xe6,0xef,0x15 }, 
+    { 0x9b,0xd9,0xba,0xe7 }, { 0x36,0xce,0x4a,0x6f },
+    { 0x09,0xd4,0xea,0x9f }, { 0x7c,0xd6,0x29,0xb0 }, 
+    { 0xb2,0xaf,0x31,0xa4 }, { 0x23,0x31,0x2a,0x3f },
+    { 0x94,0x30,0xc6,0xa5 }, { 0x66,0xc0,0x35,0xa2 }, 
+    { 0xbc,0x37,0x74,0x4e }, { 0xca,0xa6,0xfc,0x82 },
+    { 0xd0,0xb0,0xe0,0x90 }, { 0xd8,0x15,0x33,0xa7 }, 
+    { 0x98,0x4a,0xf1,0x04 }, { 0xda,0xf7,0x41,0xec },
+    { 0x50,0x0e,0x7f,0xcd }, { 0xf6,0x2f,0x17,0x91 }, 
+    { 0xd6,0x8d,0x76,0x4d }, { 0xb0,0x4d,0x43,0xef }, 
+    { 0x4d,0x54,0xcc,0xaa }, { 0x04,0xdf,0xe4,0x96 }, 
+    { 0xb5,0xe3,0x9e,0xd1 }, { 0x88,0x1b,0x4c,0x6a },
+    { 0x1f,0xb8,0xc1,0x2c }, { 0x51,0x7f,0x46,0x65 }, 
+    { 0xea,0x04,0x9d,0x5e }, { 0x35,0x5d,0x01,0x8c },
+    { 0x74,0x73,0xfa,0x87 }, { 0x41,0x2e,0xfb,0x0b }, 
+    { 0x1d,0x5a,0xb3,0x67 }, { 0xd2,0x52,0x92,0xdb },
+    { 0x56,0x33,0xe9,0x10 }, { 0x47,0x13,0x6d,0xd6 }, 
+    { 0x61,0x8c,0x9a,0xd7 }, { 0x0c,0x7a,0x37,0xa1 },
+    { 0x14,0x8e,0x59,0xf8 }, { 0x3c,0x89,0xeb,0x13 }, 
+    { 0x27,0xee,0xce,0xa9 }, { 0xc9,0x35,0xb7,0x61 },
+    { 0xe5,0xed,0xe1,0x1c }, { 0xb1,0x3c,0x7a,0x47 }, 
+    { 0xdf,0x59,0x9c,0xd2 }, { 0x73,0x3f,0x55,0xf2 },
+    { 0xce,0x79,0x18,0x14 }, { 0x37,0xbf,0x73,0xc7 }, 
+    { 0xcd,0xea,0x53,0xf7 }, { 0xaa,0x5b,0x5f,0xfd },
+    { 0x6f,0x14,0xdf,0x3d }, { 0xdb,0x86,0x78,0x44 }, 
+    { 0xf3,0x81,0xca,0xaf }, { 0xc4,0x3e,0xb9,0x68 },
+    { 0x34,0x2c,0x38,0x24 }, { 0x40,0x5f,0xc2,0xa3 }, 
+    { 0xc3,0x72,0x16,0x1d }, { 0x25,0x0c,0xbc,0xe2 },
+    { 0x49,0x8b,0x28,0x3c }, { 0x95,0x41,0xff,0x0d }, 
+    { 0x01,0x71,0x39,0xa8 }, { 0xb3,0xde,0x08,0x0c },
+    { 0xe4,0x9c,0xd8,0xb4 }, { 0xc1,0x90,0x64,0x56 }, 
+    { 0x84,0x61,0x7b,0xcb }, { 0xb6,0x70,0xd5,0x32 },
+    { 0x5c,0x74,0x48,0x6c }, { 0x57,0x42,0xd0,0xb8 }
+  };
+
+static const unsigned char T8[256][4] = 
+  {
+    { 0xf4,0xa7,0x50,0x51 }, { 0x41,0x65,0x53,0x7e },
+    { 0x17,0xa4,0xc3,0x1a }, { 0x27,0x5e,0x96,0x3a }, 
+    { 0xab,0x6b,0xcb,0x3b }, { 0x9d,0x45,0xf1,0x1f },
+    { 0xfa,0x58,0xab,0xac }, { 0xe3,0x03,0x93,0x4b }, 
+    { 0x30,0xfa,0x55,0x20 }, { 0x76,0x6d,0xf6,0xad },
+    { 0xcc,0x76,0x91,0x88 }, { 0x02,0x4c,0x25,0xf5 }, 
+    { 0xe5,0xd7,0xfc,0x4f }, { 0x2a,0xcb,0xd7,0xc5 },
+    { 0x35,0x44,0x80,0x26 }, { 0x62,0xa3,0x8f,0xb5 }, 
+    { 0xb1,0x5a,0x49,0xde }, { 0xba,0x1b,0x67,0x25 },
+    { 0xea,0x0e,0x98,0x45 }, { 0xfe,0xc0,0xe1,0x5d }, 
+    { 0x2f,0x75,0x02,0xc3 }, { 0x4c,0xf0,0x12,0x81 },
+    { 0x46,0x97,0xa3,0x8d }, { 0xd3,0xf9,0xc6,0x6b }, 
+    { 0x8f,0x5f,0xe7,0x03 }, { 0x92,0x9c,0x95,0x15 },
+    { 0x6d,0x7a,0xeb,0xbf }, { 0x52,0x59,0xda,0x95 }, 
+    { 0xbe,0x83,0x2d,0xd4 }, { 0x74,0x21,0xd3,0x58 },
+    { 0xe0,0x69,0x29,0x49 }, { 0xc9,0xc8,0x44,0x8e }, 
+    { 0xc2,0x89,0x6a,0x75 }, { 0x8e,0x79,0x78,0xf4 },
+    { 0x58,0x3e,0x6b,0x99 }, { 0xb9,0x71,0xdd,0x27 }, 
+    { 0xe1,0x4f,0xb6,0xbe }, { 0x88,0xad,0x17,0xf0 },
+    { 0x20,0xac,0x66,0xc9 }, { 0xce,0x3a,0xb4,0x7d }, 
+    { 0xdf,0x4a,0x18,0x63 }, { 0x1a,0x31,0x82,0xe5 },
+    { 0x51,0x33,0x60,0x97 }, { 0x53,0x7f,0x45,0x62 }, 
+    { 0x64,0x77,0xe0,0xb1 }, { 0x6b,0xae,0x84,0xbb },
+    { 0x81,0xa0,0x1c,0xfe }, { 0x08,0x2b,0x94,0xf9 }, 
+    { 0x48,0x68,0x58,0x70 }, { 0x45,0xfd,0x19,0x8f },
+    { 0xde,0x6c,0x87,0x94 }, { 0x7b,0xf8,0xb7,0x52 }, 
+    { 0x73,0xd3,0x23,0xab }, { 0x4b,0x02,0xe2,0x72 },
+    { 0x1f,0x8f,0x57,0xe3 }, { 0x55,0xab,0x2a,0x66 }, 
+    { 0xeb,0x28,0x07,0xb2 }, { 0xb5,0xc2,0x03,0x2f },
+    { 0xc5,0x7b,0x9a,0x86 }, { 0x37,0x08,0xa5,0xd3 }, 
+    { 0x28,0x87,0xf2,0x30 }, { 0xbf,0xa5,0xb2,0x23 },
+    { 0x03,0x6a,0xba,0x02 }, { 0x16,0x82,0x5c,0xed }, 
+    { 0xcf,0x1c,0x2b,0x8a }, { 0x79,0xb4,0x92,0xa7 },
+    { 0x07,0xf2,0xf0,0xf3 }, { 0x69,0xe2,0xa1,0x4e }, 
+    { 0xda,0xf4,0xcd,0x65 }, { 0x05,0xbe,0xd5,0x06 },
+    { 0x34,0x62,0x1f,0xd1 }, { 0xa6,0xfe,0x8a,0xc4 }, 
+    { 0x2e,0x53,0x9d,0x34 }, { 0xf3,0x55,0xa0,0xa2 },
+    { 0x8a,0xe1,0x32,0x05 }, { 0xf6,0xeb,0x75,0xa4 }, 
+    { 0x83,0xec,0x39,0x0b }, { 0x60,0xef,0xaa,0x40 },
+    { 0x71,0x9f,0x06,0x5e }, { 0x6e,0x10,0x51,0xbd }, 
+    { 0x21,0x8a,0xf9,0x3e }, { 0xdd,0x06,0x3d,0x96 },
+    { 0x3e,0x05,0xae,0xdd }, { 0xe6,0xbd,0x46,0x4d }, 
+    { 0x54,0x8d,0xb5,0x91 }, { 0xc4,0x5d,0x05,0x71 },
+    { 0x06,0xd4,0x6f,0x04 }, { 0x50,0x15,0xff,0x60 }, 
+    { 0x98,0xfb,0x24,0x19 }, { 0xbd,0xe9,0x97,0xd6 },
+    { 0x40,0x43,0xcc,0x89 }, { 0xd9,0x9e,0x77,0x67 }, 
+    { 0xe8,0x42,0xbd,0xb0 }, { 0x89,0x8b,0x88,0x07 },
+    { 0x19,0x5b,0x38,0xe7 }, { 0xc8,0xee,0xdb,0x79 }, 
+    { 0x7c,0x0a,0x47,0xa1 }, { 0x42,0x0f,0xe9,0x7c },
+    { 0x84,0x1e,0xc9,0xf8 }, { 0x00,0x00,0x00,0x00 }, 
+    { 0x80,0x86,0x83,0x09 }, { 0x2b,0xed,0x48,0x32 },
+    { 0x11,0x70,0xac,0x1e }, { 0x5a,0x72,0x4e,0x6c }, 
+    { 0x0e,0xff,0xfb,0xfd }, { 0x85,0x38,0x56,0x0f }, 
+    { 0xae,0xd5,0x1e,0x3d }, { 0x2d,0x39,0x27,0x36 }, 
+    { 0x0f,0xd9,0x64,0x0a }, { 0x5c,0xa6,0x21,0x68 },
+    { 0x5b,0x54,0xd1,0x9b }, { 0x36,0x2e,0x3a,0x24 }, 
+    { 0x0a,0x67,0xb1,0x0c }, { 0x57,0xe7,0x0f,0x93 },
+    { 0xee,0x96,0xd2,0xb4 }, { 0x9b,0x91,0x9e,0x1b }, 
+    { 0xc0,0xc5,0x4f,0x80 }, { 0xdc,0x20,0xa2,0x61 },
+    { 0x77,0x4b,0x69,0x5a }, { 0x12,0x1a,0x16,0x1c }, 
+    { 0x93,0xba,0x0a,0xe2 }, { 0xa0,0x2a,0xe5,0xc0 },
+    { 0x22,0xe0,0x43,0x3c }, { 0x1b,0x17,0x1d,0x12 }, 
+    { 0x09,0x0d,0x0b,0x0e }, { 0x8b,0xc7,0xad,0xf2 },
+    { 0xb6,0xa8,0xb9,0x2d }, { 0x1e,0xa9,0xc8,0x14 }, 
+    { 0xf1,0x19,0x85,0x57 }, { 0x75,0x07,0x4c,0xaf },
+    { 0x99,0xdd,0xbb,0xee }, { 0x7f,0x60,0xfd,0xa3 }, 
+    { 0x01,0x26,0x9f,0xf7 }, { 0x72,0xf5,0xbc,0x5c },
+    { 0x66,0x3b,0xc5,0x44 }, { 0xfb,0x7e,0x34,0x5b }, 
+    { 0x43,0x29,0x76,0x8b }, { 0x23,0xc6,0xdc,0xcb },
+    { 0xed,0xfc,0x68,0xb6 }, { 0xe4,0xf1,0x63,0xb8 }, 
+    { 0x31,0xdc,0xca,0xd7 }, { 0x63,0x85,0x10,0x42 },
+    { 0x97,0x22,0x40,0x13 }, { 0xc6,0x11,0x20,0x84 }, 
+    { 0x4a,0x24,0x7d,0x85 }, { 0xbb,0x3d,0xf8,0xd2 }, 
+    { 0xf9,0x32,0x11,0xae }, { 0x29,0xa1,0x6d,0xc7 }, 
+    { 0x9e,0x2f,0x4b,0x1d }, { 0xb2,0x30,0xf3,0xdc },
+    { 0x86,0x52,0xec,0x0d }, { 0xc1,0xe3,0xd0,0x77 }, 
+    { 0xb3,0x16,0x6c,0x2b }, { 0x70,0xb9,0x99,0xa9 },
+    { 0x94,0x48,0xfa,0x11 }, { 0xe9,0x64,0x22,0x47 }, 
+    { 0xfc,0x8c,0xc4,0xa8 }, { 0xf0,0x3f,0x1a,0xa0 },
+    { 0x7d,0x2c,0xd8,0x56 }, { 0x33,0x90,0xef,0x22 }, 
+    { 0x49,0x4e,0xc7,0x87 }, { 0x38,0xd1,0xc1,0xd9 },
+    { 0xca,0xa2,0xfe,0x8c }, { 0xd4,0x0b,0x36,0x98 }, 
+    { 0xf5,0x81,0xcf,0xa6 }, { 0x7a,0xde,0x28,0xa5 },
+    { 0xb7,0x8e,0x26,0xda }, { 0xad,0xbf,0xa4,0x3f }, 
+    { 0x3a,0x9d,0xe4,0x2c }, { 0x78,0x92,0x0d,0x50 },
+    { 0x5f,0xcc,0x9b,0x6a }, { 0x7e,0x46,0x62,0x54 }, 
+    { 0x8d,0x13,0xc2,0xf6 }, { 0xd8,0xb8,0xe8,0x90 },
+    { 0x39,0xf7,0x5e,0x2e }, { 0xc3,0xaf,0xf5,0x82 }, 
+    { 0x5d,0x80,0xbe,0x9f }, { 0xd0,0x93,0x7c,0x69 },
+    { 0xd5,0x2d,0xa9,0x6f }, { 0x25,0x12,0xb3,0xcf }, 
+    { 0xac,0x99,0x3b,0xc8 }, { 0x18,0x7d,0xa7,0x10 },
+    { 0x9c,0x63,0x6e,0xe8 }, { 0x3b,0xbb,0x7b,0xdb }, 
+    { 0x26,0x78,0x09,0xcd }, { 0x59,0x18,0xf4,0x6e },
+    { 0x9a,0xb7,0x01,0xec }, { 0x4f,0x9a,0xa8,0x83 }, 
+    { 0x95,0x6e,0x65,0xe6 }, { 0xff,0xe6,0x7e,0xaa },
+    { 0xbc,0xcf,0x08,0x21 }, { 0x15,0xe8,0xe6,0xef }, 
+    { 0xe7,0x9b,0xd9,0xba }, { 0x6f,0x36,0xce,0x4a },
+    { 0x9f,0x09,0xd4,0xea }, { 0xb0,0x7c,0xd6,0x29 }, 
+    { 0xa4,0xb2,0xaf,0x31 }, { 0x3f,0x23,0x31,0x2a },
+    { 0xa5,0x94,0x30,0xc6 }, { 0xa2,0x66,0xc0,0x35 }, 
+    { 0x4e,0xbc,0x37,0x74 }, { 0x82,0xca,0xa6,0xfc },
+    { 0x90,0xd0,0xb0,0xe0 }, { 0xa7,0xd8,0x15,0x33 }, 
+    { 0x04,0x98,0x4a,0xf1 }, { 0xec,0xda,0xf7,0x41 },
+    { 0xcd,0x50,0x0e,0x7f }, { 0x91,0xf6,0x2f,0x17 }, 
+    { 0x4d,0xd6,0x8d,0x76 }, { 0xef,0xb0,0x4d,0x43 }, 
+    { 0xaa,0x4d,0x54,0xcc }, { 0x96,0x04,0xdf,0xe4 }, 
+    { 0xd1,0xb5,0xe3,0x9e }, { 0x6a,0x88,0x1b,0x4c },
+    { 0x2c,0x1f,0xb8,0xc1 }, { 0x65,0x51,0x7f,0x46 }, 
+    { 0x5e,0xea,0x04,0x9d }, { 0x8c,0x35,0x5d,0x01 },
+    { 0x87,0x74,0x73,0xfa }, { 0x0b,0x41,0x2e,0xfb }, 
+    { 0x67,0x1d,0x5a,0xb3 }, { 0xdb,0xd2,0x52,0x92 },
+    { 0x10,0x56,0x33,0xe9 }, { 0xd6,0x47,0x13,0x6d }, 
+    { 0xd7,0x61,0x8c,0x9a }, { 0xa1,0x0c,0x7a,0x37 },
+    { 0xf8,0x14,0x8e,0x59 }, { 0x13,0x3c,0x89,0xeb }, 
+    { 0xa9,0x27,0xee,0xce }, { 0x61,0xc9,0x35,0xb7 },
+    { 0x1c,0xe5,0xed,0xe1 }, { 0x47,0xb1,0x3c,0x7a }, 
+    { 0xd2,0xdf,0x59,0x9c }, { 0xf2,0x73,0x3f,0x55 },
+    { 0x14,0xce,0x79,0x18 }, { 0xc7,0x37,0xbf,0x73 }, 
+    { 0xf7,0xcd,0xea,0x53 }, { 0xfd,0xaa,0x5b,0x5f },
+    { 0x3d,0x6f,0x14,0xdf }, { 0x44,0xdb,0x86,0x78 }, 
+    { 0xaf,0xf3,0x81,0xca }, { 0x68,0xc4,0x3e,0xb9 },
+    { 0x24,0x34,0x2c,0x38 }, { 0xa3,0x40,0x5f,0xc2 }, 
+    { 0x1d,0xc3,0x72,0x16 }, { 0xe2,0x25,0x0c,0xbc },
+    { 0x3c,0x49,0x8b,0x28 }, { 0x0d,0x95,0x41,0xff }, 
+    { 0xa8,0x01,0x71,0x39 }, { 0x0c,0xb3,0xde,0x08 },
+    { 0xb4,0xe4,0x9c,0xd8 }, { 0x56,0xc1,0x90,0x64 }, 
+    { 0xcb,0x84,0x61,0x7b }, { 0x32,0xb6,0x70,0xd5 },
+    { 0x6c,0x5c,0x74,0x48 }, { 0xb8,0x57,0x42,0xd0 }
+  };
+
+static const unsigned char S5[256] = 
+  {
+    0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
+    0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
+    0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,
+    0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
+    0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,
+    0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
+    0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,
+    0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
+    0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,
+    0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
+    0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,
+    0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
+    0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,
+    0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
+    0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,
+    0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
+    0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,
+    0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
+    0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,
+    0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
+    0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,
+    0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
+    0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,
+    0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
+    0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,
+    0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
+    0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,
+    0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
+    0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,
+    0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
+    0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
+    0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+  };
+
+static const unsigned char U1[256][4] = 
+  {
+    { 0x00,0x00,0x00,0x00 }, { 0x0e,0x09,0x0d,0x0b },
+    { 0x1c,0x12,0x1a,0x16 }, { 0x12,0x1b,0x17,0x1d }, 
+    { 0x38,0x24,0x34,0x2c }, { 0x36,0x2d,0x39,0x27 },
+    { 0x24,0x36,0x2e,0x3a }, { 0x2a,0x3f,0x23,0x31 }, 
+    { 0x70,0x48,0x68,0x58 }, { 0x7e,0x41,0x65,0x53 },
+    { 0x6c,0x5a,0x72,0x4e }, { 0x62,0x53,0x7f,0x45 }, 
+    { 0x48,0x6c,0x5c,0x74 }, { 0x46,0x65,0x51,0x7f },
+    { 0x54,0x7e,0x46,0x62 }, { 0x5a,0x77,0x4b,0x69 }, 
+    { 0xe0,0x90,0xd0,0xb0 }, { 0xee,0x99,0xdd,0xbb },
+    { 0xfc,0x82,0xca,0xa6 }, { 0xf2,0x8b,0xc7,0xad }, 
+    { 0xd8,0xb4,0xe4,0x9c }, { 0xd6,0xbd,0xe9,0x97 },
+    { 0xc4,0xa6,0xfe,0x8a }, { 0xca,0xaf,0xf3,0x81 }, 
+    { 0x90,0xd8,0xb8,0xe8 }, { 0x9e,0xd1,0xb5,0xe3 },
+    { 0x8c,0xca,0xa2,0xfe }, { 0x82,0xc3,0xaf,0xf5 }, 
+    { 0xa8,0xfc,0x8c,0xc4 }, { 0xa6,0xf5,0x81,0xcf },
+    { 0xb4,0xee,0x96,0xd2 }, { 0xba,0xe7,0x9b,0xd9 }, 
+    { 0xdb,0x3b,0xbb,0x7b }, { 0xd5,0x32,0xb6,0x70 },
+    { 0xc7,0x29,0xa1,0x6d }, { 0xc9,0x20,0xac,0x66 }, 
+    { 0xe3,0x1f,0x8f,0x57 }, { 0xed,0x16,0x82,0x5c },
+    { 0xff,0x0d,0x95,0x41 }, { 0xf1,0x04,0x98,0x4a }, 
+    { 0xab,0x73,0xd3,0x23 }, { 0xa5,0x7a,0xde,0x28 },
+    { 0xb7,0x61,0xc9,0x35 }, { 0xb9,0x68,0xc4,0x3e }, 
+    { 0x93,0x57,0xe7,0x0f }, { 0x9d,0x5e,0xea,0x04 },
+    { 0x8f,0x45,0xfd,0x19 }, { 0x81,0x4c,0xf0,0x12 }, 
+    { 0x3b,0xab,0x6b,0xcb }, { 0x35,0xa2,0x66,0xc0 },
+    { 0x27,0xb9,0x71,0xdd }, { 0x29,0xb0,0x7c,0xd6 }, 
+    { 0x03,0x8f,0x5f,0xe7 }, { 0x0d,0x86,0x52,0xec },
+    { 0x1f,0x9d,0x45,0xf1 }, { 0x11,0x94,0x48,0xfa }, 
+    { 0x4b,0xe3,0x03,0x93 }, { 0x45,0xea,0x0e,0x98 },
+    { 0x57,0xf1,0x19,0x85 }, { 0x59,0xf8,0x14,0x8e }, 
+    { 0x73,0xc7,0x37,0xbf }, { 0x7d,0xce,0x3a,0xb4 },
+    { 0x6f,0xd5,0x2d,0xa9 }, { 0x61,0xdc,0x20,0xa2 }, 
+    { 0xad,0x76,0x6d,0xf6 }, { 0xa3,0x7f,0x60,0xfd },
+    { 0xb1,0x64,0x77,0xe0 }, { 0xbf,0x6d,0x7a,0xeb }, 
+    { 0x95,0x52,0x59,0xda }, { 0x9b,0x5b,0x54,0xd1 },
+    { 0x89,0x40,0x43,0xcc }, { 0x87,0x49,0x4e,0xc7 }, 
+    { 0xdd,0x3e,0x05,0xae }, { 0xd3,0x37,0x08,0xa5 },
+    { 0xc1,0x2c,0x1f,0xb8 }, { 0xcf,0x25,0x12,0xb3 }, 
+    { 0xe5,0x1a,0x31,0x82 }, { 0xeb,0x13,0x3c,0x89 },
+    { 0xf9,0x08,0x2b,0x94 }, { 0xf7,0x01,0x26,0x9f }, 
+    { 0x4d,0xe6,0xbd,0x46 }, { 0x43,0xef,0xb0,0x4d },
+    { 0x51,0xf4,0xa7,0x50 }, { 0x5f,0xfd,0xaa,0x5b }, 
+    { 0x75,0xc2,0x89,0x6a }, { 0x7b,0xcb,0x84,0x61 },
+    { 0x69,0xd0,0x93,0x7c }, { 0x67,0xd9,0x9e,0x77 }, 
+    { 0x3d,0xae,0xd5,0x1e }, { 0x33,0xa7,0xd8,0x15 },
+    { 0x21,0xbc,0xcf,0x08 }, { 0x2f,0xb5,0xc2,0x03 }, 
+    { 0x05,0x8a,0xe1,0x32 }, { 0x0b,0x83,0xec,0x39 },
+    { 0x19,0x98,0xfb,0x24 }, { 0x17,0x91,0xf6,0x2f }, 
+    { 0x76,0x4d,0xd6,0x8d }, { 0x78,0x44,0xdb,0x86 },
+    { 0x6a,0x5f,0xcc,0x9b }, { 0x64,0x56,0xc1,0x90 }, 
+    { 0x4e,0x69,0xe2,0xa1 }, { 0x40,0x60,0xef,0xaa },
+    { 0x52,0x7b,0xf8,0xb7 }, { 0x5c,0x72,0xf5,0xbc }, 
+    { 0x06,0x05,0xbe,0xd5 }, { 0x08,0x0c,0xb3,0xde },
+    { 0x1a,0x17,0xa4,0xc3 }, { 0x14,0x1e,0xa9,0xc8 }, 
+    { 0x3e,0x21,0x8a,0xf9 }, { 0x30,0x28,0x87,0xf2 },
+    { 0x22,0x33,0x90,0xef }, { 0x2c,0x3a,0x9d,0xe4 }, 
+    { 0x96,0xdd,0x06,0x3d }, { 0x98,0xd4,0x0b,0x36 },
+    { 0x8a,0xcf,0x1c,0x2b }, { 0x84,0xc6,0x11,0x20 }, 
+    { 0xae,0xf9,0x32,0x11 }, { 0xa0,0xf0,0x3f,0x1a },
+    { 0xb2,0xeb,0x28,0x07 }, { 0xbc,0xe2,0x25,0x0c }, 
+    { 0xe6,0x95,0x6e,0x65 }, { 0xe8,0x9c,0x63,0x6e },
+    { 0xfa,0x87,0x74,0x73 }, { 0xf4,0x8e,0x79,0x78 }, 
+    { 0xde,0xb1,0x5a,0x49 }, { 0xd0,0xb8,0x57,0x42 },
+    { 0xc2,0xa3,0x40,0x5f }, { 0xcc,0xaa,0x4d,0x54 }, 
+    { 0x41,0xec,0xda,0xf7 }, { 0x4f,0xe5,0xd7,0xfc },
+    { 0x5d,0xfe,0xc0,0xe1 }, { 0x53,0xf7,0xcd,0xea }, 
+    { 0x79,0xc8,0xee,0xdb }, { 0x77,0xc1,0xe3,0xd0 },
+    { 0x65,0xda,0xf4,0xcd }, { 0x6b,0xd3,0xf9,0xc6 }, 
+    { 0x31,0xa4,0xb2,0xaf }, { 0x3f,0xad,0xbf,0xa4 },
+    { 0x2d,0xb6,0xa8,0xb9 }, { 0x23,0xbf,0xa5,0xb2 }, 
+    { 0x09,0x80,0x86,0x83 }, { 0x07,0x89,0x8b,0x88 },
+    { 0x15,0x92,0x9c,0x95 }, { 0x1b,0x9b,0x91,0x9e }, 
+    { 0xa1,0x7c,0x0a,0x47 }, { 0xaf,0x75,0x07,0x4c },
+    { 0xbd,0x6e,0x10,0x51 }, { 0xb3,0x67,0x1d,0x5a }, 
+    { 0x99,0x58,0x3e,0x6b }, { 0x97,0x51,0x33,0x60 },
+    { 0x85,0x4a,0x24,0x7d }, { 0x8b,0x43,0x29,0x76 }, 
+    { 0xd1,0x34,0x62,0x1f }, { 0xdf,0x3d,0x6f,0x14 },
+    { 0xcd,0x26,0x78,0x09 }, { 0xc3,0x2f,0x75,0x02 }, 
+    { 0xe9,0x10,0x56,0x33 }, { 0xe7,0x19,0x5b,0x38 },
+    { 0xf5,0x02,0x4c,0x25 }, { 0xfb,0x0b,0x41,0x2e }, 
+    { 0x9a,0xd7,0x61,0x8c }, { 0x94,0xde,0x6c,0x87 }, 
+    { 0x86,0xc5,0x7b,0x9a }, { 0x88,0xcc,0x76,0x91 }, 
+    { 0xa2,0xf3,0x55,0xa0 }, { 0xac,0xfa,0x58,0xab },
+    { 0xbe,0xe1,0x4f,0xb6 }, { 0xb0,0xe8,0x42,0xbd }, 
+    { 0xea,0x9f,0x09,0xd4 }, { 0xe4,0x96,0x04,0xdf },
+    { 0xf6,0x8d,0x13,0xc2 }, { 0xf8,0x84,0x1e,0xc9 }, 
+    { 0xd2,0xbb,0x3d,0xf8 }, { 0xdc,0xb2,0x30,0xf3 },
+    { 0xce,0xa9,0x27,0xee }, { 0xc0,0xa0,0x2a,0xe5 }, 
+    { 0x7a,0x47,0xb1,0x3c }, { 0x74,0x4e,0xbc,0x37 }, 
+    { 0x66,0x55,0xab,0x2a }, { 0x68,0x5c,0xa6,0x21 }, 
+    { 0x42,0x63,0x85,0x10 }, { 0x4c,0x6a,0x88,0x1b },
+    { 0x5e,0x71,0x9f,0x06 }, { 0x50,0x78,0x92,0x0d }, 
+    { 0x0a,0x0f,0xd9,0x64 }, { 0x04,0x06,0xd4,0x6f },
+    { 0x16,0x1d,0xc3,0x72 }, { 0x18,0x14,0xce,0x79 }, 
+    { 0x32,0x2b,0xed,0x48 }, { 0x3c,0x22,0xe0,0x43 },
+    { 0x2e,0x39,0xf7,0x5e }, { 0x20,0x30,0xfa,0x55 }, 
+    { 0xec,0x9a,0xb7,0x01 }, { 0xe2,0x93,0xba,0x0a },
+    { 0xf0,0x88,0xad,0x17 }, { 0xfe,0x81,0xa0,0x1c }, 
+    { 0xd4,0xbe,0x83,0x2d }, { 0xda,0xb7,0x8e,0x26 },
+    { 0xc8,0xac,0x99,0x3b }, { 0xc6,0xa5,0x94,0x30 }, 
+    { 0x9c,0xd2,0xdf,0x59 }, { 0x92,0xdb,0xd2,0x52 },
+    { 0x80,0xc0,0xc5,0x4f }, { 0x8e,0xc9,0xc8,0x44 }, 
+    { 0xa4,0xf6,0xeb,0x75 }, { 0xaa,0xff,0xe6,0x7e },
+    { 0xb8,0xe4,0xf1,0x63 }, { 0xb6,0xed,0xfc,0x68 }, 
+    { 0x0c,0x0a,0x67,0xb1 }, { 0x02,0x03,0x6a,0xba },
+    { 0x10,0x18,0x7d,0xa7 }, { 0x1e,0x11,0x70,0xac }, 
+    { 0x34,0x2e,0x53,0x9d }, { 0x3a,0x27,0x5e,0x96 },
+    { 0x28,0x3c,0x49,0x8b }, { 0x26,0x35,0x44,0x80 }, 
+    { 0x7c,0x42,0x0f,0xe9 }, { 0x72,0x4b,0x02,0xe2 },
+    { 0x60,0x50,0x15,0xff }, { 0x6e,0x59,0x18,0xf4 }, 
+    { 0x44,0x66,0x3b,0xc5 }, { 0x4a,0x6f,0x36,0xce },
+    { 0x58,0x74,0x21,0xd3 }, { 0x56,0x7d,0x2c,0xd8 }, 
+    { 0x37,0xa1,0x0c,0x7a }, { 0x39,0xa8,0x01,0x71 },
+    { 0x2b,0xb3,0x16,0x6c }, { 0x25,0xba,0x1b,0x67 }, 
+    { 0x0f,0x85,0x38,0x56 }, { 0x01,0x8c,0x35,0x5d },
+    { 0x13,0x97,0x22,0x40 }, { 0x1d,0x9e,0x2f,0x4b }, 
+    { 0x47,0xe9,0x64,0x22 }, { 0x49,0xe0,0x69,0x29 },
+    { 0x5b,0xfb,0x7e,0x34 }, { 0x55,0xf2,0x73,0x3f }, 
+    { 0x7f,0xcd,0x50,0x0e }, { 0x71,0xc4,0x5d,0x05 },
+    { 0x63,0xdf,0x4a,0x18 }, { 0x6d,0xd6,0x47,0x13 }, 
+    { 0xd7,0x31,0xdc,0xca }, { 0xd9,0x38,0xd1,0xc1 },
+    { 0xcb,0x23,0xc6,0xdc }, { 0xc5,0x2a,0xcb,0xd7 }, 
+    { 0xef,0x15,0xe8,0xe6 }, { 0xe1,0x1c,0xe5,0xed },
+    { 0xf3,0x07,0xf2,0xf0 }, { 0xfd,0x0e,0xff,0xfb }, 
+    { 0xa7,0x79,0xb4,0x92 }, { 0xa9,0x70,0xb9,0x99 },
+    { 0xbb,0x6b,0xae,0x84 }, { 0xb5,0x62,0xa3,0x8f }, 
+    { 0x9f,0x5d,0x80,0xbe }, { 0x91,0x54,0x8d,0xb5 },
+    { 0x83,0x4f,0x9a,0xa8 }, { 0x8d,0x46,0x97,0xa3 }
+  };
+
+static const unsigned char U2[256][4] = 
+  {
+    { 0x00,0x00,0x00,0x00 }, { 0x0b,0x0e,0x09,0x0d },
+    { 0x16,0x1c,0x12,0x1a }, { 0x1d,0x12,0x1b,0x17 }, 
+    { 0x2c,0x38,0x24,0x34 }, { 0x27,0x36,0x2d,0x39 },
+    { 0x3a,0x24,0x36,0x2e }, { 0x31,0x2a,0x3f,0x23 }, 
+    { 0x58,0x70,0x48,0x68 }, { 0x53,0x7e,0x41,0x65 }, 
+    { 0x4e,0x6c,0x5a,0x72 }, { 0x45,0x62,0x53,0x7f }, 
+    { 0x74,0x48,0x6c,0x5c }, { 0x7f,0x46,0x65,0x51 },
+    { 0x62,0x54,0x7e,0x46 }, { 0x69,0x5a,0x77,0x4b }, 
+    { 0xb0,0xe0,0x90,0xd0 }, { 0xbb,0xee,0x99,0xdd }, 
+    { 0xa6,0xfc,0x82,0xca }, { 0xad,0xf2,0x8b,0xc7 }, 
+    { 0x9c,0xd8,0xb4,0xe4 }, { 0x97,0xd6,0xbd,0xe9 }, 
+    { 0x8a,0xc4,0xa6,0xfe }, { 0x81,0xca,0xaf,0xf3 }, 
+    { 0xe8,0x90,0xd8,0xb8 }, { 0xe3,0x9e,0xd1,0xb5 },
+    { 0xfe,0x8c,0xca,0xa2 }, { 0xf5,0x82,0xc3,0xaf }, 
+    { 0xc4,0xa8,0xfc,0x8c }, { 0xcf,0xa6,0xf5,0x81 }, 
+    { 0xd2,0xb4,0xee,0x96 }, { 0xd9,0xba,0xe7,0x9b }, 
+    { 0x7b,0xdb,0x3b,0xbb }, { 0x70,0xd5,0x32,0xb6 }, 
+    { 0x6d,0xc7,0x29,0xa1 }, { 0x66,0xc9,0x20,0xac }, 
+    { 0x57,0xe3,0x1f,0x8f }, { 0x5c,0xed,0x16,0x82 }, 
+    { 0x41,0xff,0x0d,0x95 }, { 0x4a,0xf1,0x04,0x98 }, 
+    { 0x23,0xab,0x73,0xd3 }, { 0x28,0xa5,0x7a,0xde },
+    { 0x35,0xb7,0x61,0xc9 }, { 0x3e,0xb9,0x68,0xc4 }, 
+    { 0x0f,0x93,0x57,0xe7 }, { 0x04,0x9d,0x5e,0xea },
+    { 0x19,0x8f,0x45,0xfd }, { 0x12,0x81,0x4c,0xf0 }, 
+    { 0xcb,0x3b,0xab,0x6b }, { 0xc0,0x35,0xa2,0x66 },
+    { 0xdd,0x27,0xb9,0x71 }, { 0xd6,0x29,0xb0,0x7c }, 
+    { 0xe7,0x03,0x8f,0x5f }, { 0xec,0x0d,0x86,0x52 },
+    { 0xf1,0x1f,0x9d,0x45 }, { 0xfa,0x11,0x94,0x48 }, 
+    { 0x93,0x4b,0xe3,0x03 }, { 0x98,0x45,0xea,0x0e }, 
+    { 0x85,0x57,0xf1,0x19 }, { 0x8e,0x59,0xf8,0x14 }, 
+    { 0xbf,0x73,0xc7,0x37 }, { 0xb4,0x7d,0xce,0x3a },
+    { 0xa9,0x6f,0xd5,0x2d }, { 0xa2,0x61,0xdc,0x20 }, 
+    { 0xf6,0xad,0x76,0x6d }, { 0xfd,0xa3,0x7f,0x60 }, 
+    { 0xe0,0xb1,0x64,0x77 }, { 0xeb,0xbf,0x6d,0x7a }, 
+    { 0xda,0x95,0x52,0x59 }, { 0xd1,0x9b,0x5b,0x54 }, 
+    { 0xcc,0x89,0x40,0x43 }, { 0xc7,0x87,0x49,0x4e }, 
+    { 0xae,0xdd,0x3e,0x05 }, { 0xa5,0xd3,0x37,0x08 },
+    { 0xb8,0xc1,0x2c,0x1f }, { 0xb3,0xcf,0x25,0x12 }, 
+    { 0x82,0xe5,0x1a,0x31 }, { 0x89,0xeb,0x13,0x3c },
+    { 0x94,0xf9,0x08,0x2b }, { 0x9f,0xf7,0x01,0x26 }, 
+    { 0x46,0x4d,0xe6,0xbd }, { 0x4d,0x43,0xef,0xb0 },
+    { 0x50,0x51,0xf4,0xa7 }, { 0x5b,0x5f,0xfd,0xaa }, 
+    { 0x6a,0x75,0xc2,0x89 }, { 0x61,0x7b,0xcb,0x84 },
+    { 0x7c,0x69,0xd0,0x93 }, { 0x77,0x67,0xd9,0x9e }, 
+    { 0x1e,0x3d,0xae,0xd5 }, { 0x15,0x33,0xa7,0xd8 },
+    { 0x08,0x21,0xbc,0xcf }, { 0x03,0x2f,0xb5,0xc2 }, 
+    { 0x32,0x05,0x8a,0xe1 }, { 0x39,0x0b,0x83,0xec },
+    { 0x24,0x19,0x98,0xfb }, { 0x2f,0x17,0x91,0xf6 }, 
+    { 0x8d,0x76,0x4d,0xd6 }, { 0x86,0x78,0x44,0xdb },
+    { 0x9b,0x6a,0x5f,0xcc }, { 0x90,0x64,0x56,0xc1 }, 
+    { 0xa1,0x4e,0x69,0xe2 }, { 0xaa,0x40,0x60,0xef },
+    { 0xb7,0x52,0x7b,0xf8 }, { 0xbc,0x5c,0x72,0xf5 }, 
+    { 0xd5,0x06,0x05,0xbe }, { 0xde,0x08,0x0c,0xb3 },
+    { 0xc3,0x1a,0x17,0xa4 }, { 0xc8,0x14,0x1e,0xa9 }, 
+    { 0xf9,0x3e,0x21,0x8a }, { 0xf2,0x30,0x28,0x87 },
+    { 0xef,0x22,0x33,0x90 }, { 0xe4,0x2c,0x3a,0x9d }, 
+    { 0x3d,0x96,0xdd,0x06 }, { 0x36,0x98,0xd4,0x0b },
+    { 0x2b,0x8a,0xcf,0x1c }, { 0x20,0x84,0xc6,0x11 }, 
+    { 0x11,0xae,0xf9,0x32 }, { 0x1a,0xa0,0xf0,0x3f },
+    { 0x07,0xb2,0xeb,0x28 }, { 0x0c,0xbc,0xe2,0x25 }, 
+    { 0x65,0xe6,0x95,0x6e }, { 0x6e,0xe8,0x9c,0x63 },
+    { 0x73,0xfa,0x87,0x74 }, { 0x78,0xf4,0x8e,0x79 }, 
+    { 0x49,0xde,0xb1,0x5a }, { 0x42,0xd0,0xb8,0x57 },
+    { 0x5f,0xc2,0xa3,0x40 }, { 0x54,0xcc,0xaa,0x4d }, 
+    { 0xf7,0x41,0xec,0xda }, { 0xfc,0x4f,0xe5,0xd7 },
+    { 0xe1,0x5d,0xfe,0xc0 }, { 0xea,0x53,0xf7,0xcd }, 
+    { 0xdb,0x79,0xc8,0xee }, { 0xd0,0x77,0xc1,0xe3 },
+    { 0xcd,0x65,0xda,0xf4 }, { 0xc6,0x6b,0xd3,0xf9 }, 
+    { 0xaf,0x31,0xa4,0xb2 }, { 0xa4,0x3f,0xad,0xbf },
+    { 0xb9,0x2d,0xb6,0xa8 }, { 0xb2,0x23,0xbf,0xa5 }, 
+    { 0x83,0x09,0x80,0x86 }, { 0x88,0x07,0x89,0x8b },
+    { 0x95,0x15,0x92,0x9c }, { 0x9e,0x1b,0x9b,0x91 }, 
+    { 0x47,0xa1,0x7c,0x0a }, { 0x4c,0xaf,0x75,0x07 },
+    { 0x51,0xbd,0x6e,0x10 }, { 0x5a,0xb3,0x67,0x1d }, 
+    { 0x6b,0x99,0x58,0x3e }, { 0x60,0x97,0x51,0x33 },
+    { 0x7d,0x85,0x4a,0x24 }, { 0x76,0x8b,0x43,0x29 }, 
+    { 0x1f,0xd1,0x34,0x62 }, { 0x14,0xdf,0x3d,0x6f },
+    { 0x09,0xcd,0x26,0x78 }, { 0x02,0xc3,0x2f,0x75 }, 
+    { 0x33,0xe9,0x10,0x56 }, { 0x38,0xe7,0x19,0x5b },
+    { 0x25,0xf5,0x02,0x4c }, { 0x2e,0xfb,0x0b,0x41 }, 
+    { 0x8c,0x9a,0xd7,0x61 }, { 0x87,0x94,0xde,0x6c },
+    { 0x9a,0x86,0xc5,0x7b }, { 0x91,0x88,0xcc,0x76 }, 
+    { 0xa0,0xa2,0xf3,0x55 }, { 0xab,0xac,0xfa,0x58 },
+    { 0xb6,0xbe,0xe1,0x4f }, { 0xbd,0xb0,0xe8,0x42 }, 
+    { 0xd4,0xea,0x9f,0x09 }, { 0xdf,0xe4,0x96,0x04 },
+    { 0xc2,0xf6,0x8d,0x13 }, { 0xc9,0xf8,0x84,0x1e }, 
+    { 0xf8,0xd2,0xbb,0x3d }, { 0xf3,0xdc,0xb2,0x30 },
+    { 0xee,0xce,0xa9,0x27 }, { 0xe5,0xc0,0xa0,0x2a }, 
+    { 0x3c,0x7a,0x47,0xb1 }, { 0x37,0x74,0x4e,0xbc },
+    { 0x2a,0x66,0x55,0xab }, { 0x21,0x68,0x5c,0xa6 }, 
+    { 0x10,0x42,0x63,0x85 }, { 0x1b,0x4c,0x6a,0x88 },
+    { 0x06,0x5e,0x71,0x9f }, { 0x0d,0x50,0x78,0x92 }, 
+    { 0x64,0x0a,0x0f,0xd9 }, { 0x6f,0x04,0x06,0xd4 },
+    { 0x72,0x16,0x1d,0xc3 }, { 0x79,0x18,0x14,0xce }, 
+    { 0x48,0x32,0x2b,0xed }, { 0x43,0x3c,0x22,0xe0 },
+    { 0x5e,0x2e,0x39,0xf7 }, { 0x55,0x20,0x30,0xfa }, 
+    { 0x01,0xec,0x9a,0xb7 }, { 0x0a,0xe2,0x93,0xba },
+    { 0x17,0xf0,0x88,0xad }, { 0x1c,0xfe,0x81,0xa0 }, 
+    { 0x2d,0xd4,0xbe,0x83 }, { 0x26,0xda,0xb7,0x8e },
+    { 0x3b,0xc8,0xac,0x99 }, { 0x30,0xc6,0xa5,0x94 }, 
+    { 0x59,0x9c,0xd2,0xdf }, { 0x52,0x92,0xdb,0xd2 },
+    { 0x4f,0x80,0xc0,0xc5 }, { 0x44,0x8e,0xc9,0xc8 }, 
+    { 0x75,0xa4,0xf6,0xeb }, { 0x7e,0xaa,0xff,0xe6 },
+    { 0x63,0xb8,0xe4,0xf1 }, { 0x68,0xb6,0xed,0xfc }, 
+    { 0xb1,0x0c,0x0a,0x67 }, { 0xba,0x02,0x03,0x6a },
+    { 0xa7,0x10,0x18,0x7d }, { 0xac,0x1e,0x11,0x70 }, 
+    { 0x9d,0x34,0x2e,0x53 }, { 0x96,0x3a,0x27,0x5e },
+    { 0x8b,0x28,0x3c,0x49 }, { 0x80,0x26,0x35,0x44 }, 
+    { 0xe9,0x7c,0x42,0x0f }, { 0xe2,0x72,0x4b,0x02 },
+    { 0xff,0x60,0x50,0x15 }, { 0xf4,0x6e,0x59,0x18 }, 
+    { 0xc5,0x44,0x66,0x3b }, { 0xce,0x4a,0x6f,0x36 },
+    { 0xd3,0x58,0x74,0x21 }, { 0xd8,0x56,0x7d,0x2c }, 
+    { 0x7a,0x37,0xa1,0x0c }, { 0x71,0x39,0xa8,0x01 },
+    { 0x6c,0x2b,0xb3,0x16 }, { 0x67,0x25,0xba,0x1b }, 
+    { 0x56,0x0f,0x85,0x38 }, { 0x5d,0x01,0x8c,0x35 },
+    { 0x40,0x13,0x97,0x22 }, { 0x4b,0x1d,0x9e,0x2f }, 
+    { 0x22,0x47,0xe9,0x64 }, { 0x29,0x49,0xe0,0x69 },
+    { 0x34,0x5b,0xfb,0x7e }, { 0x3f,0x55,0xf2,0x73 }, 
+    { 0x0e,0x7f,0xcd,0x50 }, { 0x05,0x71,0xc4,0x5d },
+    { 0x18,0x63,0xdf,0x4a }, { 0x13,0x6d,0xd6,0x47 }, 
+    { 0xca,0xd7,0x31,0xdc }, { 0xc1,0xd9,0x38,0xd1 },
+    { 0xdc,0xcb,0x23,0xc6 }, { 0xd7,0xc5,0x2a,0xcb }, 
+    { 0xe6,0xef,0x15,0xe8 }, { 0xed,0xe1,0x1c,0xe5 },
+    { 0xf0,0xf3,0x07,0xf2 }, { 0xfb,0xfd,0x0e,0xff }, 
+    { 0x92,0xa7,0x79,0xb4 }, { 0x99,0xa9,0x70,0xb9 },
+    { 0x84,0xbb,0x6b,0xae }, { 0x8f,0xb5,0x62,0xa3 }, 
+    { 0xbe,0x9f,0x5d,0x80 }, { 0xb5,0x91,0x54,0x8d },
+    { 0xa8,0x83,0x4f,0x9a }, { 0xa3,0x8d,0x46,0x97 }
+  };
+
+static const unsigned char U3[256][4] = 
+  {
+    { 0x00,0x00,0x00,0x00 }, { 0x0d,0x0b,0x0e,0x09 },
+    { 0x1a,0x16,0x1c,0x12 }, { 0x17,0x1d,0x12,0x1b }, 
+    { 0x34,0x2c,0x38,0x24 }, { 0x39,0x27,0x36,0x2d },
+    { 0x2e,0x3a,0x24,0x36 }, { 0x23,0x31,0x2a,0x3f }, 
+    { 0x68,0x58,0x70,0x48 }, { 0x65,0x53,0x7e,0x41 },
+    { 0x72,0x4e,0x6c,0x5a }, { 0x7f,0x45,0x62,0x53 }, 
+    { 0x5c,0x74,0x48,0x6c }, { 0x51,0x7f,0x46,0x65 },
+    { 0x46,0x62,0x54,0x7e }, { 0x4b,0x69,0x5a,0x77 }, 
+    { 0xd0,0xb0,0xe0,0x90 }, { 0xdd,0xbb,0xee,0x99 },
+    { 0xca,0xa6,0xfc,0x82 }, { 0xc7,0xad,0xf2,0x8b }, 
+    { 0xe4,0x9c,0xd8,0xb4 }, { 0xe9,0x97,0xd6,0xbd },
+    { 0xfe,0x8a,0xc4,0xa6 }, { 0xf3,0x81,0xca,0xaf }, 
+    { 0xb8,0xe8,0x90,0xd8 }, { 0xb5,0xe3,0x9e,0xd1 },
+    { 0xa2,0xfe,0x8c,0xca }, { 0xaf,0xf5,0x82,0xc3 }, 
+    { 0x8c,0xc4,0xa8,0xfc }, { 0x81,0xcf,0xa6,0xf5 },
+    { 0x96,0xd2,0xb4,0xee }, { 0x9b,0xd9,0xba,0xe7 }, 
+    { 0xbb,0x7b,0xdb,0x3b }, { 0xb6,0x70,0xd5,0x32 },
+    { 0xa1,0x6d,0xc7,0x29 }, { 0xac,0x66,0xc9,0x20 }, 
+    { 0x8f,0x57,0xe3,0x1f }, { 0x82,0x5c,0xed,0x16 },
+    { 0x95,0x41,0xff,0x0d }, { 0x98,0x4a,0xf1,0x04 }, 
+    { 0xd3,0x23,0xab,0x73 }, { 0xde,0x28,0xa5,0x7a },
+    { 0xc9,0x35,0xb7,0x61 }, { 0xc4,0x3e,0xb9,0x68 }, 
+    { 0xe7,0x0f,0x93,0x57 }, { 0xea,0x04,0x9d,0x5e },
+    { 0xfd,0x19,0x8f,0x45 }, { 0xf0,0x12,0x81,0x4c }, 
+    { 0x6b,0xcb,0x3b,0xab }, { 0x66,0xc0,0x35,0xa2 },
+    { 0x71,0xdd,0x27,0xb9 }, { 0x7c,0xd6,0x29,0xb0 }, 
+    { 0x5f,0xe7,0x03,0x8f }, { 0x52,0xec,0x0d,0x86 },
+    { 0x45,0xf1,0x1f,0x9d }, { 0x48,0xfa,0x11,0x94 }, 
+    { 0x03,0x93,0x4b,0xe3 }, { 0x0e,0x98,0x45,0xea },
+    { 0x19,0x85,0x57,0xf1 }, { 0x14,0x8e,0x59,0xf8 }, 
+    { 0x37,0xbf,0x73,0xc7 }, { 0x3a,0xb4,0x7d,0xce }, 
+    { 0x2d,0xa9,0x6f,0xd5 }, { 0x20,0xa2,0x61,0xdc }, 
+    { 0x6d,0xf6,0xad,0x76 }, { 0x60,0xfd,0xa3,0x7f },
+    { 0x77,0xe0,0xb1,0x64 }, { 0x7a,0xeb,0xbf,0x6d }, 
+    { 0x59,0xda,0x95,0x52 }, { 0x54,0xd1,0x9b,0x5b },
+    { 0x43,0xcc,0x89,0x40 }, { 0x4e,0xc7,0x87,0x49 }, 
+    { 0x05,0xae,0xdd,0x3e }, { 0x08,0xa5,0xd3,0x37 },
+    { 0x1f,0xb8,0xc1,0x2c }, { 0x12,0xb3,0xcf,0x25 }, 
+    { 0x31,0x82,0xe5,0x1a }, { 0x3c,0x89,0xeb,0x13 }, 
+    { 0x2b,0x94,0xf9,0x08 }, { 0x26,0x9f,0xf7,0x01 }, 
+    { 0xbd,0x46,0x4d,0xe6 }, { 0xb0,0x4d,0x43,0xef }, 
+    { 0xa7,0x50,0x51,0xf4 }, { 0xaa,0x5b,0x5f,0xfd }, 
+    { 0x89,0x6a,0x75,0xc2 }, { 0x84,0x61,0x7b,0xcb }, 
+    { 0x93,0x7c,0x69,0xd0 }, { 0x9e,0x77,0x67,0xd9 }, 
+    { 0xd5,0x1e,0x3d,0xae }, { 0xd8,0x15,0x33,0xa7 },
+    { 0xcf,0x08,0x21,0xbc }, { 0xc2,0x03,0x2f,0xb5 }, 
+    { 0xe1,0x32,0x05,0x8a }, { 0xec,0x39,0x0b,0x83 },
+    { 0xfb,0x24,0x19,0x98 }, { 0xf6,0x2f,0x17,0x91 }, 
+    { 0xd6,0x8d,0x76,0x4d }, { 0xdb,0x86,0x78,0x44 }, 
+    { 0xcc,0x9b,0x6a,0x5f }, { 0xc1,0x90,0x64,0x56 }, 
+    { 0xe2,0xa1,0x4e,0x69 }, { 0xef,0xaa,0x40,0x60 }, 
+    { 0xf8,0xb7,0x52,0x7b }, { 0xf5,0xbc,0x5c,0x72 }, 
+    { 0xbe,0xd5,0x06,0x05 }, { 0xb3,0xde,0x08,0x0c }, 
+    { 0xa4,0xc3,0x1a,0x17 }, { 0xa9,0xc8,0x14,0x1e }, 
+    { 0x8a,0xf9,0x3e,0x21 }, { 0x87,0xf2,0x30,0x28 },
+    { 0x90,0xef,0x22,0x33 }, { 0x9d,0xe4,0x2c,0x3a }, 
+    { 0x06,0x3d,0x96,0xdd }, { 0x0b,0x36,0x98,0xd4 },
+    { 0x1c,0x2b,0x8a,0xcf }, { 0x11,0x20,0x84,0xc6 }, 
+    { 0x32,0x11,0xae,0xf9 }, { 0x3f,0x1a,0xa0,0xf0 },
+    { 0x28,0x07,0xb2,0xeb }, { 0x25,0x0c,0xbc,0xe2 }, 
+    { 0x6e,0x65,0xe6,0x95 }, { 0x63,0x6e,0xe8,0x9c },
+    { 0x74,0x73,0xfa,0x87 }, { 0x79,0x78,0xf4,0x8e }, 
+    { 0x5a,0x49,0xde,0xb1 }, { 0x57,0x42,0xd0,0xb8 },
+    { 0x40,0x5f,0xc2,0xa3 }, { 0x4d,0x54,0xcc,0xaa }, 
+    { 0xda,0xf7,0x41,0xec }, { 0xd7,0xfc,0x4f,0xe5 },
+    { 0xc0,0xe1,0x5d,0xfe }, { 0xcd,0xea,0x53,0xf7 }, 
+    { 0xee,0xdb,0x79,0xc8 }, { 0xe3,0xd0,0x77,0xc1 },
+    { 0xf4,0xcd,0x65,0xda }, { 0xf9,0xc6,0x6b,0xd3 }, 
+    { 0xb2,0xaf,0x31,0xa4 }, { 0xbf,0xa4,0x3f,0xad },
+    { 0xa8,0xb9,0x2d,0xb6 }, { 0xa5,0xb2,0x23,0xbf }, 
+    { 0x86,0x83,0x09,0x80 }, { 0x8b,0x88,0x07,0x89 },
+    { 0x9c,0x95,0x15,0x92 }, { 0x91,0x9e,0x1b,0x9b }, 
+    { 0x0a,0x47,0xa1,0x7c }, { 0x07,0x4c,0xaf,0x75 },
+    { 0x10,0x51,0xbd,0x6e }, { 0x1d,0x5a,0xb3,0x67 }, 
+    { 0x3e,0x6b,0x99,0x58 }, { 0x33,0x60,0x97,0x51 },
+    { 0x24,0x7d,0x85,0x4a }, { 0x29,0x76,0x8b,0x43 }, 
+    { 0x62,0x1f,0xd1,0x34 }, { 0x6f,0x14,0xdf,0x3d },
+    { 0x78,0x09,0xcd,0x26 }, { 0x75,0x02,0xc3,0x2f }, 
+    { 0x56,0x33,0xe9,0x10 }, { 0x5b,0x38,0xe7,0x19 },
+    { 0x4c,0x25,0xf5,0x02 }, { 0x41,0x2e,0xfb,0x0b }, 
+    { 0x61,0x8c,0x9a,0xd7 }, { 0x6c,0x87,0x94,0xde },
+    { 0x7b,0x9a,0x86,0xc5 }, { 0x76,0x91,0x88,0xcc }, 
+    { 0x55,0xa0,0xa2,0xf3 }, { 0x58,0xab,0xac,0xfa },
+    { 0x4f,0xb6,0xbe,0xe1 }, { 0x42,0xbd,0xb0,0xe8 }, 
+    { 0x09,0xd4,0xea,0x9f }, { 0x04,0xdf,0xe4,0x96 },
+    { 0x13,0xc2,0xf6,0x8d }, { 0x1e,0xc9,0xf8,0x84 }, 
+    { 0x3d,0xf8,0xd2,0xbb }, { 0x30,0xf3,0xdc,0xb2 },
+    { 0x27,0xee,0xce,0xa9 }, { 0x2a,0xe5,0xc0,0xa0 }, 
+    { 0xb1,0x3c,0x7a,0x47 }, { 0xbc,0x37,0x74,0x4e },
+    { 0xab,0x2a,0x66,0x55 }, { 0xa6,0x21,0x68,0x5c }, 
+    { 0x85,0x10,0x42,0x63 }, { 0x88,0x1b,0x4c,0x6a },
+    { 0x9f,0x06,0x5e,0x71 }, { 0x92,0x0d,0x50,0x78 }, 
+    { 0xd9,0x64,0x0a,0x0f }, { 0xd4,0x6f,0x04,0x06 },
+    { 0xc3,0x72,0x16,0x1d }, { 0xce,0x79,0x18,0x14 }, 
+    { 0xed,0x48,0x32,0x2b }, { 0xe0,0x43,0x3c,0x22 },
+    { 0xf7,0x5e,0x2e,0x39 }, { 0xfa,0x55,0x20,0x30 }, 
+    { 0xb7,0x01,0xec,0x9a }, { 0xba,0x0a,0xe2,0x93 },
+    { 0xad,0x17,0xf0,0x88 }, { 0xa0,0x1c,0xfe,0x81 }, 
+    { 0x83,0x2d,0xd4,0xbe }, { 0x8e,0x26,0xda,0xb7 },
+    { 0x99,0x3b,0xc8,0xac }, { 0x94,0x30,0xc6,0xa5 }, 
+    { 0xdf,0x59,0x9c,0xd2 }, { 0xd2,0x52,0x92,0xdb },
+    { 0xc5,0x4f,0x80,0xc0 }, { 0xc8,0x44,0x8e,0xc9 }, 
+    { 0xeb,0x75,0xa4,0xf6 }, { 0xe6,0x7e,0xaa,0xff },
+    { 0xf1,0x63,0xb8,0xe4 }, { 0xfc,0x68,0xb6,0xed }, 
+    { 0x67,0xb1,0x0c,0x0a }, { 0x6a,0xba,0x02,0x03 },
+    { 0x7d,0xa7,0x10,0x18 }, { 0x70,0xac,0x1e,0x11 }, 
+    { 0x53,0x9d,0x34,0x2e }, { 0x5e,0x96,0x3a,0x27 },
+    { 0x49,0x8b,0x28,0x3c }, { 0x44,0x80,0x26,0x35 }, 
+    { 0x0f,0xe9,0x7c,0x42 }, { 0x02,0xe2,0x72,0x4b },
+    { 0x15,0xff,0x60,0x50 }, { 0x18,0xf4,0x6e,0x59 }, 
+    { 0x3b,0xc5,0x44,0x66 }, { 0x36,0xce,0x4a,0x6f },
+    { 0x21,0xd3,0x58,0x74 }, { 0x2c,0xd8,0x56,0x7d }, 
+    { 0x0c,0x7a,0x37,0xa1 }, { 0x01,0x71,0x39,0xa8 },
+    { 0x16,0x6c,0x2b,0xb3 }, { 0x1b,0x67,0x25,0xba }, 
+    { 0x38,0x56,0x0f,0x85 }, { 0x35,0x5d,0x01,0x8c },
+    { 0x22,0x40,0x13,0x97 }, { 0x2f,0x4b,0x1d,0x9e }, 
+    { 0x64,0x22,0x47,0xe9 }, { 0x69,0x29,0x49,0xe0 },
+    { 0x7e,0x34,0x5b,0xfb }, { 0x73,0x3f,0x55,0xf2 }, 
+    { 0x50,0x0e,0x7f,0xcd }, { 0x5d,0x05,0x71,0xc4 },
+    { 0x4a,0x18,0x63,0xdf }, { 0x47,0x13,0x6d,0xd6 }, 
+    { 0xdc,0xca,0xd7,0x31 }, { 0xd1,0xc1,0xd9,0x38 },
+    { 0xc6,0xdc,0xcb,0x23 }, { 0xcb,0xd7,0xc5,0x2a }, 
+    { 0xe8,0xe6,0xef,0x15 }, { 0xe5,0xed,0xe1,0x1c },
+    { 0xf2,0xf0,0xf3,0x07 }, { 0xff,0xfb,0xfd,0x0e }, 
+    { 0xb4,0x92,0xa7,0x79 }, { 0xb9,0x99,0xa9,0x70 },
+    { 0xae,0x84,0xbb,0x6b }, { 0xa3,0x8f,0xb5,0x62 }, 
+    { 0x80,0xbe,0x9f,0x5d }, { 0x8d,0xb5,0x91,0x54 },
+    { 0x9a,0xa8,0x83,0x4f }, { 0x97,0xa3,0x8d,0x46 }
+  };
+
+static const unsigned char U4[256][4] =
+  {
+    { 0x00,0x00,0x00,0x00 }, { 0x09,0x0d,0x0b,0x0e },
+    { 0x12,0x1a,0x16,0x1c }, { 0x1b,0x17,0x1d,0x12 }, 
+    { 0x24,0x34,0x2c,0x38 }, { 0x2d,0x39,0x27,0x36 },
+    { 0x36,0x2e,0x3a,0x24 }, { 0x3f,0x23,0x31,0x2a }, 
+    { 0x48,0x68,0x58,0x70 }, { 0x41,0x65,0x53,0x7e },
+    { 0x5a,0x72,0x4e,0x6c }, { 0x53,0x7f,0x45,0x62 }, 
+    { 0x6c,0x5c,0x74,0x48 }, { 0x65,0x51,0x7f,0x46 },
+    { 0x7e,0x46,0x62,0x54 }, { 0x77,0x4b,0x69,0x5a }, 
+    { 0x90,0xd0,0xb0,0xe0 }, { 0x99,0xdd,0xbb,0xee },
+    { 0x82,0xca,0xa6,0xfc }, { 0x8b,0xc7,0xad,0xf2 }, 
+    { 0xb4,0xe4,0x9c,0xd8 }, { 0xbd,0xe9,0x97,0xd6 },
+    { 0xa6,0xfe,0x8a,0xc4 }, { 0xaf,0xf3,0x81,0xca }, 
+    { 0xd8,0xb8,0xe8,0x90 }, { 0xd1,0xb5,0xe3,0x9e },
+    { 0xca,0xa2,0xfe,0x8c }, { 0xc3,0xaf,0xf5,0x82 }, 
+    { 0xfc,0x8c,0xc4,0xa8 }, { 0xf5,0x81,0xcf,0xa6 },
+    { 0xee,0x96,0xd2,0xb4 }, { 0xe7,0x9b,0xd9,0xba }, 
+    { 0x3b,0xbb,0x7b,0xdb }, { 0x32,0xb6,0x70,0xd5 },
+    { 0x29,0xa1,0x6d,0xc7 }, { 0x20,0xac,0x66,0xc9 }, 
+    { 0x1f,0x8f,0x57,0xe3 }, { 0x16,0x82,0x5c,0xed },
+    { 0x0d,0x95,0x41,0xff }, { 0x04,0x98,0x4a,0xf1 }, 
+    { 0x73,0xd3,0x23,0xab }, { 0x7a,0xde,0x28,0xa5 },
+    { 0x61,0xc9,0x35,0xb7 }, { 0x68,0xc4,0x3e,0xb9 }, 
+    { 0x57,0xe7,0x0f,0x93 }, { 0x5e,0xea,0x04,0x9d },
+    { 0x45,0xfd,0x19,0x8f }, { 0x4c,0xf0,0x12,0x81 }, 
+    { 0xab,0x6b,0xcb,0x3b }, { 0xa2,0x66,0xc0,0x35 },
+    { 0xb9,0x71,0xdd,0x27 }, { 0xb0,0x7c,0xd6,0x29 }, 
+    { 0x8f,0x5f,0xe7,0x03 }, { 0x86,0x52,0xec,0x0d },
+    { 0x9d,0x45,0xf1,0x1f }, { 0x94,0x48,0xfa,0x11 }, 
+    { 0xe3,0x03,0x93,0x4b }, { 0xea,0x0e,0x98,0x45 },
+    { 0xf1,0x19,0x85,0x57 }, { 0xf8,0x14,0x8e,0x59 }, 
+    { 0xc7,0x37,0xbf,0x73 }, { 0xce,0x3a,0xb4,0x7d },
+    { 0xd5,0x2d,0xa9,0x6f }, { 0xdc,0x20,0xa2,0x61 }, 
+    { 0x76,0x6d,0xf6,0xad }, { 0x7f,0x60,0xfd,0xa3 },
+    { 0x64,0x77,0xe0,0xb1 }, { 0x6d,0x7a,0xeb,0xbf }, 
+    { 0x52,0x59,0xda,0x95 }, { 0x5b,0x54,0xd1,0x9b },
+    { 0x40,0x43,0xcc,0x89 }, { 0x49,0x4e,0xc7,0x87 }, 
+    { 0x3e,0x05,0xae,0xdd }, { 0x37,0x08,0xa5,0xd3 },
+    { 0x2c,0x1f,0xb8,0xc1 }, { 0x25,0x12,0xb3,0xcf }, 
+    { 0x1a,0x31,0x82,0xe5 }, { 0x13,0x3c,0x89,0xeb },
+    { 0x08,0x2b,0x94,0xf9 }, { 0x01,0x26,0x9f,0xf7 }, 
+    { 0xe6,0xbd,0x46,0x4d }, { 0xef,0xb0,0x4d,0x43 },
+    { 0xf4,0xa7,0x50,0x51 }, { 0xfd,0xaa,0x5b,0x5f }, 
+    { 0xc2,0x89,0x6a,0x75 }, { 0xcb,0x84,0x61,0x7b },
+    { 0xd0,0x93,0x7c,0x69 }, { 0xd9,0x9e,0x77,0x67 }, 
+    { 0xae,0xd5,0x1e,0x3d }, { 0xa7,0xd8,0x15,0x33 },
+    { 0xbc,0xcf,0x08,0x21 }, { 0xb5,0xc2,0x03,0x2f }, 
+    { 0x8a,0xe1,0x32,0x05 }, { 0x83,0xec,0x39,0x0b },
+    { 0x98,0xfb,0x24,0x19 }, { 0x91,0xf6,0x2f,0x17 }, 
+    { 0x4d,0xd6,0x8d,0x76 }, { 0x44,0xdb,0x86,0x78 },
+    { 0x5f,0xcc,0x9b,0x6a }, { 0x56,0xc1,0x90,0x64 }, 
+    { 0x69,0xe2,0xa1,0x4e }, { 0x60,0xef,0xaa,0x40 },
+    { 0x7b,0xf8,0xb7,0x52 }, { 0x72,0xf5,0xbc,0x5c }, 
+    { 0x05,0xbe,0xd5,0x06 }, { 0x0c,0xb3,0xde,0x08 },
+    { 0x17,0xa4,0xc3,0x1a }, { 0x1e,0xa9,0xc8,0x14 }, 
+    { 0x21,0x8a,0xf9,0x3e }, { 0x28,0x87,0xf2,0x30 },
+    { 0x33,0x90,0xef,0x22 }, { 0x3a,0x9d,0xe4,0x2c }, 
+    { 0xdd,0x06,0x3d,0x96 }, { 0xd4,0x0b,0x36,0x98 },
+    { 0xcf,0x1c,0x2b,0x8a }, { 0xc6,0x11,0x20,0x84 }, 
+    { 0xf9,0x32,0x11,0xae }, { 0xf0,0x3f,0x1a,0xa0 },
+    { 0xeb,0x28,0x07,0xb2 }, { 0xe2,0x25,0x0c,0xbc }, 
+    { 0x95,0x6e,0x65,0xe6 }, { 0x9c,0x63,0x6e,0xe8 },
+    { 0x87,0x74,0x73,0xfa }, { 0x8e,0x79,0x78,0xf4 }, 
+    { 0xb1,0x5a,0x49,0xde }, { 0xb8,0x57,0x42,0xd0 },
+    { 0xa3,0x40,0x5f,0xc2 }, { 0xaa,0x4d,0x54,0xcc }, 
+    { 0xec,0xda,0xf7,0x41 }, { 0xe5,0xd7,0xfc,0x4f },
+    { 0xfe,0xc0,0xe1,0x5d }, { 0xf7,0xcd,0xea,0x53 }, 
+    { 0xc8,0xee,0xdb,0x79 }, { 0xc1,0xe3,0xd0,0x77 },
+    { 0xda,0xf4,0xcd,0x65 }, { 0xd3,0xf9,0xc6,0x6b }, 
+    { 0xa4,0xb2,0xaf,0x31 }, { 0xad,0xbf,0xa4,0x3f },
+    { 0xb6,0xa8,0xb9,0x2d }, { 0xbf,0xa5,0xb2,0x23 }, 
+    { 0x80,0x86,0x83,0x09 }, { 0x89,0x8b,0x88,0x07 },
+    { 0x92,0x9c,0x95,0x15 }, { 0x9b,0x91,0x9e,0x1b }, 
+    { 0x7c,0x0a,0x47,0xa1 }, { 0x75,0x07,0x4c,0xaf },
+    { 0x6e,0x10,0x51,0xbd }, { 0x67,0x1d,0x5a,0xb3 }, 
+    { 0x58,0x3e,0x6b,0x99 }, { 0x51,0x33,0x60,0x97 },
+    { 0x4a,0x24,0x7d,0x85 }, { 0x43,0x29,0x76,0x8b }, 
+    { 0x34,0x62,0x1f,0xd1 }, { 0x3d,0x6f,0x14,0xdf },
+    { 0x26,0x78,0x09,0xcd }, { 0x2f,0x75,0x02,0xc3 }, 
+    { 0x10,0x56,0x33,0xe9 }, { 0x19,0x5b,0x38,0xe7 },
+    { 0x02,0x4c,0x25,0xf5 }, { 0x0b,0x41,0x2e,0xfb }, 
+    { 0xd7,0x61,0x8c,0x9a }, { 0xde,0x6c,0x87,0x94 },
+    { 0xc5,0x7b,0x9a,0x86 }, { 0xcc,0x76,0x91,0x88 }, 
+    { 0xf3,0x55,0xa0,0xa2 }, { 0xfa,0x58,0xab,0xac },
+    { 0xe1,0x4f,0xb6,0xbe }, { 0xe8,0x42,0xbd,0xb0 }, 
+    { 0x9f,0x09,0xd4,0xea }, { 0x96,0x04,0xdf,0xe4 },
+    { 0x8d,0x13,0xc2,0xf6 }, { 0x84,0x1e,0xc9,0xf8 }, 
+    { 0xbb,0x3d,0xf8,0xd2 }, { 0xb2,0x30,0xf3,0xdc },
+    { 0xa9,0x27,0xee,0xce }, { 0xa0,0x2a,0xe5,0xc0 }, 
+    { 0x47,0xb1,0x3c,0x7a }, { 0x4e,0xbc,0x37,0x74 },
+    { 0x55,0xab,0x2a,0x66 }, { 0x5c,0xa6,0x21,0x68 }, 
+    { 0x63,0x85,0x10,0x42 }, { 0x6a,0x88,0x1b,0x4c },
+    { 0x71,0x9f,0x06,0x5e }, { 0x78,0x92,0x0d,0x50 }, 
+    { 0x0f,0xd9,0x64,0x0a }, { 0x06,0xd4,0x6f,0x04 },
+    { 0x1d,0xc3,0x72,0x16 }, { 0x14,0xce,0x79,0x18 }, 
+    { 0x2b,0xed,0x48,0x32 }, { 0x22,0xe0,0x43,0x3c },
+    { 0x39,0xf7,0x5e,0x2e }, { 0x30,0xfa,0x55,0x20 }, 
+    { 0x9a,0xb7,0x01,0xec }, { 0x93,0xba,0x0a,0xe2 }, 
+    { 0x88,0xad,0x17,0xf0 }, { 0x81,0xa0,0x1c,0xfe }, 
+    { 0xbe,0x83,0x2d,0xd4 }, { 0xb7,0x8e,0x26,0xda },
+    { 0xac,0x99,0x3b,0xc8 }, { 0xa5,0x94,0x30,0xc6 }, 
+    { 0xd2,0xdf,0x59,0x9c }, { 0xdb,0xd2,0x52,0x92 }, 
+    { 0xc0,0xc5,0x4f,0x80 }, { 0xc9,0xc8,0x44,0x8e }, 
+    { 0xf6,0xeb,0x75,0xa4 }, { 0xff,0xe6,0x7e,0xaa },
+    { 0xe4,0xf1,0x63,0xb8 }, { 0xed,0xfc,0x68,0xb6 }, 
+    { 0x0a,0x67,0xb1,0x0c }, { 0x03,0x6a,0xba,0x02 },
+    { 0x18,0x7d,0xa7,0x10 }, { 0x11,0x70,0xac,0x1e }, 
+    { 0x2e,0x53,0x9d,0x34 }, { 0x27,0x5e,0x96,0x3a },
+    { 0x3c,0x49,0x8b,0x28 }, { 0x35,0x44,0x80,0x26 }, 
+    { 0x42,0x0f,0xe9,0x7c }, { 0x4b,0x02,0xe2,0x72 }, 
+    { 0x50,0x15,0xff,0x60 }, { 0x59,0x18,0xf4,0x6e }, 
+    { 0x66,0x3b,0xc5,0x44 }, { 0x6f,0x36,0xce,0x4a },
+    { 0x74,0x21,0xd3,0x58 }, { 0x7d,0x2c,0xd8,0x56 }, 
+    { 0xa1,0x0c,0x7a,0x37 }, { 0xa8,0x01,0x71,0x39 },
+    { 0xb3,0x16,0x6c,0x2b }, { 0xba,0x1b,0x67,0x25 }, 
+    { 0x85,0x38,0x56,0x0f }, { 0x8c,0x35,0x5d,0x01 },
+    { 0x97,0x22,0x40,0x13 }, { 0x9e,0x2f,0x4b,0x1d }, 
+    { 0xe9,0x64,0x22,0x47 }, { 0xe0,0x69,0x29,0x49 }, 
+    { 0xfb,0x7e,0x34,0x5b }, { 0xf2,0x73,0x3f,0x55 }, 
+    { 0xcd,0x50,0x0e,0x7f }, { 0xc4,0x5d,0x05,0x71 },
+    { 0xdf,0x4a,0x18,0x63 }, { 0xd6,0x47,0x13,0x6d }, 
+    { 0x31,0xdc,0xca,0xd7 }, { 0x38,0xd1,0xc1,0xd9 },
+    { 0x23,0xc6,0xdc,0xcb }, { 0x2a,0xcb,0xd7,0xc5 }, 
+    { 0x15,0xe8,0xe6,0xef }, { 0x1c,0xe5,0xed,0xe1 },
+    { 0x07,0xf2,0xf0,0xf3 }, { 0x0e,0xff,0xfb,0xfd }, 
+    { 0x79,0xb4,0x92,0xa7 }, { 0x70,0xb9,0x99,0xa9 },
+    { 0x6b,0xae,0x84,0xbb }, { 0x62,0xa3,0x8f,0xb5 }, 
+    { 0x5d,0x80,0xbe,0x9f }, { 0x54,0x8d,0xb5,0x91 },
+    { 0x4f,0x9a,0xa8,0x83 }, { 0x46,0x97,0xa3,0x8d }
+  };
+
+static const grub_uint32_t rcon[30] = 
+  { 
+    0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
+    0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
+    0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
+  };
+

=== modified file 'conf/common.rmk'
--- conf/common.rmk     2009-06-21 10:08:22 +0000
+++ conf/common.rmk     2009-06-21 10:09:16 +0000
@@ -635,3 +635,9 @@
 md5_mod_SOURCES = crypto/md5.c
 md5_mod_CFLAGS = $(COMMON_CFLAGS)
 md5_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For sha1.mod
+pkglib_MODULES += sha1.mod
+sha1_mod_SOURCES = crypto/sha1.c
+sha1_mod_CFLAGS = $(COMMON_CFLAGS)
+sha1_mod_LDFLAGS = $(COMMON_LDFLAGS)

=== added file 'crypto/sha1.c'
--- crypto/sha1.c       1970-01-01 00:00:00 +0000
+++ crypto/sha1.c       2009-06-21 10:09:16 +0000
@@ -0,0 +1,371 @@
+/* sha1.c - SHA1 hash function
+ * Copyright (C) 1998, 2001, 2002, 2003, 2008 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+/*  Test vectors:
+ *
+ *  "abc"
+ *  A999 3E36 4706 816A BA3E  2571 7850 C26C 9CD0 D89D
+ *
+ *  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ *  8498 3E44 1C3B D26E BAAE  4AA1 F951 29E5 E546 70F1
+ */
+
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/crypto.h>
+#include <grub/dl.h>
+
+#define TRANSFORM(x,d,n) transform ((x), (d), (n))
+#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
+
+typedef struct 
+{
+  grub_uint32_t           h0,h1,h2,h3,h4;
+  grub_uint32_t           nblocks;
+  unsigned char buf[64];
+  int           count;
+} SHA1_CONTEXT;
+
+static void
+sha1_init (void *context)
+{
+  SHA1_CONTEXT *hd = context;
+
+  hd->h0 = 0x67452301;
+  hd->h1 = 0xefcdab89;
+  hd->h2 = 0x98badcfe;
+  hd->h3 = 0x10325476;
+  hd->h4 = 0xc3d2e1f0;
+  hd->nblocks = 0;
+  hd->count = 0;
+}
+
+/* Round function macros. */
+#define K1  0x5A827999L
+#define K2  0x6ED9EBA1L
+#define K3  0x8F1BBCDCL
+#define K4  0xCA62C1D6L
+#define F1(x,y,z)   ( z ^ ( x & ( y ^ z ) ) )
+#define F2(x,y,z)   ( x ^ y ^ z )
+#define F3(x,y,z)   ( ( x & y ) | ( z & ( x | y ) ) )
+#define F4(x,y,z)   ( x ^ y ^ z )
+#define M(i) ( tm =    x[ i    &0x0f]  \
+    ^ x[(i-14)&0x0f]  \
+    ^ x[(i-8) &0x0f]  \
+    ^ x[(i-3) &0x0f], \
+    (x[i&0x0f] = rol(tm, 1)))
+#define R(a,b,c,d,e,f,k,m)  do { e += rol( a, 5 )     \
+  + f( b, c, d )  \
+  + k        \
+  + m;        \
+  b = rol( b, 30 );    \
+} while(0)
+
+
+/*
+ * Transform NBLOCKS of each 64 bytes (16 32-bit words) at DATA.
+ */
+static void
+transform (SHA1_CONTEXT *hd, const unsigned char *data, grub_size_t nblocks)
+{
+  register grub_uint32_t a, b, c, d, e; /* Local copies of the chaining 
variables.  */
+  register grub_uint32_t tm;            /* Helper.  */
+  grub_uint32_t x[16];                  /* The array we work on. */
+
+  /* Loop over all blocks.  */
+  for ( ;nblocks; nblocks--)
+  {
+#ifdef WORDS_BIGENDIAN
+    grub_memcpy (x, data, 64);
+    data += 64;
+#else
+    {
+      int i;
+      unsigned char *p;
+
+      for(i=0, p=(unsigned char*)x; i < 16; i++, p += 4 )
+      {
+        p[3] = *data++;
+        p[2] = *data++;
+        p[1] = *data++;
+        p[0] = *data++;
+      }
+    }
+#endif
+    /* Get the values of the chaining variables. */
+    a = hd->h0;
+    b = hd->h1;
+    c = hd->h2;
+    d = hd->h3;
+    e = hd->h4;
+
+    /* Transform. */
+    R( a, b, c, d, e, F1, K1, x[ 0] );
+    R( e, a, b, c, d, F1, K1, x[ 1] );
+    R( d, e, a, b, c, F1, K1, x[ 2] );
+    R( c, d, e, a, b, F1, K1, x[ 3] );
+    R( b, c, d, e, a, F1, K1, x[ 4] );
+    R( a, b, c, d, e, F1, K1, x[ 5] );
+    R( e, a, b, c, d, F1, K1, x[ 6] );
+    R( d, e, a, b, c, F1, K1, x[ 7] );
+    R( c, d, e, a, b, F1, K1, x[ 8] );
+    R( b, c, d, e, a, F1, K1, x[ 9] );
+    R( a, b, c, d, e, F1, K1, x[10] );
+    R( e, a, b, c, d, F1, K1, x[11] );
+    R( d, e, a, b, c, F1, K1, x[12] );
+    R( c, d, e, a, b, F1, K1, x[13] );
+    R( b, c, d, e, a, F1, K1, x[14] );
+    R( a, b, c, d, e, F1, K1, x[15] );
+    R( e, a, b, c, d, F1, K1, M(16) );
+    R( d, e, a, b, c, F1, K1, M(17) );
+    R( c, d, e, a, b, F1, K1, M(18) );
+    R( b, c, d, e, a, F1, K1, M(19) );
+    R( a, b, c, d, e, F2, K2, M(20) );
+    R( e, a, b, c, d, F2, K2, M(21) );
+    R( d, e, a, b, c, F2, K2, M(22) );
+    R( c, d, e, a, b, F2, K2, M(23) );
+    R( b, c, d, e, a, F2, K2, M(24) );
+    R( a, b, c, d, e, F2, K2, M(25) );
+    R( e, a, b, c, d, F2, K2, M(26) );
+    R( d, e, a, b, c, F2, K2, M(27) );
+    R( c, d, e, a, b, F2, K2, M(28) );
+    R( b, c, d, e, a, F2, K2, M(29) );
+    R( a, b, c, d, e, F2, K2, M(30) );
+    R( e, a, b, c, d, F2, K2, M(31) );
+    R( d, e, a, b, c, F2, K2, M(32) );
+    R( c, d, e, a, b, F2, K2, M(33) );
+    R( b, c, d, e, a, F2, K2, M(34) );
+    R( a, b, c, d, e, F2, K2, M(35) );
+    R( e, a, b, c, d, F2, K2, M(36) );
+    R( d, e, a, b, c, F2, K2, M(37) );
+    R( c, d, e, a, b, F2, K2, M(38) );
+    R( b, c, d, e, a, F2, K2, M(39) );
+    R( a, b, c, d, e, F3, K3, M(40) );
+    R( e, a, b, c, d, F3, K3, M(41) );
+    R( d, e, a, b, c, F3, K3, M(42) );
+    R( c, d, e, a, b, F3, K3, M(43) );
+    R( b, c, d, e, a, F3, K3, M(44) );
+    R( a, b, c, d, e, F3, K3, M(45) );
+    R( e, a, b, c, d, F3, K3, M(46) );
+    R( d, e, a, b, c, F3, K3, M(47) );
+    R( c, d, e, a, b, F3, K3, M(48) );
+    R( b, c, d, e, a, F3, K3, M(49) );
+    R( a, b, c, d, e, F3, K3, M(50) );
+    R( e, a, b, c, d, F3, K3, M(51) );
+    R( d, e, a, b, c, F3, K3, M(52) );
+    R( c, d, e, a, b, F3, K3, M(53) );
+    R( b, c, d, e, a, F3, K3, M(54) );
+    R( a, b, c, d, e, F3, K3, M(55) );
+    R( e, a, b, c, d, F3, K3, M(56) );
+    R( d, e, a, b, c, F3, K3, M(57) );
+    R( c, d, e, a, b, F3, K3, M(58) );
+    R( b, c, d, e, a, F3, K3, M(59) );
+    R( a, b, c, d, e, F4, K4, M(60) );
+    R( e, a, b, c, d, F4, K4, M(61) );
+    R( d, e, a, b, c, F4, K4, M(62) );
+    R( c, d, e, a, b, F4, K4, M(63) );
+    R( b, c, d, e, a, F4, K4, M(64) );
+    R( a, b, c, d, e, F4, K4, M(65) );
+    R( e, a, b, c, d, F4, K4, M(66) );
+    R( d, e, a, b, c, F4, K4, M(67) );
+    R( c, d, e, a, b, F4, K4, M(68) );
+    R( b, c, d, e, a, F4, K4, M(69) );
+    R( a, b, c, d, e, F4, K4, M(70) );
+    R( e, a, b, c, d, F4, K4, M(71) );
+    R( d, e, a, b, c, F4, K4, M(72) );
+    R( c, d, e, a, b, F4, K4, M(73) );
+    R( b, c, d, e, a, F4, K4, M(74) );
+    R( a, b, c, d, e, F4, K4, M(75) );
+    R( e, a, b, c, d, F4, K4, M(76) );
+    R( d, e, a, b, c, F4, K4, M(77) );
+    R( c, d, e, a, b, F4, K4, M(78) );
+    R( b, c, d, e, a, F4, K4, M(79) );
+
+    /* Update the chaining variables. */
+    hd->h0 += a;
+    hd->h1 += b;
+    hd->h2 += c;
+    hd->h3 += d;
+    hd->h4 += e;
+  }
+}
+
+
+/* Update the message digest with the contents
+ * of INBUF with length INLEN.
+ */
+static void
+sha1_write( void *context, const void *inbuf_arg, grub_size_t inlen)
+{
+  const unsigned char *inbuf = inbuf_arg;
+  SHA1_CONTEXT *hd = context;
+  grub_size_t nblocks;
+
+  if (hd->count == 64)  /* Flush the buffer. */
+  {
+    TRANSFORM( hd, hd->buf, 1 );
+    //      _gcry_burn_stack (88+4*sizeof(void*));
+    hd->count = 0;
+    hd->nblocks++;
+  }
+  if (!inbuf)
+    return;
+
+  if (hd->count)
+  {
+    for (; inlen && hd->count < 64; inlen--)
+      hd->buf[hd->count++] = *inbuf++;
+    sha1_write (hd, NULL, 0);
+    if (!inlen)
+      return;
+  }
+
+  nblocks = inlen / 64;
+  if (nblocks)
+  {
+    TRANSFORM (hd, inbuf, nblocks);
+    hd->count = 0;
+    hd->nblocks += nblocks;
+    inlen -= nblocks * 64;
+    inbuf += nblocks * 64;
+  }
+  //  _gcry_burn_stack (88+4*sizeof(void*));
+
+  /* Save remaining bytes.  */
+  for (; inlen && hd->count < 64; inlen--)
+    hd->buf[hd->count++] = *inbuf++;
+}
+
+
+/* The routine final terminates the computation and
+ * returns the digest.
+ * The handle is prepared for a new cycle, but adding bytes to the
+ * handle will the destroy the returned buffer.
+ * Returns: 20 bytes representing the digest.
+ */
+
+static void
+sha1_final(void *context)
+{
+  SHA1_CONTEXT *hd = context;
+
+  grub_uint32_t t, msb, lsb;
+  unsigned char *p;
+
+  sha1_write(hd, NULL, 0); /* flush */;
+
+  t = hd->nblocks;
+  /* multiply by 64 to make a byte count */
+  lsb = t << 6;
+  msb = t >> 26;
+  /* add the count */
+  t = lsb;
+  if( (lsb += hd->count) < t )
+    msb++;
+  /* multiply by 8 to make a bit count */
+  t = lsb;
+  lsb <<= 3;
+  msb <<= 3;
+  msb |= t >> 29;
+
+  if( hd->count < 56 )  /* enough room */
+  {
+    hd->buf[hd->count++] = 0x80; /* pad */
+    while( hd->count < 56 )
+      hd->buf[hd->count++] = 0;  /* pad */
+  }
+  else  /* need one extra block */
+  {
+    hd->buf[hd->count++] = 0x80; /* pad character */
+    while( hd->count < 64 )
+      hd->buf[hd->count++] = 0;
+    sha1_write(hd, NULL, 0);  /* flush */;
+    grub_memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+  }
+  /* append the 64 bit count */
+  hd->buf[56] = msb >> 24;
+  hd->buf[57] = msb >> 16;
+  hd->buf[58] = msb >>  8;
+  hd->buf[59] = msb     ;
+  hd->buf[60] = lsb >> 24;
+  hd->buf[61] = lsb >> 16;
+  hd->buf[62] = lsb >>  8;
+  hd->buf[63] = lsb     ;
+  TRANSFORM( hd, hd->buf, 1 );
+  //  _gcry_burn_stack (88+4*sizeof(void*));
+
+  p = hd->buf;
+#ifdef WORDS_BIGENDIAN
+#define X(a) do { *(grub_uint32_t*)p = hd->h##a ; p += 4; } while(0)
+#else /* little endian */
+#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16;   \
+  *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0)
+#endif
+  X(0);
+  X(1);
+  X(2);
+  X(3);
+  X(4);
+#undef X
+
+}
+
+/**
+ * GRUB2 Crypto Interface
+ * Written by Michael Gorven
+ */
+
+static grub_err_t
+grub_hash_sha1_fn (grub_cipher_params_t params, char *out,
+    const char *in, grub_size_t insize)
+{
+  SHA1_CONTEXT hd;
+
+  sha1_init (&hd);
+  sha1_write (&hd, in, insize);
+  sha1_final (&hd);
+  grub_memcpy (out, hd.buf, 20);
+
+  return GRUB_ERR_NONE;
+}
+
+static struct grub_cipher grub_cipher_sha1 = {
+  .name = "sha1",
+  .type = GRUB_CIPHER_TYPE_HASH,
+  .keysizes = (const unsigned int[]) {20},
+  .keysizes_length = 1,
+  .blocksize = 64,
+
+  .u.hash = {
+    .fn = grub_hash_sha1_fn}
+};
+
+GRUB_MOD_INIT (sha1)
+{
+  grub_crypto_cipher_register (&grub_cipher_sha1);
+}
+
+GRUB_MOD_FINI (sha1)
+{
+  grub_crypto_cipher_unregister (&grub_cipher_sha1);
+}
+
+/* vi: set et sw=2 sts=2: */

Attachment: signature.asc
Description: This is a digitally signed message part.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]