Import new random number generator files from harvey
authorRonald G. Minnich <rminnich@gmail.com>
Thu, 4 Feb 2016 01:52:35 +0000 (17:52 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 4 Feb 2016 19:56:13 +0000 (14:56 -0500)
This is the unchanged version; they will not compile at all
and need formatting.

Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/random/rijndael.h [new file with mode: 0644]
kern/include/random/sha2.h [new file with mode: 0644]
kern/lib/random/fortuna.c [new file with mode: 0644]
kern/lib/random/rijndael.c [new file with mode: 0644]
kern/lib/random/rijndael.tbl [new file with mode: 0644]
kern/lib/random/sha2.c [new file with mode: 0644]

diff --git a/kern/include/random/rijndael.h b/kern/include/random/rijndael.h
new file mode 100644 (file)
index 0000000..a284de8
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * contrib/pgcrypto/rijndael.h
+ *
+ *     $OpenBSD: rijndael.h,v 1.3 2001/05/09 23:01:32 markus Exp $ */
+
+/* This is an independent implementation of the encryption algorithm:  */
+/*                                                                                                                                             */
+/*                RIJNDAEL by Joan Daemen and Vincent Rijmen                                   */
+/*                                                                                                                                             */
+/* which is a candidate algorithm in the Advanced Encryption Standard  */
+/* programme of the US National Institute of Standards and Technology. */
+/*                                                                                                                                             */
+/* Copyright in this implementation is held by Dr B R Gladman but I            */
+/* hereby give permission for its free direct or derivative use subject */
+/* to acknowledgment of its origin and compliance with any conditions  */
+/* that the originators of the algorithm place on its exploitation.            */
+/*                                                                                                                                             */
+/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999            */
+
+typedef struct rijndaelCtx rijndaelCtx;
+
+struct rijndaelCtx
+{
+       uint32_t                k_len;
+       int                             decrypt;
+       uint32_t                e_key[64];
+       uint32_t                d_key[64];
+};
+
+
+/* Standard interface for AES cryptographic routines                           */
+
+/* These are all based on 32 bit unsigned values and will therefore */
+/* require endian conversions for big-endian architectures                     */
+
+rijndaelCtx *
+                       rijndael_set_key(rijndaelCtx *, const uint32_t *, const uint32_t, int);
+void           rijndael_encrypt(rijndaelCtx *, const uint32_t *, uint32_t *);
+void           rijndael_decrypt(rijndaelCtx *, const uint32_t *, uint32_t *);
+
+/* conventional interface */
+
+void           aes_set_key(rijndaelCtx *ctx, const uint8_t *key, unsigned keybits, int enc);
+void           aes_ecb_encrypt(rijndaelCtx *ctx, uint8_t *data, unsigned len);
+void           aes_ecb_decrypt(rijndaelCtx *ctx, uint8_t *data, unsigned len);
+void           aes_cbc_encrypt(rijndaelCtx *ctx, uint8_t *iva, uint8_t *data, unsigned len);
+void           aes_cbc_decrypt(rijndaelCtx *ctx, uint8_t *iva, uint8_t *data, unsigned len);
diff --git a/kern/include/random/sha2.h b/kern/include/random/sha2.h
new file mode 100644 (file)
index 0000000..e6ff365
--- /dev/null
@@ -0,0 +1,94 @@
+/*     contrib/pgcrypto/sha2.h */
+/*     $OpenBSD: sha2.h,v 1.2 2004/04/28 23:11:57 millert Exp $        */
+
+/*
+ * FILE:       sha2.h
+ * AUTHOR:     Aaron D. Gifford <me@aarongifford.com>
+ *
+ * Copyright (c) 2000-2001, Aaron D. Gifford
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $From: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $
+ */
+
+
+/*** SHA-224/256/384/512 Various Length Definitions ***********************/
+enum{
+       SHA224BlockLength               = 64,
+       SHA224DigestLength      = 28,
+       SHA224_digest_string_length = (SHA224DigestLength * 2 + 1),
+       SHA256BlockLength               = 64,
+       SHA256DigestLength      = 32,
+       SHA256DigestStringLength = (SHA256DigestLength * 2 + 1),
+       SHA384BlockLength               = 128,
+       SHA384DigestLength      = 48,
+       SHA384_digest_string_length = (SHA384DigestLength * 2 + 1),
+       SHA512_block_length             = 128,
+       SHA512DigestLength      = 64,
+       SHA512DigestStringLength = (SHA512DigestLength * 2 + 1)
+};
+
+/*** SHA-256/384/512 Context Structures *******************************/
+
+typedef struct SHA256Ctx SHA256Ctx;
+typedef struct SHA512Ctx SHA512Ctx;
+typedef SHA256Ctx SHA224Ctx;
+typedef SHA512Ctx SHA384Ctx;
+
+struct SHA256Ctx
+{
+       uint32_t                state[8];
+       uint64_t                bitcount;
+       uint8_t         buffer[SHA256BlockLength];
+};
+
+
+
+struct SHA512Ctx
+{
+       uint64_t                state[8];
+       uint64_t                bitcount[2];
+       uint8_t         buffer[SHA512_block_length];
+};
+
+
+void           SHA224_Init(SHA224Ctx *);
+void           SHA224_Update(SHA224Ctx *, const uint8_t *, size_t);
+void           SHA224_Final(uint8_t[SHA224DigestLength], SHA224Ctx *);
+
+void           SHA256_Init(SHA256Ctx *);
+void           SHA256_Update(SHA256Ctx *, const uint8_t *, size_t);
+void           SHA256_Final(uint8_t[SHA256DigestLength], SHA256Ctx *);
+
+void           SHA384_Init(SHA384Ctx *);
+void           SHA384_Update(SHA384Ctx *, const uint8_t *, size_t);
+void           SHA384_Final(uint8_t[SHA384DigestLength], SHA384Ctx *);
+
+void           SHA512_Init(SHA512Ctx *);
+void           SHA512_Update(SHA512Ctx *, const uint8_t *, size_t);
+void           SHA512_Final(uint8_t[SHA512DigestLength], SHA512Ctx *);
+
diff --git a/kern/lib/random/fortuna.c b/kern/lib/random/fortuna.c
new file mode 100644 (file)
index 0000000..71334bd
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ * fortuna.c
+ *             Fortuna-like PRNG.
+ *
+ * Copyright (c) 2005 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * contrib/pgcrypto/fortuna.c
+ */
+
+
+#include <u.h>
+#include <rijndael.h>
+#include <sha2.h>
+
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+
+
+
+/*
+ * Why Fortuna-like: There does not seem to be any definitive reference
+ * on Fortuna in the net.  Instead this implementation is based on
+ * following references:
+ *
+ * http://en.wikipedia.org/wiki/Fortuna_(PRNG)
+ *      - Wikipedia article
+ * http://jlcooke.ca/random/
+ *      - Jean-Luc Cooke Fortuna-based /dev/random driver for Linux.
+ */
+
+/*
+ * There is some confusion about whether and how to carry forward
+ * the state of the pools.     Seems like original Fortuna does not
+ * do it, resetting hash after each request.  I guess expecting
+ * feeding to happen more often that requesting.   This is absolutely
+ * unsuitable for pgcrypto, as nothing asynchronous happens here.
+ *
+ * J.L. Cooke fixed this by feeding previous hash to new re-initialized
+ * hash context.
+ *
+ * Fortuna predecessor Yarrow requires ability to query intermediate
+ * 'final result' from hash, without affecting it.
+ *
+ * This implementation uses the Yarrow method - asking intermediate
+ * results, but continuing with old state.
+ */
+
+
+/*
+ * Algorithm parameters
+ */
+
+/*
+ * How many pools.
+ *
+ * Original Fortuna uses 32 pools, that means 32'th pool is
+ * used not earlier than in 13th year. This is a waste in
+ * pgcrypto, as we have very low-frequancy seeding.  Here
+ * is preferable to have all entropy usable in reasonable time.
+ *
+ * With 23 pools, 23th pool is used after 9 days which seems
+ * more sane.
+ *
+ * In our case the minimal cycle time would be bit longer
+ * than the system-randomness feeding frequency.
+ */
+enum{
+       numPools        = 23,
+
+       /* in microseconds */
+       reseedInterval = 100000,        /* 0.1 sec */
+
+       /* for one big request, reseed after this many bytes */
+       reseedBytes     = (1024*1024),
+
+       /*
+       * Skip reseed if pool 0 has less than this many
+       * bytes added since last reseed.
+       */
+       pool0Fill               = (256/8),
+
+/*
+* Algorithm constants
+*/
+
+       /* Both cipher key size and hash result size */
+       block                   = 32,
+
+       /* cipher block size */
+       ciphBlock               = 16
+};
+
+
+
+
+/* for internal wrappers */
+typedef SHA256Ctx mdCtx;
+typedef rijndaelCtx ciphCtx;
+
+struct FState
+{
+       uint8_t         counter[ciphBlock];
+       uint8_t         result[ciphBlock];
+       uint8_t         key[block];
+       mdCtx           pool[numPools];
+       ciphCtx         ciph;
+       unsigned        reseedCount;
+       int32_t         lastReseedTime;
+       unsigned        pool0Bytes;
+       unsigned        rndPos;
+       int                     tricksDone;
+};
+typedef struct FState FState;
+
+
+/*
+ * Use our own wrappers here.
+ * - Need to get intermediate result from digest, without affecting it.
+ * - Need re-set key on a cipher context.
+ * - Algorithms are guaranteed to exist.
+ * - No memory allocations.
+ */
+
+static void
+ciph_init(ciphCtx * ctx, const uint8_t *key, int klen)
+{
+       rijndael_set_key(ctx, (const uint32_t *) key, klen, 1);
+}
+
+static void
+ciph_encrypt(ciphCtx * ctx, const uint8_t *in, uint8_t *out)
+{
+       rijndael_encrypt(ctx, (const uint32_t *) in, (uint32_t *) out);
+}
+
+static void
+md_init(mdCtx * ctx)
+{
+       SHA256_Init(ctx);
+}
+
+static void
+md_update(mdCtx * ctx, const uint8_t *data, int len)
+{
+       SHA256_Update(ctx, data, len);
+}
+
+static void
+md_result(mdCtx * ctx, uint8_t *dst)
+{
+       SHA256Ctx       tmp;
+
+       memmove(&tmp, ctx, sizeof(*ctx));
+       SHA256_Final(dst, &tmp);
+       memset(&tmp, 0, sizeof(tmp));
+}
+
+/*
+ * initialize state
+ */
+static void
+init_state(FState *st)
+{
+       int                     i;
+
+       memset(st, 0, sizeof(*st));
+       for (i = 0; i < numPools; i++)
+               md_init(&st->pool[i]);
+}
+
+/*
+ * Endianess does not matter.
+ * It just needs to change without repeating.
+ */
+static void
+inc_counter(FState *st)
+{
+       uint32_t           *val = (uint32_t *) st->counter;
+
+       if (++val[0])
+               return;
+       if (++val[1])
+               return;
+       if (++val[2])
+               return;
+       ++val[3];
+}
+
+/*
+ * This is called 'cipher in counter mode'.
+ */
+static void
+encrypt_counter(FState *st, uint8_t *dst)
+{
+       ciph_encrypt(&st->ciph, st->counter, dst);
+       inc_counter(st);
+}
+
+
+/*
+ * The time between reseed must be at least reseedInterval
+ * microseconds.
+ */
+static int
+enough_time_passed(FState *st)
+{
+               int                     ok;
+        int32_t now;
+        int32_t last = st->lastReseedTime;
+
+        now = seconds();
+
+        /* check how much time has passed */
+        ok = 0;
+        if (now - last >= reseedInterval)
+                ok = 1;
+
+        /* reseed will happen, update lastReseedTime */
+        if (ok)
+                st->lastReseedTime=now;
+
+        return ok;
+
+}
+
+/*
+ * generate new key from all the pools
+ */
+static void
+reseed(FState *st)
+{
+       unsigned        k;
+       unsigned        n;
+       mdCtx           key_md;
+       uint8_t         buf[block];
+
+       /* set pool as empty */
+       st->pool0Bytes = 0;
+
+       /*
+        * Both #0 and #1 reseed would use only pool 0. Just skip #0 then.
+        */
+       n = ++st->reseedCount;
+
+       /*
+        * The goal: use k-th pool only 1/(2^k) of the time.
+        */
+       md_init(&key_md);
+       for (k = 0; k < numPools; k++)
+       {
+               md_result(&st->pool[k], buf);
+               md_update(&key_md, buf, block);
+
+               if (n & 1 || !n)
+                       break;
+               n >>= 1;
+       }
+
+       /* add old key into mix too */
+       md_update(&key_md, st->key, block);
+
+       /* now we have new key */
+       md_result(&key_md, st->key);
+
+       /* use new key */
+       ciph_init(&st->ciph, st->key, block);
+
+       memset(&key_md, 0, sizeof(key_md));
+       memset(buf, 0, block);
+}
+
+/*
+ * Pick a random pool. This uses key bytes as random source.
+ */
+static unsigned
+get_rand_pool(FState *st)
+{
+       unsigned        rnd;
+
+       /*
+        * This slightly prefers lower pools - thats OK.
+        */
+       rnd = st->key[st->rndPos] % numPools;
+
+       st->rndPos++;
+       if (st->rndPos >= block)
+               st->rndPos = 0;
+
+       return rnd;
+}
+
+/*
+ * update pools
+ */
+static void
+add_entropy(FState *st, const uint8_t *data, unsigned len)
+{
+       unsigned        pos;
+       uint8_t         hash[block];
+       mdCtx           md;
+
+       /* hash given data */
+       md_init(&md);
+       md_update(&md, data, len);
+       md_result(&md, hash);
+
+       /*
+        * Make sure the pool 0 is initialized, then update randomly.
+        */
+       if (st->reseedCount == 0)
+               pos = 0;
+       else
+               pos = get_rand_pool(st);
+       md_update(&st->pool[pos], hash, block);
+
+       if (pos == 0)
+               st->pool0Bytes += len;
+
+       memset(hash, 0, block);
+       memset(&md, 0, sizeof(md));
+}
+
+/*
+ * Just take 2 next blocks as new key
+ */
+static void
+rekey(FState *st)
+{
+       encrypt_counter(st, st->key);
+       encrypt_counter(st, st->key + ciphBlock);
+       ciph_init(&st->ciph, st->key, block);
+}
+
+/*
+ * Hide public constants. (counter, pools > 0)
+ *
+ * This can also be viewed as spreading the startup
+ * entropy over all of the components.
+ */
+static void
+startup_tricks(FState *st)
+{
+       int                     i;
+       uint8_t         buf[block];
+
+       /* Use next block as counter. */
+       encrypt_counter(st, st->counter);
+
+       /* Now shuffle pools, excluding #0 */
+       for (i = 1; i < numPools; i++)
+       {
+               encrypt_counter(st, buf);
+               encrypt_counter(st, buf + ciphBlock);
+               md_update(&st->pool[i], buf, block);
+       }
+       memset(buf, 0, block);
+
+       /* Hide the key. */
+       rekey(st);
+
+       /* This can be done only once. */
+       st->tricksDone = 1;
+}
+
+static void
+extract_data(FState *st, unsigned count, uint8_t *dst)
+{
+       unsigned        n;
+       unsigned        block_nr = 0;
+
+       /* Should we reseed? */
+       if (st->pool0Bytes >= pool0Fill || st->reseedCount == 0)
+               if (enough_time_passed(st))
+                       reseed(st);
+
+       /* Do some randomization on first call */
+       if (!st->tricksDone)
+               startup_tricks(st);
+
+       while (count > 0)
+       {
+               /* produce bytes */
+               encrypt_counter(st, st->result);
+
+               /* copy result */
+               if (count > ciphBlock)
+                       n = ciphBlock;
+               else
+                       n = count;
+               memmove(dst, st->result, n);
+               dst += n;
+               count -= n;
+
+               /* must not give out too many bytes with one key */
+               block_nr++;
+               if (block_nr > (reseedBytes / ciphBlock))
+               {
+                       rekey(st);
+                       block_nr = 0;
+               }
+       }
+       /* Set new key for next request. */
+       rekey(st);
+}
+
+static FState mainState;
+static int     initDone = 0;
+
+static void init(){
+       init_state(&mainState);
+       initDone = 1;
+}
+
+/*
+ * public interface
+ */
+
+
+
+void
+fortuna_add_entropy(const uint8_t *data, unsigned len)
+{
+       if (!initDone)
+       {
+               init();
+       }
+       if (!data || !len)
+               return;
+       add_entropy(&mainState, data, len);
+}
+
+void
+fortuna_get_bytes(unsigned len, uint8_t *dst)
+{
+       if (!initDone)
+       {
+               init();
+       }
+       if (!dst || !len)
+               return;
+       extract_data(&mainState, len, dst);
+}
diff --git a/kern/lib/random/rijndael.c b/kern/lib/random/rijndael.c
new file mode 100644 (file)
index 0000000..0cc8218
--- /dev/null
@@ -0,0 +1,434 @@
+/*     $OpenBSD: rijndael.c,v 1.6 2000/12/09 18:51:34 markus Exp $ */
+
+/* contrib/pgcrypto/rijndael.c */
+
+/* This is an independent implementation of the encryption algorithm:  */
+/*                                                                                                                                             */
+/*                RIJNDAEL by Joan Daemen and Vincent Rijmen                                   */
+/*                                                                                                                                             */
+/* which is a candidate algorithm in the Advanced Encryption Standard  */
+/* programme of the US National Institute of Standards and Technology. */
+/*                                                                                                                                             */
+/* Copyright in this implementation is held by Dr B R Gladman but I            */
+/* hereby give permission for its free direct or derivative use subject */
+/* to acknowledgment of its origin and compliance with any conditions  */
+/* that the originators of the algorithm place on its exploitation.            */
+/*                                                                                                                                             */
+/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999            */
+
+/* Timing data for Rijndael (rijndael.c)
+
+Algorithm: rijndael (rijndael.c)
+
+128 bit key:
+Key Setup:       305/1389 cycles (encrypt/decrypt)
+Encrypt:          374 cycles =    68.4 mbits/sec
+Decrypt:          352 cycles =    72.7 mbits/sec
+Mean:             363 cycles =    70.5 mbits/sec
+
+192 bit key:
+Key Setup:       277/1595 cycles (encrypt/decrypt)
+Encrypt:          439 cycles =    58.3 mbits/sec
+Decrypt:          425 cycles =    60.2 mbits/sec
+Mean:             432 cycles =    59.3 mbits/sec
+
+256 bit key:
+Key Setup:       374/1960 cycles (encrypt/decrypt)
+Encrypt:          502 cycles =    51.0 mbits/sec
+Decrypt:          498 cycles =    51.4 mbits/sec
+Mean:             500 cycles =    51.2 mbits/sec
+
+*/
+#include <u.h>
+#include <libc.h>
+
+#include "rijndael.h"
+
+#include "rijndael.tbl"
+
+/* 3. Basic macros for speeding up generic operations                          */
+
+/* Circular rotate of 32 bit values                                                                    */
+
+#define rotr(x,n)      (((x) >> ((int)(n))) | ((x) << (32 - (int)(n))))
+#define rotl(x,n)      (((x) << ((int)(n))) | ((x) >> (32 - (int)(n))))
+
+/* Invert byte order in a 32 bit variable                                                      */
+
+#define bswap(x)       ((rotl((x), 8) & 0x00ff00ff) | (rotr((x), 8) & 0xff00ff00))
+
+/* Extract byte from a 32 bit quantity (little endian notation)                */
+
+#define byte(x,n)      ((uint8_t)((x) >> (8 * (n))))
+
+#define io_swap(x)     (x)
+
+#define ff_mult(a,b)   ((a) && (b) ? pow_tab[(log_tab[a] + log_tab[b]) % 255] : 0)
+
+#define f_rn(bo, bi, n, k)                                                             \
+       (bo)[n] =  ft_tab[0][byte((bi)[n],0)] ^                         \
+                        ft_tab[1][byte((bi)[((n) + 1) & 3],1)] ^       \
+                        ft_tab[2][byte((bi)[((n) + 2) & 3],2)] ^       \
+                        ft_tab[3][byte((bi)[((n) + 3) & 3],3)] ^ *((k) + (n))
+
+#define i_rn(bo, bi, n, k)                                                     \
+       (bo)[n] =  it_tab[0][byte((bi)[n],0)] ^                         \
+                        it_tab[1][byte((bi)[((n) + 3) & 3],1)] ^       \
+                        it_tab[2][byte((bi)[((n) + 2) & 3],2)] ^       \
+                        it_tab[3][byte((bi)[((n) + 1) & 3],3)] ^ *((k) + (n))
+
+#define ls_box(x)                               \
+       ( fl_tab[0][byte(x, 0)] ^        \
+         fl_tab[1][byte(x, 1)] ^        \
+         fl_tab[2][byte(x, 2)] ^        \
+         fl_tab[3][byte(x, 3)] )
+
+#define f_rl(bo, bi, n, k)                                                             \
+       (bo)[n] =  fl_tab[0][byte((bi)[n],0)] ^                         \
+                        fl_tab[1][byte((bi)[((n) + 1) & 3],1)] ^       \
+                        fl_tab[2][byte((bi)[((n) + 2) & 3],2)] ^       \
+                        fl_tab[3][byte((bi)[((n) + 3) & 3],3)] ^ *((k) + (n))
+
+#define i_rl(bo, bi, n, k)                                                             \
+       (bo)[n] =  il_tab[0][byte((bi)[n],0)] ^                         \
+                        il_tab[1][byte((bi)[((n) + 3) & 3],1)] ^       \
+                        il_tab[2][byte((bi)[((n) + 2) & 3],2)] ^       \
+                        il_tab[3][byte((bi)[((n) + 1) & 3],3)] ^ *((k) + (n))
+
+#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
+
+#define imix_col(y,x)          \
+do { \
+       u       = star_x(x);            \
+       v       = star_x(u);            \
+       w       = star_x(v);            \
+       t       = w ^ (x);                      \
+   (y) = u ^ v ^ w;            \
+   (y) ^= rotr(u ^ t,  8) ^ \
+                 rotr(v ^ t, 16) ^ \
+                 rotr(t,24);           \
+} while (0)
+
+/* initialise the key schedule from the user supplied key      */
+
+#define loop4(i)                                                                       \
+do {   t = ls_box(rotr(t,  8)) ^ rco_tab[i];              \
+       t ^= e_key[4 * i];         e_key[4 * i + 4] = t;        \
+       t ^= e_key[4 * i + 1]; e_key[4 * i + 5] = t;    \
+       t ^= e_key[4 * i + 2]; e_key[4 * i + 6] = t;    \
+       t ^= e_key[4 * i + 3]; e_key[4 * i + 7] = t;    \
+} while (0)
+
+#define loop6(i)                                                                       \
+do {   t = ls_box(rotr(t,  8)) ^ rco_tab[i];              \
+       t ^= e_key[6 * (i)];       e_key[6 * (i) + 6] = t;      \
+       t ^= e_key[6 * (i) + 1]; e_key[6 * (i) + 7] = t;        \
+       t ^= e_key[6 * (i) + 2]; e_key[6 * (i) + 8] = t;        \
+       t ^= e_key[6 * (i) + 3]; e_key[6 * (i) + 9] = t;        \
+       t ^= e_key[6 * (i) + 4]; e_key[6 * (i) + 10] = t;       \
+       t ^= e_key[6 * (i) + 5]; e_key[6 * (i) + 11] = t;       \
+} while (0)
+
+#define loop8(i)                                                                       \
+do {   t = ls_box(rotr(t,  8)) ^ rco_tab[i];              \
+       t ^= e_key[8 * (i)];     e_key[8 * (i) + 8] = t;        \
+       t ^= e_key[8 * (i) + 1]; e_key[8 * (i) + 9] = t;        \
+       t ^= e_key[8 * (i) + 2]; e_key[8 * (i) + 10] = t;       \
+       t ^= e_key[8 * (i) + 3]; e_key[8 * (i) + 11] = t;       \
+       t  = e_key[8 * (i) + 4] ^ ls_box(t);                            \
+       e_key[8 * (i) + 12] = t;                                                        \
+       t ^= e_key[8 * (i) + 5]; e_key[8 * (i) + 13] = t;       \
+       t ^= e_key[8 * (i) + 6]; e_key[8 * (i) + 14] = t;       \
+       t ^= e_key[8 * (i) + 7]; e_key[8 * (i) + 15] = t;       \
+} while (0)
+
+rijndaelCtx *
+rijndael_set_key(rijndaelCtx *ctx, const uint32_t *in_key, const uint32_t key_len,
+                                int encrypt)
+{
+       uint32_t                i,
+                               t,
+                               u,
+                               v,
+                               w;
+       uint32_t           *e_key = ctx->e_key;
+       uint32_t           *d_key = ctx->d_key;
+
+       ctx->decrypt = !encrypt;
+
+       ctx->k_len = (key_len + 31) / 32;
+
+       e_key[0] = io_swap(in_key[0]);
+       e_key[1] = io_swap(in_key[1]);
+       e_key[2] = io_swap(in_key[2]);
+       e_key[3] = io_swap(in_key[3]);
+
+       switch (ctx->k_len)
+       {
+               case 4:
+                       t = e_key[3];
+                       for (i = 0; i < 10; ++i)
+                               loop4(i);
+                       break;
+
+               case 6:
+                       e_key[4] = io_swap(in_key[4]);
+                       t = e_key[5] = io_swap(in_key[5]);
+                       for (i = 0; i < 8; ++i)
+                               loop6(i);
+                       break;
+
+               case 8:
+                       e_key[4] = io_swap(in_key[4]);
+                       e_key[5] = io_swap(in_key[5]);
+                       e_key[6] = io_swap(in_key[6]);
+                       t = e_key[7] = io_swap(in_key[7]);
+                       for (i = 0; i < 7; ++i)
+                               loop8(i);
+                       break;
+       }
+
+       if (!encrypt)
+       {
+               d_key[0] = e_key[0];
+               d_key[1] = e_key[1];
+               d_key[2] = e_key[2];
+               d_key[3] = e_key[3];
+
+               for (i = 4; i < 4 * ctx->k_len + 24; ++i)
+                       imix_col(d_key[i], e_key[i]);
+       }
+
+       return ctx;
+}
+
+/* encrypt a block of text     */
+
+#define f_nround(bo, bi, k) \
+do { \
+       f_rn(bo, bi, 0, k);             \
+       f_rn(bo, bi, 1, k);             \
+       f_rn(bo, bi, 2, k);             \
+       f_rn(bo, bi, 3, k);             \
+       k += 4;                                 \
+} while (0)
+
+#define f_lround(bo, bi, k) \
+do { \
+       f_rl(bo, bi, 0, k);             \
+       f_rl(bo, bi, 1, k);             \
+       f_rl(bo, bi, 2, k);             \
+       f_rl(bo, bi, 3, k);             \
+} while (0)
+
+void
+rijndael_encrypt(rijndaelCtx *ctx, const uint32_t *in_blk, uint32_t *out_blk)
+{
+       uint32_t                k_len = ctx->k_len;
+       uint32_t           *e_key = ctx->e_key;
+       uint32_t                b0[4],
+                               b1[4],
+                          *kp;
+
+       b0[0] = io_swap(in_blk[0]) ^ e_key[0];
+       b0[1] = io_swap(in_blk[1]) ^ e_key[1];
+       b0[2] = io_swap(in_blk[2]) ^ e_key[2];
+       b0[3] = io_swap(in_blk[3]) ^ e_key[3];
+
+       kp = e_key + 4;
+
+       if (k_len > 6)
+       {
+               f_nround(b1, b0, kp);
+               f_nround(b0, b1, kp);
+       }
+
+       if (k_len > 4)
+       {
+               f_nround(b1, b0, kp);
+               f_nround(b0, b1, kp);
+       }
+
+       f_nround(b1, b0, kp);
+       f_nround(b0, b1, kp);
+       f_nround(b1, b0, kp);
+       f_nround(b0, b1, kp);
+       f_nround(b1, b0, kp);
+       f_nround(b0, b1, kp);
+       f_nround(b1, b0, kp);
+       f_nround(b0, b1, kp);
+       f_nround(b1, b0, kp);
+       f_lround(b0, b1, kp);
+
+       out_blk[0] = io_swap(b0[0]);
+       out_blk[1] = io_swap(b0[1]);
+       out_blk[2] = io_swap(b0[2]);
+       out_blk[3] = io_swap(b0[3]);
+}
+
+/* decrypt a block of text     */
+
+#define i_nround(bo, bi, k) \
+do { \
+       i_rn(bo, bi, 0, k);             \
+       i_rn(bo, bi, 1, k);             \
+       i_rn(bo, bi, 2, k);             \
+       i_rn(bo, bi, 3, k);             \
+       k -= 4;                                 \
+} while (0)
+
+#define i_lround(bo, bi, k) \
+do { \
+       i_rl(bo, bi, 0, k);             \
+       i_rl(bo, bi, 1, k);             \
+       i_rl(bo, bi, 2, k);             \
+       i_rl(bo, bi, 3, k);             \
+} while (0)
+
+void
+rijndael_decrypt(rijndaelCtx *ctx, const uint32_t *in_blk, uint32_t *out_blk)
+{
+       uint32_t                b0[4],
+                               b1[4],
+                          *kp;
+       uint32_t                k_len = ctx->k_len;
+       uint32_t           *e_key = ctx->e_key;
+       uint32_t           *d_key = ctx->d_key;
+
+       b0[0] = io_swap(in_blk[0]) ^ e_key[4 * k_len + 24];
+       b0[1] = io_swap(in_blk[1]) ^ e_key[4 * k_len + 25];
+       b0[2] = io_swap(in_blk[2]) ^ e_key[4 * k_len + 26];
+       b0[3] = io_swap(in_blk[3]) ^ e_key[4 * k_len + 27];
+
+       kp = d_key + 4 * (k_len + 5);
+
+       if (k_len > 6)
+       {
+               i_nround(b1, b0, kp);
+               i_nround(b0, b1, kp);
+       }
+
+       if (k_len > 4)
+       {
+               i_nround(b1, b0, kp);
+               i_nround(b0, b1, kp);
+       }
+
+       i_nround(b1, b0, kp);
+       i_nround(b0, b1, kp);
+       i_nround(b1, b0, kp);
+       i_nround(b0, b1, kp);
+       i_nround(b1, b0, kp);
+       i_nround(b0, b1, kp);
+       i_nround(b1, b0, kp);
+       i_nround(b0, b1, kp);
+       i_nround(b1, b0, kp);
+       i_lround(b0, b1, kp);
+
+       out_blk[0] = io_swap(b0[0]);
+       out_blk[1] = io_swap(b0[1]);
+       out_blk[2] = io_swap(b0[2]);
+       out_blk[3] = io_swap(b0[3]);
+}
+
+/*
+ * conventional interface
+ *
+ * ATM it hopes all data is 4-byte aligned - which
+ * should be true for PX.  -marko
+ */
+
+void
+aes_set_key(rijndaelCtx *ctx, const uint8_t *key, unsigned keybits, int enc)
+{
+       uint32_t           *k;
+
+       k = (uint32_t *) key;
+       rijndael_set_key(ctx, k, keybits, enc);
+}
+
+void
+aes_ecb_encrypt(rijndaelCtx *ctx, uint8_t *data, unsigned len)
+{
+       unsigned        bs = 16;
+       uint32_t           *d;
+
+       while (len >= bs)
+       {
+               d = (uint32_t *) data;
+               rijndael_encrypt(ctx, d, d);
+
+               len -= bs;
+               data += bs;
+       }
+}
+
+void
+aes_ecb_decrypt(rijndaelCtx *ctx, uint8_t *data, unsigned len)
+{
+       unsigned        bs = 16;
+       uint32_t           *d;
+
+       while (len >= bs)
+       {
+               d = (uint32_t *) data;
+               rijndael_decrypt(ctx, d, d);
+
+               len -= bs;
+               data += bs;
+       }
+}
+
+void
+aes_cbc_encrypt(rijndaelCtx *ctx, uint8_t *iva, uint8_t *data, unsigned len)
+{
+       uint32_t           *iv = (uint32_t *) iva;
+       uint32_t           *d = (uint32_t *) data;
+       unsigned        bs = 16;
+
+       while (len >= bs)
+       {
+               d[0] ^= iv[0];
+               d[1] ^= iv[1];
+               d[2] ^= iv[2];
+               d[3] ^= iv[3];
+
+               rijndael_encrypt(ctx, d, d);
+
+               iv = d;
+               d += bs / 4;
+               len -= bs;
+       }
+}
+
+void
+aes_cbc_decrypt(rijndaelCtx *ctx, uint8_t *iva, uint8_t *data, unsigned len)
+{
+       uint32_t           *d = (uint32_t *) data;
+       unsigned        bs = 16;
+       uint32_t                buf[4],
+                               iv[4];
+
+       memcpy(iv, iva, bs);
+       while (len >= bs)
+       {
+               buf[0] = d[0];
+               buf[1] = d[1];
+               buf[2] = d[2];
+               buf[3] = d[3];
+
+               rijndael_decrypt(ctx, buf, d);
+
+               d[0] ^= iv[0];
+               d[1] ^= iv[1];
+               d[2] ^= iv[2];
+               d[3] ^= iv[3];
+
+               iv[0] = buf[0];
+               iv[1] = buf[1];
+               iv[2] = buf[2];
+               iv[3] = buf[3];
+               d += 4;
+               len -= bs;
+       }
+}
diff --git a/kern/lib/random/rijndael.tbl b/kern/lib/random/rijndael.tbl
new file mode 100644 (file)
index 0000000..130a7a6
--- /dev/null
@@ -0,0 +1,1138 @@
+/* Generated by rijndael.c */
+
+const uint8_t  pow_tab[256] = {
+  1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
+  95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
+  229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
+  83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
+  76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
+  131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
+  181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
+  254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
+  251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
+  195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
+  159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+  155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
+  252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
+  69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
+  18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
+  57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1
+};
+
+const uint8_t  log_tab[256] = {
+  1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
+  95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
+  229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
+  83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
+  76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
+  131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
+  181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
+  254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
+  251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
+  195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
+  159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+  155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
+  252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
+  69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
+  18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
+  57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1
+};
+
+const uint8_t  sbx_tab[256] = {
+  1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
+  95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
+  229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
+  83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
+  76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
+  131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
+  181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
+  254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
+  251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
+  195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
+  159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+  155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
+  252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
+  69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
+  18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
+  57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1
+};
+
+const uint8_t  isb_tab[256] = {
+  1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
+  95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
+  229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
+  83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
+  76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
+  131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
+  181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
+  254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
+  251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
+  195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
+  159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+  155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
+  252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
+  69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
+  18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
+  57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1
+};
+
+const uint32_t  ft_tab[4][256] = {
+{
+  0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6,
+  0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591,
+  0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56,
+  0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec,
+  0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
+  0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb,
+  0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45,
+  0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b,
+  0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
+  0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
+  0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9,
+  0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
+  0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d,
+  0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f,
+  0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
+  0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea,
+  0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34,
+  0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
+  0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d,
+  0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
+  0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1,
+  0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6,
+  0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972,
+  0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
+  0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
+  0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511,
+  0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe,
+  0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b,
+  0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05,
+  0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
+  0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142,
+  0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf,
+  0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
+  0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e,
+  0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
+  0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
+  0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3,
+  0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b,
+  0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
+  0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
+  0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14,
+  0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8,
+  0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4,
+  0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2,
+  0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
+  0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949,
+  0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf,
+  0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
+  0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c,
+  0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
+  0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
+  0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f,
+  0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc,
+  0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c,
+  0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
+  0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27,
+  0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
+  0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433,
+  0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9,
+  0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
+  0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a,
+  0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0,
+  0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
+  0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c
+}, {
+  0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d,
+  0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154,
+  0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d,
+  0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a,
+  0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87,
+  0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b,
+  0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea,
+  0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b,
+  0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a,
+  0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f,
+  0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908,
+  0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f,
+  0x0404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e,
+  0x18183028, 0x969637a1, 0x05050a0f, 0x9a9a2fb5,
+  0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,
+  0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f,
+  0x0909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e,
+  0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb,
+  0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce,
+  0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397,
+  0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c,
+  0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed,
+  0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b,
+  0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a,
+  0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16,
+  0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194,
+  0x45458acf, 0xf9f9e910, 0x02020406, 0x7f7ffe81,
+  0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3,
+  0x5151a2f3, 0xa3a35dfe, 0x404080c0, 0x8f8f058a,
+  0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
+  0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263,
+  0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d,
+  0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f,
+  0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39,
+  0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47,
+  0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695,
+  0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f,
+  0x22224466, 0x2a2a547e, 0x90903bab, 0x88880b83,
+  0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c,
+  0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76,
+  0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e,
+  0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4,
+  0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6,
+  0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b,
+  0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,
+  0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0,
+  0x6c6cd8b4, 0x5656acfa, 0xf4f4f307, 0xeaeacf25,
+  0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018,
+  0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72,
+  0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751,
+  0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21,
+  0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85,
+  0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa,
+  0x484890d8, 0x03030605, 0xf6f6f701, 0x0e0e1c12,
+  0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0,
+  0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9,
+  0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233,
+  0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7,
+  0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920,
+  0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
+  0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17,
+  0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8,
+  0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11,
+  0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a
+}, {
+  0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b,
+  0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5,
+  0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b,
+  0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76,
+  0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d,
+  0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0,
+  0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf,
+  0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0,
+  0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26,
+  0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc,
+  0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1,
+  0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15,
+  0x04080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3,
+  0x18302818, 0x9637a196, 0x050a0f05, 0x9a2fb59a,
+  0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,
+  0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75,
+  0x09121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a,
+  0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0,
+  0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3,
+  0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784,
+  0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced,
+  0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b,
+  0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39,
+  0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf,
+  0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb,
+  0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485,
+  0x458acf45, 0xf9e910f9, 0x02040602, 0x7ffe817f,
+  0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8,
+  0x51a2f351, 0xa35dfea3, 0x4080c040, 0x8f058a8f,
+  0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
+  0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321,
+  0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2,
+  0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec,
+  0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917,
+  0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d,
+  0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573,
+  0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc,
+  0x22446622, 0x2a547e2a, 0x903bab90, 0x880b8388,
+  0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14,
+  0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db,
+  0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a,
+  0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c,
+  0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662,
+  0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79,
+  0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,
+  0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9,
+  0x6cd8b46c, 0x56acfa56, 0xf4f307f4, 0xeacf25ea,
+  0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808,
+  0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e,
+  0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6,
+  0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f,
+  0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a,
+  0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66,
+  0x4890d848, 0x03060503, 0xf6f701f6, 0x0e1c120e,
+  0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9,
+  0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e,
+  0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311,
+  0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794,
+  0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9,
+  0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
+  0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d,
+  0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868,
+  0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f,
+  0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16
+}, {
+  0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b,
+  0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5,
+  0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b,
+  0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676,
+  0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d,
+  0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0,
+  0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf,
+  0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0,
+  0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626,
+  0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc,
+  0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1,
+  0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515,
+  0x080c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3,
+  0x30281818, 0x37a19696, 0x0a0f0505, 0x2fb59a9a,
+  0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,
+  0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575,
+  0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a,
+  0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0,
+  0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3,
+  0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484,
+  0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded,
+  0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b,
+  0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939,
+  0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf,
+  0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb,
+  0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585,
+  0x8acf4545, 0xe910f9f9, 0x04060202, 0xfe817f7f,
+  0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8,
+  0xa2f35151, 0x5dfea3a3, 0x80c04040, 0x058a8f8f,
+  0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
+  0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121,
+  0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2,
+  0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec,
+  0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717,
+  0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d,
+  0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373,
+  0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc,
+  0x44662222, 0x547e2a2a, 0x3bab9090, 0x0b838888,
+  0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414,
+  0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb,
+  0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a,
+  0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c,
+  0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262,
+  0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979,
+  0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,
+  0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9,
+  0xd8b46c6c, 0xacfa5656, 0xf307f4f4, 0xcf25eaea,
+  0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808,
+  0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e,
+  0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6,
+  0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f,
+  0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a,
+  0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666,
+  0x90d84848, 0x06050303, 0xf701f6f6, 0x1c120e0e,
+  0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9,
+  0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e,
+  0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111,
+  0xd2bb6969, 0xa970d9d9, 0x07898e8e, 0x33a79494,
+  0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9,
+  0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
+  0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d,
+  0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868,
+  0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f,
+  0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616
+}
+};
+
+const uint32_t  it_tab[4][256] = {
+{
+  0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a,
+  0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b,
+  0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5,
+  0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5,
+  0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
+  0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b,
+  0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295,
+  0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e,
+  0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927,
+  0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
+  0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362,
+  0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9,
+  0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52,
+  0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566,
+  0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
+  0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed,
+  0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e,
+  0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4,
+  0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4,
+  0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
+  0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d,
+  0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060,
+  0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967,
+  0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879,
+  0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
+  0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c,
+  0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36,
+  0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624,
+  0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b,
+  0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
+  0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12,
+  0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14,
+  0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3,
+  0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b,
+  0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
+  0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684,
+  0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7,
+  0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177,
+  0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947,
+  0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
+  0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498,
+  0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f,
+  0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54,
+  0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382,
+  0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
+  0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb,
+  0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83,
+  0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef,
+  0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029,
+  0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
+  0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733,
+  0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117,
+  0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4,
+  0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546,
+  0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
+  0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d,
+  0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb,
+  0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a,
+  0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773,
+  0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
+  0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2,
+  0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff,
+  0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664,
+  0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0
+}, {
+  0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96,
+  0x6bab3bcb, 0x459d1ff1, 0x58faacab, 0x03e34b93,
+  0xfa302055, 0x6d76adf6, 0x76cc8891, 0x4c02f525,
+  0xd7e54ffc, 0xcb2ac5d7, 0x44352680, 0xa362b58f,
+  0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1,
+  0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6,
+  0x5f8f03e7, 0x9c921595, 0x7a6dbfeb, 0x595295da,
+  0x83bed42d, 0x217458d3, 0x69e04929, 0xc8c98e44,
+  0x89c2756a, 0x798ef478, 0x3e58996b, 0x71b927dd,
+  0x4fe1beb6, 0xad88f017, 0xac20c966, 0x3ace7db4,
+  0x4adf6318, 0x311ae582, 0x33519760, 0x7f536245,
+  0x7764b1e0, 0xae6bbb84, 0xa081fe1c, 0x2b08f994,
+  0x68487058, 0xfd458f19, 0x6cde9487, 0xf87b52b7,
+  0xd373ab23, 0x024b72e2, 0x8f1fe357, 0xab55662a,
+  0x28ebb207, 0xc2b52f03, 0x7bc5869a, 0x0837d3a5,
+  0x872830f2, 0xa5bf23b2, 0x6a0302ba, 0x8216ed5c,
+  0x1ccf8a2b, 0xb479a792, 0xf207f3f0, 0xe2694ea1,
+  0xf4da65cd, 0xbe0506d5, 0x6234d11f, 0xfea6c48a,
+  0x532e349d, 0x55f3a2a0, 0xe18a0532, 0xebf6a475,
+  0xec830b39, 0xef6040aa, 0x9f715e06, 0x106ebd51,
+  0x8a213ef9, 0x06dd963d, 0x053eddae, 0xbde64d46,
+  0x8d5491b5, 0x5dc47105, 0xd406046f, 0x155060ff,
+  0xfb981924, 0xe9bdd697, 0x434089cc, 0x9ed96777,
+  0x42e8b0bd, 0x8b890788, 0x5b19e738, 0xeec879db,
+  0x0a7ca147, 0x0f427ce9, 0x1e84f8c9, 0x00000000,
+  0x86800983, 0xed2b3248, 0x70111eac, 0x725a6c4e,
+  0xff0efdfb, 0x38850f56, 0xd5ae3d1e, 0x392d3627,
+  0xd90f0a64, 0xa65c6821, 0x545b9bd1, 0x2e36243a,
+  0x670a0cb1, 0xe757930f, 0x96eeb4d2, 0x919b1b9e,
+  0xc5c0804f, 0x20dc61a2, 0x4b775a69, 0x1a121c16,
+  0xba93e20a, 0x2aa0c0e5, 0xe0223c43, 0x171b121d,
+  0x0d090e0b, 0xc78bf2ad, 0xa8b62db9, 0xa91e14c8,
+  0x19f15785, 0x0775af4c, 0xdd99eebb, 0x607fa3fd,
+  0x2601f79f, 0xf5725cbc, 0x3b6644c5, 0x7efb5b34,
+  0x29438b76, 0xc623cbdc, 0xfcedb668, 0xf1e4b863,
+  0xdc31d7ca, 0x85634210, 0x22971340, 0x11c68420,
+  0x244a857d, 0x3dbbd2f8, 0x32f9ae11, 0xa129c76d,
+  0x2f9e1d4b, 0x30b2dcf3, 0x52860dec, 0xe3c177d0,
+  0x16b32b6c, 0xb970a999, 0x489411fa, 0x64e94722,
+  0x8cfca8c4, 0x3ff0a01a, 0x2c7d56d8, 0x903322ef,
+  0x4e4987c7, 0xd138d9c1, 0xa2ca8cfe, 0x0bd49836,
+  0x81f5a6cf, 0xde7aa528, 0x8eb7da26, 0xbfad3fa4,
+  0x9d3a2ce4, 0x9278500d, 0xcc5f6a9b, 0x467e5462,
+  0x138df6c2, 0xb8d890e8, 0xf7392e5e, 0xafc382f5,
+  0x805d9fbe, 0x93d0697c, 0x2dd56fa9, 0x1225cfb3,
+  0x99acc83b, 0x7d1810a7, 0x639ce86e, 0xbb3bdb7b,
+  0x7826cd09, 0x18596ef4, 0xb79aec01, 0x9a4f83a8,
+  0x6e95e665, 0xe6ffaa7e, 0xcfbc2108, 0xe815efe6,
+  0x9be7bad9, 0x366f4ace, 0x099fead4, 0x7cb029d6,
+  0xb2a431af, 0x233f2a31, 0x94a5c630, 0x66a235c0,
+  0xbc4e7437, 0xca82fca6, 0xd090e0b0, 0xd8a73315,
+  0x9804f14a, 0xdaec41f7, 0x50cd7f0e, 0xf691172f,
+  0xd64d768d, 0xb0ef434d, 0x4daacc54, 0x0496e4df,
+  0xb5d19ee3, 0x886a4c1b, 0x1f2cc1b8, 0x5165467f,
+  0xea5e9d04, 0x358c015d, 0x7487fa73, 0x410bfb2e,
+  0x1d67b35a, 0xd2db9252, 0x5610e933, 0x47d66d13,
+  0x61d79a8c, 0x0ca1377a, 0x14f8598e, 0x3c13eb89,
+  0x27a9ceee, 0xc961b735, 0xe51ce1ed, 0xb1477a3c,
+  0xdfd29c59, 0x73f2553f, 0xce141879, 0x37c773bf,
+  0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886,
+  0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f,
+  0xc31d1672, 0x25e2bc0c, 0x493c288b, 0x950dff41,
+  0x01a83971, 0xb30c08de, 0xe4b4d89c, 0xc1566490,
+  0x84cb7b61, 0xb632d570, 0x5c6c4874, 0x57b8d042
+}, {
+  0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e,
+  0xab3bcb6b, 0x9d1ff145, 0xfaacab58, 0xe34b9303,
+  0x302055fa, 0x76adf66d, 0xcc889176, 0x02f5254c,
+  0xe54ffcd7, 0x2ac5d7cb, 0x35268044, 0x62b58fa3,
+  0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0,
+  0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9,
+  0x8f03e75f, 0x9215959c, 0x6dbfeb7a, 0x5295da59,
+  0xbed42d83, 0x7458d321, 0xe0492969, 0xc98e44c8,
+  0xc2756a89, 0x8ef47879, 0x58996b3e, 0xb927dd71,
+  0xe1beb64f, 0x88f017ad, 0x20c966ac, 0xce7db43a,
+  0xdf63184a, 0x1ae58231, 0x51976033, 0x5362457f,
+  0x64b1e077, 0x6bbb84ae, 0x81fe1ca0, 0x08f9942b,
+  0x48705868, 0x458f19fd, 0xde94876c, 0x7b52b7f8,
+  0x73ab23d3, 0x4b72e202, 0x1fe3578f, 0x55662aab,
+  0xebb20728, 0xb52f03c2, 0xc5869a7b, 0x37d3a508,
+  0x2830f287, 0xbf23b2a5, 0x0302ba6a, 0x16ed5c82,
+  0xcf8a2b1c, 0x79a792b4, 0x07f3f0f2, 0x694ea1e2,
+  0xda65cdf4, 0x0506d5be, 0x34d11f62, 0xa6c48afe,
+  0x2e349d53, 0xf3a2a055, 0x8a0532e1, 0xf6a475eb,
+  0x830b39ec, 0x6040aaef, 0x715e069f, 0x6ebd5110,
+  0x213ef98a, 0xdd963d06, 0x3eddae05, 0xe64d46bd,
+  0x5491b58d, 0xc471055d, 0x06046fd4, 0x5060ff15,
+  0x981924fb, 0xbdd697e9, 0x4089cc43, 0xd967779e,
+  0xe8b0bd42, 0x8907888b, 0x19e7385b, 0xc879dbee,
+  0x7ca1470a, 0x427ce90f, 0x84f8c91e, 0x00000000,
+  0x80098386, 0x2b3248ed, 0x111eac70, 0x5a6c4e72,
+  0x0efdfbff, 0x850f5638, 0xae3d1ed5, 0x2d362739,
+  0x0f0a64d9, 0x5c6821a6, 0x5b9bd154, 0x36243a2e,
+  0x0a0cb167, 0x57930fe7, 0xeeb4d296, 0x9b1b9e91,
+  0xc0804fc5, 0xdc61a220, 0x775a694b, 0x121c161a,
+  0x93e20aba, 0xa0c0e52a, 0x223c43e0, 0x1b121d17,
+  0x090e0b0d, 0x8bf2adc7, 0xb62db9a8, 0x1e14c8a9,
+  0xf1578519, 0x75af4c07, 0x99eebbdd, 0x7fa3fd60,
+  0x01f79f26, 0x725cbcf5, 0x6644c53b, 0xfb5b347e,
+  0x438b7629, 0x23cbdcc6, 0xedb668fc, 0xe4b863f1,
+  0x31d7cadc, 0x63421085, 0x97134022, 0xc6842011,
+  0x4a857d24, 0xbbd2f83d, 0xf9ae1132, 0x29c76da1,
+  0x9e1d4b2f, 0xb2dcf330, 0x860dec52, 0xc177d0e3,
+  0xb32b6c16, 0x70a999b9, 0x9411fa48, 0xe9472264,
+  0xfca8c48c, 0xf0a01a3f, 0x7d56d82c, 0x3322ef90,
+  0x4987c74e, 0x38d9c1d1, 0xca8cfea2, 0xd498360b,
+  0xf5a6cf81, 0x7aa528de, 0xb7da268e, 0xad3fa4bf,
+  0x3a2ce49d, 0x78500d92, 0x5f6a9bcc, 0x7e546246,
+  0x8df6c213, 0xd890e8b8, 0x392e5ef7, 0xc382f5af,
+  0x5d9fbe80, 0xd0697c93, 0xd56fa92d, 0x25cfb312,
+  0xacc83b99, 0x1810a77d, 0x9ce86e63, 0x3bdb7bbb,
+  0x26cd0978, 0x596ef418, 0x9aec01b7, 0x4f83a89a,
+  0x95e6656e, 0xffaa7ee6, 0xbc2108cf, 0x15efe6e8,
+  0xe7bad99b, 0x6f4ace36, 0x9fead409, 0xb029d67c,
+  0xa431afb2, 0x3f2a3123, 0xa5c63094, 0xa235c066,
+  0x4e7437bc, 0x82fca6ca, 0x90e0b0d0, 0xa73315d8,
+  0x04f14a98, 0xec41f7da, 0xcd7f0e50, 0x91172ff6,
+  0x4d768dd6, 0xef434db0, 0xaacc544d, 0x96e4df04,
+  0xd19ee3b5, 0x6a4c1b88, 0x2cc1b81f, 0x65467f51,
+  0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0x0bfb2e41,
+  0x67b35a1d, 0xdb9252d2, 0x10e93356, 0xd66d1347,
+  0xd79a8c61, 0xa1377a0c, 0xf8598e14, 0x13eb893c,
+  0xa9ceee27, 0x61b735c9, 0x1ce1ede5, 0x477a3cb1,
+  0xd29c59df, 0xf2553f73, 0x141879ce, 0xc773bf37,
+  0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db,
+  0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40,
+  0x1d1672c3, 0xe2bc0c25, 0x3c288b49, 0x0dff4195,
+  0xa8397101, 0x0c08deb3, 0xb4d89ce4, 0x566490c1,
+  0xcb7b6184, 0x32d570b6, 0x6c48745c, 0xb8d04257
+}, {
+  0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27,
+  0x3bcb6bab, 0x1ff1459d, 0xacab58fa, 0x4b9303e3,
+  0x2055fa30, 0xadf66d76, 0x889176cc, 0xf5254c02,
+  0x4ffcd7e5, 0xc5d7cb2a, 0x26804435, 0xb58fa362,
+  0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe,
+  0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3,
+  0x03e75f8f, 0x15959c92, 0xbfeb7a6d, 0x95da5952,
+  0xd42d83be, 0x58d32174, 0x492969e0, 0x8e44c8c9,
+  0x756a89c2, 0xf478798e, 0x996b3e58, 0x27dd71b9,
+  0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace,
+  0x63184adf, 0xe582311a, 0x97603351, 0x62457f53,
+  0xb1e07764, 0xbb84ae6b, 0xfe1ca081, 0xf9942b08,
+  0x70586848, 0x8f19fd45, 0x94876cde, 0x52b7f87b,
+  0xab23d373, 0x72e2024b, 0xe3578f1f, 0x662aab55,
+  0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837,
+  0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216,
+  0x8a2b1ccf, 0xa792b479, 0xf3f0f207, 0x4ea1e269,
+  0x65cdf4da, 0x06d5be05, 0xd11f6234, 0xc48afea6,
+  0x349d532e, 0xa2a055f3, 0x0532e18a, 0xa475ebf6,
+  0x0b39ec83, 0x40aaef60, 0x5e069f71, 0xbd51106e,
+  0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6,
+  0x91b58d54, 0x71055dc4, 0x046fd406, 0x60ff1550,
+  0x1924fb98, 0xd697e9bd, 0x89cc4340, 0x67779ed9,
+  0xb0bd42e8, 0x07888b89, 0xe7385b19, 0x79dbeec8,
+  0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000,
+  0x09838680, 0x3248ed2b, 0x1eac7011, 0x6c4e725a,
+  0xfdfbff0e, 0x0f563885, 0x3d1ed5ae, 0x3627392d,
+  0x0a64d90f, 0x6821a65c, 0x9bd1545b, 0x243a2e36,
+  0x0cb1670a, 0x930fe757, 0xb4d296ee, 0x1b9e919b,
+  0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12,
+  0xe20aba93, 0xc0e52aa0, 0x3c43e022, 0x121d171b,
+  0x0e0b0d09, 0xf2adc78b, 0x2db9a8b6, 0x14c8a91e,
+  0x578519f1, 0xaf4c0775, 0xeebbdd99, 0xa3fd607f,
+  0xf79f2601, 0x5cbcf572, 0x44c53b66, 0x5b347efb,
+  0x8b762943, 0xcbdcc623, 0xb668fced, 0xb863f1e4,
+  0xd7cadc31, 0x42108563, 0x13402297, 0x842011c6,
+  0x857d244a, 0xd2f83dbb, 0xae1132f9, 0xc76da129,
+  0x1d4b2f9e, 0xdcf330b2, 0x0dec5286, 0x77d0e3c1,
+  0x2b6c16b3, 0xa999b970, 0x11fa4894, 0x472264e9,
+  0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, 0x22ef9033,
+  0x87c74e49, 0xd9c1d138, 0x8cfea2ca, 0x98360bd4,
+  0xa6cf81f5, 0xa528de7a, 0xda268eb7, 0x3fa4bfad,
+  0x2ce49d3a, 0x500d9278, 0x6a9bcc5f, 0x5462467e,
+  0xf6c2138d, 0x90e8b8d8, 0x2e5ef739, 0x82f5afc3,
+  0x9fbe805d, 0x697c93d0, 0x6fa92dd5, 0xcfb31225,
+  0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b,
+  0xcd097826, 0x6ef41859, 0xec01b79a, 0x83a89a4f,
+  0xe6656e95, 0xaa7ee6ff, 0x2108cfbc, 0xefe6e815,
+  0xbad99be7, 0x4ace366f, 0xead4099f, 0x29d67cb0,
+  0x31afb2a4, 0x2a31233f, 0xc63094a5, 0x35c066a2,
+  0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7,
+  0xf14a9804, 0x41f7daec, 0x7f0e50cd, 0x172ff691,
+  0x768dd64d, 0x434db0ef, 0xcc544daa, 0xe4df0496,
+  0x9ee3b5d1, 0x4c1b886a, 0xc1b81f2c, 0x467f5165,
+  0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b,
+  0xb35a1d67, 0x9252d2db, 0xe9335610, 0x6d1347d6,
+  0x9a8c61d7, 0x377a0ca1, 0x598e14f8, 0xeb893c13,
+  0xceee27a9, 0xb735c961, 0xe1ede51c, 0x7a3cb147,
+  0x9c59dfd2, 0x553f73f2, 0x1879ce14, 0x73bf37c7,
+  0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44,
+  0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3,
+  0x1672c31d, 0xbc0c25e2, 0x288b493c, 0xff41950d,
+  0x397101a8, 0x08deb30c, 0xd89ce4b4, 0x6490c156,
+  0x7b6184cb, 0xd570b632, 0x48745c6c, 0xd04257b8
+}
+};
+
+const uint32_t  fl_tab[4][256] = {
+{
+  0x00000063, 0x0000007c, 0x00000077, 0x0000007b,
+  0x000000f2, 0x0000006b, 0x0000006f, 0x000000c5,
+  0x00000030, 0x00000001, 0x00000067, 0x0000002b,
+  0x000000fe, 0x000000d7, 0x000000ab, 0x00000076,
+  0x000000ca, 0x00000082, 0x000000c9, 0x0000007d,
+  0x000000fa, 0x00000059, 0x00000047, 0x000000f0,
+  0x000000ad, 0x000000d4, 0x000000a2, 0x000000af,
+  0x0000009c, 0x000000a4, 0x00000072, 0x000000c0,
+  0x000000b7, 0x000000fd, 0x00000093, 0x00000026,
+  0x00000036, 0x0000003f, 0x000000f7, 0x000000cc,
+  0x00000034, 0x000000a5, 0x000000e5, 0x000000f1,
+  0x00000071, 0x000000d8, 0x00000031, 0x00000015,
+  0x00000004, 0x000000c7, 0x00000023, 0x000000c3,
+  0x00000018, 0x00000096, 0x00000005, 0x0000009a,
+  0x00000007, 0x00000012, 0x00000080, 0x000000e2,
+  0x000000eb, 0x00000027, 0x000000b2, 0x00000075,
+  0x00000009, 0x00000083, 0x0000002c, 0x0000001a,
+  0x0000001b, 0x0000006e, 0x0000005a, 0x000000a0,
+  0x00000052, 0x0000003b, 0x000000d6, 0x000000b3,
+  0x00000029, 0x000000e3, 0x0000002f, 0x00000084,
+  0x00000053, 0x000000d1, 0x00000000, 0x000000ed,
+  0x00000020, 0x000000fc, 0x000000b1, 0x0000005b,
+  0x0000006a, 0x000000cb, 0x000000be, 0x00000039,
+  0x0000004a, 0x0000004c, 0x00000058, 0x000000cf,
+  0x000000d0, 0x000000ef, 0x000000aa, 0x000000fb,
+  0x00000043, 0x0000004d, 0x00000033, 0x00000085,
+  0x00000045, 0x000000f9, 0x00000002, 0x0000007f,
+  0x00000050, 0x0000003c, 0x0000009f, 0x000000a8,
+  0x00000051, 0x000000a3, 0x00000040, 0x0000008f,
+  0x00000092, 0x0000009d, 0x00000038, 0x000000f5,
+  0x000000bc, 0x000000b6, 0x000000da, 0x00000021,
+  0x00000010, 0x000000ff, 0x000000f3, 0x000000d2,
+  0x000000cd, 0x0000000c, 0x00000013, 0x000000ec,
+  0x0000005f, 0x00000097, 0x00000044, 0x00000017,
+  0x000000c4, 0x000000a7, 0x0000007e, 0x0000003d,
+  0x00000064, 0x0000005d, 0x00000019, 0x00000073,
+  0x00000060, 0x00000081, 0x0000004f, 0x000000dc,
+  0x00000022, 0x0000002a, 0x00000090, 0x00000088,
+  0x00000046, 0x000000ee, 0x000000b8, 0x00000014,
+  0x000000de, 0x0000005e, 0x0000000b, 0x000000db,
+  0x000000e0, 0x00000032, 0x0000003a, 0x0000000a,
+  0x00000049, 0x00000006, 0x00000024, 0x0000005c,
+  0x000000c2, 0x000000d3, 0x000000ac, 0x00000062,
+  0x00000091, 0x00000095, 0x000000e4, 0x00000079,
+  0x000000e7, 0x000000c8, 0x00000037, 0x0000006d,
+  0x0000008d, 0x000000d5, 0x0000004e, 0x000000a9,
+  0x0000006c, 0x00000056, 0x000000f4, 0x000000ea,
+  0x00000065, 0x0000007a, 0x000000ae, 0x00000008,
+  0x000000ba, 0x00000078, 0x00000025, 0x0000002e,
+  0x0000001c, 0x000000a6, 0x000000b4, 0x000000c6,
+  0x000000e8, 0x000000dd, 0x00000074, 0x0000001f,
+  0x0000004b, 0x000000bd, 0x0000008b, 0x0000008a,
+  0x00000070, 0x0000003e, 0x000000b5, 0x00000066,
+  0x00000048, 0x00000003, 0x000000f6, 0x0000000e,
+  0x00000061, 0x00000035, 0x00000057, 0x000000b9,
+  0x00000086, 0x000000c1, 0x0000001d, 0x0000009e,
+  0x000000e1, 0x000000f8, 0x00000098, 0x00000011,
+  0x00000069, 0x000000d9, 0x0000008e, 0x00000094,
+  0x0000009b, 0x0000001e, 0x00000087, 0x000000e9,
+  0x000000ce, 0x00000055, 0x00000028, 0x000000df,
+  0x0000008c, 0x000000a1, 0x00000089, 0x0000000d,
+  0x000000bf, 0x000000e6, 0x00000042, 0x00000068,
+  0x00000041, 0x00000099, 0x0000002d, 0x0000000f,
+  0x000000b0, 0x00000054, 0x000000bb, 0x00000016
+}, {
+  0x00006300, 0x00007c00, 0x00007700, 0x00007b00,
+  0x0000f200, 0x00006b00, 0x00006f00, 0x0000c500,
+  0x00003000, 0x00000100, 0x00006700, 0x00002b00,
+  0x0000fe00, 0x0000d700, 0x0000ab00, 0x00007600,
+  0x0000ca00, 0x00008200, 0x0000c900, 0x00007d00,
+  0x0000fa00, 0x00005900, 0x00004700, 0x0000f000,
+  0x0000ad00, 0x0000d400, 0x0000a200, 0x0000af00,
+  0x00009c00, 0x0000a400, 0x00007200, 0x0000c000,
+  0x0000b700, 0x0000fd00, 0x00009300, 0x00002600,
+  0x00003600, 0x00003f00, 0x0000f700, 0x0000cc00,
+  0x00003400, 0x0000a500, 0x0000e500, 0x0000f100,
+  0x00007100, 0x0000d800, 0x00003100, 0x00001500,
+  0x00000400, 0x0000c700, 0x00002300, 0x0000c300,
+  0x00001800, 0x00009600, 0x00000500, 0x00009a00,
+  0x00000700, 0x00001200, 0x00008000, 0x0000e200,
+  0x0000eb00, 0x00002700, 0x0000b200, 0x00007500,
+  0x00000900, 0x00008300, 0x00002c00, 0x00001a00,
+  0x00001b00, 0x00006e00, 0x00005a00, 0x0000a000,
+  0x00005200, 0x00003b00, 0x0000d600, 0x0000b300,
+  0x00002900, 0x0000e300, 0x00002f00, 0x00008400,
+  0x00005300, 0x0000d100, 0x00000000, 0x0000ed00,
+  0x00002000, 0x0000fc00, 0x0000b100, 0x00005b00,
+  0x00006a00, 0x0000cb00, 0x0000be00, 0x00003900,
+  0x00004a00, 0x00004c00, 0x00005800, 0x0000cf00,
+  0x0000d000, 0x0000ef00, 0x0000aa00, 0x0000fb00,
+  0x00004300, 0x00004d00, 0x00003300, 0x00008500,
+  0x00004500, 0x0000f900, 0x00000200, 0x00007f00,
+  0x00005000, 0x00003c00, 0x00009f00, 0x0000a800,
+  0x00005100, 0x0000a300, 0x00004000, 0x00008f00,
+  0x00009200, 0x00009d00, 0x00003800, 0x0000f500,
+  0x0000bc00, 0x0000b600, 0x0000da00, 0x00002100,
+  0x00001000, 0x0000ff00, 0x0000f300, 0x0000d200,
+  0x0000cd00, 0x00000c00, 0x00001300, 0x0000ec00,
+  0x00005f00, 0x00009700, 0x00004400, 0x00001700,
+  0x0000c400, 0x0000a700, 0x00007e00, 0x00003d00,
+  0x00006400, 0x00005d00, 0x00001900, 0x00007300,
+  0x00006000, 0x00008100, 0x00004f00, 0x0000dc00,
+  0x00002200, 0x00002a00, 0x00009000, 0x00008800,
+  0x00004600, 0x0000ee00, 0x0000b800, 0x00001400,
+  0x0000de00, 0x00005e00, 0x00000b00, 0x0000db00,
+  0x0000e000, 0x00003200, 0x00003a00, 0x00000a00,
+  0x00004900, 0x00000600, 0x00002400, 0x00005c00,
+  0x0000c200, 0x0000d300, 0x0000ac00, 0x00006200,
+  0x00009100, 0x00009500, 0x0000e400, 0x00007900,
+  0x0000e700, 0x0000c800, 0x00003700, 0x00006d00,
+  0x00008d00, 0x0000d500, 0x00004e00, 0x0000a900,
+  0x00006c00, 0x00005600, 0x0000f400, 0x0000ea00,
+  0x00006500, 0x00007a00, 0x0000ae00, 0x00000800,
+  0x0000ba00, 0x00007800, 0x00002500, 0x00002e00,
+  0x00001c00, 0x0000a600, 0x0000b400, 0x0000c600,
+  0x0000e800, 0x0000dd00, 0x00007400, 0x00001f00,
+  0x00004b00, 0x0000bd00, 0x00008b00, 0x00008a00,
+  0x00007000, 0x00003e00, 0x0000b500, 0x00006600,
+  0x00004800, 0x00000300, 0x0000f600, 0x00000e00,
+  0x00006100, 0x00003500, 0x00005700, 0x0000b900,
+  0x00008600, 0x0000c100, 0x00001d00, 0x00009e00,
+  0x0000e100, 0x0000f800, 0x00009800, 0x00001100,
+  0x00006900, 0x0000d900, 0x00008e00, 0x00009400,
+  0x00009b00, 0x00001e00, 0x00008700, 0x0000e900,
+  0x0000ce00, 0x00005500, 0x00002800, 0x0000df00,
+  0x00008c00, 0x0000a100, 0x00008900, 0x00000d00,
+  0x0000bf00, 0x0000e600, 0x00004200, 0x00006800,
+  0x00004100, 0x00009900, 0x00002d00, 0x00000f00,
+  0x0000b000, 0x00005400, 0x0000bb00, 0x00001600
+}, {
+  0x00630000, 0x007c0000, 0x00770000, 0x007b0000,
+  0x00f20000, 0x006b0000, 0x006f0000, 0x00c50000,
+  0x00300000, 0x00010000, 0x00670000, 0x002b0000,
+  0x00fe0000, 0x00d70000, 0x00ab0000, 0x00760000,
+  0x00ca0000, 0x00820000, 0x00c90000, 0x007d0000,
+  0x00fa0000, 0x00590000, 0x00470000, 0x00f00000,
+  0x00ad0000, 0x00d40000, 0x00a20000, 0x00af0000,
+  0x009c0000, 0x00a40000, 0x00720000, 0x00c00000,
+  0x00b70000, 0x00fd0000, 0x00930000, 0x00260000,
+  0x00360000, 0x003f0000, 0x00f70000, 0x00cc0000,
+  0x00340000, 0x00a50000, 0x00e50000, 0x00f10000,
+  0x00710000, 0x00d80000, 0x00310000, 0x00150000,
+  0x00040000, 0x00c70000, 0x00230000, 0x00c30000,
+  0x00180000, 0x00960000, 0x00050000, 0x009a0000,
+  0x00070000, 0x00120000, 0x00800000, 0x00e20000,
+  0x00eb0000, 0x00270000, 0x00b20000, 0x00750000,
+  0x00090000, 0x00830000, 0x002c0000, 0x001a0000,
+  0x001b0000, 0x006e0000, 0x005a0000, 0x00a00000,
+  0x00520000, 0x003b0000, 0x00d60000, 0x00b30000,
+  0x00290000, 0x00e30000, 0x002f0000, 0x00840000,
+  0x00530000, 0x00d10000, 0x00000000, 0x00ed0000,
+  0x00200000, 0x00fc0000, 0x00b10000, 0x005b0000,
+  0x006a0000, 0x00cb0000, 0x00be0000, 0x00390000,
+  0x004a0000, 0x004c0000, 0x00580000, 0x00cf0000,
+  0x00d00000, 0x00ef0000, 0x00aa0000, 0x00fb0000,
+  0x00430000, 0x004d0000, 0x00330000, 0x00850000,
+  0x00450000, 0x00f90000, 0x00020000, 0x007f0000,
+  0x00500000, 0x003c0000, 0x009f0000, 0x00a80000,
+  0x00510000, 0x00a30000, 0x00400000, 0x008f0000,
+  0x00920000, 0x009d0000, 0x00380000, 0x00f50000,
+  0x00bc0000, 0x00b60000, 0x00da0000, 0x00210000,
+  0x00100000, 0x00ff0000, 0x00f30000, 0x00d20000,
+  0x00cd0000, 0x000c0000, 0x00130000, 0x00ec0000,
+  0x005f0000, 0x00970000, 0x00440000, 0x00170000,
+  0x00c40000, 0x00a70000, 0x007e0000, 0x003d0000,
+  0x00640000, 0x005d0000, 0x00190000, 0x00730000,
+  0x00600000, 0x00810000, 0x004f0000, 0x00dc0000,
+  0x00220000, 0x002a0000, 0x00900000, 0x00880000,
+  0x00460000, 0x00ee0000, 0x00b80000, 0x00140000,
+  0x00de0000, 0x005e0000, 0x000b0000, 0x00db0000,
+  0x00e00000, 0x00320000, 0x003a0000, 0x000a0000,
+  0x00490000, 0x00060000, 0x00240000, 0x005c0000,
+  0x00c20000, 0x00d30000, 0x00ac0000, 0x00620000,
+  0x00910000, 0x00950000, 0x00e40000, 0x00790000,
+  0x00e70000, 0x00c80000, 0x00370000, 0x006d0000,
+  0x008d0000, 0x00d50000, 0x004e0000, 0x00a90000,
+  0x006c0000, 0x00560000, 0x00f40000, 0x00ea0000,
+  0x00650000, 0x007a0000, 0x00ae0000, 0x00080000,
+  0x00ba0000, 0x00780000, 0x00250000, 0x002e0000,
+  0x001c0000, 0x00a60000, 0x00b40000, 0x00c60000,
+  0x00e80000, 0x00dd0000, 0x00740000, 0x001f0000,
+  0x004b0000, 0x00bd0000, 0x008b0000, 0x008a0000,
+  0x00700000, 0x003e0000, 0x00b50000, 0x00660000,
+  0x00480000, 0x00030000, 0x00f60000, 0x000e0000,
+  0x00610000, 0x00350000, 0x00570000, 0x00b90000,
+  0x00860000, 0x00c10000, 0x001d0000, 0x009e0000,
+  0x00e10000, 0x00f80000, 0x00980000, 0x00110000,
+  0x00690000, 0x00d90000, 0x008e0000, 0x00940000,
+  0x009b0000, 0x001e0000, 0x00870000, 0x00e90000,
+  0x00ce0000, 0x00550000, 0x00280000, 0x00df0000,
+  0x008c0000, 0x00a10000, 0x00890000, 0x000d0000,
+  0x00bf0000, 0x00e60000, 0x00420000, 0x00680000,
+  0x00410000, 0x00990000, 0x002d0000, 0x000f0000,
+  0x00b00000, 0x00540000, 0x00bb0000, 0x00160000
+}, {
+  0x63000000, 0x7c000000, 0x77000000, 0x7b000000,
+  0xf2000000, 0x6b000000, 0x6f000000, 0xc5000000,
+  0x30000000, 0x01000000, 0x67000000, 0x2b000000,
+  0xfe000000, 0xd7000000, 0xab000000, 0x76000000,
+  0xca000000, 0x82000000, 0xc9000000, 0x7d000000,
+  0xfa000000, 0x59000000, 0x47000000, 0xf0000000,
+  0xad000000, 0xd4000000, 0xa2000000, 0xaf000000,
+  0x9c000000, 0xa4000000, 0x72000000, 0xc0000000,
+  0xb7000000, 0xfd000000, 0x93000000, 0x26000000,
+  0x36000000, 0x3f000000, 0xf7000000, 0xcc000000,
+  0x34000000, 0xa5000000, 0xe5000000, 0xf1000000,
+  0x71000000, 0xd8000000, 0x31000000, 0x15000000,
+  0x04000000, 0xc7000000, 0x23000000, 0xc3000000,
+  0x18000000, 0x96000000, 0x05000000, 0x9a000000,
+  0x07000000, 0x12000000, 0x80000000, 0xe2000000,
+  0xeb000000, 0x27000000, 0xb2000000, 0x75000000,
+  0x09000000, 0x83000000, 0x2c000000, 0x1a000000,
+  0x1b000000, 0x6e000000, 0x5a000000, 0xa0000000,
+  0x52000000, 0x3b000000, 0xd6000000, 0xb3000000,
+  0x29000000, 0xe3000000, 0x2f000000, 0x84000000,
+  0x53000000, 0xd1000000, 0x00000000, 0xed000000,
+  0x20000000, 0xfc000000, 0xb1000000, 0x5b000000,
+  0x6a000000, 0xcb000000, 0xbe000000, 0x39000000,
+  0x4a000000, 0x4c000000, 0x58000000, 0xcf000000,
+  0xd0000000, 0xef000000, 0xaa000000, 0xfb000000,
+  0x43000000, 0x4d000000, 0x33000000, 0x85000000,
+  0x45000000, 0xf9000000, 0x02000000, 0x7f000000,
+  0x50000000, 0x3c000000, 0x9f000000, 0xa8000000,
+  0x51000000, 0xa3000000, 0x40000000, 0x8f000000,
+  0x92000000, 0x9d000000, 0x38000000, 0xf5000000,
+  0xbc000000, 0xb6000000, 0xda000000, 0x21000000,
+  0x10000000, 0xff000000, 0xf3000000, 0xd2000000,
+  0xcd000000, 0x0c000000, 0x13000000, 0xec000000,
+  0x5f000000, 0x97000000, 0x44000000, 0x17000000,
+  0xc4000000, 0xa7000000, 0x7e000000, 0x3d000000,
+  0x64000000, 0x5d000000, 0x19000000, 0x73000000,
+  0x60000000, 0x81000000, 0x4f000000, 0xdc000000,
+  0x22000000, 0x2a000000, 0x90000000, 0x88000000,
+  0x46000000, 0xee000000, 0xb8000000, 0x14000000,
+  0xde000000, 0x5e000000, 0x0b000000, 0xdb000000,
+  0xe0000000, 0x32000000, 0x3a000000, 0x0a000000,
+  0x49000000, 0x06000000, 0x24000000, 0x5c000000,
+  0xc2000000, 0xd3000000, 0xac000000, 0x62000000,
+  0x91000000, 0x95000000, 0xe4000000, 0x79000000,
+  0xe7000000, 0xc8000000, 0x37000000, 0x6d000000,
+  0x8d000000, 0xd5000000, 0x4e000000, 0xa9000000,
+  0x6c000000, 0x56000000, 0xf4000000, 0xea000000,
+  0x65000000, 0x7a000000, 0xae000000, 0x08000000,
+  0xba000000, 0x78000000, 0x25000000, 0x2e000000,
+  0x1c000000, 0xa6000000, 0xb4000000, 0xc6000000,
+  0xe8000000, 0xdd000000, 0x74000000, 0x1f000000,
+  0x4b000000, 0xbd000000, 0x8b000000, 0x8a000000,
+  0x70000000, 0x3e000000, 0xb5000000, 0x66000000,
+  0x48000000, 0x03000000, 0xf6000000, 0x0e000000,
+  0x61000000, 0x35000000, 0x57000000, 0xb9000000,
+  0x86000000, 0xc1000000, 0x1d000000, 0x9e000000,
+  0xe1000000, 0xf8000000, 0x98000000, 0x11000000,
+  0x69000000, 0xd9000000, 0x8e000000, 0x94000000,
+  0x9b000000, 0x1e000000, 0x87000000, 0xe9000000,
+  0xce000000, 0x55000000, 0x28000000, 0xdf000000,
+  0x8c000000, 0xa1000000, 0x89000000, 0x0d000000,
+  0xbf000000, 0xe6000000, 0x42000000, 0x68000000,
+  0x41000000, 0x99000000, 0x2d000000, 0x0f000000,
+  0xb0000000, 0x54000000, 0xbb000000, 0x16000000
+}
+};
+
+const uint32_t  il_tab[4][256] = {
+{
+  0x00000052, 0x00000009, 0x0000006a, 0x000000d5,
+  0x00000030, 0x00000036, 0x000000a5, 0x00000038,
+  0x000000bf, 0x00000040, 0x000000a3, 0x0000009e,
+  0x00000081, 0x000000f3, 0x000000d7, 0x000000fb,
+  0x0000007c, 0x000000e3, 0x00000039, 0x00000082,
+  0x0000009b, 0x0000002f, 0x000000ff, 0x00000087,
+  0x00000034, 0x0000008e, 0x00000043, 0x00000044,
+  0x000000c4, 0x000000de, 0x000000e9, 0x000000cb,
+  0x00000054, 0x0000007b, 0x00000094, 0x00000032,
+  0x000000a6, 0x000000c2, 0x00000023, 0x0000003d,
+  0x000000ee, 0x0000004c, 0x00000095, 0x0000000b,
+  0x00000042, 0x000000fa, 0x000000c3, 0x0000004e,
+  0x00000008, 0x0000002e, 0x000000a1, 0x00000066,
+  0x00000028, 0x000000d9, 0x00000024, 0x000000b2,
+  0x00000076, 0x0000005b, 0x000000a2, 0x00000049,
+  0x0000006d, 0x0000008b, 0x000000d1, 0x00000025,
+  0x00000072, 0x000000f8, 0x000000f6, 0x00000064,
+  0x00000086, 0x00000068, 0x00000098, 0x00000016,
+  0x000000d4, 0x000000a4, 0x0000005c, 0x000000cc,
+  0x0000005d, 0x00000065, 0x000000b6, 0x00000092,
+  0x0000006c, 0x00000070, 0x00000048, 0x00000050,
+  0x000000fd, 0x000000ed, 0x000000b9, 0x000000da,
+  0x0000005e, 0x00000015, 0x00000046, 0x00000057,
+  0x000000a7, 0x0000008d, 0x0000009d, 0x00000084,
+  0x00000090, 0x000000d8, 0x000000ab, 0x00000000,
+  0x0000008c, 0x000000bc, 0x000000d3, 0x0000000a,
+  0x000000f7, 0x000000e4, 0x00000058, 0x00000005,
+  0x000000b8, 0x000000b3, 0x00000045, 0x00000006,
+  0x000000d0, 0x0000002c, 0x0000001e, 0x0000008f,
+  0x000000ca, 0x0000003f, 0x0000000f, 0x00000002,
+  0x000000c1, 0x000000af, 0x000000bd, 0x00000003,
+  0x00000001, 0x00000013, 0x0000008a, 0x0000006b,
+  0x0000003a, 0x00000091, 0x00000011, 0x00000041,
+  0x0000004f, 0x00000067, 0x000000dc, 0x000000ea,
+  0x00000097, 0x000000f2, 0x000000cf, 0x000000ce,
+  0x000000f0, 0x000000b4, 0x000000e6, 0x00000073,
+  0x00000096, 0x000000ac, 0x00000074, 0x00000022,
+  0x000000e7, 0x000000ad, 0x00000035, 0x00000085,
+  0x000000e2, 0x000000f9, 0x00000037, 0x000000e8,
+  0x0000001c, 0x00000075, 0x000000df, 0x0000006e,
+  0x00000047, 0x000000f1, 0x0000001a, 0x00000071,
+  0x0000001d, 0x00000029, 0x000000c5, 0x00000089,
+  0x0000006f, 0x000000b7, 0x00000062, 0x0000000e,
+  0x000000aa, 0x00000018, 0x000000be, 0x0000001b,
+  0x000000fc, 0x00000056, 0x0000003e, 0x0000004b,
+  0x000000c6, 0x000000d2, 0x00000079, 0x00000020,
+  0x0000009a, 0x000000db, 0x000000c0, 0x000000fe,
+  0x00000078, 0x000000cd, 0x0000005a, 0x000000f4,
+  0x0000001f, 0x000000dd, 0x000000a8, 0x00000033,
+  0x00000088, 0x00000007, 0x000000c7, 0x00000031,
+  0x000000b1, 0x00000012, 0x00000010, 0x00000059,
+  0x00000027, 0x00000080, 0x000000ec, 0x0000005f,
+  0x00000060, 0x00000051, 0x0000007f, 0x000000a9,
+  0x00000019, 0x000000b5, 0x0000004a, 0x0000000d,
+  0x0000002d, 0x000000e5, 0x0000007a, 0x0000009f,
+  0x00000093, 0x000000c9, 0x0000009c, 0x000000ef,
+  0x000000a0, 0x000000e0, 0x0000003b, 0x0000004d,
+  0x000000ae, 0x0000002a, 0x000000f5, 0x000000b0,
+  0x000000c8, 0x000000eb, 0x000000bb, 0x0000003c,
+  0x00000083, 0x00000053, 0x00000099, 0x00000061,
+  0x00000017, 0x0000002b, 0x00000004, 0x0000007e,
+  0x000000ba, 0x00000077, 0x000000d6, 0x00000026,
+  0x000000e1, 0x00000069, 0x00000014, 0x00000063,
+  0x00000055, 0x00000021, 0x0000000c, 0x0000007d
+}, {
+  0x00005200, 0x00000900, 0x00006a00, 0x0000d500,
+  0x00003000, 0x00003600, 0x0000a500, 0x00003800,
+  0x0000bf00, 0x00004000, 0x0000a300, 0x00009e00,
+  0x00008100, 0x0000f300, 0x0000d700, 0x0000fb00,
+  0x00007c00, 0x0000e300, 0x00003900, 0x00008200,
+  0x00009b00, 0x00002f00, 0x0000ff00, 0x00008700,
+  0x00003400, 0x00008e00, 0x00004300, 0x00004400,
+  0x0000c400, 0x0000de00, 0x0000e900, 0x0000cb00,
+  0x00005400, 0x00007b00, 0x00009400, 0x00003200,
+  0x0000a600, 0x0000c200, 0x00002300, 0x00003d00,
+  0x0000ee00, 0x00004c00, 0x00009500, 0x00000b00,
+  0x00004200, 0x0000fa00, 0x0000c300, 0x00004e00,
+  0x00000800, 0x00002e00, 0x0000a100, 0x00006600,
+  0x00002800, 0x0000d900, 0x00002400, 0x0000b200,
+  0x00007600, 0x00005b00, 0x0000a200, 0x00004900,
+  0x00006d00, 0x00008b00, 0x0000d100, 0x00002500,
+  0x00007200, 0x0000f800, 0x0000f600, 0x00006400,
+  0x00008600, 0x00006800, 0x00009800, 0x00001600,
+  0x0000d400, 0x0000a400, 0x00005c00, 0x0000cc00,
+  0x00005d00, 0x00006500, 0x0000b600, 0x00009200,
+  0x00006c00, 0x00007000, 0x00004800, 0x00005000,
+  0x0000fd00, 0x0000ed00, 0x0000b900, 0x0000da00,
+  0x00005e00, 0x00001500, 0x00004600, 0x00005700,
+  0x0000a700, 0x00008d00, 0x00009d00, 0x00008400,
+  0x00009000, 0x0000d800, 0x0000ab00, 0x00000000,
+  0x00008c00, 0x0000bc00, 0x0000d300, 0x00000a00,
+  0x0000f700, 0x0000e400, 0x00005800, 0x00000500,
+  0x0000b800, 0x0000b300, 0x00004500, 0x00000600,
+  0x0000d000, 0x00002c00, 0x00001e00, 0x00008f00,
+  0x0000ca00, 0x00003f00, 0x00000f00, 0x00000200,
+  0x0000c100, 0x0000af00, 0x0000bd00, 0x00000300,
+  0x00000100, 0x00001300, 0x00008a00, 0x00006b00,
+  0x00003a00, 0x00009100, 0x00001100, 0x00004100,
+  0x00004f00, 0x00006700, 0x0000dc00, 0x0000ea00,
+  0x00009700, 0x0000f200, 0x0000cf00, 0x0000ce00,
+  0x0000f000, 0x0000b400, 0x0000e600, 0x00007300,
+  0x00009600, 0x0000ac00, 0x00007400, 0x00002200,
+  0x0000e700, 0x0000ad00, 0x00003500, 0x00008500,
+  0x0000e200, 0x0000f900, 0x00003700, 0x0000e800,
+  0x00001c00, 0x00007500, 0x0000df00, 0x00006e00,
+  0x00004700, 0x0000f100, 0x00001a00, 0x00007100,
+  0x00001d00, 0x00002900, 0x0000c500, 0x00008900,
+  0x00006f00, 0x0000b700, 0x00006200, 0x00000e00,
+  0x0000aa00, 0x00001800, 0x0000be00, 0x00001b00,
+  0x0000fc00, 0x00005600, 0x00003e00, 0x00004b00,
+  0x0000c600, 0x0000d200, 0x00007900, 0x00002000,
+  0x00009a00, 0x0000db00, 0x0000c000, 0x0000fe00,
+  0x00007800, 0x0000cd00, 0x00005a00, 0x0000f400,
+  0x00001f00, 0x0000dd00, 0x0000a800, 0x00003300,
+  0x00008800, 0x00000700, 0x0000c700, 0x00003100,
+  0x0000b100, 0x00001200, 0x00001000, 0x00005900,
+  0x00002700, 0x00008000, 0x0000ec00, 0x00005f00,
+  0x00006000, 0x00005100, 0x00007f00, 0x0000a900,
+  0x00001900, 0x0000b500, 0x00004a00, 0x00000d00,
+  0x00002d00, 0x0000e500, 0x00007a00, 0x00009f00,
+  0x00009300, 0x0000c900, 0x00009c00, 0x0000ef00,
+  0x0000a000, 0x0000e000, 0x00003b00, 0x00004d00,
+  0x0000ae00, 0x00002a00, 0x0000f500, 0x0000b000,
+  0x0000c800, 0x0000eb00, 0x0000bb00, 0x00003c00,
+  0x00008300, 0x00005300, 0x00009900, 0x00006100,
+  0x00001700, 0x00002b00, 0x00000400, 0x00007e00,
+  0x0000ba00, 0x00007700, 0x0000d600, 0x00002600,
+  0x0000e100, 0x00006900, 0x00001400, 0x00006300,
+  0x00005500, 0x00002100, 0x00000c00, 0x00007d00
+}, {
+  0x00520000, 0x00090000, 0x006a0000, 0x00d50000,
+  0x00300000, 0x00360000, 0x00a50000, 0x00380000,
+  0x00bf0000, 0x00400000, 0x00a30000, 0x009e0000,
+  0x00810000, 0x00f30000, 0x00d70000, 0x00fb0000,
+  0x007c0000, 0x00e30000, 0x00390000, 0x00820000,
+  0x009b0000, 0x002f0000, 0x00ff0000, 0x00870000,
+  0x00340000, 0x008e0000, 0x00430000, 0x00440000,
+  0x00c40000, 0x00de0000, 0x00e90000, 0x00cb0000,
+  0x00540000, 0x007b0000, 0x00940000, 0x00320000,
+  0x00a60000, 0x00c20000, 0x00230000, 0x003d0000,
+  0x00ee0000, 0x004c0000, 0x00950000, 0x000b0000,
+  0x00420000, 0x00fa0000, 0x00c30000, 0x004e0000,
+  0x00080000, 0x002e0000, 0x00a10000, 0x00660000,
+  0x00280000, 0x00d90000, 0x00240000, 0x00b20000,
+  0x00760000, 0x005b0000, 0x00a20000, 0x00490000,
+  0x006d0000, 0x008b0000, 0x00d10000, 0x00250000,
+  0x00720000, 0x00f80000, 0x00f60000, 0x00640000,
+  0x00860000, 0x00680000, 0x00980000, 0x00160000,
+  0x00d40000, 0x00a40000, 0x005c0000, 0x00cc0000,
+  0x005d0000, 0x00650000, 0x00b60000, 0x00920000,
+  0x006c0000, 0x00700000, 0x00480000, 0x00500000,
+  0x00fd0000, 0x00ed0000, 0x00b90000, 0x00da0000,
+  0x005e0000, 0x00150000, 0x00460000, 0x00570000,
+  0x00a70000, 0x008d0000, 0x009d0000, 0x00840000,
+  0x00900000, 0x00d80000, 0x00ab0000, 0x00000000,
+  0x008c0000, 0x00bc0000, 0x00d30000, 0x000a0000,
+  0x00f70000, 0x00e40000, 0x00580000, 0x00050000,
+  0x00b80000, 0x00b30000, 0x00450000, 0x00060000,
+  0x00d00000, 0x002c0000, 0x001e0000, 0x008f0000,
+  0x00ca0000, 0x003f0000, 0x000f0000, 0x00020000,
+  0x00c10000, 0x00af0000, 0x00bd0000, 0x00030000,
+  0x00010000, 0x00130000, 0x008a0000, 0x006b0000,
+  0x003a0000, 0x00910000, 0x00110000, 0x00410000,
+  0x004f0000, 0x00670000, 0x00dc0000, 0x00ea0000,
+  0x00970000, 0x00f20000, 0x00cf0000, 0x00ce0000,
+  0x00f00000, 0x00b40000, 0x00e60000, 0x00730000,
+  0x00960000, 0x00ac0000, 0x00740000, 0x00220000,
+  0x00e70000, 0x00ad0000, 0x00350000, 0x00850000,
+  0x00e20000, 0x00f90000, 0x00370000, 0x00e80000,
+  0x001c0000, 0x00750000, 0x00df0000, 0x006e0000,
+  0x00470000, 0x00f10000, 0x001a0000, 0x00710000,
+  0x001d0000, 0x00290000, 0x00c50000, 0x00890000,
+  0x006f0000, 0x00b70000, 0x00620000, 0x000e0000,
+  0x00aa0000, 0x00180000, 0x00be0000, 0x001b0000,
+  0x00fc0000, 0x00560000, 0x003e0000, 0x004b0000,
+  0x00c60000, 0x00d20000, 0x00790000, 0x00200000,
+  0x009a0000, 0x00db0000, 0x00c00000, 0x00fe0000,
+  0x00780000, 0x00cd0000, 0x005a0000, 0x00f40000,
+  0x001f0000, 0x00dd0000, 0x00a80000, 0x00330000,
+  0x00880000, 0x00070000, 0x00c70000, 0x00310000,
+  0x00b10000, 0x00120000, 0x00100000, 0x00590000,
+  0x00270000, 0x00800000, 0x00ec0000, 0x005f0000,
+  0x00600000, 0x00510000, 0x007f0000, 0x00a90000,
+  0x00190000, 0x00b50000, 0x004a0000, 0x000d0000,
+  0x002d0000, 0x00e50000, 0x007a0000, 0x009f0000,
+  0x00930000, 0x00c90000, 0x009c0000, 0x00ef0000,
+  0x00a00000, 0x00e00000, 0x003b0000, 0x004d0000,
+  0x00ae0000, 0x002a0000, 0x00f50000, 0x00b00000,
+  0x00c80000, 0x00eb0000, 0x00bb0000, 0x003c0000,
+  0x00830000, 0x00530000, 0x00990000, 0x00610000,
+  0x00170000, 0x002b0000, 0x00040000, 0x007e0000,
+  0x00ba0000, 0x00770000, 0x00d60000, 0x00260000,
+  0x00e10000, 0x00690000, 0x00140000, 0x00630000,
+  0x00550000, 0x00210000, 0x000c0000, 0x007d0000
+}, {
+  0x52000000, 0x09000000, 0x6a000000, 0xd5000000,
+  0x30000000, 0x36000000, 0xa5000000, 0x38000000,
+  0xbf000000, 0x40000000, 0xa3000000, 0x9e000000,
+  0x81000000, 0xf3000000, 0xd7000000, 0xfb000000,
+  0x7c000000, 0xe3000000, 0x39000000, 0x82000000,
+  0x9b000000, 0x2f000000, 0xff000000, 0x87000000,
+  0x34000000, 0x8e000000, 0x43000000, 0x44000000,
+  0xc4000000, 0xde000000, 0xe9000000, 0xcb000000,
+  0x54000000, 0x7b000000, 0x94000000, 0x32000000,
+  0xa6000000, 0xc2000000, 0x23000000, 0x3d000000,
+  0xee000000, 0x4c000000, 0x95000000, 0x0b000000,
+  0x42000000, 0xfa000000, 0xc3000000, 0x4e000000,
+  0x08000000, 0x2e000000, 0xa1000000, 0x66000000,
+  0x28000000, 0xd9000000, 0x24000000, 0xb2000000,
+  0x76000000, 0x5b000000, 0xa2000000, 0x49000000,
+  0x6d000000, 0x8b000000, 0xd1000000, 0x25000000,
+  0x72000000, 0xf8000000, 0xf6000000, 0x64000000,
+  0x86000000, 0x68000000, 0x98000000, 0x16000000,
+  0xd4000000, 0xa4000000, 0x5c000000, 0xcc000000,
+  0x5d000000, 0x65000000, 0xb6000000, 0x92000000,
+  0x6c000000, 0x70000000, 0x48000000, 0x50000000,
+  0xfd000000, 0xed000000, 0xb9000000, 0xda000000,
+  0x5e000000, 0x15000000, 0x46000000, 0x57000000,
+  0xa7000000, 0x8d000000, 0x9d000000, 0x84000000,
+  0x90000000, 0xd8000000, 0xab000000, 0x00000000,
+  0x8c000000, 0xbc000000, 0xd3000000, 0x0a000000,
+  0xf7000000, 0xe4000000, 0x58000000, 0x05000000,
+  0xb8000000, 0xb3000000, 0x45000000, 0x06000000,
+  0xd0000000, 0x2c000000, 0x1e000000, 0x8f000000,
+  0xca000000, 0x3f000000, 0x0f000000, 0x02000000,
+  0xc1000000, 0xaf000000, 0xbd000000, 0x03000000,
+  0x01000000, 0x13000000, 0x8a000000, 0x6b000000,
+  0x3a000000, 0x91000000, 0x11000000, 0x41000000,
+  0x4f000000, 0x67000000, 0xdc000000, 0xea000000,
+  0x97000000, 0xf2000000, 0xcf000000, 0xce000000,
+  0xf0000000, 0xb4000000, 0xe6000000, 0x73000000,
+  0x96000000, 0xac000000, 0x74000000, 0x22000000,
+  0xe7000000, 0xad000000, 0x35000000, 0x85000000,
+  0xe2000000, 0xf9000000, 0x37000000, 0xe8000000,
+  0x1c000000, 0x75000000, 0xdf000000, 0x6e000000,
+  0x47000000, 0xf1000000, 0x1a000000, 0x71000000,
+  0x1d000000, 0x29000000, 0xc5000000, 0x89000000,
+  0x6f000000, 0xb7000000, 0x62000000, 0x0e000000,
+  0xaa000000, 0x18000000, 0xbe000000, 0x1b000000,
+  0xfc000000, 0x56000000, 0x3e000000, 0x4b000000,
+  0xc6000000, 0xd2000000, 0x79000000, 0x20000000,
+  0x9a000000, 0xdb000000, 0xc0000000, 0xfe000000,
+  0x78000000, 0xcd000000, 0x5a000000, 0xf4000000,
+  0x1f000000, 0xdd000000, 0xa8000000, 0x33000000,
+  0x88000000, 0x07000000, 0xc7000000, 0x31000000,
+  0xb1000000, 0x12000000, 0x10000000, 0x59000000,
+  0x27000000, 0x80000000, 0xec000000, 0x5f000000,
+  0x60000000, 0x51000000, 0x7f000000, 0xa9000000,
+  0x19000000, 0xb5000000, 0x4a000000, 0x0d000000,
+  0x2d000000, 0xe5000000, 0x7a000000, 0x9f000000,
+  0x93000000, 0xc9000000, 0x9c000000, 0xef000000,
+  0xa0000000, 0xe0000000, 0x3b000000, 0x4d000000,
+  0xae000000, 0x2a000000, 0xf5000000, 0xb0000000,
+  0xc8000000, 0xeb000000, 0xbb000000, 0x3c000000,
+  0x83000000, 0x53000000, 0x99000000, 0x61000000,
+  0x17000000, 0x2b000000, 0x04000000, 0x7e000000,
+  0xba000000, 0x77000000, 0xd6000000, 0x26000000,
+  0xe1000000, 0x69000000, 0x14000000, 0x63000000,
+  0x55000000, 0x21000000, 0x0c000000, 0x7d000000
+}
+};
+
+const uint32_t rco_tab[10] = {
+  0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
+  0x00000020, 0x00000040, 0x00000080, 0x0000001b, 0x00000036
+};
diff --git a/kern/lib/random/sha2.c b/kern/lib/random/sha2.c
new file mode 100644 (file)
index 0000000..2a8a726
--- /dev/null
@@ -0,0 +1,709 @@
+/*     $OpenBSD: sha2.c,v 1.6 2004/05/03 02:57:36 millert Exp $        */
+
+/*
+ * FILE:       sha2.c
+ * AUTHOR:     Aaron D. Gifford <me@aarongifford.com>
+ *
+ * Copyright (c) 2000-2001, Aaron D. Gifford
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
+ *
+ * contrib/pgcrypto/sha2.c
+ */
+
+#include "u.h"
+#include <libc.h>
+#include "sha2.h"
+
+
+/*** SHA-256/512 Various Length Definitions ***********************/
+enum{
+       SHA256ShortBlockLength  = (SHA256BlockLength - 8),
+       SHA512ShortBlockLength  = (SHA512_block_length - 16)
+};
+
+/*
+ * Macro for incrementally adding the unsigned 64-bit integer n to the
+ * unsigned 128-bit integer (represented using a two-element array of
+ * 64-bit words):
+ */
+#define ADDINC128(w,n) { \
+       (w)[0] += (uint64_t)(n); \
+       if ((w)[0] < (n)) { \
+               (w)[1]++; \
+       } \
+}
+
+/*** THE SIX LOGICAL FUNCTIONS ****************************************/
+/*
+ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
+ *
+ *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
+ *   S is a ROTATION) because the SHA-256/384/512 description document
+ *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
+ *   same "backwards" definition.
+ */
+/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
+#define R(b,x)                 ((x) >> (b))
+/* 32-bit Rotate-right (used in SHA-256): */
+#define S32(b,x)       (((x) >> (b)) | ((x) << (32 - (b))))
+/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
+#define S64(b,x)       (((x) >> (b)) | ((x) << (64 - (b))))
+
+/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+#define Ch(x,y,z)      (((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z)     (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/* Four of six logical functions used in SHA-256: */
+#define Sigma0_256(x)  (S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
+#define Sigma1_256(x)  (S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
+#define sigma0_256(x)  (S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
+#define sigma1_256(x)  (S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
+
+/* Four of six logical functions used in SHA-384 and SHA-512: */
+#define Sigma0_512(x)  (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
+#define Sigma1_512(x)  (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
+#define sigma0_512(x)  (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
+#define sigma1_512(x)  (S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
+
+/*** INTERNAL FUNCTION PROTOTYPES *************************************/
+/* NOTE: These should not be accessed directly from outside this
+ * library -- they are intended for private internal visibility/use
+ * only.
+ */
+static void SHA512_Last(SHA512Ctx*);
+static void SHA256_Transform(SHA256Ctx*, const uint32_t*);
+static void SHA512_Transform(SHA512Ctx*, const uint64_t*);
+
+/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
+/* Hash constant words K for SHA-256: */
+const uint32_t K256[64] = {
+       0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+       0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+       0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+       0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+       0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+       0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+       0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+       0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+       0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+       0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+       0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+       0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+       0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+       0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+       0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+       0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* Initial hash value H for SHA-224: */
+const uint32_t sha224_initial_hash_value[8] = {
+       0xc1059ed8UL,
+       0x367cd507UL,
+       0x3070dd17UL,
+       0xf70e5939UL,
+       0xffc00b31UL,
+       0x68581511UL,
+       0x64f98fa7UL,
+       0xbefa4fa4UL
+};
+
+/* Initial hash value H for SHA-256: */
+static const uint32_t sha256_initial_hash_value[8] = {
+       0x6a09e667UL,
+       0xbb67ae85UL,
+       0x3c6ef372UL,
+       0xa54ff53aUL,
+       0x510e527fUL,
+       0x9b05688cUL,
+       0x1f83d9abUL,
+       0x5be0cd19UL
+};
+
+/* Hash constant words K for SHA-384 and SHA-512: */
+static const uint64_t K512[80] = {
+       0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+       0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+       0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+       0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+       0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+       0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+       0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+       0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+       0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+       0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+       0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+       0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+       0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+       0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+       0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+       0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+       0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+       0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+       0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+       0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+       0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+       0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+       0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+       0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+       0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+       0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+       0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+       0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+       0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+       0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+       0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+       0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+       0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+       0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+       0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+       0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+       0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+       0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+       0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+       0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+/* Initial hash value H for SHA-384 */
+static const uint64_t sha384_initial_hash_value[8] = {
+       0xcbbb9d5dc1059ed8ULL,
+       0x629a292a367cd507ULL,
+       0x9159015a3070dd17ULL,
+       0x152fecd8f70e5939ULL,
+       0x67332667ffc00b31ULL,
+       0x8eb44a8768581511ULL,
+       0xdb0c2e0d64f98fa7ULL,
+       0x47b5481dbefa4fa4ULL
+};
+
+/* Initial hash value H for SHA-512 */
+static const uint64_t sha512_initial_hash_value[8] = {
+       0x6a09e667f3bcc908ULL,
+       0xbb67ae8584caa73bULL,
+       0x3c6ef372fe94f82bULL,
+       0xa54ff53a5f1d36f1ULL,
+       0x510e527fade682d1ULL,
+       0x9b05688c2b3e6c1fULL,
+       0x1f83d9abfb41bd6bULL,
+       0x5be0cd19137e2179ULL
+};
+
+
+/*** SHA-256: *********************************************************/
+void
+SHA256_Init(SHA256Ctx *context)
+{
+       if (context == nil)
+               return;
+       memmove(context->state, sha256_initial_hash_value, SHA256DigestLength);
+       memset(context->buffer, 0, SHA256BlockLength);
+       context->bitcount = 0;
+}
+static void
+SHA256_Transform(SHA256Ctx *context, const uint32_t *data)
+{
+       uint32_t                a,
+                               b,
+                               c,
+                               d,
+                               e,
+                               f,
+                               g,
+                               h,
+                               s0,
+                               s1;
+       uint32_t                T1,
+                               T2,
+                          *W256;
+       int                     j;
+
+       W256 = (uint32_t *) context->buffer;
+
+       /* Initialize registers with the prev. intermediate value */
+       a = context->state[0];
+       b = context->state[1];
+       c = context->state[2];
+       d = context->state[3];
+       e = context->state[4];
+       f = context->state[5];
+       g = context->state[6];
+       h = context->state[7];
+
+       j = 0;
+       do
+       {
+               W256[j] = (uint32_t) data[3] | ((uint32_t) data[2] << 8) |
+                       ((uint32_t) data[1] << 16) | ((uint32_t) data[0] << 24);
+               data += 4;
+               /* Apply the SHA-256 compression function to update a..h */
+               T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
+               T2 = Sigma0_256(a) + Maj(a, b, c);
+               h = g;
+               g = f;
+               f = e;
+               e = d + T1;
+               d = c;
+               c = b;
+               b = a;
+               a = T1 + T2;
+
+               j++;
+       } while (j < 16);
+
+       do
+       {
+               /* Part of the message block expansion: */
+               s0 = W256[(j + 1) & 0x0f];
+               s0 = sigma0_256(s0);
+               s1 = W256[(j + 14) & 0x0f];
+               s1 = sigma1_256(s1);
+
+               /* Apply the SHA-256 compression function to update a..h */
+               T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
+                       (W256[j & 0x0f] += s1 + W256[(j + 9) & 0x0f] + s0);
+               T2 = Sigma0_256(a) + Maj(a, b, c);
+               h = g;
+               g = f;
+               f = e;
+               e = d + T1;
+               d = c;
+               c = b;
+               b = a;
+               a = T1 + T2;
+
+               j++;
+       } while (j < 64);
+
+       /* Compute the current intermediate hash value */
+       context->state[0] += a;
+       context->state[1] += b;
+       context->state[2] += c;
+       context->state[3] += d;
+       context->state[4] += e;
+       context->state[5] += f;
+       context->state[6] += g;
+       context->state[7] += h;
+
+       /* Clean up */
+       a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+void
+SHA256_Update(SHA256Ctx *context, const uint8_t *data, size_t len)
+{
+       size_t          freespace,
+                               usedspace;
+
+       /* Calling with no data is valid (we do nothing) */
+       if (len == 0)
+               return;
+
+       usedspace = (context->bitcount >> 3) % SHA256BlockLength;
+       if (usedspace > 0)
+       {
+               /* Calculate how much free space is available in the buffer */
+               freespace = SHA256BlockLength - usedspace;
+
+               if (len >= freespace)
+               {
+                       /* Fill the buffer completely and process it */
+                       memmove(&context->buffer[usedspace], data, freespace);
+                       context->bitcount += freespace << 3;
+                       len -= freespace;
+                       data += freespace;
+                       SHA256_Transform(context, (uint32_t*)context->buffer);
+               }
+               else
+               {
+                       /* The buffer is not yet full */
+                       memmove(&context->buffer[usedspace], data, len);
+                       context->bitcount += len << 3;
+                       /* Clean up: */
+                       usedspace = freespace = 0;
+                       return;
+               }
+       }
+       while (len >= SHA256BlockLength)
+       {
+               /* Process as many complete blocks as we can */
+               SHA256_Transform(context, (const uint32_t*)data);
+               context->bitcount += SHA256BlockLength << 3;
+               len -= SHA256BlockLength;
+               data += SHA256BlockLength;
+       }
+       if (len > 0)
+       {
+               /* There's left-overs, so save 'em */
+               memmove(context->buffer, data, len);
+               context->bitcount += len << 3;
+       }
+       /* Clean up: */
+       usedspace = freespace = 0;
+}
+
+static void
+SHA256_Last(SHA256Ctx *context)
+{
+       unsigned int usedspace;
+
+       usedspace = (context->bitcount >> 3) % SHA256BlockLength;
+
+       if (usedspace > 0)
+       {
+               /* Begin padding with a 1 bit: */
+               context->buffer[usedspace++] = 0x80;
+
+               if (usedspace <= SHA256ShortBlockLength)
+               {
+                       /* Set-up for the last transform: */
+                       memset(&context->buffer[usedspace], 0, SHA256ShortBlockLength - usedspace);
+               }
+               else
+               {
+                       if (usedspace < SHA256BlockLength)
+                       {
+                               memset(&context->buffer[usedspace], 0, SHA256BlockLength - usedspace);
+                       }
+                       /* Do second-to-last transform: */
+                       SHA256_Transform(context, (uint32_t*)context->buffer);
+
+                       /* And set-up for the last transform: */
+                       memset(context->buffer, 0, SHA256ShortBlockLength);
+               }
+       }
+       else
+       {
+               /* Set-up for the last transform: */
+               memset(context->buffer, 0, SHA256ShortBlockLength);
+
+               /* Begin padding with a 1 bit: */
+               *context->buffer = 0x80;
+       }
+       /* Set the bit count: */
+       *(uint64_t *) &context->buffer[SHA256ShortBlockLength] = context->bitcount;
+
+       /* Final transform: */
+       SHA256_Transform(context, (uint32_t*)context->buffer);
+}
+
+void
+SHA256_Final(uint8_t digest[], SHA256Ctx *context)
+{
+       /* If no digest buffer is passed, we don't bother doing this: */
+       if (digest != nil)
+       {
+               SHA256_Last(context);
+
+               memmove(digest, context->state, SHA256DigestLength);
+       }
+
+       /* Clean up state data: */
+       memset(context, 0, sizeof(*context));
+}
+
+
+/*** SHA-512: *********************************************************/
+void
+SHA512_Init(SHA512Ctx *context)
+{
+       if (context == nil)
+               return;
+       memmove(context->state, sha512_initial_hash_value, SHA512DigestLength);
+       memset(context->buffer, 0, SHA512_block_length);
+       context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+static void
+SHA512_Transform(SHA512Ctx *context, const uint64_t *data)
+{
+       uint64_t                a,
+                               b,
+                               c,
+                               d,
+                               e,
+                               f,
+                               g,
+                               h,
+                               s0,
+                               s1;
+       uint64_t                T1,
+                               T2,
+                          *W512 = (uint64_t *) context->buffer;
+       int                     j;
+
+       /* Initialize registers with the prev. intermediate value */
+       a = context->state[0];
+       b = context->state[1];
+       c = context->state[2];
+       d = context->state[3];
+       e = context->state[4];
+       f = context->state[5];
+       g = context->state[6];
+       h = context->state[7];
+
+       j = 0;
+       do
+       {
+               W512[j] = (uint64_t) data[7] | ((uint64_t) data[6] << 8) |
+                       ((uint64_t) data[5] << 16) | ((uint64_t) data[4] << 24) |
+                       ((uint64_t) data[3] << 32) | ((uint64_t) data[2] << 40) |
+                       ((uint64_t) data[1] << 48) | ((uint64_t) data[0] << 56);
+               data += 8;
+               /* Apply the SHA-512 compression function to update a..h */
+               T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
+               T2 = Sigma0_512(a) + Maj(a, b, c);
+               h = g;
+               g = f;
+               f = e;
+               e = d + T1;
+               d = c;
+               c = b;
+               b = a;
+               a = T1 + T2;
+
+               j++;
+       } while (j < 16);
+
+       do
+       {
+               /* Part of the message block expansion: */
+               s0 = W512[(j + 1) & 0x0f];
+               s0 = sigma0_512(s0);
+               s1 = W512[(j + 14) & 0x0f];
+               s1 = sigma1_512(s1);
+
+               /* Apply the SHA-512 compression function to update a..h */
+               T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
+                       (W512[j & 0x0f] += s1 + W512[(j + 9) & 0x0f] + s0);
+               T2 = Sigma0_512(a) + Maj(a, b, c);
+               h = g;
+               g = f;
+               f = e;
+               e = d + T1;
+               d = c;
+               c = b;
+               b = a;
+               a = T1 + T2;
+
+               j++;
+       } while (j < 80);
+
+       /* Compute the current intermediate hash value */
+       context->state[0] += a;
+       context->state[1] += b;
+       context->state[2] += c;
+       context->state[3] += d;
+       context->state[4] += e;
+       context->state[5] += f;
+       context->state[6] += g;
+       context->state[7] += h;
+
+       /* Clean up */
+       a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+void
+SHA512_Update(SHA512Ctx *context, const uint8_t *data, size_t len)
+{
+       size_t          freespace,
+                               usedspace;
+
+       /* Calling with no data is valid (we do nothing) */
+       if (len == 0)
+               return;
+
+       usedspace = (context->bitcount[0] >> 3) % SHA512_block_length;
+       if (usedspace > 0)
+       {
+               /* Calculate how much free space is available in the buffer */
+               freespace = SHA512_block_length - usedspace;
+
+               if (len >= freespace)
+               {
+                       /* Fill the buffer completely and process it */
+                       memmove(&context->buffer[usedspace], data, freespace);
+                       ADDINC128(context->bitcount, freespace << 3);
+                       len -= freespace;
+                       data += freespace;
+                       SHA512_Transform(context, (uint64_t*)context->buffer);
+               }
+               else
+               {
+                       /* The buffer is not yet full */
+                       memmove(&context->buffer[usedspace], data, len);
+                       ADDINC128(context->bitcount, len << 3);
+                       /* Clean up: */
+                       usedspace = freespace = 0;
+                       return;
+               }
+       }
+       while (len >= SHA512_block_length)
+       {
+               /* Process as many complete blocks as we can */
+               SHA512_Transform(context, (const uint64_t*)data);
+               ADDINC128(context->bitcount, SHA512_block_length << 3);
+               len -= SHA512_block_length;
+               data += SHA512_block_length;
+       }
+       if (len > 0)
+       {
+               /* There's left-overs, so save 'em */
+               memmove(context->buffer, data, len);
+               ADDINC128(context->bitcount, len << 3);
+       }
+       /* Clean up: */
+       usedspace = freespace = 0;
+}
+
+static void
+SHA512_Last(SHA512Ctx *context)
+{
+       unsigned int usedspace;
+
+       usedspace = (context->bitcount[0] >> 3) % SHA512_block_length;
+
+       if (usedspace > 0)
+       {
+               /* Begin padding with a 1 bit: */
+               context->buffer[usedspace++] = 0x80;
+
+               if (usedspace <= SHA512ShortBlockLength)
+               {
+                       /* Set-up for the last transform: */
+                       memset(&context->buffer[usedspace], 0, SHA512ShortBlockLength - usedspace);
+               }
+               else
+               {
+                       if (usedspace < SHA512_block_length)
+                       {
+                               memset(&context->buffer[usedspace], 0, SHA512_block_length - usedspace);
+                       }
+                       /* Do second-to-last transform: */
+                       SHA512_Transform(context, (uint64_t*)context->buffer);
+
+                       /* And set-up for the last transform: */
+                       memset(context->buffer, 0, SHA512_block_length - 2);
+               }
+       }
+       else
+       {
+               /* Prepare for final transform: */
+               memset(context->buffer, 0, SHA512ShortBlockLength);
+
+               /* Begin padding with a 1 bit: */
+               *context->buffer = 0x80;
+       }
+       /* Store the length of input data (in bits): */
+       *(uint64_t *) &context->buffer[SHA512ShortBlockLength] = context->bitcount[1];
+       *(uint64_t *) &context->buffer[SHA512ShortBlockLength + 8] = context->bitcount[0];
+
+       /* Final transform: */
+       SHA512_Transform(context, (uint64_t*)context->buffer);
+}
+
+void
+SHA512_Final(uint8_t digest[], SHA512Ctx *context)
+{
+       /* If no digest buffer is passed, we don't bother doing this: */
+       if (digest != nil)
+       {
+               SHA512_Last(context);
+
+               /* Save the hash data for output: */
+               memmove(digest, context->state, SHA512DigestLength);
+       }
+
+       /* Zero out state data */
+       memset(context, 0, sizeof(*context));
+}
+
+
+/*** SHA-384: *********************************************************/
+void
+SHA384_Init(SHA384Ctx *context)
+{
+       if (context == nil)
+               return;
+       memmove(context->state, sha384_initial_hash_value, SHA512DigestLength);
+       memset(context->buffer, 0, SHA384BlockLength);
+       context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+void
+SHA384_Update(SHA384Ctx *context, const uint8_t *data, size_t len)
+{
+       SHA512_Update((SHA512Ctx *) context, data, len);
+}
+
+void
+SHA384_Final(uint8_t digest[], SHA384Ctx *context)
+{
+       /* If no digest buffer is passed, we don't bother doing this: */
+       if (digest != nil)
+       {
+               SHA512_Last((SHA512Ctx *) context);
+
+               /* Save the hash data for output: */
+               memmove(digest, context->state, SHA384DigestLength);
+       }
+
+       /* Zero out state data */
+       memset(context, 0, sizeof(*context));
+}
+
+/*** SHA-224: *********************************************************/
+void
+SHA224_Init(SHA224Ctx *context)
+{
+       if (context == nil)
+               return;
+       memmove(context->state, sha224_initial_hash_value, SHA256DigestLength);
+       memset(context->buffer, 0, SHA256BlockLength);
+       context->bitcount = 0;
+}
+
+void
+SHA224_Update(SHA224Ctx *context, const uint8_t *data, size_t len)
+{
+       SHA256_Update((SHA256Ctx *) context, data, len);
+}
+
+void
+SHA224_Final(uint8_t digest[], SHA224Ctx *context)
+{
+       /* If no digest buffer is passed, we don't bother doing this: */
+       if (digest != nil)
+       {
+               SHA256_Last(context);
+
+               memmove(digest, context->state, SHA224DigestLength);
+       }
+
+       /* Clean up state data: */
+       memset(context, 0, sizeof(*context));
+}