changeset 0:d7da3b1e1540 libtomcrypt

put back the 0.95 makefile which was inadvertently merged over
author Matt Johnston <matt@ucc.asn.au>
date Mon, 31 May 2004 18:21:40 +0000
parents
children 059ec00f32a1
files LICENSE PLAN aes.c aes_tab.c ampi.c authors base64.c blowfish.c burn_stack.c cast5.c cbc_decrypt.c cbc_encrypt.c cbc_start.c cfb_decrypt.c cfb_encrypt.c cfb_start.c changes crypt.c crypt.out crypt.pdf crypt.tex crypt_argchk.c crypt_cipher_descriptor.c crypt_cipher_is_valid.c crypt_find_cipher.c crypt_find_cipher_any.c crypt_find_cipher_id.c crypt_find_hash.c crypt_find_hash_any.c crypt_find_hash_id.c crypt_find_prng.c crypt_hash_descriptor.c crypt_hash_is_valid.c crypt_prng_descriptor.c crypt_prng_is_valid.c crypt_register_cipher.c crypt_register_hash.c crypt_register_prng.c crypt_unregister_cipher.c crypt_unregister_hash.c crypt_unregister_prng.c ctr_decrypt.c ctr_encrypt.c ctr_start.c demos/encrypt.c demos/hashsum.c demos/small.c demos/test.c demos/tv_gen.c demos/x86_prof.c des.c dh.c dh_sys.c dsa_export.c dsa_free.c dsa_import.c dsa_make_key.c dsa_sign_hash.c dsa_verify_hash.c dsa_verify_key.c eax_addheader.c eax_decrypt.c eax_decrypt_verify_memory.c eax_done.c eax_encrypt.c eax_encrypt_authenticate_memory.c eax_init.c eax_test.c ecb_decrypt.c ecb_encrypt.c ecb_start.c ecc.c ecc_sys.c examples/ch1-01.c examples/ch1-02.c examples/ch1-03.c examples/ch2-01.c gf.c hash_file.c hash_filehandle.c hash_memory.c hmac_done.c hmac_file.c hmac_init.c hmac_memory.c hmac_process.c hmac_test.c is_prime.c keyring.c makefile makefile.cygwin_dll makefile.icc makefile.msvc md2.c md4.c md5.c mpi.c mycrypt.h mycrypt_argchk.h mycrypt_cfg.h mycrypt_cipher.h mycrypt_custom.h mycrypt_gf.h mycrypt_hash.h mycrypt_kr.h mycrypt_macros.h mycrypt_misc.h mycrypt_pk.h mycrypt_pkcs.h mycrypt_prng.h noekeon.c notes/base64_tv.txt notes/cipher_tv.txt notes/eax_tv.txt notes/etc/whirlgen.c notes/etc/whirltest.c notes/hash_tv.txt notes/hmac_tv.txt notes/ocb_tv.txt notes/omac_tv.txt notes/pmac_tv.txt notes/tech0001.txt notes/tech0002.txt notes/tech0003.txt ocb_decrypt.c ocb_decrypt_verify_memory.c ocb_done_decrypt.c ocb_done_encrypt.c ocb_encrypt.c ocb_encrypt_authenticate_memory.c ocb_init.c ocb_ntz.c ocb_shift_xor.c ocb_test.c ofb_decrypt.c ofb_encrypt.c ofb_start.c omac_done.c omac_file.c omac_init.c omac_memory.c omac_process.c omac_test.c packet_store_header.c packet_valid_header.c pkcs_1_i2osp.c pkcs_1_mgf1.c pkcs_1_oaep_decode.c pkcs_1_oaep_encode.c pkcs_1_os2ip.c pkcs_1_pss_decode.c pkcs_1_pss_encode.c pkcs_5_1.c pkcs_5_2.c pmac_done.c pmac_file.c pmac_init.c pmac_memory.c pmac_ntz.c pmac_process.c pmac_shift_xor.c pmac_test.c rand_prime.c rc2.c rc4.c rc5.c rc6.c rmd128.c rmd160.c rng_get_bytes.c rng_make_prng.c rsa.c rsa_exptmod.c rsa_free.c rsa_make_key.c rsa_sys.c s_ocb_done.c safer.c safer_tab.c saferp.c serpent.c sha1.c sha224.c sha256.c sha384.c sha512.c skipjack.c sprng.c strings.c tiger.c tommath.h twofish.c twofish_tab.c whirl.c whirltab.c xtea.c yarrow.c zeromem.c
diffstat 198 files changed, 49909 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,9 @@
+LibTomCrypt is public domain.  As should all quality software be.
+
+All of the software was either written by or donated to Tom St Denis for the purposes
+of this project.  The only exception is the SAFER.C source which has no known
+license status (assumed copyrighted) which is why SAFER,C is shipped as disabled.
+
+Tom St Denis
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PLAN	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,38 @@
+The following functions are marked for removal and/or behavioural change by v1.00 of LibTomCrypt
+
+1.  RSA Support
+
+      rsa_pad, rsa_signpad, rsa_depad, rsa_signdepad, rsa_import, rsa_export
+
+They will be replaced with PKCS #1 compliant OAEP/PSS padding function as early as v0.96
+
+2.  DSA Support
+
+      dsa_import, dsa_export
+
+Will be replaced with suitable DSS [what is the standard?] compliant formats.  Planned for v0.96
+
+3.  Key Ring Support
+  
+      (all)
+
+The entire API will be dropped as early as v0.96.  It was just an experiment and nobody uses it anyways.
+
+4.  Test Harness
+ 
+      demos/test.c
+
+The test harness is well overdue for a makeover.  Planned for as early as v0.97
+
+
+Put things in order...
+
+v0.96  -- removed keyring.c and gf.c
+       -- removed LTC RSA padding
+       -- DSS support [whatever this entails]
+       -- Bug fixes/updates to the PKCS/DSS support, should be stable in this release
+
+v0.97  -- Re-written test harness
+       -- More demos in the manual and demos/ directory
+
+... future???
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aes.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,606 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+
+/* AES implementation by Tom St Denis
+ *
+ * Derived from the Public Domain source code by
+ 
+---  
+  * rijndael-alg-fst.c
+  *
+  * @version 3.0 (December 2000)
+  *
+  * Optimised ANSI C code for the Rijndael cipher (now AES)
+  *
+  * @author Vincent Rijmen <[email protected]>
+  * @author Antoon Bosselaers <[email protected]>
+  * @author Paulo Barreto <[email protected]>
+---
+ */
+
+#include "mycrypt.h"
+
+#ifdef RIJNDAEL
+
+const struct _cipher_descriptor rijndael_desc =
+{
+    "rijndael",
+    6,
+    16, 32, 16, 10,
+    &rijndael_setup,
+    &rijndael_ecb_encrypt,
+    &rijndael_ecb_decrypt,
+    &rijndael_test,
+    &rijndael_keysize
+};
+
+const struct _cipher_descriptor aes_desc =
+{
+    "aes",
+    6,
+    16, 32, 16, 10,
+    &rijndael_setup,
+    &rijndael_ecb_encrypt,
+    &rijndael_ecb_decrypt,
+    &rijndael_test,
+    &rijndael_keysize
+};
+
+#include "aes_tab.c"
+
+int rijndael_setup(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
+{
+    int i, j;
+    ulong32 temp, *rk, *rrk;
+    
+    _ARGCHK(key != NULL);
+    _ARGCHK(skey != NULL);
+    
+    if (keylen != 16 && keylen != 24 && keylen != 32) {
+       return CRYPT_INVALID_KEYSIZE;
+    }
+    
+    if (rounds != 0 && rounds != (10 + ((keylen/8)-2)*2)) {
+       return CRYPT_INVALID_ROUNDS;
+    }
+    
+    skey->rijndael.Nr = 10 + ((keylen/8)-2)*2;
+        
+    /* setup the forward key */
+    i                 = 0;
+    rk                = skey->rijndael.eK;
+    LOAD32H(rk[0], key     );
+    LOAD32H(rk[1], key +  4);
+    LOAD32H(rk[2], key +  8);
+    LOAD32H(rk[3], key + 12);
+    if (keylen == 16) {
+        j = 44;
+        for (;;) {
+            temp  = rk[3];
+            rk[4] = rk[0] ^
+                (Te4_3[byte(temp, 2)]) ^
+                (Te4_2[byte(temp, 1)]) ^
+                (Te4_1[byte(temp, 0)]) ^
+                (Te4_0[byte(temp, 3)]) ^
+                rcon[i];
+            rk[5] = rk[1] ^ rk[4];
+            rk[6] = rk[2] ^ rk[5];
+            rk[7] = rk[3] ^ rk[6];
+            if (++i == 10) {
+               break;
+            }
+            rk += 4;
+        }
+    } else if (keylen == 24) {
+        j = 52;   
+        LOAD32H(rk[4], key + 16);
+        LOAD32H(rk[5], key + 20);
+        for (;;) {
+        #ifdef _MSC_VER
+            temp = skey->rijndael.eK[rk - skey->rijndael.eK + 5]; 
+        #else
+            temp = rk[5];
+        #endif
+            rk[ 6] = rk[ 0] ^
+                (Te4_3[byte(temp, 2)]) ^
+                (Te4_2[byte(temp, 1)]) ^
+                (Te4_1[byte(temp, 0)]) ^
+                (Te4_0[byte(temp, 3)]) ^
+                rcon[i];
+            rk[ 7] = rk[ 1] ^ rk[ 6];
+            rk[ 8] = rk[ 2] ^ rk[ 7];
+            rk[ 9] = rk[ 3] ^ rk[ 8];
+            if (++i == 8) {
+                break;
+            }
+            rk[10] = rk[ 4] ^ rk[ 9];
+            rk[11] = rk[ 5] ^ rk[10];
+            rk += 6;
+        }
+    } else if (keylen == 32) {
+        j = 60;
+        LOAD32H(rk[4], key + 16);
+        LOAD32H(rk[5], key + 20);
+        LOAD32H(rk[6], key + 24);
+        LOAD32H(rk[7], key + 28);
+        for (;;) {
+        #ifdef _MSC_VER
+            temp = skey->rijndael.eK[rk - skey->rijndael.eK + 7]; 
+        #else
+            temp = rk[7];
+        #endif
+            rk[ 8] = rk[ 0] ^
+                (Te4_3[byte(temp, 2)]) ^
+                (Te4_2[byte(temp, 1)]) ^
+                (Te4_1[byte(temp, 0)]) ^
+                (Te4_0[byte(temp, 3)]) ^
+                rcon[i];
+            rk[ 9] = rk[ 1] ^ rk[ 8];
+            rk[10] = rk[ 2] ^ rk[ 9];
+            rk[11] = rk[ 3] ^ rk[10];
+            if (++i == 7) {
+                break;
+            }
+            temp = rk[11];
+            rk[12] = rk[ 4] ^
+                (Te4_3[byte(temp, 3)]) ^
+                (Te4_2[byte(temp, 2)]) ^
+                (Te4_1[byte(temp, 1)]) ^
+                (Te4_0[byte(temp, 0)]);
+            rk[13] = rk[ 5] ^ rk[12];
+            rk[14] = rk[ 6] ^ rk[13];
+            rk[15] = rk[ 7] ^ rk[14];
+            rk += 8;
+        }
+    } else {
+       /* this can't happen */
+       j = 4;
+    }
+    
+    /* setup the inverse key now */
+    rk   = skey->rijndael.dK;
+    rrk  = skey->rijndael.eK + j - 4; 
+    
+    /* apply the inverse MixColumn transform to all round keys but the first and the last: */
+    /* copy first */
+    *rk++ = *rrk++;
+    *rk++ = *rrk++;
+    *rk++ = *rrk++;
+    *rk   = *rrk;
+    rk -= 3; rrk -= 3;
+    
+    for (i = 1; i < skey->rijndael.Nr; i++) {
+        rrk -= 4;
+        rk  += 4;
+    #ifdef SMALL_CODE        
+        temp = rrk[0];
+        rk[0] =
+            Td0(255 & Te4[byte(temp, 3)]) ^
+            Td1(255 & Te4[byte(temp, 2)]) ^
+            Td2(255 & Te4[byte(temp, 1)]) ^
+            Td3(255 & Te4[byte(temp, 0)]);
+        temp = rrk[1];
+        rk[1] =
+            Td0(255 & Te4[byte(temp, 3)]) ^
+            Td1(255 & Te4[byte(temp, 2)]) ^
+            Td2(255 & Te4[byte(temp, 1)]) ^
+            Td3(255 & Te4[byte(temp, 0)]);
+        temp = rrk[2];
+        rk[2] =
+            Td0(255 & Te4[byte(temp, 3)]) ^
+            Td1(255 & Te4[byte(temp, 2)]) ^
+            Td2(255 & Te4[byte(temp, 1)]) ^
+            Td3(255 & Te4[byte(temp, 0)]);
+        temp = rrk[3];
+        rk[3] =
+            Td0(255 & Te4[byte(temp, 3)]) ^
+            Td1(255 & Te4[byte(temp, 2)]) ^
+            Td2(255 & Te4[byte(temp, 1)]) ^
+            Td3(255 & Te4[byte(temp, 0)]);
+     #else
+        temp = rrk[0];
+        rk[0] =
+            Tks0[byte(temp, 3)] ^
+            Tks1[byte(temp, 2)] ^
+            Tks2[byte(temp, 1)] ^
+            Tks3[byte(temp, 0)];
+        temp = rrk[1];
+        rk[1] =
+            Tks0[byte(temp, 3)] ^
+            Tks1[byte(temp, 2)] ^
+            Tks2[byte(temp, 1)] ^
+            Tks3[byte(temp, 0)];
+        temp = rrk[2];
+        rk[2] =
+            Tks0[byte(temp, 3)] ^
+            Tks1[byte(temp, 2)] ^
+            Tks2[byte(temp, 1)] ^
+            Tks3[byte(temp, 0)];
+        temp = rrk[3];
+        rk[3] =
+            Tks0[byte(temp, 3)] ^
+            Tks1[byte(temp, 2)] ^
+            Tks2[byte(temp, 1)] ^
+            Tks3[byte(temp, 0)];
+      #endif            
+     
+    }
+
+    /* copy last */
+    rrk -= 4;
+    rk  += 4;
+    *rk++ = *rrk++;
+    *rk++ = *rrk++;
+    *rk++ = *rrk++;
+    *rk   = *rrk;
+
+    return CRYPT_OK;   
+}
+
+#ifdef CLEAN_STACK
+static void _rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) 
+#else
+void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
+#endif
+{
+    ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
+    int Nr, r;
+   
+    _ARGCHK(pt != NULL);
+    _ARGCHK(ct != NULL);
+    _ARGCHK(skey != NULL);
+    
+    Nr = skey->rijndael.Nr;
+    rk = skey->rijndael.eK;
+    
+    /*
+     * map byte array block to cipher state
+     * and add initial round key:
+     */
+    LOAD32H(s0, pt      ); s0 ^= rk[0];
+    LOAD32H(s1, pt  +  4); s1 ^= rk[1];
+    LOAD32H(s2, pt  +  8); s2 ^= rk[2];
+    LOAD32H(s3, pt  + 12); s3 ^= rk[3];
+
+    /*
+     * Nr - 1 full rounds:
+     */
+    r = Nr >> 1;
+    for (;;) {
+        t0 =
+            Te0(byte(s0, 3)) ^
+            Te1(byte(s1, 2)) ^
+            Te2(byte(s2, 1)) ^
+            Te3(byte(s3, 0)) ^
+            rk[4];
+        t1 =
+            Te0(byte(s1, 3)) ^
+            Te1(byte(s2, 2)) ^
+            Te2(byte(s3, 1)) ^
+            Te3(byte(s0, 0)) ^
+            rk[5];
+        t2 =
+            Te0(byte(s2, 3)) ^
+            Te1(byte(s3, 2)) ^
+            Te2(byte(s0, 1)) ^
+            Te3(byte(s1, 0)) ^
+            rk[6];
+        t3 =
+            Te0(byte(s3, 3)) ^
+            Te1(byte(s0, 2)) ^
+            Te2(byte(s1, 1)) ^
+            Te3(byte(s2, 0)) ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+        s0 =
+            Te0(byte(t0, 3)) ^
+            Te1(byte(t1, 2)) ^
+            Te2(byte(t2, 1)) ^
+            Te3(byte(t3, 0)) ^
+            rk[0];
+        s1 =
+            Te0(byte(t1, 3)) ^
+            Te1(byte(t2, 2)) ^
+            Te2(byte(t3, 1)) ^
+            Te3(byte(t0, 0)) ^
+            rk[1];
+        s2 =
+            Te0(byte(t2, 3)) ^
+            Te1(byte(t3, 2)) ^
+            Te2(byte(t0, 1)) ^
+            Te3(byte(t1, 0)) ^
+            rk[2];
+        s3 =
+            Te0(byte(t3, 3)) ^
+            Te1(byte(t0, 2)) ^
+            Te2(byte(t1, 1)) ^
+            Te3(byte(t2, 0)) ^
+            rk[3];
+    }
+    /*
+     * apply last round and
+     * map cipher state to byte array block:
+     */
+    s0 =
+        (Te4_3[(t0 >> 24)       ]) ^
+        (Te4_2[(t1 >> 16) & 0xff]) ^
+        (Te4_1[(t2 >>  8) & 0xff]) ^
+        (Te4_0[(t3      ) & 0xff]) ^
+        rk[0];
+    STORE32H(s0, ct);
+    s1 =
+        (Te4_3[(t1 >> 24)       ]) ^
+        (Te4_2[(t2 >> 16) & 0xff]) ^
+        (Te4_1[(t3 >>  8) & 0xff]) ^
+        (Te4_0[(t0      ) & 0xff]) ^
+        rk[1];
+    STORE32H(s1, ct+4);
+    s2 =
+        (Te4_3[(t2 >> 24)       ]) ^
+        (Te4_2[(t3 >> 16) & 0xff]) ^
+        (Te4_1[(t0 >>  8) & 0xff]) ^
+        (Te4_0[(t1      ) & 0xff]) ^
+        rk[2];
+    STORE32H(s2, ct+8);
+    s3 =
+        (Te4_3[(t3 >> 24)       ]) ^
+        (Te4_2[(t0 >> 16) & 0xff]) ^
+        (Te4_1[(t1 >>  8) & 0xff]) ^
+        (Te4_0[(t2      ) & 0xff]) ^ 
+        rk[3];
+    STORE32H(s3, ct+12);
+}
+
+#ifdef CLEAN_STACK
+void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) 
+{
+   _rijndael_ecb_encrypt(pt, ct, skey);
+   burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) 
+#else
+void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
+#endif
+{
+    ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
+    int Nr, r;
+
+    _ARGCHK(pt != NULL);
+    _ARGCHK(ct != NULL);
+    _ARGCHK(skey != NULL);
+    
+    Nr = skey->rijndael.Nr;
+    rk = skey->rijndael.dK;
+
+    /*
+     * map byte array block to cipher state
+     * and add initial round key:
+     */
+    LOAD32H(s0, ct      ); s0 ^= rk[0];
+    LOAD32H(s1, ct  +  4); s1 ^= rk[1];
+    LOAD32H(s2, ct  +  8); s2 ^= rk[2];
+    LOAD32H(s3, ct  + 12); s3 ^= rk[3];
+
+    /*
+     * Nr - 1 full rounds:
+     */
+    r = Nr >> 1;
+    for (;;) {
+
+        t0 =
+            Td0(byte(s0, 3)) ^
+            Td1(byte(s3, 2)) ^
+            Td2(byte(s2, 1)) ^
+            Td3(byte(s1, 0)) ^
+            rk[4];
+        t1 =
+            Td0(byte(s1, 3)) ^
+            Td1(byte(s0, 2)) ^
+            Td2(byte(s3, 1)) ^
+            Td3(byte(s2, 0)) ^
+            rk[5];
+        t2 =
+            Td0(byte(s2, 3)) ^
+            Td1(byte(s1, 2)) ^
+            Td2(byte(s0, 1)) ^
+            Td3(byte(s3, 0)) ^
+            rk[6];
+        t3 =
+            Td0(byte(s3, 3)) ^
+            Td1(byte(s2, 2)) ^
+            Td2(byte(s1, 1)) ^
+            Td3(byte(s0, 0)) ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+
+        s0 =
+            Td0(byte(t0, 3)) ^
+            Td1(byte(t3, 2)) ^
+            Td2(byte(t2, 1)) ^
+            Td3(byte(t1, 0)) ^
+            rk[0];
+        s1 =
+            Td0(byte(t1, 3)) ^
+            Td1(byte(t0, 2)) ^
+            Td2(byte(t3, 1)) ^
+            Td3(byte(t2, 0)) ^
+            rk[1];
+        s2 =
+            Td0(byte(t2, 3)) ^
+            Td1(byte(t1, 2)) ^
+            Td2(byte(t0, 1)) ^
+            Td3(byte(t3, 0)) ^
+            rk[2];
+        s3 =
+            Td0(byte(t3, 3)) ^
+            Td1(byte(t2, 2)) ^
+            Td2(byte(t1, 1)) ^
+            Td3(byte(t0, 0)) ^
+            rk[3];
+    }
+
+    /*
+     * apply last round and
+     * map cipher state to byte array block:
+     */
+    s0 =
+        (Td4[(t0 >> 24)       ] & 0xff000000) ^
+        (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+        (Td4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
+        (Td4[(t1      ) & 0xff] & 0x000000ff) ^
+        rk[0];
+    STORE32H(s0, pt);
+    s1 =
+        (Td4[(t1 >> 24)       ] & 0xff000000) ^
+        (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+        (Td4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
+        (Td4[(t2      ) & 0xff] & 0x000000ff) ^
+        rk[1];
+    STORE32H(s1, pt+4);
+    s2 =
+        (Td4[(t2 >> 24)       ] & 0xff000000) ^
+        (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+        (Td4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
+        (Td4[(t3      ) & 0xff] & 0x000000ff) ^
+        rk[2];
+    STORE32H(s2, pt+8);
+    s3 =
+        (Td4[(t3 >> 24)       ] & 0xff000000) ^
+        (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+        (Td4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
+        (Td4[(t0      ) & 0xff] & 0x000000ff) ^
+        rk[3];
+    STORE32H(s3, pt+12);
+}
+
+
+#ifdef CLEAN_STACK
+void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) 
+{
+   _rijndael_ecb_decrypt(ct, pt, skey);
+   burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
+}
+#endif
+
+int rijndael_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+ int err;
+ static const struct {
+     int keylen;
+     unsigned char key[32], pt[16], ct[16];
+ } tests[] = {
+    { 16,
+      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, 
+      { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+      { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 
+        0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }
+    }, { 
+      24,
+      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
+      { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+      { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, 
+        0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }
+    }, {
+      32,
+      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
+        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+      { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+      { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 
+        0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }
+    }
+ };
+ 
+ symmetric_key key;
+ unsigned char tmp[2][16];
+ int i, y;
+ 
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+    zeromem(&key, sizeof(key));
+    if ((err = rijndael_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { 
+       return err;
+    }
+  
+    rijndael_ecb_encrypt(tests[i].pt, tmp[0], &key);
+    rijndael_ecb_decrypt(tmp[0], tmp[1], &key);
+    if (memcmp(tmp[0], tests[i].ct, 16) || memcmp(tmp[1], tests[i].pt, 16)) { 
+#if 0
+       printf("\n\nTest %d failed\n", i);
+       if (memcmp(tmp[0], tests[i].ct, 16)) {
+          printf("CT: ");
+          for (i = 0; i < 16; i++) {
+             printf("%02x ", tmp[0][i]);
+          }
+          printf("\n");
+       } else {
+          printf("PT: ");
+          for (i = 0; i < 16; i++) {
+             printf("%02x ", tmp[1][i]);
+          }
+          printf("\n");
+       }
+#endif       
+        return CRYPT_FAIL_TESTVECTOR;
+    }
+
+      /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+      for (y = 0; y < 16; y++) tmp[0][y] = 0;
+      for (y = 0; y < 1000; y++) rijndael_ecb_encrypt(tmp[0], tmp[0], &key);
+      for (y = 0; y < 1000; y++) rijndael_ecb_decrypt(tmp[0], tmp[0], &key);
+      for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+ }       
+ return CRYPT_OK;
+ #endif
+}
+
+int rijndael_keysize(int *desired_keysize)
+{
+   _ARGCHK(desired_keysize != NULL);
+
+   if (*desired_keysize < 16)
+      return CRYPT_INVALID_KEYSIZE;
+   if (*desired_keysize < 24) {
+      *desired_keysize = 16;
+      return CRYPT_OK;
+   } else if (*desired_keysize < 32) {
+      *desired_keysize = 24;
+      return CRYPT_OK;
+   } else {
+      *desired_keysize = 32;
+      return CRYPT_OK;
+   }
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aes_tab.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,1008 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+/* The precomputed tables for AES */
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+static const ulong32 TE0[256] = {
+    0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,
+    0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,
+    0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL,
+    0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL,
+    0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL,
+    0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL,
+    0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL,
+    0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL,
+    0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL,
+    0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL,
+    0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL,
+    0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL,
+    0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL,
+    0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL,
+    0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL,
+    0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL,
+    0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL,
+    0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL,
+    0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL,
+    0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL,
+    0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL,
+    0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL,
+    0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL,
+    0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL,
+    0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL,
+    0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL,
+    0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL,
+    0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL,
+    0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL,
+    0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL,
+    0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL,
+    0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL,
+    0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL,
+    0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL,
+    0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL,
+    0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL,
+    0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL,
+    0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL,
+    0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL,
+    0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL,
+    0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL,
+    0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL,
+    0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL,
+    0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL,
+    0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL,
+    0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL,
+    0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL,
+    0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL,
+    0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL,
+    0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL,
+    0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL,
+    0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL,
+    0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL,
+    0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL,
+    0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL,
+    0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL,
+    0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL,
+    0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL,
+    0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL,
+    0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL,
+    0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL,
+    0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL,
+    0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL,
+    0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL,
+};
+
+static const ulong32 Te4[256] = {
+    0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL,
+    0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL,
+    0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL,
+    0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL,
+    0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL,
+    0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL,
+    0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL,
+    0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL,
+    0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL,
+    0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL,
+    0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL,
+    0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL,
+    0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL,
+    0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL,
+    0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL,
+    0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL,
+    0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL,
+    0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL,
+    0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL,
+    0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL,
+    0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL,
+    0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL,
+    0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL,
+    0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL,
+    0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL,
+    0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL,
+    0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL,
+    0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL,
+    0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL,
+    0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL,
+    0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL,
+    0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL,
+    0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL,
+    0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL,
+    0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL,
+    0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL,
+    0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL,
+    0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL,
+    0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL,
+    0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL,
+    0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL,
+    0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL,
+    0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL,
+    0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL,
+    0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL,
+    0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL,
+    0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL,
+    0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL,
+    0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL,
+    0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL,
+    0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL,
+    0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL,
+    0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL,
+    0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL,
+    0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL,
+    0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL,
+    0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL,
+    0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL,
+    0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL,
+    0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL,
+    0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL,
+    0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL,
+    0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL,
+    0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL,
+};
+
+static const ulong32 TD0[256] = {
+    0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,
+    0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,
+    0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL,
+    0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL,
+    0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL,
+    0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL,
+    0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL,
+    0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL,
+    0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL,
+    0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL,
+    0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL,
+    0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL,
+    0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL,
+    0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL,
+    0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL,
+    0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL,
+    0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL,
+    0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL,
+    0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL,
+    0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL,
+    0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL,
+    0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL,
+    0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL,
+    0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL,
+    0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL,
+    0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL,
+    0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL,
+    0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL,
+    0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL,
+    0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL,
+    0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL,
+    0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL,
+    0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL,
+    0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL,
+    0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL,
+    0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL,
+    0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL,
+    0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL,
+    0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL,
+    0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL,
+    0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL,
+    0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL,
+    0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL,
+    0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL,
+    0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL,
+    0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL,
+    0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL,
+    0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL,
+    0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL,
+    0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL,
+    0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL,
+    0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL,
+    0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL,
+    0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL,
+    0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL,
+    0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL,
+    0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL,
+    0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL,
+    0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL,
+    0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL,
+    0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL,
+    0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL,
+    0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL,
+    0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL,
+};
+
+static const ulong32 Td4[256] = {
+    0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL,
+    0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL,
+    0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL,
+    0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL,
+    0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL,
+    0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL,
+    0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL,
+    0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL,
+    0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL,
+    0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL,
+    0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL,
+    0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL,
+    0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL,
+    0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL,
+    0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL,
+    0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL,
+    0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL,
+    0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL,
+    0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL,
+    0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL,
+    0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL,
+    0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL,
+    0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL,
+    0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL,
+    0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL,
+    0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL,
+    0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL,
+    0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL,
+    0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL,
+    0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL,
+    0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL,
+    0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL,
+    0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL,
+    0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL,
+    0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL,
+    0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL,
+    0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL,
+    0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL,
+    0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL,
+    0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL,
+    0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL,
+    0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL,
+    0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL,
+    0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL,
+    0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL,
+    0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL,
+    0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL,
+    0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL,
+    0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL,
+    0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL,
+    0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL,
+    0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL,
+    0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL,
+    0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL,
+    0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL,
+    0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL,
+    0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL,
+    0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL,
+    0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL,
+    0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL,
+    0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL,
+    0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL,
+    0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL,
+    0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL,
+};
+
+#ifdef SMALL_CODE
+
+#define Te0(x) TE0[x]
+#define Te1(x) ROR(TE0[x], 8)
+#define Te2(x) ROR(TE0[x], 16)
+#define Te3(x) ROR(TE0[x], 24)
+
+#define Td0(x) TD0[x]
+#define Td1(x) ROR(TD0[x], 8)
+#define Td2(x) ROR(TD0[x], 16)
+#define Td3(x) ROR(TD0[x], 24)
+
+#define Te4_0 0x000000FF & Te4
+#define Te4_1 0x0000FF00 & Te4
+#define Te4_2 0x00FF0000 & Te4
+#define Te4_3 0xFF000000 & Te4
+
+#else
+
+#define Te0(x) TE0[x]
+#define Te1(x) TE1[x]
+#define Te2(x) TE2[x]
+#define Te3(x) TE3[x]
+
+#define Td0(x) TD0[x]
+#define Td1(x) TD1[x]
+#define Td2(x) TD2[x]
+#define Td3(x) TD3[x]
+
+static const ulong32 TE1[256] = {
+    0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL,
+    0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL,
+    0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL,
+    0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL,
+    0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL,
+    0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL,
+    0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL,
+    0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL,
+    0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL,
+    0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL,
+    0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL,
+    0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL,
+    0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL,
+    0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL,
+    0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL,
+    0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL,
+    0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL,
+    0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL,
+    0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL,
+    0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL,
+    0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL,
+    0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL,
+    0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL,
+    0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL,
+    0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL,
+    0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL,
+    0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL,
+    0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL,
+    0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL,
+    0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL,
+    0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL,
+    0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL,
+    0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL,
+    0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL,
+    0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL,
+    0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL,
+    0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL,
+    0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL,
+    0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL,
+    0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL,
+    0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL,
+    0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL,
+    0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL,
+    0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL,
+    0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL,
+    0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL,
+    0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL,
+    0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL,
+    0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL,
+    0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL,
+    0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL,
+    0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL,
+    0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL,
+    0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL,
+    0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL,
+    0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL,
+    0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL,
+    0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL,
+    0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL,
+    0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL,
+    0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL,
+    0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL,
+    0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL,
+    0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL,
+};
+static const ulong32 TE2[256] = {
+    0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL,
+    0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL,
+    0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL,
+    0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL,
+    0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL,
+    0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL,
+    0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL,
+    0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL,
+    0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL,
+    0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL,
+    0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL,
+    0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL,
+    0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL,
+    0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL,
+    0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL,
+    0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL,
+    0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL,
+    0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL,
+    0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL,
+    0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL,
+    0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL,
+    0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL,
+    0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL,
+    0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL,
+    0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL,
+    0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL,
+    0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL,
+    0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL,
+    0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL,
+    0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL,
+    0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL,
+    0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL,
+    0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL,
+    0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL,
+    0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL,
+    0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL,
+    0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL,
+    0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL,
+    0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL,
+    0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL,
+    0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL,
+    0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL,
+    0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL,
+    0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL,
+    0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL,
+    0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL,
+    0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL,
+    0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL,
+    0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL,
+    0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL,
+    0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL,
+    0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL,
+    0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL,
+    0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL,
+    0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL,
+    0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL,
+    0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL,
+    0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL,
+    0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL,
+    0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL,
+    0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL,
+    0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL,
+    0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL,
+    0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL,
+};
+static const ulong32 TE3[256] = {
+
+    0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL,
+    0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL,
+    0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL,
+    0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL,
+    0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL,
+    0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL,
+    0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL,
+    0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL,
+    0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL,
+    0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL,
+    0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL,
+    0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL,
+    0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL,
+    0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL,
+    0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL,
+    0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL,
+    0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL,
+    0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL,
+    0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL,
+    0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL,
+    0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL,
+    0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL,
+    0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL,
+    0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL,
+    0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL,
+    0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL,
+    0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL,
+    0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL,
+    0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL,
+    0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL,
+    0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL,
+    0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL,
+    0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL,
+    0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL,
+    0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL,
+    0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL,
+    0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL,
+    0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL,
+    0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL,
+    0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL,
+    0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL,
+    0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL,
+    0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL,
+    0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL,
+    0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL,
+    0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL,
+    0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL,
+    0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL,
+    0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL,
+    0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL,
+    0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL,
+    0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL,
+    0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL,
+    0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL,
+    0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL,
+    0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL,
+    0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL,
+    0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL,
+    0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL,
+    0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL,
+    0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL,
+    0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL,
+    0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL,
+    0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL,
+};
+
+static const ulong32 Te4_0[] = {
+0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL, 
+0x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL, 
+0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL, 
+0x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL, 
+0x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL, 
+0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL, 
+0x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL, 
+0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL, 
+0x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL, 
+0x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL, 
+0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL, 
+0x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL, 
+0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL, 
+0x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL, 
+0x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL, 
+0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL, 
+0x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL, 
+0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL, 
+0x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL, 
+0x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL, 
+0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL, 
+0x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL, 
+0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL, 
+0x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL, 
+0x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL, 
+0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL, 
+0x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL, 
+0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL, 
+0x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL, 
+0x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL, 
+0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL, 
+0x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL
+};
+
+static const ulong32 Te4_1[] = {
+0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL, 
+0x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL, 
+0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL, 
+0x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL, 
+0x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL, 
+0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL, 
+0x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL, 
+0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL, 
+0x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL, 
+0x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL, 
+0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL, 
+0x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL, 
+0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL, 
+0x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL, 
+0x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL, 
+0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL, 
+0x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL, 
+0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL, 
+0x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL, 
+0x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL, 
+0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL, 
+0x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL, 
+0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL, 
+0x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL, 
+0x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL, 
+0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL, 
+0x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL, 
+0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL, 
+0x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL, 
+0x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL, 
+0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL, 
+0x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL
+};
+
+static const ulong32 Te4_2[] = {
+0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL, 
+0x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL, 
+0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL, 
+0x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL, 
+0x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL, 
+0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL, 
+0x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL, 
+0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL, 
+0x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL, 
+0x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL, 
+0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL, 
+0x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL, 
+0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL, 
+0x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL, 
+0x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL, 
+0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL, 
+0x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL, 
+0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL, 
+0x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL, 
+0x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL, 
+0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL, 
+0x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL, 
+0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL, 
+0x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL, 
+0x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL, 
+0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL, 
+0x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL, 
+0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL, 
+0x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL, 
+0x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL, 
+0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL, 
+0x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL
+};
+
+static const ulong32 Te4_3[] = {
+0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL, 
+0x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL, 
+0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL, 
+0xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL, 
+0xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL, 
+0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL, 
+0x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL, 
+0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL, 
+0x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL, 
+0x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL, 
+0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL, 
+0x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL, 
+0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL, 
+0x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL, 
+0x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL, 
+0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL, 
+0xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL, 
+0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL, 
+0x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL, 
+0x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL, 
+0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL, 
+0xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL, 
+0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL, 
+0x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL, 
+0xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL, 
+0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL, 
+0x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL, 
+0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL, 
+0xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL, 
+0x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL, 
+0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL, 
+0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL
+};
+
+static const ulong32 TD1[256] = {
+    0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL,
+    0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL,
+    0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL,
+    0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL,
+    0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL,
+    0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL,
+    0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL,
+    0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL,
+    0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL,
+    0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL,
+    0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL,
+    0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL,
+    0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL,
+    0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL,
+    0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL,
+    0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL,
+    0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL,
+    0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL,
+    0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL,
+    0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL,
+    0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL,
+    0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL,
+    0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL,
+    0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL,
+    0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL,
+    0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL,
+    0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL,
+    0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL,
+    0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL,
+    0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL,
+    0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL,
+    0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL,
+    0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL,
+    0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL,
+    0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL,
+    0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL,
+    0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL,
+    0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL,
+    0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL,
+    0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL,
+    0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL,
+    0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL,
+    0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL,
+    0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL,
+    0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL,
+    0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL,
+    0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL,
+    0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL,
+    0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL,
+    0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL,
+    0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL,
+    0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL,
+    0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL,
+    0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL,
+    0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL,
+    0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL,
+    0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL,
+    0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL,
+    0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL,
+    0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL,
+    0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL,
+    0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL,
+    0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL,
+    0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL,
+};
+static const ulong32 TD2[256] = {
+    0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL,
+    0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL,
+    0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL,
+    0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL,
+    0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL,
+    0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL,
+    0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL,
+    0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL,
+    0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL,
+    0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL,
+    0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL,
+    0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL,
+    0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL,
+    0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL,
+    0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL,
+    0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL,
+    0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL,
+    0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL,
+    0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL,
+    0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL,
+    0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL,
+    0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL,
+    0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL,
+    0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL,
+    0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL,
+    0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL,
+    0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL,
+    0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL,
+    0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL,
+    0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL,
+    0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL,
+    0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL,
+    0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL,
+    0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL,
+    0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL,
+    0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL,
+    0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL,
+    0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL,
+    0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL,
+    0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL,
+    0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL,
+    0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL,
+    0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL,
+    0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL,
+    0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL,
+    0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL,
+    0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL,
+    0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL,
+    0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL,
+    0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL,
+    0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL,
+    0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL,
+    0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL,
+    0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL,
+    0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL,
+    0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL,
+    0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL,
+    0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL,
+    0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL,
+    0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL,
+    0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL,
+    0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL,
+    0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL,
+    0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL,
+};
+static const ulong32 TD3[256] = {
+    0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL,
+    0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL,
+    0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL,
+    0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL,
+    0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL,
+    0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL,
+    0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL,
+    0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL,
+    0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL,
+    0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL,
+    0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL,
+    0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL,
+    0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL,
+    0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL,
+    0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL,
+    0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL,
+    0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL,
+    0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL,
+    0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL,
+    0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL,
+    0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL,
+    0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL,
+    0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL,
+    0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL,
+    0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL,
+    0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL,
+    0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL,
+    0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL,
+    0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL,
+    0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL,
+    0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL,
+    0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL,
+    0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL,
+    0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL,
+    0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL,
+    0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL,
+    0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL,
+    0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL,
+    0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL,
+    0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL,
+    0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL,
+    0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL,
+    0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL,
+    0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL,
+    0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL,
+    0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL,
+    0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL,
+    0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL,
+    0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL,
+    0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL,
+    0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL,
+    0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL,
+    0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL,
+    0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL,
+    0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL,
+    0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL,
+    0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL,
+    0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL,
+    0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL,
+    0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL,
+    0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL,
+    0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL,
+    0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL,
+    0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL,
+};
+
+static const ulong32 Tks0[] = {
+0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL, 
+0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL, 
+0xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL, 
+0x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL, 
+0xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL, 
+0xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL, 
+0x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL, 
+0x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL, 
+0xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL, 
+0xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL, 
+0x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL, 
+0x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL, 
+0x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL, 
+0x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL, 
+0x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL, 
+0xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL, 
+0x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL, 
+0x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL, 
+0xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL, 
+0xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL, 
+0x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL, 
+0xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL, 
+0x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL, 
+0x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL, 
+0xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL, 
+0x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL, 
+0x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL, 
+0x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL, 
+0x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL, 
+0x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL, 
+0xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL, 
+0xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL
+};
+
+static const ulong32 Tks1[] = {
+0x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL, 
+0x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL, 
+0xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL, 
+0xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL, 
+0x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL, 
+0x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL, 
+0xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL, 
+0x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL, 
+0xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL, 
+0xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL, 
+0x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL, 
+0x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL, 
+0x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL, 
+0xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL, 
+0x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL, 
+0x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL, 
+0xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL, 
+0xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL, 
+0x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL, 
+0x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL, 
+0x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL, 
+0xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL, 
+0x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL, 
+0x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL, 
+0x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL, 
+0x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL, 
+0xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL, 
+0xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL, 
+0x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL, 
+0x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL, 
+0xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL, 
+0x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL
+};
+
+static const ulong32 Tks2[] = {
+0x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL, 
+0x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL, 
+0xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL, 
+0xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL, 
+0xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL, 
+0xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL, 
+0x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL, 
+0x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL, 
+0x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL, 
+0x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL, 
+0xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL, 
+0xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL, 
+0xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL, 
+0xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL, 
+0x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL, 
+0x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL, 
+0xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL, 
+0xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL, 
+0x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL, 
+0x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL, 
+0x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL, 
+0x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL, 
+0xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL, 
+0xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL, 
+0xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL, 
+0xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL, 
+0x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL, 
+0x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL, 
+0x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL, 
+0x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL, 
+0xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL, 
+0xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL
+};
+
+static const ulong32 Tks3[] = {
+0x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL, 
+0x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL, 
+0x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL, 
+0xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL, 
+0x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL, 
+0x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL, 
+0xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL, 
+0xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL, 
+0x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL, 
+0x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL, 
+0xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL, 
+0xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL, 
+0x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL, 
+0x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL, 
+0xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL, 
+0x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL, 
+0xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL, 
+0xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL, 
+0x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL, 
+0x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL, 
+0xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL, 
+0x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL, 
+0x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL, 
+0x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL, 
+0x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL, 
+0xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL, 
+0x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL, 
+0x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL, 
+0xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL, 
+0xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL, 
+0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL, 
+0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL
+};
+
+#endif /* SMALL CODE */
+
+static const ulong32 rcon[] = {
+    0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
+    0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,
+    0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ampi.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,55 @@
+/* Code submitted by Svante Seleborg, cleaned up by Tom St Denis */
+
+#include "mycrypt.h"
+#include <stdarg.h>
+
+#ifdef MPI
+
+mp_err mp_init_multi(mp_int *mp, ...) 
+{
+    mp_err res = MP_OKAY;      /* Assume ok until proven otherwise */
+    int n = 0;                 /* Number of ok inits */
+    mp_int* cur_arg = mp;
+    va_list args;
+
+    va_start(args, mp);        /* init args to next argument from caller */
+    while (cur_arg != NULL) {
+        if (mp_init(cur_arg) != MP_OKAY) {
+            /* Oops - error! Back-track and mp_clear what we already
+               succeeded in init-ing, then return error.
+            */
+            va_list clean_args;
+            cur_arg = mp;
+            va_start(clean_args, mp);
+            while (n--) {
+                mp_clear(cur_arg);
+                cur_arg = va_arg(clean_args, mp_int*);
+            }
+            va_end(clean_args);
+            res = MP_MEM;
+            break;
+        }
+        n++;
+        cur_arg = va_arg(args, mp_int*);
+    }
+    va_end(args);
+    return res;                /* Assumed ok, if error flagged above. */
+}
+
+/*
+    Clear all arguments given, ended by a NULL marker.
+*/
+void mp_clear_multi(mp_int *mp, ...) 
+{
+    mp_int* next_mp = mp;
+    va_list args;
+    va_start(args, mp);
+    while (next_mp != NULL) {
+        mp_clear(next_mp);
+        next_mp = va_arg(args, mp_int*);
+    }
+    va_end(args);
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authors	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,55 @@
+This is a list of people who have contributed [directly or indirectly] to the project
+[in no partcular order].  If you have helped and your name is not here email me at
[email protected].
+
+
+1) [email protected]
+
+   Gave help porting the lib to MSVC particularly pointed out various warnings and errors.
+
+2) Richard Heathfield
+
+   Gave a lot of help concerning valid C portable code.  
+
+3) Ajay K. Agrawal
+
+   Helped port the library to MSVC and spotted a few bugs and errors.
+
+4) Brian Gladman
+
+   Wrote the AES and Serpent code used.  Found a bug in the hash code for certain types of inputs.
+
+5) Svante Seleborg
+
+   Submitted the "ampi.c" code as well as many suggestions on improving the readability of the source code.
+
+6) Clay Culver
+
+   Submitted a fix for "rsa.c" which cleaned up some code.  Submited some other fixes too.  :-)
+   Clay has helped find bugs in various pieces of code including the registry functions, base64 routines 
+   and the make process.  He is also now the primary author of the libtomcrypt reference manual and has plan
+   at making a HTML version.
+
+7) Jason Klapste
+
+   Submitted fixes to the yarrow, hash, make process and test code as well as other subtle bug fixes.  The 
+yarrow code can now default to any cipher/hash that is left after you remove them from a build.
+
+8) Dobes Vandermeer <[email protected]>
+
+   Submitted HMAC code that worked flawlessly out of the box... good job!  Also submitted a MD4 routine.
+   Submitted some modified DES code that was merged into the code base [using the libtomcrypt API]
+
+9) Wayne Scott ([email protected])
+  
+   Submitted base64 that complies with the RFC standards.  Submitted some ideas to improve the RSA key generation
+   as well.
+   
+10) Sky Schulz ([email protected])
+
+   Has submitted a set of ideas to improve the library and make it more attractive for professional users.
+   
+11) Mike Frysinger 
+
+   Together with Clay came up with a more "unix friendly" makefile.  Mike Frysinger has been keeping copies of 
+   the library for the Gentoo linux distribution.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/base64.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,121 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+/* compliant base64 code donated by Wayne Scott ([email protected]) */
+#include "mycrypt.h"
+
+#ifdef BASE64
+
+static const char *codes = 
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const unsigned char map[256] = {
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
+ 52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
+255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,
+  7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,
+ 19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,
+255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
+ 37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
+ 49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255 };
+
+int base64_encode(const unsigned char *in,  unsigned long len, 
+                        unsigned char *out, unsigned long *outlen)
+{
+   unsigned long i, len2, leven;
+   unsigned char *p;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* valid output size ? */
+   len2 = 4 * ((len + 2) / 3);
+   if (*outlen < len2 + 1) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   p = out;
+   leven = 3*(len / 3);
+   for (i = 0; i < leven; i += 3) {
+       *p++ = codes[(in[0] >> 2) & 0x3F];
+       *p++ = codes[(((in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F];
+       *p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F];
+       *p++ = codes[in[2] & 0x3F];
+       in += 3;
+   }
+   /* Pad it if necessary...  */
+   if (i < len) {
+       unsigned a = in[0];
+       unsigned b = (i+1 < len) ? in[1] : 0;
+
+       *p++ = codes[(a >> 2) & 0x3F];
+       *p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F];
+       *p++ = (i+1 < len) ? codes[(((b & 0xf) << 2)) & 0x3F] : '=';
+       *p++ = '=';
+   }
+
+   /* append a NULL byte */
+   *p = '\0';
+
+   /* return ok */
+   *outlen = p - out;
+   return CRYPT_OK;
+}
+
+int base64_decode(const unsigned char *in,  unsigned long len, 
+                        unsigned char *out, unsigned long *outlen)
+{
+   unsigned long t, x, y, z;
+   unsigned char c;
+   int           g;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   g = 3;
+   for (x = y = z = t = 0; x < len; x++) {
+       c = map[in[x]&0xFF];
+       if (c == 255) continue;
+       if (c == 254) { c = 0; g--; }
+       t = (t<<6)|c;
+       if (++y == 4) {
+          if (z + g > *outlen) { 
+             return CRYPT_BUFFER_OVERFLOW; 
+          }
+          out[z++] = (unsigned char)((t>>16)&255);
+          if (g > 1) out[z++] = (unsigned char)((t>>8)&255);
+          if (g > 2) out[z++] = (unsigned char)(t&255);
+          y = t = 0;
+       }
+   }
+   if (y != 0) {
+       return CRYPT_INVALID_PACKET;
+   }
+   *outlen = z;
+   return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/blowfish.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,541 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+#ifdef BLOWFISH
+
+const struct _cipher_descriptor blowfish_desc =
+{
+    "blowfish",
+    0,
+    8, 56, 8, 16,
+    &blowfish_setup,
+    &blowfish_ecb_encrypt,
+    &blowfish_ecb_decrypt,
+    &blowfish_test,
+    &blowfish_keysize
+};
+
+static const ulong32 ORIG_P[16 + 2] = {
+        0x243F6A88UL, 0x85A308D3UL, 0x13198A2EUL, 0x03707344UL,
+        0xA4093822UL, 0x299F31D0UL, 0x082EFA98UL, 0xEC4E6C89UL,
+        0x452821E6UL, 0x38D01377UL, 0xBE5466CFUL, 0x34E90C6CUL,
+        0xC0AC29B7UL, 0xC97C50DDUL, 0x3F84D5B5UL, 0xB5470917UL,
+        0x9216D5D9UL, 0x8979FB1BUL
+};
+
+static const ulong32 ORIG_S[4][256] = {
+    {   0xD1310BA6UL, 0x98DFB5ACUL, 0x2FFD72DBUL, 0xD01ADFB7UL,
+        0xB8E1AFEDUL, 0x6A267E96UL, 0xBA7C9045UL, 0xF12C7F99UL,
+        0x24A19947UL, 0xB3916CF7UL, 0x0801F2E2UL, 0x858EFC16UL,
+        0x636920D8UL, 0x71574E69UL, 0xA458FEA3UL, 0xF4933D7EUL,
+        0x0D95748FUL, 0x728EB658UL, 0x718BCD58UL, 0x82154AEEUL,
+        0x7B54A41DUL, 0xC25A59B5UL, 0x9C30D539UL, 0x2AF26013UL,
+        0xC5D1B023UL, 0x286085F0UL, 0xCA417918UL, 0xB8DB38EFUL,
+        0x8E79DCB0UL, 0x603A180EUL, 0x6C9E0E8BUL, 0xB01E8A3EUL,
+        0xD71577C1UL, 0xBD314B27UL, 0x78AF2FDAUL, 0x55605C60UL,
+        0xE65525F3UL, 0xAA55AB94UL, 0x57489862UL, 0x63E81440UL,
+        0x55CA396AUL, 0x2AAB10B6UL, 0xB4CC5C34UL, 0x1141E8CEUL,
+        0xA15486AFUL, 0x7C72E993UL, 0xB3EE1411UL, 0x636FBC2AUL,
+        0x2BA9C55DUL, 0x741831F6UL, 0xCE5C3E16UL, 0x9B87931EUL,
+        0xAFD6BA33UL, 0x6C24CF5CUL, 0x7A325381UL, 0x28958677UL,
+        0x3B8F4898UL, 0x6B4BB9AFUL, 0xC4BFE81BUL, 0x66282193UL,
+        0x61D809CCUL, 0xFB21A991UL, 0x487CAC60UL, 0x5DEC8032UL,
+        0xEF845D5DUL, 0xE98575B1UL, 0xDC262302UL, 0xEB651B88UL,
+        0x23893E81UL, 0xD396ACC5UL, 0x0F6D6FF3UL, 0x83F44239UL,
+        0x2E0B4482UL, 0xA4842004UL, 0x69C8F04AUL, 0x9E1F9B5EUL,
+        0x21C66842UL, 0xF6E96C9AUL, 0x670C9C61UL, 0xABD388F0UL,
+        0x6A51A0D2UL, 0xD8542F68UL, 0x960FA728UL, 0xAB5133A3UL,
+        0x6EEF0B6CUL, 0x137A3BE4UL, 0xBA3BF050UL, 0x7EFB2A98UL,
+        0xA1F1651DUL, 0x39AF0176UL, 0x66CA593EUL, 0x82430E88UL,
+        0x8CEE8619UL, 0x456F9FB4UL, 0x7D84A5C3UL, 0x3B8B5EBEUL,
+        0xE06F75D8UL, 0x85C12073UL, 0x401A449FUL, 0x56C16AA6UL,
+        0x4ED3AA62UL, 0x363F7706UL, 0x1BFEDF72UL, 0x429B023DUL,
+        0x37D0D724UL, 0xD00A1248UL, 0xDB0FEAD3UL, 0x49F1C09BUL,
+        0x075372C9UL, 0x80991B7BUL, 0x25D479D8UL, 0xF6E8DEF7UL,
+        0xE3FE501AUL, 0xB6794C3BUL, 0x976CE0BDUL, 0x04C006BAUL,
+        0xC1A94FB6UL, 0x409F60C4UL, 0x5E5C9EC2UL, 0x196A2463UL,
+        0x68FB6FAFUL, 0x3E6C53B5UL, 0x1339B2EBUL, 0x3B52EC6FUL,
+        0x6DFC511FUL, 0x9B30952CUL, 0xCC814544UL, 0xAF5EBD09UL,
+        0xBEE3D004UL, 0xDE334AFDUL, 0x660F2807UL, 0x192E4BB3UL,
+        0xC0CBA857UL, 0x45C8740FUL, 0xD20B5F39UL, 0xB9D3FBDBUL,
+        0x5579C0BDUL, 0x1A60320AUL, 0xD6A100C6UL, 0x402C7279UL,
+        0x679F25FEUL, 0xFB1FA3CCUL, 0x8EA5E9F8UL, 0xDB3222F8UL,
+        0x3C7516DFUL, 0xFD616B15UL, 0x2F501EC8UL, 0xAD0552ABUL,
+        0x323DB5FAUL, 0xFD238760UL, 0x53317B48UL, 0x3E00DF82UL,
+        0x9E5C57BBUL, 0xCA6F8CA0UL, 0x1A87562EUL, 0xDF1769DBUL,
+        0xD542A8F6UL, 0x287EFFC3UL, 0xAC6732C6UL, 0x8C4F5573UL,
+        0x695B27B0UL, 0xBBCA58C8UL, 0xE1FFA35DUL, 0xB8F011A0UL,
+        0x10FA3D98UL, 0xFD2183B8UL, 0x4AFCB56CUL, 0x2DD1D35BUL,
+        0x9A53E479UL, 0xB6F84565UL, 0xD28E49BCUL, 0x4BFB9790UL,
+        0xE1DDF2DAUL, 0xA4CB7E33UL, 0x62FB1341UL, 0xCEE4C6E8UL,
+        0xEF20CADAUL, 0x36774C01UL, 0xD07E9EFEUL, 0x2BF11FB4UL,
+        0x95DBDA4DUL, 0xAE909198UL, 0xEAAD8E71UL, 0x6B93D5A0UL,
+        0xD08ED1D0UL, 0xAFC725E0UL, 0x8E3C5B2FUL, 0x8E7594B7UL,
+        0x8FF6E2FBUL, 0xF2122B64UL, 0x8888B812UL, 0x900DF01CUL,
+        0x4FAD5EA0UL, 0x688FC31CUL, 0xD1CFF191UL, 0xB3A8C1ADUL,
+        0x2F2F2218UL, 0xBE0E1777UL, 0xEA752DFEUL, 0x8B021FA1UL,
+        0xE5A0CC0FUL, 0xB56F74E8UL, 0x18ACF3D6UL, 0xCE89E299UL,
+        0xB4A84FE0UL, 0xFD13E0B7UL, 0x7CC43B81UL, 0xD2ADA8D9UL,
+        0x165FA266UL, 0x80957705UL, 0x93CC7314UL, 0x211A1477UL,
+        0xE6AD2065UL, 0x77B5FA86UL, 0xC75442F5UL, 0xFB9D35CFUL,
+        0xEBCDAF0CUL, 0x7B3E89A0UL, 0xD6411BD3UL, 0xAE1E7E49UL,
+        0x00250E2DUL, 0x2071B35EUL, 0x226800BBUL, 0x57B8E0AFUL,
+        0x2464369BUL, 0xF009B91EUL, 0x5563911DUL, 0x59DFA6AAUL,
+        0x78C14389UL, 0xD95A537FUL, 0x207D5BA2UL, 0x02E5B9C5UL,
+        0x83260376UL, 0x6295CFA9UL, 0x11C81968UL, 0x4E734A41UL,
+        0xB3472DCAUL, 0x7B14A94AUL, 0x1B510052UL, 0x9A532915UL,
+        0xD60F573FUL, 0xBC9BC6E4UL, 0x2B60A476UL, 0x81E67400UL,
+        0x08BA6FB5UL, 0x571BE91FUL, 0xF296EC6BUL, 0x2A0DD915UL,
+        0xB6636521UL, 0xE7B9F9B6UL, 0xFF34052EUL, 0xC5855664UL,
+        0x53B02D5DUL, 0xA99F8FA1UL, 0x08BA4799UL, 0x6E85076AUL   },
+    {   0x4B7A70E9UL, 0xB5B32944UL, 0xDB75092EUL, 0xC4192623UL,
+        0xAD6EA6B0UL, 0x49A7DF7DUL, 0x9CEE60B8UL, 0x8FEDB266UL,
+        0xECAA8C71UL, 0x699A17FFUL, 0x5664526CUL, 0xC2B19EE1UL,
+        0x193602A5UL, 0x75094C29UL, 0xA0591340UL, 0xE4183A3EUL,
+        0x3F54989AUL, 0x5B429D65UL, 0x6B8FE4D6UL, 0x99F73FD6UL,
+        0xA1D29C07UL, 0xEFE830F5UL, 0x4D2D38E6UL, 0xF0255DC1UL,
+        0x4CDD2086UL, 0x8470EB26UL, 0x6382E9C6UL, 0x021ECC5EUL,
+        0x09686B3FUL, 0x3EBAEFC9UL, 0x3C971814UL, 0x6B6A70A1UL,
+        0x687F3584UL, 0x52A0E286UL, 0xB79C5305UL, 0xAA500737UL,
+        0x3E07841CUL, 0x7FDEAE5CUL, 0x8E7D44ECUL, 0x5716F2B8UL,
+        0xB03ADA37UL, 0xF0500C0DUL, 0xF01C1F04UL, 0x0200B3FFUL,
+        0xAE0CF51AUL, 0x3CB574B2UL, 0x25837A58UL, 0xDC0921BDUL,
+        0xD19113F9UL, 0x7CA92FF6UL, 0x94324773UL, 0x22F54701UL,
+        0x3AE5E581UL, 0x37C2DADCUL, 0xC8B57634UL, 0x9AF3DDA7UL,
+        0xA9446146UL, 0x0FD0030EUL, 0xECC8C73EUL, 0xA4751E41UL,
+        0xE238CD99UL, 0x3BEA0E2FUL, 0x3280BBA1UL, 0x183EB331UL,
+        0x4E548B38UL, 0x4F6DB908UL, 0x6F420D03UL, 0xF60A04BFUL,
+        0x2CB81290UL, 0x24977C79UL, 0x5679B072UL, 0xBCAF89AFUL,
+        0xDE9A771FUL, 0xD9930810UL, 0xB38BAE12UL, 0xDCCF3F2EUL,
+        0x5512721FUL, 0x2E6B7124UL, 0x501ADDE6UL, 0x9F84CD87UL,
+        0x7A584718UL, 0x7408DA17UL, 0xBC9F9ABCUL, 0xE94B7D8CUL,
+        0xEC7AEC3AUL, 0xDB851DFAUL, 0x63094366UL, 0xC464C3D2UL,
+        0xEF1C1847UL, 0x3215D908UL, 0xDD433B37UL, 0x24C2BA16UL,
+        0x12A14D43UL, 0x2A65C451UL, 0x50940002UL, 0x133AE4DDUL,
+        0x71DFF89EUL, 0x10314E55UL, 0x81AC77D6UL, 0x5F11199BUL,
+        0x043556F1UL, 0xD7A3C76BUL, 0x3C11183BUL, 0x5924A509UL,
+        0xF28FE6EDUL, 0x97F1FBFAUL, 0x9EBABF2CUL, 0x1E153C6EUL,
+        0x86E34570UL, 0xEAE96FB1UL, 0x860E5E0AUL, 0x5A3E2AB3UL,
+        0x771FE71CUL, 0x4E3D06FAUL, 0x2965DCB9UL, 0x99E71D0FUL,
+        0x803E89D6UL, 0x5266C825UL, 0x2E4CC978UL, 0x9C10B36AUL,
+        0xC6150EBAUL, 0x94E2EA78UL, 0xA5FC3C53UL, 0x1E0A2DF4UL,
+        0xF2F74EA7UL, 0x361D2B3DUL, 0x1939260FUL, 0x19C27960UL,
+        0x5223A708UL, 0xF71312B6UL, 0xEBADFE6EUL, 0xEAC31F66UL,
+        0xE3BC4595UL, 0xA67BC883UL, 0xB17F37D1UL, 0x018CFF28UL,
+        0xC332DDEFUL, 0xBE6C5AA5UL, 0x65582185UL, 0x68AB9802UL,
+        0xEECEA50FUL, 0xDB2F953BUL, 0x2AEF7DADUL, 0x5B6E2F84UL,
+        0x1521B628UL, 0x29076170UL, 0xECDD4775UL, 0x619F1510UL,
+        0x13CCA830UL, 0xEB61BD96UL, 0x0334FE1EUL, 0xAA0363CFUL,
+        0xB5735C90UL, 0x4C70A239UL, 0xD59E9E0BUL, 0xCBAADE14UL,
+        0xEECC86BCUL, 0x60622CA7UL, 0x9CAB5CABUL, 0xB2F3846EUL,
+        0x648B1EAFUL, 0x19BDF0CAUL, 0xA02369B9UL, 0x655ABB50UL,
+        0x40685A32UL, 0x3C2AB4B3UL, 0x319EE9D5UL, 0xC021B8F7UL,
+        0x9B540B19UL, 0x875FA099UL, 0x95F7997EUL, 0x623D7DA8UL,
+        0xF837889AUL, 0x97E32D77UL, 0x11ED935FUL, 0x16681281UL,
+        0x0E358829UL, 0xC7E61FD6UL, 0x96DEDFA1UL, 0x7858BA99UL,
+        0x57F584A5UL, 0x1B227263UL, 0x9B83C3FFUL, 0x1AC24696UL,
+        0xCDB30AEBUL, 0x532E3054UL, 0x8FD948E4UL, 0x6DBC3128UL,
+        0x58EBF2EFUL, 0x34C6FFEAUL, 0xFE28ED61UL, 0xEE7C3C73UL,
+        0x5D4A14D9UL, 0xE864B7E3UL, 0x42105D14UL, 0x203E13E0UL,
+        0x45EEE2B6UL, 0xA3AAABEAUL, 0xDB6C4F15UL, 0xFACB4FD0UL,
+        0xC742F442UL, 0xEF6ABBB5UL, 0x654F3B1DUL, 0x41CD2105UL,
+        0xD81E799EUL, 0x86854DC7UL, 0xE44B476AUL, 0x3D816250UL,
+        0xCF62A1F2UL, 0x5B8D2646UL, 0xFC8883A0UL, 0xC1C7B6A3UL,
+        0x7F1524C3UL, 0x69CB7492UL, 0x47848A0BUL, 0x5692B285UL,
+        0x095BBF00UL, 0xAD19489DUL, 0x1462B174UL, 0x23820E00UL,
+        0x58428D2AUL, 0x0C55F5EAUL, 0x1DADF43EUL, 0x233F7061UL,
+        0x3372F092UL, 0x8D937E41UL, 0xD65FECF1UL, 0x6C223BDBUL,
+        0x7CDE3759UL, 0xCBEE7460UL, 0x4085F2A7UL, 0xCE77326EUL,
+        0xA6078084UL, 0x19F8509EUL, 0xE8EFD855UL, 0x61D99735UL,
+        0xA969A7AAUL, 0xC50C06C2UL, 0x5A04ABFCUL, 0x800BCADCUL,
+        0x9E447A2EUL, 0xC3453484UL, 0xFDD56705UL, 0x0E1E9EC9UL,
+        0xDB73DBD3UL, 0x105588CDUL, 0x675FDA79UL, 0xE3674340UL,
+        0xC5C43465UL, 0x713E38D8UL, 0x3D28F89EUL, 0xF16DFF20UL,
+        0x153E21E7UL, 0x8FB03D4AUL, 0xE6E39F2BUL, 0xDB83ADF7UL   },
+    {   0xE93D5A68UL, 0x948140F7UL, 0xF64C261CUL, 0x94692934UL,
+        0x411520F7UL, 0x7602D4F7UL, 0xBCF46B2EUL, 0xD4A20068UL,
+        0xD4082471UL, 0x3320F46AUL, 0x43B7D4B7UL, 0x500061AFUL,
+        0x1E39F62EUL, 0x97244546UL, 0x14214F74UL, 0xBF8B8840UL,
+        0x4D95FC1DUL, 0x96B591AFUL, 0x70F4DDD3UL, 0x66A02F45UL,
+        0xBFBC09ECUL, 0x03BD9785UL, 0x7FAC6DD0UL, 0x31CB8504UL,
+        0x96EB27B3UL, 0x55FD3941UL, 0xDA2547E6UL, 0xABCA0A9AUL,
+        0x28507825UL, 0x530429F4UL, 0x0A2C86DAUL, 0xE9B66DFBUL,
+        0x68DC1462UL, 0xD7486900UL, 0x680EC0A4UL, 0x27A18DEEUL,
+        0x4F3FFEA2UL, 0xE887AD8CUL, 0xB58CE006UL, 0x7AF4D6B6UL,
+        0xAACE1E7CUL, 0xD3375FECUL, 0xCE78A399UL, 0x406B2A42UL,
+        0x20FE9E35UL, 0xD9F385B9UL, 0xEE39D7ABUL, 0x3B124E8BUL,
+        0x1DC9FAF7UL, 0x4B6D1856UL, 0x26A36631UL, 0xEAE397B2UL,
+        0x3A6EFA74UL, 0xDD5B4332UL, 0x6841E7F7UL, 0xCA7820FBUL,
+        0xFB0AF54EUL, 0xD8FEB397UL, 0x454056ACUL, 0xBA489527UL,
+        0x55533A3AUL, 0x20838D87UL, 0xFE6BA9B7UL, 0xD096954BUL,
+        0x55A867BCUL, 0xA1159A58UL, 0xCCA92963UL, 0x99E1DB33UL,
+        0xA62A4A56UL, 0x3F3125F9UL, 0x5EF47E1CUL, 0x9029317CUL,
+        0xFDF8E802UL, 0x04272F70UL, 0x80BB155CUL, 0x05282CE3UL,
+        0x95C11548UL, 0xE4C66D22UL, 0x48C1133FUL, 0xC70F86DCUL,
+        0x07F9C9EEUL, 0x41041F0FUL, 0x404779A4UL, 0x5D886E17UL,
+        0x325F51EBUL, 0xD59BC0D1UL, 0xF2BCC18FUL, 0x41113564UL,
+        0x257B7834UL, 0x602A9C60UL, 0xDFF8E8A3UL, 0x1F636C1BUL,
+        0x0E12B4C2UL, 0x02E1329EUL, 0xAF664FD1UL, 0xCAD18115UL,
+        0x6B2395E0UL, 0x333E92E1UL, 0x3B240B62UL, 0xEEBEB922UL,
+        0x85B2A20EUL, 0xE6BA0D99UL, 0xDE720C8CUL, 0x2DA2F728UL,
+        0xD0127845UL, 0x95B794FDUL, 0x647D0862UL, 0xE7CCF5F0UL,
+        0x5449A36FUL, 0x877D48FAUL, 0xC39DFD27UL, 0xF33E8D1EUL,
+        0x0A476341UL, 0x992EFF74UL, 0x3A6F6EABUL, 0xF4F8FD37UL,
+        0xA812DC60UL, 0xA1EBDDF8UL, 0x991BE14CUL, 0xDB6E6B0DUL,
+        0xC67B5510UL, 0x6D672C37UL, 0x2765D43BUL, 0xDCD0E804UL,
+        0xF1290DC7UL, 0xCC00FFA3UL, 0xB5390F92UL, 0x690FED0BUL,
+        0x667B9FFBUL, 0xCEDB7D9CUL, 0xA091CF0BUL, 0xD9155EA3UL,
+        0xBB132F88UL, 0x515BAD24UL, 0x7B9479BFUL, 0x763BD6EBUL,
+        0x37392EB3UL, 0xCC115979UL, 0x8026E297UL, 0xF42E312DUL,
+        0x6842ADA7UL, 0xC66A2B3BUL, 0x12754CCCUL, 0x782EF11CUL,
+        0x6A124237UL, 0xB79251E7UL, 0x06A1BBE6UL, 0x4BFB6350UL,
+        0x1A6B1018UL, 0x11CAEDFAUL, 0x3D25BDD8UL, 0xE2E1C3C9UL,
+        0x44421659UL, 0x0A121386UL, 0xD90CEC6EUL, 0xD5ABEA2AUL,
+        0x64AF674EUL, 0xDA86A85FUL, 0xBEBFE988UL, 0x64E4C3FEUL,
+        0x9DBC8057UL, 0xF0F7C086UL, 0x60787BF8UL, 0x6003604DUL,
+        0xD1FD8346UL, 0xF6381FB0UL, 0x7745AE04UL, 0xD736FCCCUL,
+        0x83426B33UL, 0xF01EAB71UL, 0xB0804187UL, 0x3C005E5FUL,
+        0x77A057BEUL, 0xBDE8AE24UL, 0x55464299UL, 0xBF582E61UL,
+        0x4E58F48FUL, 0xF2DDFDA2UL, 0xF474EF38UL, 0x8789BDC2UL,
+        0x5366F9C3UL, 0xC8B38E74UL, 0xB475F255UL, 0x46FCD9B9UL,
+        0x7AEB2661UL, 0x8B1DDF84UL, 0x846A0E79UL, 0x915F95E2UL,
+        0x466E598EUL, 0x20B45770UL, 0x8CD55591UL, 0xC902DE4CUL,
+        0xB90BACE1UL, 0xBB8205D0UL, 0x11A86248UL, 0x7574A99EUL,
+        0xB77F19B6UL, 0xE0A9DC09UL, 0x662D09A1UL, 0xC4324633UL,
+        0xE85A1F02UL, 0x09F0BE8CUL, 0x4A99A025UL, 0x1D6EFE10UL,
+        0x1AB93D1DUL, 0x0BA5A4DFUL, 0xA186F20FUL, 0x2868F169UL,
+        0xDCB7DA83UL, 0x573906FEUL, 0xA1E2CE9BUL, 0x4FCD7F52UL,
+        0x50115E01UL, 0xA70683FAUL, 0xA002B5C4UL, 0x0DE6D027UL,
+        0x9AF88C27UL, 0x773F8641UL, 0xC3604C06UL, 0x61A806B5UL,
+        0xF0177A28UL, 0xC0F586E0UL, 0x006058AAUL, 0x30DC7D62UL,
+        0x11E69ED7UL, 0x2338EA63UL, 0x53C2DD94UL, 0xC2C21634UL,
+        0xBBCBEE56UL, 0x90BCB6DEUL, 0xEBFC7DA1UL, 0xCE591D76UL,
+        0x6F05E409UL, 0x4B7C0188UL, 0x39720A3DUL, 0x7C927C24UL,
+        0x86E3725FUL, 0x724D9DB9UL, 0x1AC15BB4UL, 0xD39EB8FCUL,
+        0xED545578UL, 0x08FCA5B5UL, 0xD83D7CD3UL, 0x4DAD0FC4UL,
+        0x1E50EF5EUL, 0xB161E6F8UL, 0xA28514D9UL, 0x6C51133CUL,
+        0x6FD5C7E7UL, 0x56E14EC4UL, 0x362ABFCEUL, 0xDDC6C837UL,
+        0xD79A3234UL, 0x92638212UL, 0x670EFA8EUL, 0x406000E0UL  },
+    {   0x3A39CE37UL, 0xD3FAF5CFUL, 0xABC27737UL, 0x5AC52D1BUL,
+        0x5CB0679EUL, 0x4FA33742UL, 0xD3822740UL, 0x99BC9BBEUL,
+        0xD5118E9DUL, 0xBF0F7315UL, 0xD62D1C7EUL, 0xC700C47BUL,
+        0xB78C1B6BUL, 0x21A19045UL, 0xB26EB1BEUL, 0x6A366EB4UL,
+        0x5748AB2FUL, 0xBC946E79UL, 0xC6A376D2UL, 0x6549C2C8UL,
+        0x530FF8EEUL, 0x468DDE7DUL, 0xD5730A1DUL, 0x4CD04DC6UL,
+        0x2939BBDBUL, 0xA9BA4650UL, 0xAC9526E8UL, 0xBE5EE304UL,
+        0xA1FAD5F0UL, 0x6A2D519AUL, 0x63EF8CE2UL, 0x9A86EE22UL,
+        0xC089C2B8UL, 0x43242EF6UL, 0xA51E03AAUL, 0x9CF2D0A4UL,
+        0x83C061BAUL, 0x9BE96A4DUL, 0x8FE51550UL, 0xBA645BD6UL,
+        0x2826A2F9UL, 0xA73A3AE1UL, 0x4BA99586UL, 0xEF5562E9UL,
+        0xC72FEFD3UL, 0xF752F7DAUL, 0x3F046F69UL, 0x77FA0A59UL,
+        0x80E4A915UL, 0x87B08601UL, 0x9B09E6ADUL, 0x3B3EE593UL,
+        0xE990FD5AUL, 0x9E34D797UL, 0x2CF0B7D9UL, 0x022B8B51UL,
+        0x96D5AC3AUL, 0x017DA67DUL, 0xD1CF3ED6UL, 0x7C7D2D28UL,
+        0x1F9F25CFUL, 0xADF2B89BUL, 0x5AD6B472UL, 0x5A88F54CUL,
+        0xE029AC71UL, 0xE019A5E6UL, 0x47B0ACFDUL, 0xED93FA9BUL,
+        0xE8D3C48DUL, 0x283B57CCUL, 0xF8D56629UL, 0x79132E28UL,
+        0x785F0191UL, 0xED756055UL, 0xF7960E44UL, 0xE3D35E8CUL,
+        0x15056DD4UL, 0x88F46DBAUL, 0x03A16125UL, 0x0564F0BDUL,
+        0xC3EB9E15UL, 0x3C9057A2UL, 0x97271AECUL, 0xA93A072AUL,
+        0x1B3F6D9BUL, 0x1E6321F5UL, 0xF59C66FBUL, 0x26DCF319UL,
+        0x7533D928UL, 0xB155FDF5UL, 0x03563482UL, 0x8ABA3CBBUL,
+        0x28517711UL, 0xC20AD9F8UL, 0xABCC5167UL, 0xCCAD925FUL,
+        0x4DE81751UL, 0x3830DC8EUL, 0x379D5862UL, 0x9320F991UL,
+        0xEA7A90C2UL, 0xFB3E7BCEUL, 0x5121CE64UL, 0x774FBE32UL,
+        0xA8B6E37EUL, 0xC3293D46UL, 0x48DE5369UL, 0x6413E680UL,
+        0xA2AE0810UL, 0xDD6DB224UL, 0x69852DFDUL, 0x09072166UL,
+        0xB39A460AUL, 0x6445C0DDUL, 0x586CDECFUL, 0x1C20C8AEUL,
+        0x5BBEF7DDUL, 0x1B588D40UL, 0xCCD2017FUL, 0x6BB4E3BBUL,
+        0xDDA26A7EUL, 0x3A59FF45UL, 0x3E350A44UL, 0xBCB4CDD5UL,
+        0x72EACEA8UL, 0xFA6484BBUL, 0x8D6612AEUL, 0xBF3C6F47UL,
+        0xD29BE463UL, 0x542F5D9EUL, 0xAEC2771BUL, 0xF64E6370UL,
+        0x740E0D8DUL, 0xE75B1357UL, 0xF8721671UL, 0xAF537D5DUL,
+        0x4040CB08UL, 0x4EB4E2CCUL, 0x34D2466AUL, 0x0115AF84UL,
+        0xE1B00428UL, 0x95983A1DUL, 0x06B89FB4UL, 0xCE6EA048UL,
+        0x6F3F3B82UL, 0x3520AB82UL, 0x011A1D4BUL, 0x277227F8UL,
+        0x611560B1UL, 0xE7933FDCUL, 0xBB3A792BUL, 0x344525BDUL,
+        0xA08839E1UL, 0x51CE794BUL, 0x2F32C9B7UL, 0xA01FBAC9UL,
+        0xE01CC87EUL, 0xBCC7D1F6UL, 0xCF0111C3UL, 0xA1E8AAC7UL,
+        0x1A908749UL, 0xD44FBD9AUL, 0xD0DADECBUL, 0xD50ADA38UL,
+        0x0339C32AUL, 0xC6913667UL, 0x8DF9317CUL, 0xE0B12B4FUL,
+        0xF79E59B7UL, 0x43F5BB3AUL, 0xF2D519FFUL, 0x27D9459CUL,
+        0xBF97222CUL, 0x15E6FC2AUL, 0x0F91FC71UL, 0x9B941525UL,
+        0xFAE59361UL, 0xCEB69CEBUL, 0xC2A86459UL, 0x12BAA8D1UL,
+        0xB6C1075EUL, 0xE3056A0CUL, 0x10D25065UL, 0xCB03A442UL,
+        0xE0EC6E0EUL, 0x1698DB3BUL, 0x4C98A0BEUL, 0x3278E964UL,
+        0x9F1F9532UL, 0xE0D392DFUL, 0xD3A0342BUL, 0x8971F21EUL,
+        0x1B0A7441UL, 0x4BA3348CUL, 0xC5BE7120UL, 0xC37632D8UL,
+        0xDF359F8DUL, 0x9B992F2EUL, 0xE60B6F47UL, 0x0FE3F11DUL,
+        0xE54CDA54UL, 0x1EDAD891UL, 0xCE6279CFUL, 0xCD3E7E6FUL,
+        0x1618B166UL, 0xFD2C1D05UL, 0x848FD2C5UL, 0xF6FB2299UL,
+        0xF523F357UL, 0xA6327623UL, 0x93A83531UL, 0x56CCCD02UL,
+        0xACF08162UL, 0x5A75EBB5UL, 0x6E163697UL, 0x88D273CCUL,
+        0xDE966292UL, 0x81B949D0UL, 0x4C50901BUL, 0x71C65614UL,
+        0xE6C6C7BDUL, 0x327A140AUL, 0x45E1D006UL, 0xC3F27B9AUL,
+        0xC9AA53FDUL, 0x62A80F00UL, 0xBB25BFE2UL, 0x35BDD2F6UL,
+        0x71126905UL, 0xB2040222UL, 0xB6CBCF7CUL, 0xCD769C2BUL,
+        0x53113EC0UL, 0x1640E3D3UL, 0x38ABBD60UL, 0x2547ADF0UL,
+        0xBA38209CUL, 0xF746CE76UL, 0x77AFA1C5UL, 0x20756060UL,
+        0x85CBFE4EUL, 0x8AE88DD8UL, 0x7AAAF9B0UL, 0x4CF9AA7EUL,
+        0x1948C25CUL, 0x02FB8A8CUL, 0x01C36AE4UL, 0xD6EBE1F9UL,
+        0x90D4F869UL, 0xA65CDEA0UL, 0x3F09252DUL, 0xC208E69FUL,
+        0xB74E6132UL, 0xCE77E25BUL, 0x578FDFE3UL, 0x3AC372E6UL  }
+};
+
+int blowfish_setup(const unsigned char *key, int keylen, int num_rounds,
+                   symmetric_key *skey)
+{
+   ulong32 x, y, z, A;
+   unsigned char B[8];
+
+   _ARGCHK(key != NULL);
+   _ARGCHK(skey != NULL);
+
+   /* check key length */
+   if (keylen < 8 || keylen > 56) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+
+   /* check rounds */
+   if (num_rounds != 0 && num_rounds != 16) {
+      return CRYPT_INVALID_ROUNDS;
+   }   
+
+   /* load in key bytes (Supplied by David Hopwood) */
+   for (x = y = 0; x < 18; x++) {
+       A = 0;
+       for (z = 0; z < 4; z++) {
+           A = (A << 8) | ((ulong32)key[y++] & 255);
+           if (y == (ulong32)keylen) { 
+              y = 0; 
+           }
+       }
+       skey->blowfish.K[x] = ORIG_P[x] ^ A;
+   }
+
+   /* copy sboxes */
+   for (x = 0; x < 4; x++) {
+       for (y = 0; y < 256; y++) {
+           skey->blowfish.S[x][y] = ORIG_S[x][y];
+       }
+   }
+
+   /* encrypt K array */
+   for (x = 0; x < 8; x++) {
+       B[x] = 0;
+   }
+   
+   for (x = 0; x < 18; x += 2) {
+       /* encrypt it */
+       blowfish_ecb_encrypt(B, B, skey);
+       /* copy it */
+       LOAD32H(skey->blowfish.K[x], &B[0]);
+       LOAD32H(skey->blowfish.K[x+1], &B[4]);
+   }
+
+   /* encrypt S array */
+   for (x = 0; x < 4; x++) {
+       for (y = 0; y < 256; y += 2) {
+          /* encrypt it */
+          blowfish_ecb_encrypt(B, B, skey);
+          /* copy it */
+          LOAD32H(skey->blowfish.S[x][y], &B[0]);
+          LOAD32H(skey->blowfish.S[x][y+1], &B[4]);
+       }
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(B, sizeof(B));
+#endif
+
+   return CRYPT_OK;
+}
+
+#ifndef __GNUC__
+#define F(x) ((S1[byte(x,3)] + S2[byte(x,2)]) ^ S3[byte(x,1)]) + S4[byte(x,0)]
+#else
+#define F(x) ((key->blowfish.S[0][byte(x,3)] + key->blowfish.S[1][byte(x,2)]) ^ key->blowfish.S[2][byte(x,1)]) + key->blowfish.S[3][byte(x,0)]
+#endif
+
+#ifdef CLEAN_STACK
+static void _blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#else
+void blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#endif
+{
+   ulong32 L, R;
+   int r;
+#ifndef __GNUC__
+   ulong32 *S1, *S2, *S3, *S4;
+#endif
+
+    _ARGCHK(pt != NULL);
+    _ARGCHK(ct != NULL);
+    _ARGCHK(key != NULL);
+
+#ifndef __GNUC__
+    S1 = key->blowfish.S[0];
+    S2 = key->blowfish.S[1];
+    S3 = key->blowfish.S[2];
+    S4 = key->blowfish.S[3];
+#endif
+
+   /* load it */
+   LOAD32H(L, &pt[0]);
+   LOAD32H(R, &pt[4]);
+
+   /* do 16 rounds */
+   for (r = 0; r < 16; ) {
+      L ^= key->blowfish.K[r++];  R ^= F(L);
+      R ^= key->blowfish.K[r++];  L ^= F(R);
+      L ^= key->blowfish.K[r++];  R ^= F(L);
+      R ^= key->blowfish.K[r++];  L ^= F(R);
+   }
+
+   /* last keying */
+   R ^= key->blowfish.K[17];
+   L ^= key->blowfish.K[16];
+
+   /* store */
+   STORE32H(R, &ct[0]);
+   STORE32H(L, &ct[4]);
+}
+
+#ifdef CLEAN_STACK
+void blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+{
+    _blowfish_ecb_encrypt(pt, ct, key);
+    burn_stack(sizeof(ulong32) * 2 + sizeof(int));
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#else
+void blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#endif
+{
+   ulong32 L, R;
+   int r;
+#ifndef __GNUC__
+   ulong32 *S1, *S2, *S3, *S4;
+#endif
+
+    _ARGCHK(pt != NULL);
+    _ARGCHK(ct != NULL);
+    _ARGCHK(key != NULL);
+    
+#ifndef __GNUC__
+    S1 = key->blowfish.S[0];
+    S2 = key->blowfish.S[1];
+    S3 = key->blowfish.S[2];
+    S4 = key->blowfish.S[3];
+#endif
+
+   /* load it */
+   LOAD32H(R, &ct[0]);
+   LOAD32H(L, &ct[4]);
+
+   /* undo last keying */
+   R ^= key->blowfish.K[17];
+   L ^= key->blowfish.K[16];
+
+   /* do 16 rounds */
+   for (r = 15; r > 0; ) {
+      L ^= F(R); R ^= key->blowfish.K[r--];
+      R ^= F(L); L ^= key->blowfish.K[r--];
+      L ^= F(R); R ^= key->blowfish.K[r--];
+      R ^= F(L); L ^= key->blowfish.K[r--];
+   }
+
+   /* store */
+   STORE32H(L, &pt[0]);
+   STORE32H(R, &pt[4]);
+}
+
+#ifdef CLEAN_STACK
+void blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+{
+    _blowfish_ecb_decrypt(ct, pt, key);
+    burn_stack(sizeof(ulong32) * 2 + sizeof(int));
+}
+#endif
+
+
+int blowfish_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+   int err;
+   symmetric_key key;
+   static const struct {
+          unsigned char key[8], pt[8], ct[8];
+   } tests[] = {
+       {
+           { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+           { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+           { 0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}
+       },
+       {
+           { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+           { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+           { 0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}
+       },
+       {
+           { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+           { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+           { 0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}
+       }
+   };
+   unsigned char tmp[2][8];
+   int x, y;
+
+   for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
+      /* setup key */
+      if ((err = blowfish_setup(tests[x].key, 8, 16, &key)) != CRYPT_OK) {
+         return err;
+      }
+
+      /* encrypt and decrypt */
+      blowfish_ecb_encrypt(tests[x].pt, tmp[0], &key);
+      blowfish_ecb_decrypt(tmp[0], tmp[1], &key);
+
+      /* compare */
+      if ((memcmp(tmp[0], tests[x].ct, 8) != 0) || (memcmp(tmp[1], tests[x].pt, 8) != 0)) {
+         return CRYPT_FAIL_TESTVECTOR;
+      }
+
+      /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+      for (y = 0; y < 8; y++) tmp[0][y] = 0;
+      for (y = 0; y < 1000; y++) blowfish_ecb_encrypt(tmp[0], tmp[0], &key);
+      for (y = 0; y < 1000; y++) blowfish_ecb_decrypt(tmp[0], tmp[0], &key);
+      for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+   }
+   return CRYPT_OK;
+ #endif
+}
+
+int blowfish_keysize(int *desired_keysize)
+{
+   _ARGCHK(desired_keysize != NULL);
+
+   if (*desired_keysize < 8) {
+      return CRYPT_INVALID_KEYSIZE;
+   } else if (*desired_keysize > 56) {
+      *desired_keysize = 56;
+   }
+   return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/burn_stack.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,21 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+void burn_stack(unsigned long len)
+{
+   unsigned char buf[32];
+   zeromem(buf, sizeof(buf));
+   if (len > (unsigned long)sizeof(buf))
+      burn_stack(len - sizeof(buf));
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cast5.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,669 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+/* Implementation of CAST5 (RFC 2144) by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef CAST5
+
+const struct _cipher_descriptor cast5_desc = {
+   "cast5",
+   15,
+   5, 16, 8, 16,
+   &cast5_setup,
+   &cast5_ecb_encrypt,
+   &cast5_ecb_decrypt,
+   &cast5_test,
+   &cast5_keysize
+};
+
+static const ulong32 S1[256] = {
+0x30fb40d4UL, 0x9fa0ff0bUL, 0x6beccd2fUL, 0x3f258c7aUL, 0x1e213f2fUL, 0x9c004dd3UL, 
+0x6003e540UL, 0xcf9fc949UL, 0xbfd4af27UL, 0x88bbbdb5UL, 0xe2034090UL, 0x98d09675UL, 
+0x6e63a0e0UL, 0x15c361d2UL, 0xc2e7661dUL, 0x22d4ff8eUL, 0x28683b6fUL, 0xc07fd059UL, 
+0xff2379c8UL, 0x775f50e2UL, 0x43c340d3UL, 0xdf2f8656UL, 0x887ca41aUL, 0xa2d2bd2dUL, 
+0xa1c9e0d6UL, 0x346c4819UL, 0x61b76d87UL, 0x22540f2fUL, 0x2abe32e1UL, 0xaa54166bUL, 
+0x22568e3aUL, 0xa2d341d0UL, 0x66db40c8UL, 0xa784392fUL, 0x004dff2fUL, 0x2db9d2deUL, 
+0x97943facUL, 0x4a97c1d8UL, 0x527644b7UL, 0xb5f437a7UL, 0xb82cbaefUL, 0xd751d159UL, 
+0x6ff7f0edUL, 0x5a097a1fUL, 0x827b68d0UL, 0x90ecf52eUL, 0x22b0c054UL, 0xbc8e5935UL, 
+0x4b6d2f7fUL, 0x50bb64a2UL, 0xd2664910UL, 0xbee5812dUL, 0xb7332290UL, 0xe93b159fUL, 
+0xb48ee411UL, 0x4bff345dUL, 0xfd45c240UL, 0xad31973fUL, 0xc4f6d02eUL, 0x55fc8165UL, 
+0xd5b1caadUL, 0xa1ac2daeUL, 0xa2d4b76dUL, 0xc19b0c50UL, 0x882240f2UL, 0x0c6e4f38UL, 
+0xa4e4bfd7UL, 0x4f5ba272UL, 0x564c1d2fUL, 0xc59c5319UL, 0xb949e354UL, 0xb04669feUL, 
+0xb1b6ab8aUL, 0xc71358ddUL, 0x6385c545UL, 0x110f935dUL, 0x57538ad5UL, 0x6a390493UL, 
+0xe63d37e0UL, 0x2a54f6b3UL, 0x3a787d5fUL, 0x6276a0b5UL, 0x19a6fcdfUL, 0x7a42206aUL, 
+0x29f9d4d5UL, 0xf61b1891UL, 0xbb72275eUL, 0xaa508167UL, 0x38901091UL, 0xc6b505ebUL, 
+0x84c7cb8cUL, 0x2ad75a0fUL, 0x874a1427UL, 0xa2d1936bUL, 0x2ad286afUL, 0xaa56d291UL, 
+0xd7894360UL, 0x425c750dUL, 0x93b39e26UL, 0x187184c9UL, 0x6c00b32dUL, 0x73e2bb14UL, 
+0xa0bebc3cUL, 0x54623779UL, 0x64459eabUL, 0x3f328b82UL, 0x7718cf82UL, 0x59a2cea6UL, 
+0x04ee002eUL, 0x89fe78e6UL, 0x3fab0950UL, 0x325ff6c2UL, 0x81383f05UL, 0x6963c5c8UL, 
+0x76cb5ad6UL, 0xd49974c9UL, 0xca180dcfUL, 0x380782d5UL, 0xc7fa5cf6UL, 0x8ac31511UL, 
+0x35e79e13UL, 0x47da91d0UL, 0xf40f9086UL, 0xa7e2419eUL, 0x31366241UL, 0x051ef495UL, 
+0xaa573b04UL, 0x4a805d8dUL, 0x548300d0UL, 0x00322a3cUL, 0xbf64cddfUL, 0xba57a68eUL, 
+0x75c6372bUL, 0x50afd341UL, 0xa7c13275UL, 0x915a0bf5UL, 0x6b54bfabUL, 0x2b0b1426UL, 
+0xab4cc9d7UL, 0x449ccd82UL, 0xf7fbf265UL, 0xab85c5f3UL, 0x1b55db94UL, 0xaad4e324UL, 
+0xcfa4bd3fUL, 0x2deaa3e2UL, 0x9e204d02UL, 0xc8bd25acUL, 0xeadf55b3UL, 0xd5bd9e98UL, 
+0xe31231b2UL, 0x2ad5ad6cUL, 0x954329deUL, 0xadbe4528UL, 0xd8710f69UL, 0xaa51c90fUL, 
+0xaa786bf6UL, 0x22513f1eUL, 0xaa51a79bUL, 0x2ad344ccUL, 0x7b5a41f0UL, 0xd37cfbadUL, 
+0x1b069505UL, 0x41ece491UL, 0xb4c332e6UL, 0x032268d4UL, 0xc9600accUL, 0xce387e6dUL, 
+0xbf6bb16cUL, 0x6a70fb78UL, 0x0d03d9c9UL, 0xd4df39deUL, 0xe01063daUL, 0x4736f464UL, 
+0x5ad328d8UL, 0xb347cc96UL, 0x75bb0fc3UL, 0x98511bfbUL, 0x4ffbcc35UL, 0xb58bcf6aUL, 
+0xe11f0abcUL, 0xbfc5fe4aUL, 0xa70aec10UL, 0xac39570aUL, 0x3f04442fUL, 0x6188b153UL, 
+0xe0397a2eUL, 0x5727cb79UL, 0x9ceb418fUL, 0x1cacd68dUL, 0x2ad37c96UL, 0x0175cb9dUL, 
+0xc69dff09UL, 0xc75b65f0UL, 0xd9db40d8UL, 0xec0e7779UL, 0x4744ead4UL, 0xb11c3274UL, 
+0xdd24cb9eUL, 0x7e1c54bdUL, 0xf01144f9UL, 0xd2240eb1UL, 0x9675b3fdUL, 0xa3ac3755UL, 
+0xd47c27afUL, 0x51c85f4dUL, 0x56907596UL, 0xa5bb15e6UL, 0x580304f0UL, 0xca042cf1UL, 
+0x011a37eaUL, 0x8dbfaadbUL, 0x35ba3e4aUL, 0x3526ffa0UL, 0xc37b4d09UL, 0xbc306ed9UL, 
+0x98a52666UL, 0x5648f725UL, 0xff5e569dUL, 0x0ced63d0UL, 0x7c63b2cfUL, 0x700b45e1UL, 
+0xd5ea50f1UL, 0x85a92872UL, 0xaf1fbda7UL, 0xd4234870UL, 0xa7870bf3UL, 0x2d3b4d79UL, 
+0x42e04198UL, 0x0cd0ede7UL, 0x26470db8UL, 0xf881814cUL, 0x474d6ad7UL, 0x7c0c5e5cUL, 
+0xd1231959UL, 0x381b7298UL, 0xf5d2f4dbUL, 0xab838653UL, 0x6e2f1e23UL, 0x83719c9eUL, 
+0xbd91e046UL, 0x9a56456eUL, 0xdc39200cUL, 0x20c8c571UL, 0x962bda1cUL, 0xe1e696ffUL, 
+0xb141ab08UL, 0x7cca89b9UL, 0x1a69e783UL, 0x02cc4843UL, 0xa2f7c579UL, 0x429ef47dUL, 
+0x427b169cUL, 0x5ac9f049UL, 0xdd8f0f00UL, 0x5c8165bfUL};
+
+static const ulong32 S2[256] = {
+0x1f201094UL, 0xef0ba75bUL, 0x69e3cf7eUL, 0x393f4380UL, 0xfe61cf7aUL, 0xeec5207aUL, 
+0x55889c94UL, 0x72fc0651UL, 0xada7ef79UL, 0x4e1d7235UL, 0xd55a63ceUL, 0xde0436baUL, 
+0x99c430efUL, 0x5f0c0794UL, 0x18dcdb7dUL, 0xa1d6eff3UL, 0xa0b52f7bUL, 0x59e83605UL, 
+0xee15b094UL, 0xe9ffd909UL, 0xdc440086UL, 0xef944459UL, 0xba83ccb3UL, 0xe0c3cdfbUL, 
+0xd1da4181UL, 0x3b092ab1UL, 0xf997f1c1UL, 0xa5e6cf7bUL, 0x01420ddbUL, 0xe4e7ef5bUL, 
+0x25a1ff41UL, 0xe180f806UL, 0x1fc41080UL, 0x179bee7aUL, 0xd37ac6a9UL, 0xfe5830a4UL, 
+0x98de8b7fUL, 0x77e83f4eUL, 0x79929269UL, 0x24fa9f7bUL, 0xe113c85bUL, 0xacc40083UL, 
+0xd7503525UL, 0xf7ea615fUL, 0x62143154UL, 0x0d554b63UL, 0x5d681121UL, 0xc866c359UL, 
+0x3d63cf73UL, 0xcee234c0UL, 0xd4d87e87UL, 0x5c672b21UL, 0x071f6181UL, 0x39f7627fUL, 
+0x361e3084UL, 0xe4eb573bUL, 0x602f64a4UL, 0xd63acd9cUL, 0x1bbc4635UL, 0x9e81032dUL, 
+0x2701f50cUL, 0x99847ab4UL, 0xa0e3df79UL, 0xba6cf38cUL, 0x10843094UL, 0x2537a95eUL, 
+0xf46f6ffeUL, 0xa1ff3b1fUL, 0x208cfb6aUL, 0x8f458c74UL, 0xd9e0a227UL, 0x4ec73a34UL, 
+0xfc884f69UL, 0x3e4de8dfUL, 0xef0e0088UL, 0x3559648dUL, 0x8a45388cUL, 0x1d804366UL, 
+0x721d9bfdUL, 0xa58684bbUL, 0xe8256333UL, 0x844e8212UL, 0x128d8098UL, 0xfed33fb4UL, 
+0xce280ae1UL, 0x27e19ba5UL, 0xd5a6c252UL, 0xe49754bdUL, 0xc5d655ddUL, 0xeb667064UL, 
+0x77840b4dUL, 0xa1b6a801UL, 0x84db26a9UL, 0xe0b56714UL, 0x21f043b7UL, 0xe5d05860UL, 
+0x54f03084UL, 0x066ff472UL, 0xa31aa153UL, 0xdadc4755UL, 0xb5625dbfUL, 0x68561be6UL, 
+0x83ca6b94UL, 0x2d6ed23bUL, 0xeccf01dbUL, 0xa6d3d0baUL, 0xb6803d5cUL, 0xaf77a709UL, 
+0x33b4a34cUL, 0x397bc8d6UL, 0x5ee22b95UL, 0x5f0e5304UL, 0x81ed6f61UL, 0x20e74364UL, 
+0xb45e1378UL, 0xde18639bUL, 0x881ca122UL, 0xb96726d1UL, 0x8049a7e8UL, 0x22b7da7bUL, 
+0x5e552d25UL, 0x5272d237UL, 0x79d2951cUL, 0xc60d894cUL, 0x488cb402UL, 0x1ba4fe5bUL, 
+0xa4b09f6bUL, 0x1ca815cfUL, 0xa20c3005UL, 0x8871df63UL, 0xb9de2fcbUL, 0x0cc6c9e9UL, 
+0x0beeff53UL, 0xe3214517UL, 0xb4542835UL, 0x9f63293cUL, 0xee41e729UL, 0x6e1d2d7cUL, 
+0x50045286UL, 0x1e6685f3UL, 0xf33401c6UL, 0x30a22c95UL, 0x31a70850UL, 0x60930f13UL, 
+0x73f98417UL, 0xa1269859UL, 0xec645c44UL, 0x52c877a9UL, 0xcdff33a6UL, 0xa02b1741UL, 
+0x7cbad9a2UL, 0x2180036fUL, 0x50d99c08UL, 0xcb3f4861UL, 0xc26bd765UL, 0x64a3f6abUL, 
+0x80342676UL, 0x25a75e7bUL, 0xe4e6d1fcUL, 0x20c710e6UL, 0xcdf0b680UL, 0x17844d3bUL, 
+0x31eef84dUL, 0x7e0824e4UL, 0x2ccb49ebUL, 0x846a3baeUL, 0x8ff77888UL, 0xee5d60f6UL, 
+0x7af75673UL, 0x2fdd5cdbUL, 0xa11631c1UL, 0x30f66f43UL, 0xb3faec54UL, 0x157fd7faUL, 
+0xef8579ccUL, 0xd152de58UL, 0xdb2ffd5eUL, 0x8f32ce19UL, 0x306af97aUL, 0x02f03ef8UL, 
+0x99319ad5UL, 0xc242fa0fUL, 0xa7e3ebb0UL, 0xc68e4906UL, 0xb8da230cUL, 0x80823028UL, 
+0xdcdef3c8UL, 0xd35fb171UL, 0x088a1bc8UL, 0xbec0c560UL, 0x61a3c9e8UL, 0xbca8f54dUL, 
+0xc72feffaUL, 0x22822e99UL, 0x82c570b4UL, 0xd8d94e89UL, 0x8b1c34bcUL, 0x301e16e6UL, 
+0x273be979UL, 0xb0ffeaa6UL, 0x61d9b8c6UL, 0x00b24869UL, 0xb7ffce3fUL, 0x08dc283bUL, 
+0x43daf65aUL, 0xf7e19798UL, 0x7619b72fUL, 0x8f1c9ba4UL, 0xdc8637a0UL, 0x16a7d3b1UL, 
+0x9fc393b7UL, 0xa7136eebUL, 0xc6bcc63eUL, 0x1a513742UL, 0xef6828bcUL, 0x520365d6UL, 
+0x2d6a77abUL, 0x3527ed4bUL, 0x821fd216UL, 0x095c6e2eUL, 0xdb92f2fbUL, 0x5eea29cbUL, 
+0x145892f5UL, 0x91584f7fUL, 0x5483697bUL, 0x2667a8ccUL, 0x85196048UL, 0x8c4baceaUL, 
+0x833860d4UL, 0x0d23e0f9UL, 0x6c387e8aUL, 0x0ae6d249UL, 0xb284600cUL, 0xd835731dUL, 
+0xdcb1c647UL, 0xac4c56eaUL, 0x3ebd81b3UL, 0x230eabb0UL, 0x6438bc87UL, 0xf0b5b1faUL, 
+0x8f5ea2b3UL, 0xfc184642UL, 0x0a036b7aUL, 0x4fb089bdUL, 0x649da589UL, 0xa345415eUL, 
+0x5c038323UL, 0x3e5d3bb9UL, 0x43d79572UL, 0x7e6dd07cUL, 0x06dfdf1eUL, 0x6c6cc4efUL, 
+0x7160a539UL, 0x73bfbe70UL, 0x83877605UL, 0x4523ecf1UL};
+
+static const ulong32 S3[256] = {
+0x8defc240UL, 0x25fa5d9fUL, 0xeb903dbfUL, 0xe810c907UL, 0x47607fffUL, 0x369fe44bUL, 
+0x8c1fc644UL, 0xaececa90UL, 0xbeb1f9bfUL, 0xeefbcaeaUL, 0xe8cf1950UL, 0x51df07aeUL, 
+0x920e8806UL, 0xf0ad0548UL, 0xe13c8d83UL, 0x927010d5UL, 0x11107d9fUL, 0x07647db9UL, 
+0xb2e3e4d4UL, 0x3d4f285eUL, 0xb9afa820UL, 0xfade82e0UL, 0xa067268bUL, 0x8272792eUL, 
+0x553fb2c0UL, 0x489ae22bUL, 0xd4ef9794UL, 0x125e3fbcUL, 0x21fffceeUL, 0x825b1bfdUL, 
+0x9255c5edUL, 0x1257a240UL, 0x4e1a8302UL, 0xbae07fffUL, 0x528246e7UL, 0x8e57140eUL, 
+0x3373f7bfUL, 0x8c9f8188UL, 0xa6fc4ee8UL, 0xc982b5a5UL, 0xa8c01db7UL, 0x579fc264UL, 
+0x67094f31UL, 0xf2bd3f5fUL, 0x40fff7c1UL, 0x1fb78dfcUL, 0x8e6bd2c1UL, 0x437be59bUL, 
+0x99b03dbfUL, 0xb5dbc64bUL, 0x638dc0e6UL, 0x55819d99UL, 0xa197c81cUL, 0x4a012d6eUL, 
+0xc5884a28UL, 0xccc36f71UL, 0xb843c213UL, 0x6c0743f1UL, 0x8309893cUL, 0x0feddd5fUL, 
+0x2f7fe850UL, 0xd7c07f7eUL, 0x02507fbfUL, 0x5afb9a04UL, 0xa747d2d0UL, 0x1651192eUL, 
+0xaf70bf3eUL, 0x58c31380UL, 0x5f98302eUL, 0x727cc3c4UL, 0x0a0fb402UL, 0x0f7fef82UL, 
+0x8c96fdadUL, 0x5d2c2aaeUL, 0x8ee99a49UL, 0x50da88b8UL, 0x8427f4a0UL, 0x1eac5790UL, 
+0x796fb449UL, 0x8252dc15UL, 0xefbd7d9bUL, 0xa672597dUL, 0xada840d8UL, 0x45f54504UL, 
+0xfa5d7403UL, 0xe83ec305UL, 0x4f91751aUL, 0x925669c2UL, 0x23efe941UL, 0xa903f12eUL, 
+0x60270df2UL, 0x0276e4b6UL, 0x94fd6574UL, 0x927985b2UL, 0x8276dbcbUL, 0x02778176UL, 
+0xf8af918dUL, 0x4e48f79eUL, 0x8f616ddfUL, 0xe29d840eUL, 0x842f7d83UL, 0x340ce5c8UL, 
+0x96bbb682UL, 0x93b4b148UL, 0xef303cabUL, 0x984faf28UL, 0x779faf9bUL, 0x92dc560dUL, 
+0x224d1e20UL, 0x8437aa88UL, 0x7d29dc96UL, 0x2756d3dcUL, 0x8b907ceeUL, 0xb51fd240UL, 
+0xe7c07ce3UL, 0xe566b4a1UL, 0xc3e9615eUL, 0x3cf8209dUL, 0x6094d1e3UL, 0xcd9ca341UL, 
+0x5c76460eUL, 0x00ea983bUL, 0xd4d67881UL, 0xfd47572cUL, 0xf76cedd9UL, 0xbda8229cUL, 
+0x127dadaaUL, 0x438a074eUL, 0x1f97c090UL, 0x081bdb8aUL, 0x93a07ebeUL, 0xb938ca15UL, 
+0x97b03cffUL, 0x3dc2c0f8UL, 0x8d1ab2ecUL, 0x64380e51UL, 0x68cc7bfbUL, 0xd90f2788UL, 
+0x12490181UL, 0x5de5ffd4UL, 0xdd7ef86aUL, 0x76a2e214UL, 0xb9a40368UL, 0x925d958fUL, 
+0x4b39fffaUL, 0xba39aee9UL, 0xa4ffd30bUL, 0xfaf7933bUL, 0x6d498623UL, 0x193cbcfaUL, 
+0x27627545UL, 0x825cf47aUL, 0x61bd8ba0UL, 0xd11e42d1UL, 0xcead04f4UL, 0x127ea392UL, 
+0x10428db7UL, 0x8272a972UL, 0x9270c4a8UL, 0x127de50bUL, 0x285ba1c8UL, 0x3c62f44fUL, 
+0x35c0eaa5UL, 0xe805d231UL, 0x428929fbUL, 0xb4fcdf82UL, 0x4fb66a53UL, 0x0e7dc15bUL, 
+0x1f081fabUL, 0x108618aeUL, 0xfcfd086dUL, 0xf9ff2889UL, 0x694bcc11UL, 0x236a5caeUL, 
+0x12deca4dUL, 0x2c3f8cc5UL, 0xd2d02dfeUL, 0xf8ef5896UL, 0xe4cf52daUL, 0x95155b67UL, 
+0x494a488cUL, 0xb9b6a80cUL, 0x5c8f82bcUL, 0x89d36b45UL, 0x3a609437UL, 0xec00c9a9UL, 
+0x44715253UL, 0x0a874b49UL, 0xd773bc40UL, 0x7c34671cUL, 0x02717ef6UL, 0x4feb5536UL, 
+0xa2d02fffUL, 0xd2bf60c4UL, 0xd43f03c0UL, 0x50b4ef6dUL, 0x07478cd1UL, 0x006e1888UL, 
+0xa2e53f55UL, 0xb9e6d4bcUL, 0xa2048016UL, 0x97573833UL, 0xd7207d67UL, 0xde0f8f3dUL, 
+0x72f87b33UL, 0xabcc4f33UL, 0x7688c55dUL, 0x7b00a6b0UL, 0x947b0001UL, 0x570075d2UL, 
+0xf9bb88f8UL, 0x8942019eUL, 0x4264a5ffUL, 0x856302e0UL, 0x72dbd92bUL, 0xee971b69UL, 
+0x6ea22fdeUL, 0x5f08ae2bUL, 0xaf7a616dUL, 0xe5c98767UL, 0xcf1febd2UL, 0x61efc8c2UL, 
+0xf1ac2571UL, 0xcc8239c2UL, 0x67214cb8UL, 0xb1e583d1UL, 0xb7dc3e62UL, 0x7f10bdceUL, 
+0xf90a5c38UL, 0x0ff0443dUL, 0x606e6dc6UL, 0x60543a49UL, 0x5727c148UL, 0x2be98a1dUL, 
+0x8ab41738UL, 0x20e1be24UL, 0xaf96da0fUL, 0x68458425UL, 0x99833be5UL, 0x600d457dUL, 
+0x282f9350UL, 0x8334b362UL, 0xd91d1120UL, 0x2b6d8da0UL, 0x642b1e31UL, 0x9c305a00UL, 
+0x52bce688UL, 0x1b03588aUL, 0xf7baefd5UL, 0x4142ed9cUL, 0xa4315c11UL, 0x83323ec5UL, 
+0xdfef4636UL, 0xa133c501UL, 0xe9d3531cUL, 0xee353783UL};
+
+static const ulong32 S4[256] = {
+0x9db30420UL, 0x1fb6e9deUL, 0xa7be7befUL, 0xd273a298UL, 0x4a4f7bdbUL, 0x64ad8c57UL, 
+0x85510443UL, 0xfa020ed1UL, 0x7e287affUL, 0xe60fb663UL, 0x095f35a1UL, 0x79ebf120UL, 
+0xfd059d43UL, 0x6497b7b1UL, 0xf3641f63UL, 0x241e4adfUL, 0x28147f5fUL, 0x4fa2b8cdUL, 
+0xc9430040UL, 0x0cc32220UL, 0xfdd30b30UL, 0xc0a5374fUL, 0x1d2d00d9UL, 0x24147b15UL, 
+0xee4d111aUL, 0x0fca5167UL, 0x71ff904cUL, 0x2d195ffeUL, 0x1a05645fUL, 0x0c13fefeUL, 
+0x081b08caUL, 0x05170121UL, 0x80530100UL, 0xe83e5efeUL, 0xac9af4f8UL, 0x7fe72701UL, 
+0xd2b8ee5fUL, 0x06df4261UL, 0xbb9e9b8aUL, 0x7293ea25UL, 0xce84ffdfUL, 0xf5718801UL, 
+0x3dd64b04UL, 0xa26f263bUL, 0x7ed48400UL, 0x547eebe6UL, 0x446d4ca0UL, 0x6cf3d6f5UL, 
+0x2649abdfUL, 0xaea0c7f5UL, 0x36338cc1UL, 0x503f7e93UL, 0xd3772061UL, 0x11b638e1UL, 
+0x72500e03UL, 0xf80eb2bbUL, 0xabe0502eUL, 0xec8d77deUL, 0x57971e81UL, 0xe14f6746UL, 
+0xc9335400UL, 0x6920318fUL, 0x081dbb99UL, 0xffc304a5UL, 0x4d351805UL, 0x7f3d5ce3UL, 
+0xa6c866c6UL, 0x5d5bcca9UL, 0xdaec6feaUL, 0x9f926f91UL, 0x9f46222fUL, 0x3991467dUL, 
+0xa5bf6d8eUL, 0x1143c44fUL, 0x43958302UL, 0xd0214eebUL, 0x022083b8UL, 0x3fb6180cUL, 
+0x18f8931eUL, 0x281658e6UL, 0x26486e3eUL, 0x8bd78a70UL, 0x7477e4c1UL, 0xb506e07cUL, 
+0xf32d0a25UL, 0x79098b02UL, 0xe4eabb81UL, 0x28123b23UL, 0x69dead38UL, 0x1574ca16UL, 
+0xdf871b62UL, 0x211c40b7UL, 0xa51a9ef9UL, 0x0014377bUL, 0x041e8ac8UL, 0x09114003UL, 
+0xbd59e4d2UL, 0xe3d156d5UL, 0x4fe876d5UL, 0x2f91a340UL, 0x557be8deUL, 0x00eae4a7UL, 
+0x0ce5c2ecUL, 0x4db4bba6UL, 0xe756bdffUL, 0xdd3369acUL, 0xec17b035UL, 0x06572327UL, 
+0x99afc8b0UL, 0x56c8c391UL, 0x6b65811cUL, 0x5e146119UL, 0x6e85cb75UL, 0xbe07c002UL, 
+0xc2325577UL, 0x893ff4ecUL, 0x5bbfc92dUL, 0xd0ec3b25UL, 0xb7801ab7UL, 0x8d6d3b24UL, 
+0x20c763efUL, 0xc366a5fcUL, 0x9c382880UL, 0x0ace3205UL, 0xaac9548aUL, 0xeca1d7c7UL, 
+0x041afa32UL, 0x1d16625aUL, 0x6701902cUL, 0x9b757a54UL, 0x31d477f7UL, 0x9126b031UL, 
+0x36cc6fdbUL, 0xc70b8b46UL, 0xd9e66a48UL, 0x56e55a79UL, 0x026a4cebUL, 0x52437effUL, 
+0x2f8f76b4UL, 0x0df980a5UL, 0x8674cde3UL, 0xedda04ebUL, 0x17a9be04UL, 0x2c18f4dfUL, 
+0xb7747f9dUL, 0xab2af7b4UL, 0xefc34d20UL, 0x2e096b7cUL, 0x1741a254UL, 0xe5b6a035UL, 
+0x213d42f6UL, 0x2c1c7c26UL, 0x61c2f50fUL, 0x6552daf9UL, 0xd2c231f8UL, 0x25130f69UL, 
+0xd8167fa2UL, 0x0418f2c8UL, 0x001a96a6UL, 0x0d1526abUL, 0x63315c21UL, 0x5e0a72ecUL, 
+0x49bafefdUL, 0x187908d9UL, 0x8d0dbd86UL, 0x311170a7UL, 0x3e9b640cUL, 0xcc3e10d7UL, 
+0xd5cad3b6UL, 0x0caec388UL, 0xf73001e1UL, 0x6c728affUL, 0x71eae2a1UL, 0x1f9af36eUL, 
+0xcfcbd12fUL, 0xc1de8417UL, 0xac07be6bUL, 0xcb44a1d8UL, 0x8b9b0f56UL, 0x013988c3UL, 
+0xb1c52fcaUL, 0xb4be31cdUL, 0xd8782806UL, 0x12a3a4e2UL, 0x6f7de532UL, 0x58fd7eb6UL, 
+0xd01ee900UL, 0x24adffc2UL, 0xf4990fc5UL, 0x9711aac5UL, 0x001d7b95UL, 0x82e5e7d2UL, 
+0x109873f6UL, 0x00613096UL, 0xc32d9521UL, 0xada121ffUL, 0x29908415UL, 0x7fbb977fUL, 
+0xaf9eb3dbUL, 0x29c9ed2aUL, 0x5ce2a465UL, 0xa730f32cUL, 0xd0aa3fe8UL, 0x8a5cc091UL, 
+0xd49e2ce7UL, 0x0ce454a9UL, 0xd60acd86UL, 0x015f1919UL, 0x77079103UL, 0xdea03af6UL, 
+0x78a8565eUL, 0xdee356dfUL, 0x21f05cbeUL, 0x8b75e387UL, 0xb3c50651UL, 0xb8a5c3efUL, 
+0xd8eeb6d2UL, 0xe523be77UL, 0xc2154529UL, 0x2f69efdfUL, 0xafe67afbUL, 0xf470c4b2UL, 
+0xf3e0eb5bUL, 0xd6cc9876UL, 0x39e4460cUL, 0x1fda8538UL, 0x1987832fUL, 0xca007367UL, 
+0xa99144f8UL, 0x296b299eUL, 0x492fc295UL, 0x9266beabUL, 0xb5676e69UL, 0x9bd3dddaUL, 
+0xdf7e052fUL, 0xdb25701cUL, 0x1b5e51eeUL, 0xf65324e6UL, 0x6afce36cUL, 0x0316cc04UL, 
+0x8644213eUL, 0xb7dc59d0UL, 0x7965291fUL, 0xccd6fd43UL, 0x41823979UL, 0x932bcdf6UL, 
+0xb657c34dUL, 0x4edfd282UL, 0x7ae5290cUL, 0x3cb9536bUL, 0x851e20feUL, 0x9833557eUL, 
+0x13ecf0b0UL, 0xd3ffb372UL, 0x3f85c5c1UL, 0x0aef7ed2UL};
+
+static const ulong32 S5[256] = {
+0x7ec90c04UL, 0x2c6e74b9UL, 0x9b0e66dfUL, 0xa6337911UL, 0xb86a7fffUL, 0x1dd358f5UL, 
+0x44dd9d44UL, 0x1731167fUL, 0x08fbf1faUL, 0xe7f511ccUL, 0xd2051b00UL, 0x735aba00UL, 
+0x2ab722d8UL, 0x386381cbUL, 0xacf6243aUL, 0x69befd7aUL, 0xe6a2e77fUL, 0xf0c720cdUL, 
+0xc4494816UL, 0xccf5c180UL, 0x38851640UL, 0x15b0a848UL, 0xe68b18cbUL, 0x4caadeffUL, 
+0x5f480a01UL, 0x0412b2aaUL, 0x259814fcUL, 0x41d0efe2UL, 0x4e40b48dUL, 0x248eb6fbUL, 
+0x8dba1cfeUL, 0x41a99b02UL, 0x1a550a04UL, 0xba8f65cbUL, 0x7251f4e7UL, 0x95a51725UL, 
+0xc106ecd7UL, 0x97a5980aUL, 0xc539b9aaUL, 0x4d79fe6aUL, 0xf2f3f763UL, 0x68af8040UL, 
+0xed0c9e56UL, 0x11b4958bUL, 0xe1eb5a88UL, 0x8709e6b0UL, 0xd7e07156UL, 0x4e29fea7UL, 
+0x6366e52dUL, 0x02d1c000UL, 0xc4ac8e05UL, 0x9377f571UL, 0x0c05372aUL, 0x578535f2UL, 
+0x2261be02UL, 0xd642a0c9UL, 0xdf13a280UL, 0x74b55bd2UL, 0x682199c0UL, 0xd421e5ecUL, 
+0x53fb3ce8UL, 0xc8adedb3UL, 0x28a87fc9UL, 0x3d959981UL, 0x5c1ff900UL, 0xfe38d399UL, 
+0x0c4eff0bUL, 0x062407eaUL, 0xaa2f4fb1UL, 0x4fb96976UL, 0x90c79505UL, 0xb0a8a774UL, 
+0xef55a1ffUL, 0xe59ca2c2UL, 0xa6b62d27UL, 0xe66a4263UL, 0xdf65001fUL, 0x0ec50966UL, 
+0xdfdd55bcUL, 0x29de0655UL, 0x911e739aUL, 0x17af8975UL, 0x32c7911cUL, 0x89f89468UL, 
+0x0d01e980UL, 0x524755f4UL, 0x03b63cc9UL, 0x0cc844b2UL, 0xbcf3f0aaUL, 0x87ac36e9UL, 
+0xe53a7426UL, 0x01b3d82bUL, 0x1a9e7449UL, 0x64ee2d7eUL, 0xcddbb1daUL, 0x01c94910UL, 
+0xb868bf80UL, 0x0d26f3fdUL, 0x9342ede7UL, 0x04a5c284UL, 0x636737b6UL, 0x50f5b616UL, 
+0xf24766e3UL, 0x8eca36c1UL, 0x136e05dbUL, 0xfef18391UL, 0xfb887a37UL, 0xd6e7f7d4UL, 
+0xc7fb7dc9UL, 0x3063fcdfUL, 0xb6f589deUL, 0xec2941daUL, 0x26e46695UL, 0xb7566419UL, 
+0xf654efc5UL, 0xd08d58b7UL, 0x48925401UL, 0xc1bacb7fUL, 0xe5ff550fUL, 0xb6083049UL, 
+0x5bb5d0e8UL, 0x87d72e5aUL, 0xab6a6ee1UL, 0x223a66ceUL, 0xc62bf3cdUL, 0x9e0885f9UL, 
+0x68cb3e47UL, 0x086c010fUL, 0xa21de820UL, 0xd18b69deUL, 0xf3f65777UL, 0xfa02c3f6UL, 
+0x407edac3UL, 0xcbb3d550UL, 0x1793084dUL, 0xb0d70ebaUL, 0x0ab378d5UL, 0xd951fb0cUL, 
+0xded7da56UL, 0x4124bbe4UL, 0x94ca0b56UL, 0x0f5755d1UL, 0xe0e1e56eUL, 0x6184b5beUL, 
+0x580a249fUL, 0x94f74bc0UL, 0xe327888eUL, 0x9f7b5561UL, 0xc3dc0280UL, 0x05687715UL, 
+0x646c6bd7UL, 0x44904db3UL, 0x66b4f0a3UL, 0xc0f1648aUL, 0x697ed5afUL, 0x49e92ff6UL, 
+0x309e374fUL, 0x2cb6356aUL, 0x85808573UL, 0x4991f840UL, 0x76f0ae02UL, 0x083be84dUL, 
+0x28421c9aUL, 0x44489406UL, 0x736e4cb8UL, 0xc1092910UL, 0x8bc95fc6UL, 0x7d869cf4UL, 
+0x134f616fUL, 0x2e77118dUL, 0xb31b2be1UL, 0xaa90b472UL, 0x3ca5d717UL, 0x7d161bbaUL, 
+0x9cad9010UL, 0xaf462ba2UL, 0x9fe459d2UL, 0x45d34559UL, 0xd9f2da13UL, 0xdbc65487UL, 
+0xf3e4f94eUL, 0x176d486fUL, 0x097c13eaUL, 0x631da5c7UL, 0x445f7382UL, 0x175683f4UL, 
+0xcdc66a97UL, 0x70be0288UL, 0xb3cdcf72UL, 0x6e5dd2f3UL, 0x20936079UL, 0x459b80a5UL, 
+0xbe60e2dbUL, 0xa9c23101UL, 0xeba5315cUL, 0x224e42f2UL, 0x1c5c1572UL, 0xf6721b2cUL, 
+0x1ad2fff3UL, 0x8c25404eUL, 0x324ed72fUL, 0x4067b7fdUL, 0x0523138eUL, 0x5ca3bc78UL, 
+0xdc0fd66eUL, 0x75922283UL, 0x784d6b17UL, 0x58ebb16eUL, 0x44094f85UL, 0x3f481d87UL, 
+0xfcfeae7bUL, 0x77b5ff76UL, 0x8c2302bfUL, 0xaaf47556UL, 0x5f46b02aUL, 0x2b092801UL, 
+0x3d38f5f7UL, 0x0ca81f36UL, 0x52af4a8aUL, 0x66d5e7c0UL, 0xdf3b0874UL, 0x95055110UL, 
+0x1b5ad7a8UL, 0xf61ed5adUL, 0x6cf6e479UL, 0x20758184UL, 0xd0cefa65UL, 0x88f7be58UL, 
+0x4a046826UL, 0x0ff6f8f3UL, 0xa09c7f70UL, 0x5346aba0UL, 0x5ce96c28UL, 0xe176eda3UL, 
+0x6bac307fUL, 0x376829d2UL, 0x85360fa9UL, 0x17e3fe2aUL, 0x24b79767UL, 0xf5a96b20UL, 
+0xd6cd2595UL, 0x68ff1ebfUL, 0x7555442cUL, 0xf19f06beUL, 0xf9e0659aUL, 0xeeb9491dUL, 
+0x34010718UL, 0xbb30cab8UL, 0xe822fe15UL, 0x88570983UL, 0x750e6249UL, 0xda627e55UL, 
+0x5e76ffa8UL, 0xb1534546UL, 0x6d47de08UL, 0xefe9e7d4UL};
+
+static const ulong32 S6[256] = {
+0xf6fa8f9dUL, 0x2cac6ce1UL, 0x4ca34867UL, 0xe2337f7cUL, 0x95db08e7UL, 0x016843b4UL, 
+0xeced5cbcUL, 0x325553acUL, 0xbf9f0960UL, 0xdfa1e2edUL, 0x83f0579dUL, 0x63ed86b9UL, 
+0x1ab6a6b8UL, 0xde5ebe39UL, 0xf38ff732UL, 0x8989b138UL, 0x33f14961UL, 0xc01937bdUL, 
+0xf506c6daUL, 0xe4625e7eUL, 0xa308ea99UL, 0x4e23e33cUL, 0x79cbd7ccUL, 0x48a14367UL, 
+0xa3149619UL, 0xfec94bd5UL, 0xa114174aUL, 0xeaa01866UL, 0xa084db2dUL, 0x09a8486fUL, 
+0xa888614aUL, 0x2900af98UL, 0x01665991UL, 0xe1992863UL, 0xc8f30c60UL, 0x2e78ef3cUL, 
+0xd0d51932UL, 0xcf0fec14UL, 0xf7ca07d2UL, 0xd0a82072UL, 0xfd41197eUL, 0x9305a6b0UL, 
+0xe86be3daUL, 0x74bed3cdUL, 0x372da53cUL, 0x4c7f4448UL, 0xdab5d440UL, 0x6dba0ec3UL, 
+0x083919a7UL, 0x9fbaeed9UL, 0x49dbcfb0UL, 0x4e670c53UL, 0x5c3d9c01UL, 0x64bdb941UL, 
+0x2c0e636aUL, 0xba7dd9cdUL, 0xea6f7388UL, 0xe70bc762UL, 0x35f29adbUL, 0x5c4cdd8dUL, 
+0xf0d48d8cUL, 0xb88153e2UL, 0x08a19866UL, 0x1ae2eac8UL, 0x284caf89UL, 0xaa928223UL, 
+0x9334be53UL, 0x3b3a21bfUL, 0x16434be3UL, 0x9aea3906UL, 0xefe8c36eUL, 0xf890cdd9UL, 
+0x80226daeUL, 0xc340a4a3UL, 0xdf7e9c09UL, 0xa694a807UL, 0x5b7c5eccUL, 0x221db3a6UL, 
+0x9a69a02fUL, 0x68818a54UL, 0xceb2296fUL, 0x53c0843aUL, 0xfe893655UL, 0x25bfe68aUL, 
+0xb4628abcUL, 0xcf222ebfUL, 0x25ac6f48UL, 0xa9a99387UL, 0x53bddb65UL, 0xe76ffbe7UL, 
+0xe967fd78UL, 0x0ba93563UL, 0x8e342bc1UL, 0xe8a11be9UL, 0x4980740dUL, 0xc8087dfcUL, 
+0x8de4bf99UL, 0xa11101a0UL, 0x7fd37975UL, 0xda5a26c0UL, 0xe81f994fUL, 0x9528cd89UL, 
+0xfd339fedUL, 0xb87834bfUL, 0x5f04456dUL, 0x22258698UL, 0xc9c4c83bUL, 0x2dc156beUL, 
+0x4f628daaUL, 0x57f55ec5UL, 0xe2220abeUL, 0xd2916ebfUL, 0x4ec75b95UL, 0x24f2c3c0UL, 
+0x42d15d99UL, 0xcd0d7fa0UL, 0x7b6e27ffUL, 0xa8dc8af0UL, 0x7345c106UL, 0xf41e232fUL, 
+0x35162386UL, 0xe6ea8926UL, 0x3333b094UL, 0x157ec6f2UL, 0x372b74afUL, 0x692573e4UL, 
+0xe9a9d848UL, 0xf3160289UL, 0x3a62ef1dUL, 0xa787e238UL, 0xf3a5f676UL, 0x74364853UL, 
+0x20951063UL, 0x4576698dUL, 0xb6fad407UL, 0x592af950UL, 0x36f73523UL, 0x4cfb6e87UL, 
+0x7da4cec0UL, 0x6c152daaUL, 0xcb0396a8UL, 0xc50dfe5dUL, 0xfcd707abUL, 0x0921c42fUL, 
+0x89dff0bbUL, 0x5fe2be78UL, 0x448f4f33UL, 0x754613c9UL, 0x2b05d08dUL, 0x48b9d585UL, 
+0xdc049441UL, 0xc8098f9bUL, 0x7dede786UL, 0xc39a3373UL, 0x42410005UL, 0x6a091751UL, 
+0x0ef3c8a6UL, 0x890072d6UL, 0x28207682UL, 0xa9a9f7beUL, 0xbf32679dUL, 0xd45b5b75UL, 
+0xb353fd00UL, 0xcbb0e358UL, 0x830f220aUL, 0x1f8fb214UL, 0xd372cf08UL, 0xcc3c4a13UL, 
+0x8cf63166UL, 0x061c87beUL, 0x88c98f88UL, 0x6062e397UL, 0x47cf8e7aUL, 0xb6c85283UL, 
+0x3cc2acfbUL, 0x3fc06976UL, 0x4e8f0252UL, 0x64d8314dUL, 0xda3870e3UL, 0x1e665459UL, 
+0xc10908f0UL, 0x513021a5UL, 0x6c5b68b7UL, 0x822f8aa0UL, 0x3007cd3eUL, 0x74719eefUL, 
+0xdc872681UL, 0x073340d4UL, 0x7e432fd9UL, 0x0c5ec241UL, 0x8809286cUL, 0xf592d891UL, 
+0x08a930f6UL, 0x957ef305UL, 0xb7fbffbdUL, 0xc266e96fUL, 0x6fe4ac98UL, 0xb173ecc0UL, 
+0xbc60b42aUL, 0x953498daUL, 0xfba1ae12UL, 0x2d4bd736UL, 0x0f25faabUL, 0xa4f3fcebUL, 
+0xe2969123UL, 0x257f0c3dUL, 0x9348af49UL, 0x361400bcUL, 0xe8816f4aUL, 0x3814f200UL, 
+0xa3f94043UL, 0x9c7a54c2UL, 0xbc704f57UL, 0xda41e7f9UL, 0xc25ad33aUL, 0x54f4a084UL, 
+0xb17f5505UL, 0x59357cbeUL, 0xedbd15c8UL, 0x7f97c5abUL, 0xba5ac7b5UL, 0xb6f6deafUL, 
+0x3a479c3aUL, 0x5302da25UL, 0x653d7e6aUL, 0x54268d49UL, 0x51a477eaUL, 0x5017d55bUL, 
+0xd7d25d88UL, 0x44136c76UL, 0x0404a8c8UL, 0xb8e5a121UL, 0xb81a928aUL, 0x60ed5869UL, 
+0x97c55b96UL, 0xeaec991bUL, 0x29935913UL, 0x01fdb7f1UL, 0x088e8dfaUL, 0x9ab6f6f5UL, 
+0x3b4cbf9fUL, 0x4a5de3abUL, 0xe6051d35UL, 0xa0e1d855UL, 0xd36b4cf1UL, 0xf544edebUL, 
+0xb0e93524UL, 0xbebb8fbdUL, 0xa2d762cfUL, 0x49c92f54UL, 0x38b5f331UL, 0x7128a454UL, 
+0x48392905UL, 0xa65b1db8UL, 0x851c97bdUL, 0xd675cf2fUL};
+
+static const ulong32 S7[256] = {
+0x85e04019UL, 0x332bf567UL, 0x662dbfffUL, 0xcfc65693UL, 0x2a8d7f6fUL, 0xab9bc912UL, 
+0xde6008a1UL, 0x2028da1fUL, 0x0227bce7UL, 0x4d642916UL, 0x18fac300UL, 0x50f18b82UL, 
+0x2cb2cb11UL, 0xb232e75cUL, 0x4b3695f2UL, 0xb28707deUL, 0xa05fbcf6UL, 0xcd4181e9UL, 
+0xe150210cUL, 0xe24ef1bdUL, 0xb168c381UL, 0xfde4e789UL, 0x5c79b0d8UL, 0x1e8bfd43UL, 
+0x4d495001UL, 0x38be4341UL, 0x913cee1dUL, 0x92a79c3fUL, 0x089766beUL, 0xbaeeadf4UL, 
+0x1286becfUL, 0xb6eacb19UL, 0x2660c200UL, 0x7565bde4UL, 0x64241f7aUL, 0x8248dca9UL, 
+0xc3b3ad66UL, 0x28136086UL, 0x0bd8dfa8UL, 0x356d1cf2UL, 0x107789beUL, 0xb3b2e9ceUL, 
+0x0502aa8fUL, 0x0bc0351eUL, 0x166bf52aUL, 0xeb12ff82UL, 0xe3486911UL, 0xd34d7516UL, 
+0x4e7b3affUL, 0x5f43671bUL, 0x9cf6e037UL, 0x4981ac83UL, 0x334266ceUL, 0x8c9341b7UL, 
+0xd0d854c0UL, 0xcb3a6c88UL, 0x47bc2829UL, 0x4725ba37UL, 0xa66ad22bUL, 0x7ad61f1eUL, 
+0x0c5cbafaUL, 0x4437f107UL, 0xb6e79962UL, 0x42d2d816UL, 0x0a961288UL, 0xe1a5c06eUL, 
+0x13749e67UL, 0x72fc081aUL, 0xb1d139f7UL, 0xf9583745UL, 0xcf19df58UL, 0xbec3f756UL, 
+0xc06eba30UL, 0x07211b24UL, 0x45c28829UL, 0xc95e317fUL, 0xbc8ec511UL, 0x38bc46e9UL, 
+0xc6e6fa14UL, 0xbae8584aUL, 0xad4ebc46UL, 0x468f508bUL, 0x7829435fUL, 0xf124183bUL, 
+0x821dba9fUL, 0xaff60ff4UL, 0xea2c4e6dUL, 0x16e39264UL, 0x92544a8bUL, 0x009b4fc3UL, 
+0xaba68cedUL, 0x9ac96f78UL, 0x06a5b79aUL, 0xb2856e6eUL, 0x1aec3ca9UL, 0xbe838688UL, 
+0x0e0804e9UL, 0x55f1be56UL, 0xe7e5363bUL, 0xb3a1f25dUL, 0xf7debb85UL, 0x61fe033cUL, 
+0x16746233UL, 0x3c034c28UL, 0xda6d0c74UL, 0x79aac56cUL, 0x3ce4e1adUL, 0x51f0c802UL, 
+0x98f8f35aUL, 0x1626a49fUL, 0xeed82b29UL, 0x1d382fe3UL, 0x0c4fb99aUL, 0xbb325778UL, 
+0x3ec6d97bUL, 0x6e77a6a9UL, 0xcb658b5cUL, 0xd45230c7UL, 0x2bd1408bUL, 0x60c03eb7UL, 
+0xb9068d78UL, 0xa33754f4UL, 0xf430c87dUL, 0xc8a71302UL, 0xb96d8c32UL, 0xebd4e7beUL, 
+0xbe8b9d2dUL, 0x7979fb06UL, 0xe7225308UL, 0x8b75cf77UL, 0x11ef8da4UL, 0xe083c858UL, 
+0x8d6b786fUL, 0x5a6317a6UL, 0xfa5cf7a0UL, 0x5dda0033UL, 0xf28ebfb0UL, 0xf5b9c310UL, 
+0xa0eac280UL, 0x08b9767aUL, 0xa3d9d2b0UL, 0x79d34217UL, 0x021a718dUL, 0x9ac6336aUL, 
+0x2711fd60UL, 0x438050e3UL, 0x069908a8UL, 0x3d7fedc4UL, 0x826d2befUL, 0x4eeb8476UL, 
+0x488dcf25UL, 0x36c9d566UL, 0x28e74e41UL, 0xc2610acaUL, 0x3d49a9cfUL, 0xbae3b9dfUL, 
+0xb65f8de6UL, 0x92aeaf64UL, 0x3ac7d5e6UL, 0x9ea80509UL, 0xf22b017dUL, 0xa4173f70UL, 
+0xdd1e16c3UL, 0x15e0d7f9UL, 0x50b1b887UL, 0x2b9f4fd5UL, 0x625aba82UL, 0x6a017962UL, 
+0x2ec01b9cUL, 0x15488aa9UL, 0xd716e740UL, 0x40055a2cUL, 0x93d29a22UL, 0xe32dbf9aUL, 
+0x058745b9UL, 0x3453dc1eUL, 0xd699296eUL, 0x496cff6fUL, 0x1c9f4986UL, 0xdfe2ed07UL, 
+0xb87242d1UL, 0x19de7eaeUL, 0x053e561aUL, 0x15ad6f8cUL, 0x66626c1cUL, 0x7154c24cUL, 
+0xea082b2aUL, 0x93eb2939UL, 0x17dcb0f0UL, 0x58d4f2aeUL, 0x9ea294fbUL, 0x52cf564cUL, 
+0x9883fe66UL, 0x2ec40581UL, 0x763953c3UL, 0x01d6692eUL, 0xd3a0c108UL, 0xa1e7160eUL, 
+0xe4f2dfa6UL, 0x693ed285UL, 0x74904698UL, 0x4c2b0eddUL, 0x4f757656UL, 0x5d393378UL, 
+0xa132234fUL, 0x3d321c5dUL, 0xc3f5e194UL, 0x4b269301UL, 0xc79f022fUL, 0x3c997e7eUL, 
+0x5e4f9504UL, 0x3ffafbbdUL, 0x76f7ad0eUL, 0x296693f4UL, 0x3d1fce6fUL, 0xc61e45beUL, 
+0xd3b5ab34UL, 0xf72bf9b7UL, 0x1b0434c0UL, 0x4e72b567UL, 0x5592a33dUL, 0xb5229301UL, 
+0xcfd2a87fUL, 0x60aeb767UL, 0x1814386bUL, 0x30bcc33dUL, 0x38a0c07dUL, 0xfd1606f2UL, 
+0xc363519bUL, 0x589dd390UL, 0x5479f8e6UL, 0x1cb8d647UL, 0x97fd61a9UL, 0xea7759f4UL, 
+0x2d57539dUL, 0x569a58cfUL, 0xe84e63adUL, 0x462e1b78UL, 0x6580f87eUL, 0xf3817914UL, 
+0x91da55f4UL, 0x40a230f3UL, 0xd1988f35UL, 0xb6e318d2UL, 0x3ffa50bcUL, 0x3d40f021UL, 
+0xc3c0bdaeUL, 0x4958c24cUL, 0x518f36b2UL, 0x84b1d370UL, 0x0fedce83UL, 0x878ddadaUL, 
+0xf2a279c7UL, 0x94e01be8UL, 0x90716f4bUL, 0x954b8aa3UL};
+
+static const ulong32 S8[256] = {
+0xe216300dUL, 0xbbddfffcUL, 0xa7ebdabdUL, 0x35648095UL, 0x7789f8b7UL, 0xe6c1121bUL, 
+0x0e241600UL, 0x052ce8b5UL, 0x11a9cfb0UL, 0xe5952f11UL, 0xece7990aUL, 0x9386d174UL, 
+0x2a42931cUL, 0x76e38111UL, 0xb12def3aUL, 0x37ddddfcUL, 0xde9adeb1UL, 0x0a0cc32cUL, 
+0xbe197029UL, 0x84a00940UL, 0xbb243a0fUL, 0xb4d137cfUL, 0xb44e79f0UL, 0x049eedfdUL, 
+0x0b15a15dUL, 0x480d3168UL, 0x8bbbde5aUL, 0x669ded42UL, 0xc7ece831UL, 0x3f8f95e7UL, 
+0x72df191bUL, 0x7580330dUL, 0x94074251UL, 0x5c7dcdfaUL, 0xabbe6d63UL, 0xaa402164UL, 
+0xb301d40aUL, 0x02e7d1caUL, 0x53571daeUL, 0x7a3182a2UL, 0x12a8ddecUL, 0xfdaa335dUL, 
+0x176f43e8UL, 0x71fb46d4UL, 0x38129022UL, 0xce949ad4UL, 0xb84769adUL, 0x965bd862UL, 
+0x82f3d055UL, 0x66fb9767UL, 0x15b80b4eUL, 0x1d5b47a0UL, 0x4cfde06fUL, 0xc28ec4b8UL, 
+0x57e8726eUL, 0x647a78fcUL, 0x99865d44UL, 0x608bd593UL, 0x6c200e03UL, 0x39dc5ff6UL, 
+0x5d0b00a3UL, 0xae63aff2UL, 0x7e8bd632UL, 0x70108c0cUL, 0xbbd35049UL, 0x2998df04UL, 
+0x980cf42aUL, 0x9b6df491UL, 0x9e7edd53UL, 0x06918548UL, 0x58cb7e07UL, 0x3b74ef2eUL, 
+0x522fffb1UL, 0xd24708ccUL, 0x1c7e27cdUL, 0xa4eb215bUL, 0x3cf1d2e2UL, 0x19b47a38UL, 
+0x424f7618UL, 0x35856039UL, 0x9d17dee7UL, 0x27eb35e6UL, 0xc9aff67bUL, 0x36baf5b8UL, 
+0x09c467cdUL, 0xc18910b1UL, 0xe11dbf7bUL, 0x06cd1af8UL, 0x7170c608UL, 0x2d5e3354UL, 
+0xd4de495aUL, 0x64c6d006UL, 0xbcc0c62cUL, 0x3dd00db3UL, 0x708f8f34UL, 0x77d51b42UL, 
+0x264f620fUL, 0x24b8d2bfUL, 0x15c1b79eUL, 0x46a52564UL, 0xf8d7e54eUL, 0x3e378160UL, 
+0x7895cda5UL, 0x859c15a5UL, 0xe6459788UL, 0xc37bc75fUL, 0xdb07ba0cUL, 0x0676a3abUL, 
+0x7f229b1eUL, 0x31842e7bUL, 0x24259fd7UL, 0xf8bef472UL, 0x835ffcb8UL, 0x6df4c1f2UL, 
+0x96f5b195UL, 0xfd0af0fcUL, 0xb0fe134cUL, 0xe2506d3dUL, 0x4f9b12eaUL, 0xf215f225UL, 
+0xa223736fUL, 0x9fb4c428UL, 0x25d04979UL, 0x34c713f8UL, 0xc4618187UL, 0xea7a6e98UL, 
+0x7cd16efcUL, 0x1436876cUL, 0xf1544107UL, 0xbedeee14UL, 0x56e9af27UL, 0xa04aa441UL, 
+0x3cf7c899UL, 0x92ecbae6UL, 0xdd67016dUL, 0x151682ebUL, 0xa842eedfUL, 0xfdba60b4UL, 
+0xf1907b75UL, 0x20e3030fUL, 0x24d8c29eUL, 0xe139673bUL, 0xefa63fb8UL, 0x71873054UL, 
+0xb6f2cf3bUL, 0x9f326442UL, 0xcb15a4ccUL, 0xb01a4504UL, 0xf1e47d8dUL, 0x844a1be5UL, 
+0xbae7dfdcUL, 0x42cbda70UL, 0xcd7dae0aUL, 0x57e85b7aUL, 0xd53f5af6UL, 0x20cf4d8cUL, 
+0xcea4d428UL, 0x79d130a4UL, 0x3486ebfbUL, 0x33d3cddcUL, 0x77853b53UL, 0x37effcb5UL, 
+0xc5068778UL, 0xe580b3e6UL, 0x4e68b8f4UL, 0xc5c8b37eUL, 0x0d809ea2UL, 0x398feb7cUL, 
+0x132a4f94UL, 0x43b7950eUL, 0x2fee7d1cUL, 0x223613bdUL, 0xdd06caa2UL, 0x37df932bUL, 
+0xc4248289UL, 0xacf3ebc3UL, 0x5715f6b7UL, 0xef3478ddUL, 0xf267616fUL, 0xc148cbe4UL, 
+0x9052815eUL, 0x5e410fabUL, 0xb48a2465UL, 0x2eda7fa4UL, 0xe87b40e4UL, 0xe98ea084UL, 
+0x5889e9e1UL, 0xefd390fcUL, 0xdd07d35bUL, 0xdb485694UL, 0x38d7e5b2UL, 0x57720101UL, 
+0x730edebcUL, 0x5b643113UL, 0x94917e4fUL, 0x503c2fbaUL, 0x646f1282UL, 0x7523d24aUL, 
+0xe0779695UL, 0xf9c17a8fUL, 0x7a5b2121UL, 0xd187b896UL, 0x29263a4dUL, 0xba510cdfUL, 
+0x81f47c9fUL, 0xad1163edUL, 0xea7b5965UL, 0x1a00726eUL, 0x11403092UL, 0x00da6d77UL, 
+0x4a0cdd61UL, 0xad1f4603UL, 0x605bdfb0UL, 0x9eedc364UL, 0x22ebe6a8UL, 0xcee7d28aUL, 
+0xa0e736a0UL, 0x5564a6b9UL, 0x10853209UL, 0xc7eb8f37UL, 0x2de705caUL, 0x8951570fUL, 
+0xdf09822bUL, 0xbd691a6cUL, 0xaa12e4f2UL, 0x87451c0fUL, 0xe0f6a27aUL, 0x3ada4819UL, 
+0x4cf1764fUL, 0x0d771c2bUL, 0x67cdb156UL, 0x350d8384UL, 0x5938fa0fUL, 0x42399ef3UL, 
+0x36997b07UL, 0x0e84093dUL, 0x4aa93e61UL, 0x8360d87bUL, 0x1fa98b0cUL, 0x1149382cUL, 
+0xe97625a5UL, 0x0614d1b7UL, 0x0e25244bUL, 0x0c768347UL, 0x589e8d82UL, 0x0d2059d1UL, 
+0xa466bb1eUL, 0xf8da0a82UL, 0x04f19130UL, 0xba6e4ec0UL, 0x99265164UL, 0x1ee7230dUL, 
+0x50b2ad80UL, 0xeaee6801UL, 0x8db2a283UL, 0xea8bf59eUL};
+
+/* returns the i'th byte of a variable */
+#ifdef _MSC_VER
+   #define GB(x, i) ((unsigned char)((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3))))
+#else   
+   #define GB(x, i) (((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3)))&255)
+#endif   
+
+#ifdef CLEAN_STACK
+static int _cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#else
+int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#endif
+{
+   ulong32 x[4], z[4];
+   unsigned char buf[16];
+   int y, i;
+
+   _ARGCHK(key != NULL);
+   _ARGCHK(skey != NULL);
+
+   if (num_rounds != 12 && num_rounds != 16 && num_rounds != 0) {
+      return CRYPT_INVALID_ROUNDS; 
+   }
+ 
+   if (num_rounds == 12 && keylen > 10) {
+      return CRYPT_INVALID_ROUNDS;
+   }
+
+   if (keylen < 5 || keylen > 16) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+
+   /* extend the key as required */
+   zeromem(buf, sizeof(buf));
+   memcpy(buf, key, (size_t)keylen);
+
+   /* load and start the awful looking network */
+   for (y = 0; y < 4; y++) {
+       LOAD32H(x[3-y],buf+4*y);
+   }
+
+   for (i = y = 0; y < 2; y++) {
+        z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)];
+        z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)];
+        z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)];
+        z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)];
+        skey->cast5.K[i++] = S5[GB(z, 0x8)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0x7)] ^ S8[GB(z, 0x6)] ^ S5[GB(z, 0x2)];
+        skey->cast5.K[i++] = S5[GB(z, 0xA)] ^ S6[GB(z, 0xB)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S6[GB(z, 0x6)];
+        skey->cast5.K[i++] = S5[GB(z, 0xC)] ^ S6[GB(z, 0xd)] ^ S7[GB(z, 0x3)] ^ S8[GB(z, 0x2)] ^ S7[GB(z, 0x9)];
+        skey->cast5.K[i++] = S5[GB(z, 0xE)] ^ S6[GB(z, 0xF)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x0)] ^ S8[GB(z, 0xc)];
+
+        x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)];
+        x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)];
+        x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)];
+        x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)];
+        skey->cast5.K[i++] = S5[GB(x, 0x3)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0xc)] ^ S8[GB(x, 0xd)] ^ S5[GB(x, 0x8)];
+        skey->cast5.K[i++] = S5[GB(x, 0x1)] ^ S6[GB(x, 0x0)] ^ S7[GB(x, 0xe)] ^ S8[GB(x, 0xf)] ^ S6[GB(x, 0xd)];
+        skey->cast5.K[i++] = S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x8)] ^ S8[GB(x, 0x9)] ^ S7[GB(x, 0x3)];
+        skey->cast5.K[i++] = S5[GB(x, 0x5)] ^ S6[GB(x, 0x4)] ^ S7[GB(x, 0xa)] ^ S8[GB(x, 0xb)] ^ S8[GB(x, 0x7)];
+
+        /* second half */
+        z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)];
+        z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)];
+        z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)];
+        z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)];
+        skey->cast5.K[i++] = S5[GB(z, 0x3)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0xc)] ^ S8[GB(z, 0xd)] ^ S5[GB(z, 0x9)];
+        skey->cast5.K[i++] = S5[GB(z, 0x1)] ^ S6[GB(z, 0x0)] ^ S7[GB(z, 0xe)] ^ S8[GB(z, 0xf)] ^ S6[GB(z, 0xc)];
+        skey->cast5.K[i++] = S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x8)] ^ S8[GB(z, 0x9)] ^ S7[GB(z, 0x2)];
+        skey->cast5.K[i++] = S5[GB(z, 0x5)] ^ S6[GB(z, 0x4)] ^ S7[GB(z, 0xa)] ^ S8[GB(z, 0xb)] ^ S8[GB(z, 0x6)];
+
+        x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)];
+        x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)];
+        x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)];
+        x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)];
+        skey->cast5.K[i++] = S5[GB(x, 0x8)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0x7)] ^ S8[GB(x, 0x6)] ^ S5[GB(x, 0x3)];
+        skey->cast5.K[i++] = S5[GB(x, 0xa)] ^ S6[GB(x, 0xb)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S6[GB(x, 0x7)];
+        skey->cast5.K[i++] = S5[GB(x, 0xc)] ^ S6[GB(x, 0xd)] ^ S7[GB(x, 0x3)] ^ S8[GB(x, 0x2)] ^ S7[GB(x, 0x8)];
+        skey->cast5.K[i++] = S5[GB(x, 0xe)] ^ S6[GB(x, 0xf)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x0)] ^ S8[GB(x, 0xd)];
+   }
+
+   skey->cast5.keylen = keylen;
+
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+   zeromem(x, sizeof(x));
+   zeromem(z, sizeof(z));
+#endif  
+
+   return CRYPT_OK;
+}
+
+#ifdef CLEAN_STACK
+int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+   int z;
+   z = _cast5_setup(key, keylen, num_rounds, skey);
+   burn_stack(sizeof(ulong32)*8 + 16 + sizeof(int)*2);
+   return z;
+}
+#endif
+
+#ifdef _MSC_VER
+   #define INLINE __inline
+#else
+   #define INLINE 
+#endif   
+   
+INLINE static ulong32 FI(ulong32 R, ulong32 Km, ulong32 Kr)
+{
+   ulong32 I;
+   I = (Km + R);
+   I = ROL(I, Kr);
+   return ((S1[byte(I, 3)] ^ S2[byte(I,2)]) - S3[byte(I,1)]) + S4[byte(I,0)];
+}
+   
+INLINE static ulong32 FII(ulong32 R, ulong32 Km, ulong32 Kr)
+{
+   ulong32 I;
+   I = (Km ^ R);
+   I = ROL(I, Kr);
+   return ((S1[byte(I, 3)] - S2[byte(I,2)]) + S3[byte(I,1)]) ^ S4[byte(I,0)];
+}
+
+INLINE static ulong32 FIII(ulong32 R, ulong32 Km, ulong32 Kr)
+{
+   ulong32 I;
+   I = (Km - R);
+   I = ROL(I, Kr);
+   return ((S1[byte(I, 3)] + S2[byte(I,2)]) ^ S3[byte(I,1)]) - S4[byte(I,0)];
+}
+
+#ifdef CLEAN_STACK
+static void _cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#else
+void cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#endif
+{
+   ulong32 R, L;
+
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(key != NULL);
+
+   LOAD32H(L,&pt[0]); 
+   LOAD32H(R,&pt[4]);
+   L ^= FI(R, key->cast5.K[0], key->cast5.K[16]);
+   R ^= FII(L, key->cast5.K[1], key->cast5.K[17]);
+   L ^= FIII(R, key->cast5.K[2], key->cast5.K[18]);
+   R ^= FI(L, key->cast5.K[3], key->cast5.K[19]);
+   L ^= FII(R, key->cast5.K[4], key->cast5.K[20]);
+   R ^= FIII(L, key->cast5.K[5], key->cast5.K[21]);
+   L ^= FI(R, key->cast5.K[6], key->cast5.K[22]);
+   R ^= FII(L, key->cast5.K[7], key->cast5.K[23]);
+   L ^= FIII(R, key->cast5.K[8], key->cast5.K[24]);
+   R ^= FI(L, key->cast5.K[9], key->cast5.K[25]);
+   L ^= FII(R, key->cast5.K[10], key->cast5.K[26]);
+   R ^= FIII(L, key->cast5.K[11], key->cast5.K[27]);
+   if (key->cast5.keylen > 10) {
+      L ^= FI(R, key->cast5.K[12], key->cast5.K[28]);
+      R ^= FII(L, key->cast5.K[13], key->cast5.K[29]);
+      L ^= FIII(R, key->cast5.K[14], key->cast5.K[30]);
+      R ^= FI(L, key->cast5.K[15], key->cast5.K[31]);
+   }
+   STORE32H(R,&ct[0]);
+   STORE32H(L,&ct[4]);
+}
+
+
+#ifdef CLEAN_STACK
+void cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+{
+   _cast5_ecb_encrypt(pt,ct,key);
+   burn_stack(sizeof(ulong32)*3);
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#else
+void cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#endif
+{
+   ulong32 R, L;
+
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(key != NULL);
+
+   LOAD32H(R,&ct[0]); 
+   LOAD32H(L,&ct[4]);
+   if (key->cast5.keylen > 10) {
+      R ^= FI(L, key->cast5.K[15], key->cast5.K[31]);
+      L ^= FIII(R, key->cast5.K[14], key->cast5.K[30]);
+      R ^= FII(L, key->cast5.K[13], key->cast5.K[29]);
+      L ^= FI(R, key->cast5.K[12], key->cast5.K[28]);
+   }
+   R ^= FIII(L, key->cast5.K[11], key->cast5.K[27]);
+   L ^= FII(R, key->cast5.K[10], key->cast5.K[26]);
+   R ^= FI(L, key->cast5.K[9], key->cast5.K[25]);
+   L ^= FIII(R, key->cast5.K[8], key->cast5.K[24]);
+   R ^= FII(L, key->cast5.K[7], key->cast5.K[23]);
+   L ^= FI(R, key->cast5.K[6], key->cast5.K[22]);
+   R ^= FIII(L, key->cast5.K[5], key->cast5.K[21]);
+   L ^= FII(R, key->cast5.K[4], key->cast5.K[20]);
+   R ^= FI(L, key->cast5.K[3], key->cast5.K[19]);
+   L ^= FIII(R, key->cast5.K[2], key->cast5.K[18]);
+   R ^= FII(L, key->cast5.K[1], key->cast5.K[17]);
+   L ^= FI(R, key->cast5.K[0], key->cast5.K[16]);
+   STORE32H(L,&pt[0]);
+   STORE32H(R,&pt[4]);
+}
+
+#ifdef CLEAN_STACK
+void cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+{
+   _cast5_ecb_decrypt(ct,pt,key);
+   burn_stack(sizeof(ulong32)*3);
+}
+#endif
+
+int cast5_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+   static const struct {
+       int keylen;
+       unsigned char key[16];
+       unsigned char pt[8];
+       unsigned char ct[8];
+   } tests[] = {
+     { 16,
+       {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A},
+       {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+       {0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2}
+     },
+     { 10,
+       {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+       {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+       {0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B},
+     },
+     { 5,
+       {0x01, 0x23, 0x45, 0x67, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+       {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
+       {0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E}
+     }
+   };
+   int i, y, err;
+   symmetric_key key;
+   unsigned char tmp[2][8];
+
+   for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+       if ((err = cast5_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
+          return err;
+       }
+       cast5_ecb_encrypt(tests[i].pt, tmp[0], &key);
+       cast5_ecb_decrypt(tmp[0], tmp[1], &key);
+       if ((memcmp(tmp[0], tests[i].ct, 8) != 0) || (memcmp(tmp[1], tests[i].pt, 8) != 0)) {
+          return CRYPT_FAIL_TESTVECTOR;
+       }
+      /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+      for (y = 0; y < 8; y++) tmp[0][y] = 0;
+      for (y = 0; y < 1000; y++) cast5_ecb_encrypt(tmp[0], tmp[0], &key);
+      for (y = 0; y < 1000; y++) cast5_ecb_decrypt(tmp[0], tmp[0], &key);
+      for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+   
+   }
+   return CRYPT_OK;
+ #endif
+}
+
+int cast5_keysize(int *desired_keysize)
+{
+   _ARGCHK(desired_keysize != NULL);
+   if (*desired_keysize < 5) {
+      return CRYPT_INVALID_KEYSIZE;
+   } else if (*desired_keysize > 16) {
+      *desired_keysize = 16;
+   }
+   return CRYPT_OK;
+} 
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cbc_decrypt.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,56 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+#ifdef CBC
+
+int cbc_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_CBC *cbc)
+{
+   int x, err;
+   unsigned char tmp[MAXBLOCKSIZE], tmp2[MAXBLOCKSIZE];
+
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(cbc != NULL);
+
+   /* decrypt the block from ct into tmp */
+   if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
+       return err;
+   }
+   cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key);
+   
+   /* is blocklen valid? */
+   if (cbc->blocklen < 0 || cbc->blocklen > (int)sizeof(cbc->IV)) {
+      return CRYPT_INVALID_ARG;
+   } 
+
+   /* xor IV against the plaintext of the previous step */
+   for (x = 0; x < cbc->blocklen; x++) { 
+       /* copy CT in case ct == pt */
+       tmp2[x] = ct[x]; 
+
+       /* actually decrypt the byte */
+       pt[x] = tmp[x] ^ cbc->IV[x]; 
+   }
+
+   /* replace IV with this current ciphertext */ 
+   for (x = 0; x < cbc->blocklen; x++) {
+       cbc->IV[x] = tmp2[x];
+   }
+   #ifdef CLEAN_STACK
+      zeromem(tmp, sizeof(tmp));
+      zeromem(tmp2, sizeof(tmp2));
+   #endif
+   return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cbc_encrypt.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,52 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+#ifdef CBC
+
+int cbc_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_CBC *cbc)
+{
+   int x, err;
+   unsigned char tmp[MAXBLOCKSIZE];
+
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(cbc != NULL);
+
+   if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
+       return err;
+   }
+   
+   /* is blocklen valid? */
+   if (cbc->blocklen < 0 || cbc->blocklen > (int)sizeof(cbc->IV)) {
+      return CRYPT_INVALID_ARG;
+   }    
+
+   /* xor IV against plaintext */
+   for (x = 0; x < cbc->blocklen; x++) {
+       tmp[x] = pt[x] ^ cbc->IV[x];
+   }
+
+   /* encrypt */
+   cipher_descriptor[cbc->cipher].ecb_encrypt(tmp, ct, &cbc->key);
+
+   /* store IV [ciphertext] for a future block */
+   for (x = 0; x < cbc->blocklen; x++) {
+       cbc->IV[x] = ct[x];
+   }
+
+   #ifdef CLEAN_STACK
+      zeromem(tmp, sizeof(tmp));
+   #endif
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cbc_start.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,43 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+#ifdef CBC
+
+int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, 
+              int keylen, int num_rounds, symmetric_CBC *cbc)
+{
+   int x, err;
+ 
+   _ARGCHK(IV != NULL);
+   _ARGCHK(key != NULL);
+   _ARGCHK(cbc != NULL);
+
+   /* bad param? */
+   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* setup cipher */
+   if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* copy IV */
+   cbc->blocklen = cipher_descriptor[cipher].block_length;
+   cbc->cipher   = cipher;
+   for (x = 0; x < cbc->blocklen; x++) {
+       cbc->IV[x] = IV[x];
+   }
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cfb_decrypt.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,48 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+#ifdef CFB
+
+int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb)
+{
+   int err;
+
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(cfb != NULL);
+
+   if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
+       return err;
+   }
+
+   /* is blocklen/padlen valid? */
+   if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) ||
+       cfb->padlen   < 0 || cfb->padlen   > (int)sizeof(cfb->pad)) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   while (len-- > 0) {
+       if (cfb->padlen == cfb->blocklen) {
+          cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key);
+          cfb->padlen = 0;
+       }
+       cfb->pad[cfb->padlen] = *ct;
+       *pt = *ct ^ cfb->IV[cfb->padlen];
+       ++pt; 
+       ++ct;
+       ++cfb->padlen;
+   }
+   return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cfb_encrypt.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,46 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+#ifdef CFB
+
+int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb)
+{
+   int err;
+
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(cfb != NULL);
+
+   if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
+       return err;
+   }
+
+   /* is blocklen/padlen valid? */
+   if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) ||
+       cfb->padlen   < 0 || cfb->padlen   > (int)sizeof(cfb->pad)) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   while (len-- > 0) {
+       if (cfb->padlen == cfb->blocklen) {
+          cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key);
+          cfb->padlen = 0;
+       }
+       cfb->pad[cfb->padlen] = (*ct = *pt ^ cfb->IV[cfb->padlen]);
+       ++pt; 
+       ++ct;
+       ++cfb->padlen;
+   }
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cfb_start.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,47 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+#ifdef CFB
+
+int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, 
+              int keylen, int num_rounds, symmetric_CFB *cfb)
+{
+   int x, err;
+
+   _ARGCHK(IV != NULL);
+   _ARGCHK(key != NULL);
+   _ARGCHK(cfb != NULL);
+
+   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+      return err;
+   }
+   
+
+   /* copy data */
+   cfb->cipher = cipher;
+   cfb->blocklen = cipher_descriptor[cipher].block_length;
+   for (x = 0; x < cfb->blocklen; x++)
+       cfb->IV[x] = IV[x];
+
+   /* init the cipher */
+   if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cfb->key)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* encrypt the IV */
+   cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->IV, cfb->IV, &cfb->key);
+   cfb->padlen = 0;
+
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/changes	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,957 @@
+May 12th, 2004
+v0.95  -- Optimized AES and WHIRLPOOL for SMALL_CODE by taking advantage of the fact
+          the transforms are circulant.  AES dropped 5KB and WHIRLPOOL dropped 13KB
+          using the default build options on the x86.
+       -- Updated eax so the eax_done() would clear the state [like hmac,pmac,ocb] when
+          CLEAN_STACK has been defined.
+       -- added LTC_TEST support to rmd160
+       -- updates to mycrypt_pk.h
+       -- updated rand_prime() to faciliate making RSA composites 
+       -- DSA/RSA now makes composites of the exact size desired.
+       -- Refactored quite a bit of the code, fewer functions per C file
+       -- cleaned up the makefiles to organize the objects logically
+       -- added ICC makefile along with "profiled" targets for both GNU and ICC compilers
+       -- Marked functions for removal before v1.00 see PLAN for more information
+       -- GCC 3.4.0 tested and seems to work
+       -- Added PKCS #5 support
+       -- Fixed typo in comment header of .C files  ;-)
+       -- Added PKCS #1 OAEP and PSS support.  
+       
+Feb 20th, 2004
+v0.94  -- removed unused variables from ocb.c and fixed it to match known test vectors.
+       -- Added PMAC support, minor changes to OMAC/EAX code [I think....]
+       -- Teamed up with Brian Gladman.  His code verifies against my vectors and my code
+          verifies against his test vectors.  Hazaa for co-operation!
+       -- Various small changes (added missing ARGCHKs and cleaned up indentation)
+       -- Optimization to base64, removed unused variable "c"
+       -- Added base64 gen to demos/tv_gen.c
+       -- Fix to demos/x86_prof.c to correctly identify the i386 architecture... weird...
+       -- Fixed up all of the PK code by adding missing error checking, removed "res" variables,
+          shrunk some stack variables, removed non-required stack variables and added proper
+          error conversion from MPI to LTC codes.  I also spotted a few "off by one" error
+          checking which could have been used to force the code to read past the end of
+          the buffer (in theory, haven't checked if it would work) by a few bytes.
+       -- Added checks to OUTPUT_BIGNUM so the *_export() functions cannot overflow the output and I 
+          also modded it so it stores in the output provided to the function (that is not on
+          the local stack) which saves memory and time.
+       -- Made SAFER default to disabled for now (plans are to cleanhouse write an implementation later)
+       -- Added the 512-bit one-way hash WHIRLPOOL which clocks in at 138 cycles per byte on my
+          Athlon XP [for comparison, SHA-512 clocks in at 77 cycles per byte].  This code uses the 
+          teams new sbox design (not the original NESSIE one).
+      
+
+Jan 25th, 2004
+v0.93  -- [note: deleted v0.93 changes by accident... recreating from memory...]
+       -- Fix to RC2 to not deference pointer before ARGCHK
+       -- Fix to NOEKEON to match published test vectors as well as cleaned up the code a bit
+       -- Optimized Twofish [down to 28 cycles/byte on my box] and Blowfish
+       -- Fix to OMAC to test cipher block size first [prevents wasting any time]
+       -- Added more OMAC test vectors
+       -- Added EAX Encrypt+Authenticate support
+       -- Fix to DSA to check return of a few LTM functions I forgot [mp_to_unsigned_bin]
+       -- Added common headers to all C files
+       -- CTR mode supports big and little [default] endian counters now.  
+       -- fix to find_cipher_any() so that it can handle a fragmented cipher_descriptor table.
+       -- added find_hash_any() akin to find_cipher_any().
+       -- Added EAX code to demos/tv_gen.c  Hazaa! 
+       -- Removed SONY defines and files from codebase.
+       -- Added OCB support [patents be damned] and to demos/tv_gen.c
+       -- Merge all of the INPUT/OUTPUT BIGNUM macros (less toc) into mycrypt_pk.h
+       -- Made appropriate changes to the debug string in crypt.c
+
+Dec 24th, 2003
+v0.92  -- Updated the config.pl script so the options have more details.
+       -- Updated demos/tv_gen to include RIPEMD hashes
+       -- Updated Twofish so when TWOFISH_ALL_TABLES is defined a pre-computed RS table
+          is included [speedup: slight, about 4k cycles on my Athlon].
+       -- Re-wrote the twofish large key generation [the four 8x32 key dependent tables].  Now about twice as fast.
+          With both optimizations [e.g. TWOFISH_ALL_TABLES defined] a 128-bit Twofish key can now be scheduled
+          in 26,000 cycles on my Athlon XP [as opposed to 49,000 before] when optimized for size.
+       -- config.pl has been updated so rmd128.o and rmd160.o are objects included in the build [oops]
+       -- Andrew Mann found a bug in rsa_exptmod() which wouldn't indicate if the wrong type of key was specified
+          (e.g. not PK_PRIVATE or PK_PUBLIC)
+       -- Fixed up demos/x86_prof so it sorts the output now :-)  
+       -- The project is now powered by radioactive rubber pants.
+       -- Fixed dh_encrypt_key() so if you pass it a hash with a smaller output than the input key it 
+          will return CRYPT_INVALID_HASH [to match what ecc_encrypt_key() will do]
+       -- Merge the store/encrypt key part of ecc_encrypt_key() as per dh_encrypt_key() [can you guess what I'm upto?]
+       -- Massive updates to the prime generation code.  I use the LTM random prime functions [and provide a nice 
+          interface between the LTC PRNG's and the LTM generic prng prototype].  I also use a variable number of tests
+          depending on the input size.  This nicely speeds up most prime generation/testing within the library.
+       -- Added SHA-224 to the list of hashes.
+       -- Made HMAC test vectors constant and static [takes ROM space instead of RAM]
+       -- This release was brought to you by the letter P which stands for Patent Infringement.
+       -- Added generic HASH_PROCESS macro to mycrypt_hash.h which simplifies the hash "process" functions
+          I also optimized the compression functions of all but MD2 to not perform input copies when avoidable.
+       -- Removed the division from the Blowfish setup function [dropped 3k cycles on my Athlon]
+       -- Added stack cleaning to rijndael, cast5 so now all ciphers have CLEAN_STACK code.  
+       -- Added Skipjack to the list of ciphers [made appropriate changes to demos/test.c, demos/tv_gen.c and 
+          demos/x86_prof.c]
+       -- Added mechanical testing to cipher test vector routines.  Now it encrypts 1000 times, then decrypts and
+          compares.  Any fault (e.g. bug in code, compiler) in the routines is likely to show through.  Doesn't
+          stress test the key gen though...
+       -- Matt Johnson found a bug in the blowfish.c  apparently I was out of my mind and put twofish defines in there 
+          The code now builds with any config.  Thanks.
+       -- Added OMAC1 Message Authentication Code support to the library.
+       -- Re-prototyped the hash "process" and "done" to prevent buffer overflows [which don't seem easy to exploit].  
+          Updated HMAC code to use them too.  Hazaa!
+       -- Fixed bug in ECC code which wouldn't do an _ARGCHK on stat in ecc_verify_hash().
+       -- Fixed [temp fix] bug in all PK where the OUTPUT_BIGNUM macros would not trap errors on the to_unsigned_bin 
+          conversion [now returns CRYPT_MEM, will fix it up better later]
+       -- Added DSA to the list of supported PK algorithms.  
+       -- Fixed up various ciphers to &255 the input key bytes where required [e.g. where used to index a table] to prevent
+          problems on platforms where CHAR_BIT != 8 
+       -- Merged in LibTomMath v0.28
+       -- Updated demos/x86_prof.c to use Yarrow during the key sched testing [was horribly slow on platforms with blockable
+          /dev/random]. 
+       -- Added OMAC/HMAC tests to demos/tv_gen and I now store the output of this in notes/ 
+       -- Fixed a bug in config.pl that wouldn't have TWOFISH_TABLES defined by default (too many commas on the line)
+       -- Fixed bug in hmac_done().  Apparently FIPS-198 [HMAC] specifies that the output can be truncated.  My code
+          would not support that (does now just like the new OMAC code).
+       -- Removed "hashsize" from hmac_state as it wasn't being used.
+       -- Made demos/test.c stop if OMAC or HMAC tests fail (instead of just printing a failed message and keep going).
+       -- Updated notes/tech0003.txt to take into account the existence of Skipjack [also I fixed a few typos].
+       -- Slight changes to Noekeon, with SMALL_CODE undefined it uses a fully unrolled version.  Dropped +10 cycles/byte
+          on my Athlon (35 cycles per byte or 410.4Mbit/sec at 1795Mhz)
+       -- Added _ARGCHK() calls to is_prime() for the two input pointers.
+
+Sept 25th, 2003
+v0.91  -- HMAC fix of 0.90 was incorrect for keys larger than the block size of the hash.
+       -- Added error CRYPT_FILE_NOTFOUND for the file [hmac/hash] routines.
+       -- Added RIPEMD hashes to the hashsum demo.
+       -- Added hashsum demo to MSVC makefile.
+       -- Added RMD160 to the x86_prof demo [oops]
+       -- Merged in LibTomMath-0.27 with a patch to mp_shrink() that will be in LibTomMath-0.28
+          Fixes another potential memory leak.
+
+Sept 7th, 2003
+v0.90  -- new ROL/ROR for x86 GCC
+       -- Jochen Katz submitted a patch to the makefile to prevent "make" from making the .a library
+          when not required.
+       == By default the KR code is not enabled [it's only a demo anyways!]
+       -- changed the "buf" in ecc_make_key from 4KB to 128 bytes [since the largest key is 65 bytes]
+       -- hmac_done() now requires you pass it the size of the destination buffer to prevent
+          buffer overflows.  (API CHANGE)
+       -- hmac/hash filebased routines now return CRYPT_NOP if NO_FILE is defined.
+       -- I've removed the primes from dh.c and replaced them with DR safe primes suitable for the default
+          configuration of LibTomMath.  Check out these comparisons on a 1.3Ghz Athlon XP, optimized for size,
+
+768-bit,     4 vs.  10
+1024-bit,    8 vs.  18
+1280-bit,   12 vs.  34
+1536-bit,   20 vs.  56
+1792-bit    28 vs.  88
+2048-bit,   40 vs. 124
+2560-bit,   71 vs. 234
+3072-bit,  113 vs. 386
+4096-bit,  283 vs. 916
+
+          Times are all in milliseconds for key generation.  New primes times on the left.  This makes the code binary
+          incompatible with previous releases.  However, this addition is long overdue as LibTomMath has supported DR
+          reductions for quite some time.
+       -- Added RIPE-MD 128 and 160 to the list of supported hashes [10 in total].
+       -- The project has been released as public domain.  TDCAL no longer applies.
+
+July 15th, 2003
+v0.89  -- Fix a bug in bits.c which would prevent it from building with msvc
+       -- Merged in LibTomMath v0.24 [and I used the alloc/free macros this time!]
+       -- Removed the LTC version of next_prime() and replaced it with a call to the
+          mp_prime_next_prime() from LibTomMath
+       -- reverted bits.c to the 0.86 copy since the new one doesn't build in MSVC
+          or cygwin.
+
+Jul 10th, 2003
+v0.88  -- Sped up CAST5 key schedule for MSVC
+       -- added "ulong32" which allows people on 64-bit platforms to force the 32-bit tables in
+          ciphers like blowfish and AES to be 32-bits.  E.g. when unsigned long is 64-bits.
+       -- Optimized the SAFER-SK64, SAFER-SK128, SAFER+, RC5 and RC6 key schedule [big time!]
+       -- Optimized SHA-1 and SHA-256 quite a bit too.
+       -- Fixed up the makefile to use -fomit-frame-pointer more liberally
+       -- Added tv_gen program which makes test vectors for ciphers/hashes
+       -- Merged in LibTomMath v0.22
+       
+Jun 19th, 2003
+v0.87  -- Many MSVC optimizations to the code base
+       -- Improved the AES and Twofish key schedule [faster, more constant time]
+       -- Tons of optimizations here and there.  
+       
+Jun 15th, 2003
+v0.86  -- Fixed up AES to workaround MSVC optimizer bug
+       -- Merged in fresh LTM base [based on v0.20] so there are no warnings with MSVC
+       -- Wrote x86_prof which will time the hashes and ciphers downto cycles per byte.
+       -- Fixed up demos/encrypt to remove serpent_desc from the list
+       -- Re-enabled MSVC optimizations w00t w00t
+       -- Replaced "errno" with "err" in all functions that had it so it wouldn't clash
+          with the global "errno"
+       -- Removed a set of unused variables from certain functions
+       -- Removed {#line 0 "..."} stuff from mpi.c to comply with ISO C  :-)
+       
+Jun 11th, 2003
+v0.85  -- Swapped in a new AES routine
+       -- Removed Serpent
+       -- Added TDCAL policy document
+       
+Jun 1st, 2003
+v0.84  -- Removed a 4KB buffer from rsa_decrypt_key that wasn't being used no more
+       -- Fixed another potential buffer problem.  Not an overflow but could cause the 
+          PK import routines to read past the end of the buffer.
+       -- Optimized the ECC mulmod more by removing a if condition that will always be false
+       -- Optimized prime.c to not include a 2nd prime table, removed code from is_prime calls prime
+          test from LibTomMath now
+       -- Added LTC_TEST define which when defined will enable the test vector routines [see mycrypt_custom.h]
+       -- Removed ampi.o from the depends cuz it ain't no not working in *nix with it [routines are in mpi.c now].
+        
+
+Mar 29th, 2003
+v0.83  -- Optimized the ecc_mulmod, it's faster and takes less heap/stack space
+       -- Fixed a free memory error in ecc_mulmod and del_point which would try to free NULL
+       -- Fixed two serious bugs in rsa_decrypt_key and rsa_verify_hash that would allow a trivialy
+          buffer overflow.
+       -- Fixed a bug in the hmac testing code if you don't register all the hashes it won't return
+          errors now.
+       
+Mar 15th, 2003
+v0.82  -- Manual updated
+       -- Added MSVC makefile [back, actually its written from scratch to work with NMAKE]
+       -- Change to HMAC helper functions API to avoid buffer overflow [source changes]
+       -- the rsa_encrypt_key was supposed to reject key sizes out of bounds ... 
+          same fix to the rsa_sign_hash 
+       -- Added code to ensure that that chaining mode code (cfb/ofb/ctr/cbc) have valid
+          structures when being called.  E.g. the indexes to the pad/ivs are not out of bounds
+       -- Cleaned up the DES code and simplified the core desfunc routine.
+       -- Simplified one of the boolean functions in MD4
+       
+Jan 16th, 2003
+v0.81  -- Merged in new makefile from Clay Culver and Mike Frysinger
+       -- Sped up the ECC mulmod() routine by making the word size adapt to the input.  Saves a whopping 9 point
+          operations on 521-bit keys now (translates to about 8ms on my Athlon XP).  I also now use barrett reduction
+          as much as possible.  This sped the routine up quite a bit.
+       -- Fixed a huge flaw in ecc_verify_hash() where it would return CRYPT_OK on error... Now fixed.
+       -- Fixed up config.pl by fixing an invalid query and the file is saved in non-windows [e.g. not CR/LF] format
+          (fix due to Mika Bostr�m)
+       -- Merged in LibTomMath for kicks
+       -- Changed the build process so that by default "mycrypt_custom.h" is included and provided
+          The makefile doesn't include any build options anymore
+       -- Removed the PS2 and VC makefiles.
+       
+Dec 16th, 2002
+v0.80  -- Found a change I made to the MPI that is questionable.  Not quite a bug but definately not desired.  Had todo
+          with the digit shifting.  In v0.79 I simply truncated without zeroing.  It didn't cause problems during my
+          testing but I fixed it up none the less.
+       -- Optimized s_mp_mul_dig() from MPI to do a minimal number of passes.
+       -- Fixed in rsa_exptmod() where I was getting the size of the result.  Basically it accomplishes the same thing
+          but the fixed code is more readable.
+       -- Fixed slight bug in dh_sign_hash() where the random "k" value was 1 byte shorter than it should have been.  I've
+          also made the #define FAST_PK speed up signatures as well.  Essentially FAST_PK tells the DH sub-system to 
+          limit any private exponent to 256-bits.   Note that when FAST_PK is defined does not make the library
+          binary or source incompatible with a copy of the library with it undefined.
+       -- Removed the DSA code.  If you want fast diffie-hellman just define FAST_PK :-)
+       -- Updated dh_sign_hash()/dh_verify_hash() to export "unsigned" bignums.  Saves two bytes but is not binary
+          compatible with the previous release... sorry!  I've performed the same fix to the ecc code as well.
+       -- Fixed up the PK code to remove all use of mp_toraw() and mp_read_raw() [get all the changes out of the way now]
+       -- Fixed a bug in the DH code where it missed trapping a few errors if they occurred.
+       -- Fixed a slight "its-not-a-bug-but-could-be-done-better" bug in the next_prime() function.  Essentially it was
+          testing to ensure that in the loop that searches for the next candidate that the step never grows beyond
+          65000.  Should have been testing for MP_DIGIT_MAX
+       -- Spruced up the config.pl script.  It now makes a header file "mycrypt_custom.h" which can be included *before*
+          you include mycrypt.h.  This allows you to add libtomcrypt to a project without completely changing your make
+          system around.  Note that you should use the makefile it writes to at least build the library initially.
+       -- Used splint to check alot of the code out.  Tons of minor fixes and explicit casts added.
+       -- Also made all the internal functions of MPI are now static to avoid poluting the namespace
+       -- **Notice**:  There are no planned future releases for at least a month from the this release date.
+       
+Dec 14th, 2002
+v0.79  -- Change to PK code [binary and source].  I made it so you have to pass the buffer size to the *_decrypt_key and
+          *_verify_hash functions.  This prevents malformed packets from performing buffer overflows.  I've also trimmed
+          the packet header size [by 4 bytes].
+       -- Made the test program halt on the first error it occurs.  Also made it trap more errors than before.
+       -- Wrote the first chapter of my new book [DRAFT!], not in this package but check my website!
+       -- Included a perl script "config.pl" that will make "makefile.out" according to the users needs.  
+       -- Added shell script to look for latest release
+       -- Merge DH and ECC key defines from mycrypt_cfg.h into the makefiles
+       -- updated the makefile to use BSD friendly archiving invokations
+       -- Changed the DH and ECC code to use base64 static key settings [e.g. the primes].  Dropped the code size by 3KB
+          and is ever-so-slightly faster than before.
+       -- added "mp_shrink" function to shrink the size of bignums.  Specially useful for PK code :-)
+       -- Added new exptmod function that calculates a^b mod c with fewer multiplies then before [~20% for crypto
+          sized numbers].  Also added a "low mem" variant that doesn't use more than 20KB [upto 4096 bit nums] of
+          heap todo the calculation.  Both are #define'able controlled
+       -- Added XREALLOC macro to provide realloc() functionality.
+       -- Added fix where in rsa_import() if you imported a public key or a non-optimized key it would free the mp_int's
+          not being used.
+       -- Fixed potential bug in the ECC code.  Only would occur on platforms where char is not eight bits [which isn't
+          often!]
+       -- Fixed up the ECC point multiplication, its about 15% faster now
+       -- While I was at it [since the lib isn't binary backwards compatible anyways] I've fixed the PK export routines
+          so they export as "unsigned" types saving 1 byte per bignum outputted.  Not a lot but heck why not.
+          
+Nov 28th, 2002
+v0.78  -- Made the default ARGCHK macro a function call instead which reduced the code size from 264KB to 239KB.
+       -- Fixed a bug in the XTEA keysize function which called ARGCHK incorrectly.
+       -- Added Noekeon block cipher at 2,800 bytes of object code and 345Mbit/sec it is a welcome addition.
+       -- Made the KR code check if the other PK systems are included [provides error when building otherwise].
+       -- Made "aes" an alias for Rijndael via a pre-processor macro.  Now you can use "aes_ecb_encrypt", etc... :-)
+          Thanks to Jean-Luc Cooke for the "buzzword conformance" suggestion.
+       -- Removed the old PK code entirely (e.g. rsa_sign, dh_encrypt).  The *_sign_hash and *_encrypt_key functions
+          are all that is to remain.
+       -- **NOTE** Changed the PK *_import (including the keyring) routine to accept a "inlen" parameter.  This fixes a
+          bug where improperly made key packets could result in reading passed the end of the buffer.  This means
+          the code is no longer source compatible but still binary compatible.
+       -- Fixed a few other minor bugs in the PK import code while I was at it.
+       
+Nov 26th, 2002
+v0.77  -- Updated the XTEA code to use pre-computed keys.  With optimizations for speed it achieves 222Mbit/sec
+          compared to the 121Mbit/sec before.  It is 288 bytes bigger than before.
+       -- Cleaned up some of the ciphers and hashes (coding style, cosmetic changes)
+       -- Optimized AES slightly for 256-bit keys [only one if statement now, still two for 192-bit keys]
+       -- Removed most test cases from Blowfish, left three of them there.  Makes it smaller and faster to test.
+       -- Changed the primality routines around.  I now use 8 rounds of Rabin-Miller, I use 256 primes in the sieve
+          step and the "rand_prime" function uses a modified sieve that avoids alot of un-needed bignum work.
+       -- Fixed a bug in the ECC/DH signatures where the keys "setting" value was not checked for validity.  This means
+          that a invalid value could have caused segfaults, etc...
+       -- **NOTE** Changed the way the ECC/DH export/import functions work.  They are source but not binary compatible
+          with v0.76.  Essentially insteading of exporting the setting index like before I export the key size.  Now
+          if you ever re-configure which key settings are supported the lib will still be able to make use of your 
+          keys.
+       -- Optimized Blowfish by inlining the round function, unrolling it for four rounds then using a for loop for the 
+          rest.  It achieves a rate of 425Mbit/sec with the new code compared to 314Mbit/sec before.  The new blowfish 
+          object file is 7,813 bytes compared to 8,663 before and is 850 bytes smaller.  So the code is both smaller and 
+          faster!
+       -- Optimized Twofish as well by inlining the round function.  Gets ~400Mbit/sec compared to 280Mbit/sec before
+          and the code is only 78 bytes larger than the previous copy.
+       -- Removed SMALL_PRIME_TAB build option.  I use the smaller table always.
+       -- Fixed some mistakes concerning prime generation in the manual.
+       -- [Note: sizes/speeds are for GCC 3.2 on an x86 Athlon XP @ 1.53Ghz]
+
+Nov 25th, 2002
+v0.76  -- Updated makefiles a bit more, use "-Os" instead of "-O2" to optimize for size.  Got the lib
+          downto 265KB using GCC 3.2 on my x86 box.
+       -- Updated the SAFER+, Twofish and Rijndael test vector routine to use the table driven design.
+       -- Updated all other test vector routines to return as soon as an error is found
+       -- fixed a bug in the test program where errors in the hash test routines would not be reported
+          correctly.  I found this by temporarily changing one of the bytes of the test vectors.  All the
+          hashes check out [the demos/test.c would still have reported an error, just the wrong one].
+          
+
+Nov 24th, 2002
+v0.75  -- Fixed a flaw in hash_filehandle, it should ARGCHK that the filehandle is not NULL
+       -- Fixed a bug where in hash_file if the call to hash_filehandle failed the open file would 
+          not be closed.
+       -- Added more strict rules to build process, starting to weed out "oh this works in GCC" style code
+          In the next release "-Wconversion" will be enabled which will deal with all implicit casts.
+
+Nov 22nd, 2002 [later in the day]
+v0.74  -- Wrote a small variant of SAFER+ which shaved 50KB off the size of the library on x86 platforms
+       -- Wrote a build option to remove the PK packet functions [keeps the encrypt_key/sign_hash functions]
+       -- Wrote a small variant of Rijndael (trimmed 13KB)
+       -- Trimmed the TIGER/192 hash function a bit
+       -- Overall the entire lib compiled is 295KB [down from 400KB before]
+       -- Fixed a few minor oversights in the MSVC makefile
+
+Nov 22nd, 2002
+v0.73  -- Fixed bug in RC4 code where it could only use 255 byte keys.
+       -- Fixed bug in yarrow code where it would allow cast5 or md2 to be used with it...
+       -- Removed the ecc compress/expand points from the global scope.  Reduces namespace polution
+       -- Fixed bug where if you used the SPRNG you couldn't pass NULL as your prng_state which you should be
+          able todo since the SPRNG has no state...
+       -- Corrected some oversights in the manual and the examples...
+       -- By default the GF(2^W) math library is excluded from the build.  The source is maintained because I wrote it
+          and like it :-).  This way the built library is a tad smaller
+       -- the MSVC makefile will now build for a SPACE optimized library rather than TIME optimized.
+
+Nov 21th, 2002
+v0.72  -- Fixed bug in the prime testing.  In the Miller-Rabin test I was raising the base to "N-1" not "r".
+          The math still worked out fine because in effect it was performing a Fermat test.  Tested the new code and it 
+          works properly
+       -- Fixed some of the code where it was still using the old error syntax
+       -- Sped up the RSA decrypt/sign routines
+       -- Optimized the ecc_shared_secret routine to not use so much stack
+       -- Fixed up the makefile to make releases where the version # is in the file name and directory it will unzip
+          to
+
+Nov 19th, 2002
+v0.71  -- HELP TOM.  I need tuition for the January semester.  Now I don't want to force donations [nor will I ever]
+          but I really need the help!  See my website http://tom.iahu.ca/help_tom.html for more details.  Please help
+          if you can! 
+       --------------------------------------------------------------------------------------------------------------
+       -- Officially the library is no longer supported in GCC 3.2 in windows [cygwin].
+          In windows you can either use GCC 2.95.3 or try your luck with 3.2  It seems that
+          "-fomit-frame-pointer" is broken in the windows build [but not the linux x86 build???]
+          If you simply must use 3.2 then I suggest you limit the optimizations to simply "-O2"
+       -- Started new error handling API.  Similar to the previous except there are more error codes than just
+          CRYPT_ERROR
+       -- Added my implementation of the MD2 hash function [despite the errors in the RFC I managed to get it right!]
+       -- Merged in more changes from Sky Schulz.  I have to make mention here that he has been a tremendous help in 
+          getting me motivated to make some much needed updates to the library!
+       -- Fixed one of the many mistakes in the manual as pointed out by Daniel Richards
+       -- Fixed a bug in the RC4 code [wasn't setting up the key correctly]
+       -- Added my implementation of the CAST5 [aka CAST-128] block cipher (conforms...)
+       -- Fixed numerous bugs in the PK code.  Essentially I was "freeing" keys when the import failed.  This is neither
+          required nor a good a idea [double free].  
+       -- Tom needs a job.
+       -- Fixed up the test harness as requested by Sky Schulz.  Also modifed the timing routines to run for X seconds
+          and count # of ops performed.  This is more suitable than say encrypting 10 million blocks on a slow processor
+          where it could take minutes!
+       -- Modified test programs hashsum/encrypt to use the new algorithms and error handling syntax
+       -- Removed the PKCS code since it was incomplete.  In the future I plan on writing a "add-on" library that
+          provides PKCS support... 
+       -- updated the config system so the #defines are in the makefiles instead of mycrypt_cfg.h  
+       -- Willing to work on an hourly basis for 15$ CDN per hour.
+       -- updated the test program to not test ciphers not included
+       -- updated the makefile to make "rsa_sys.c" a dependency of rsa.o [helps develop the code...]
+       -- fixed numerous failures to detect buffer overflows [minor] in the PK code.
+       -- fixed the safer [64-bit block version] test routines which didn't check the returns of the setup
+          function
+       -- check out my CV at http://tom.iahu.ca/cv.html
+       -- removed the GBA makefile and code from demos/test.c [not a particularly useful demo...]
+       -- merged in rudimentary [for testing] PS2 RNG from Sky Schulz
+       -- merged in PS2 timer code [only shell included due to NDA reasons...]
+       -- updated HMAC code to return errors where possible
+       -- Thanks go to Sky Schulz who bought me a RegCode for TextPad [the official editor of libtomcrypt]
+
+Nov 12th, 2002
+v0.70  -- Updated so you can swap out the default malloc/calloc/free routines at build time with others. (Sky Schulz)
+       -- Sky Schulz contributed some code towards autodetecting the PS2 in mycrypt_cfg.h
+       -- Added PS2 makefile contributed by Sky Schulz [see a pattern forming?]
+       -- Added ability to have no FILE I/O functions at all (see makefile), Sky Schulz....
+       -- Added support for substituting out the clock() function (Sky Schulz)
+       -- Fixed up makefile to include new headers in the HEADERS variable
+       -- Removed "coin.c" as its not really useful anyways
+       -- Removed many "debug" printfs that would show up on failures.  Basically I wanted to ensure the only output
+          would be from the developer themselves.
+       -- Added "rc4.c" a RC4 implementation with a PRNG interface.  Since RC4 isn't a block cipher it wouldn't work
+          too well as a block cipher.
+       -- Fixed ARGCHK macro usage when ARGTYPE=1 throughout the code
+       -- updated makefile to make subdirectory properly (Sku Schulz)
+       -- Started towards new API setup.  Instead of checking for "== CRYPT_ERROR" you should check "!= CRYPT_OK"
+          In future releases functions will return things other than CRYPT_ERROR on error to give more useful
+          thread safe error reporting.  The manual will be updated to reflect this.  For this release all
+          errors are returned as CRYPT_ERROR (except as noted) but in future releases this will change.         
+       -- Removed the zlib branch since its not really required anyways.  Makes the package smaller
+
+Nov 11th, 2002
+v0.69  -- Added ARGCHK (see mycrypt_argchk.h) "arguement checking" to all functions that accept pointers
+       -- Note I forgot to change the CRYPT version tag in v0.68... fixed now.
+
+Nov 8th, 2002
+v0.68  -- Fixed flaw in kr_import/kr_export that wasted 4 bytes.  Source but not binary compatible with v0.67
+       -- Fixed bug in kr_find_name that used memcmp to match strings.  Uses strncmp now.
+       -- kr_clear now sets the pointer to NULL to facilate debugging [e.g. using the keyring after clearing]
+       -- static functions in _write/_read in keyring.c now check the return of ctr_encrypt/ctr_decrypt.
+       -- Updated blowfish/rc2/rc5/rc6 keysize() function to not reject keys larger than the biggest key the
+          respective ciphers can use.  
+       -- Fixed a bug in hashsum demo that would report the hash for files that don't exist!
+
+Oct 16th, 2002
+v0.67  -- Moved the function prototypes into files mycrypt_*.h.  To "install" the lib just copy all the 
+          header files "*.h" from the base of this project into your global include path.
+       -- Made the OFB/CFB/CTR functions use "unsigned long" for the length instead of "int"
+       -- Added keyring support for the PK functions
+       -- ***API CHANGE*** changed the ecc_make_key and dh_make_key to act more like rsa_make_key.  Basically
+          move the first argument to the next to last.
+       -- Fixed bug in dh_test() that wouldn't test the primality of the order of the sub-group
+       -- replaced the primes in the DH code with new ones that are larger than the size they are 
+          associated with.  That is a 1024-bit DH key will have a 1025-bit prime as the modulus
+       -- cleaned up all the PK code, changed a bit of the API around [not source compatible with v0.66]
+       -- major editing of the manual, started Docer program
+       -- added 160 and 224 bit key settings for ECC.  This makes the DH and ECC binary wise incompatible with v0.66
+       -- Added an additional check for memory errors in is_prime() and cleaned up prime.c a bit
+       -- Removed ID_TAG from all files [meh, not a big fan...]
+       -- Removed unused variable from yarrow state and made AES/SHA256 the default cipher/hash combo
+       -- Fixed a bug in the Yarrow code that called prng_is_valid instead of cipher_is_valid from yarrow_start()
+       -- The ECB/CBC/OFB/CFB/CTR wrappers now check that the cipher is valid in the encrypt/decrypt calls
+          Returns int now instead of void.
+
+Sept 24th, 2002
+v0.66  -- Updated the /demos/test.c program to time the hashes correctly.  Also it uses the yarrow PRNG for all of the 
+          tests meaning its possible to run on RNG less platforms 
+       -- Updated the /demos/hashsum.c program to hash from the standard input
+       -- Updated the RSA code to make keys a bit quicker [update by Wayne Scott] by not making both primes at the same
+          time.
+       -- Dan Kaminsky suggested some cleanups for the code and the MPI config
+          Code ships in unix LF format by default now too... will still build in MSVC and all... but if you want
+          to read the stuff you'll have to convert it 
+       -- Changes to the manual to reflect new API [e.g. hash_memory/file have v0.65 prototypes]and some typos fixed
+
+Sept 20th, 2002
+v0.65  -- Wayne Scott ([email protected]) made a few of suggestions to improve the library.  Most 
+          importantly he pointed out the math lib is not really required.  He's also tested the lib on 18 
+          different platforms.  According to him with only a few troubles [lack of /dev/random, etc] the 
+          library worked as it was supposed to.  You can find the list at 
+          http://www.bitkeeper.com/Products.BitKeeper.Platforms.html
+       -- Updated the hash_file and hash_memory functions to keep track of the size of the output
+       -- Wayne Scott updated the demos/test.c file to use the SPRNG less and Yarrow more
+       -- Modified the mycrypt_cfg.h to autodetect x86-32 machines
+
+Sept 19th, 2002
+v0.64  -- wrote makefile for the GBA device [and hacked the demos/test.c file to support it conditionally]
+       -- Fixed error in PK (e.g. ECC, RSA, DH) import functions where I was clobbering the packet error messages
+       -- fixed more typos in the manual
+       -- removed all unused variables from the core library (ignore the ID_TAG stuff)
+       -- added "const char *crypt_build_settings" string which is a build time constant that gives a listing
+          of all the build time options.  Useful for debugging since you can send that to me and I will know what 
+          exactly you had set for the mycrypt_cfg.h file.
+       -- Added control over endianess.  Out of the box it defaults to endianess neutral but you can trivially 
+          configure the library for your platform.  Using this I boosted RC5 from 660Mbit/sec to 785Mbit/sec on my 
+          Athlon box.  See "mycrypt_cfg.h" for more information.
+
+Sept 11th, 2002
+v0.63  -- Made hashsum demo output like the original md5sum program 
+       -- Made additions to the examples in the manual (fixed them up a bunch)
+       -- Merged in the base64 code from Wayne Scott ([email protected])
+
+Aug 29th, 2002
+v0.62  -- Added the CLEAN_STACK functionality to several of the hashes I forgot to update.
+
+Aug 9th, 2002
+v0.61  -- Fixed a bug in the DES code [oops I read something wrong].
+
+Aug 8th, 2002
+v0.60  -- Merged in DES code [and wrote 3DES-EDE code based on it] from Dobes V.
+
+Aug 7th, 2002
+v0.59  -- Fixed a "unsigned long long" bug that caused v0.58 not to build in MSVC.
+       -- Cleaned up a little in the makefile
+       -- added code that times the hash functions too in the test program
+
+Aug 3rd, 2002
+v0.58  -- Added more stack cleaning conditionals throughout the code.  
+       -- corrected some CLEAR_STACK conditionals... should have been CLEAN_STACK
+       -- Simplified the RSA, DH and ECC encrypt() routines where they use CTR to encode the message
+          now they only make one call to ctr_encrypt()/ctr_decrypt().
+
+Aug 2nd, 2002
+v0.57  -- Fixed a few errors messages in the SAFER code to actually report the correct cipher name.
+       -- rsa_encrypt() uses the "keysize()" method of the cipher being used to more accurately pick a
+          key size.  By default rsa_encrypt() will choose to use a 256-bit key but the cipher can turn that 
+          down if required.
+       -- The rsa_exptmod() function will now more reliably detect invalid inputs (e.g. greater than the modulus).
+       -- The padding method for RSA is more clearly documented.  Namely if you want to encrypt/sign something of length
+          N then your modulus must be of length 1+3N.  So to sign a message with say SHA-384 [48 bytes] you need a 
+          145 byte (1160 bits) modulus.  This is all in the manual now.
+       -- Added build option CLEAN_STACK which will allow you to choose whether you want to clean the stack or not after every
+          cipher/hash call
+       -- Sped up the hash "process()" functions by not copying one byte at a time.
+       ++ (added just after I uploaded...)
+          MD4 process() now handles input buffers > 64 bytes
+
+Aug 1st, 2002
+v0.56  -- Cleaned up the comments in the Blowfish code.
+       -- Oh yeah, in v0.55 I made all of the descriptor elements constant.  I just forgot to mention it.
+       -- fixed a couple of places where descriptor indexes were tested wrong.  Not a huge bug but now its harder
+          to mess up.
+       -- Added the SAFER [64-bit block] ciphers K64, SK64, K128 and SK128 to the library.
+       -- Added the RC2 block cipher to the library.
+       -- Changed the SAFER define for the SAFER+ cipher to SAFERP so that the new SAFER [64-bit] ciphers
+          can use them with less confusion.
+
+July 29th, 2002
+v0.55  -- My god stupid Blowfish has yet again been fixed.  I swear I hate that cipher.  Next bug in it and boom its out of the
+          library.  Use AES or something else cuz I really hate Blowfish at this stage....
+       -- Partial PKCS support [hint DONT USE IT YET CUZ ITS UNTESTED!]
+
+July 19th, 2002
+v0.54  -- Blowfish now conforms to known test vectors.  Silly bad coding tom!
+       -- RC5/RC6/Serpent all have more test vectors now [and they seemed to have been working before]
+
+July 18th, 2002
+v0.53  -- Added more test vectors to the blowfish code just for kicks [and they are const now too :-)]
+       -- added prng/hash/cipher is_valid functions and used them in all of the PK code so you can't enter the code
+          with an invalid index ever now.
+       -- Simplified the Yarrow code once again :-)
+
+July 12th, 2002
+v0.52  -- Fixed a bug in MD4 where the hash descriptor ID was the same as SHA-512.  Now MD4 will work with
+          all the routines...
+       -- Fixed the comments in SHA-512 to be a bit more meaningful
+       -- In md4 I made the PADDING array const [again to store it in ROM]
+       -- in hash_file I switched the constant "512" to "sizeof(buf)" to be a bit safer
+       -- in SHA-1's test routine I fixed the string literal to say SHA-1 not sha1
+       -- Fixed a logical error in the CTR code which would make it skip the first IV value.  This means
+          the CTR code from v0.52 will be incompatible [binary wise] with previous releases but it makes more
+          sense this way.
+       -- Added {} braces for as many if/for/blocks of code I could find.  My rule is that every for/if/while/do block
+          must have {} braces around it.
+       -- made the rounds table in saferp_setup const [again for the ROM think about the ROM!]
+       -- fixed RC5 since it no longer requires rc5 to be registered in the lib.  It used to since the descriptors used to 
+          be part of the table...
+       -- the packet.c code now makes crypt_error literal string errors when an error occurs
+       -- cleaned up the SAFER+ key schedule to be a bit easier to read.
+       -- fixed a huge bug in Twofish with the TWOFISH_SMALL define.  Because I clean the stack now I had
+          changed the "g_func()" to be called indirectly.  I forgot to actually return the return of the Twofish
+          g_func() function which caused it not to work... [does now :-)]
+
+July 11th, 2002
+v0.51  -- Fixed a bug in SHA512/384 code for multi-block messages.
+       -- Added more test vectors to the SHA384/512 and TIGER hash functions
+       -- cleaned up the hash done routines to make more sense
+ 
+July 10th, 2002
+v0.50  -- Fixed yarrow.c so that the cipher/hash used would be registered.  Also fixed
+          a bug where the SAFER+ name was "safer" but should have been "safer+".
+       -- Added an element to the hash descriptors that gives the size of a block [sent into the compressor]
+       -- Cleaned up the support for HMAC's
+       -- Cleaned up the test vector routines to make the test vector data const.  This means on some platforms it will be
+          placed in ROM not RAM now.
+       -- Added MD4 code submited by Dobes Vandermeer ([email protected])
+       -- Added "burn_stack" function [idea taken from another source of crypto code].  The idea is if a function has
+          alot of variables it will clean up better.  Functions like the ecb serpent and twofish code will now have their
+          stacks cleaned and the rest of the code is getting much more straightforward.
+       -- Added a hashing demo by Daniel Richards ([email protected])
+       -- I (Tom) modified some of the test vector routines to use more vectors ala Dobes style.
+          For example, the MD5/SHA1 code now uses all of the test vectors from the RFC/FIPS spec.
+       -- Fixed the register/unregister functions to properly report errors in crypt_error
+       -- Correctly updated yarrow code to remove a few unused variables.
+       -- Updated manual to fix a few erroneous examples.
+       -- Added section on Hash based Message Authentication Codes (HMAC) to the manual
+
+June 19th, 2002
+v0.46  -- Added in HMAC code from Dobes Vandermeer ([email protected])
+
+June 8th, 2002
+v0.45  -- Fixed bug in rc5.c where if you called rc5_setup() before registering RC5 it would cause
+          undefined behaviour.
+       -- Fixed mycrypt_cfg.h to eliminate the 224 bit ECC key.
+       -- made the "default" makefile target have depends on mycrypt.h and mycrypt_cfg.h
+
+Apr 4th, 2002
+v0.44  -- Fixed bug in ecc.c::new_point() where if the initial malloc fails it would not catch it.
+
+Mar 22nd, 2002
+v0.43  -- Changed the ZLIB code over to the 1.1.4 code base to avoid the "double free" bug.  
+       -- Updated the GCC makefile not to use -O3 or -funroll-loops
+       -- Version tag in mycrypt.h has been updated :-)
+
+Mar 10th, 2002
+v0.42  -- The RNG code can now use /dev/urandom before trying /dev/random (J. Klapste)
+
+Mar 3rd, 2002
+v0.41  -- Added support to link and use ciphers at compile time.  This can greatly reduce the code size!
+       -- Added a demo to show off how small an application can get... 46kb!
+       -- Disastry pointed out that Blowfish is supposed to be high endian.
+       -- Made registry code for the PRNGs as well [now the smallest useable link is 43kb]
+
+Feb 11th, 2002
+v0.40  -- RSA signatures use [and check for] fixed padding scheme.
+       -- I'm developing in Linux now :-)
+       -- No more warnings from GCC 2.96
+
+Feb 5th, 2002
+v0.39  -- Updated the XTEA code to work in accordance with the XTEA design
+
+January 24th, 2002
+v0.38  -- CFB and OFB modes can now handle blocks of variable size like the CTR code
+       -- Wrote a wrapper around the memory compress functions in Zlib that act like the functions
+          in the rest of my crypto lib
+
+January 23rd, 2002
+v0.37  -- Added support code so that if a hash size and key size for a cipher don't match up they will
+          use the next lower key supported.  (mainly for the PK code).  So you can now use SHA-1 with
+          Twofish, etc...
+       -- Added more options for Twofish.  You can now tell it to use precomputed sboxes and MDS multiplications
+          This will speed up the TWOFISH_SMALL implementation by increasing the code size by 1024 bytes.
+       -- Fixed a bug in prime.c that would not use the correct table if you undefined SMALL_PRIME_TAB
+       -- Fixed all of the PK packet code to use the same header format [see packet.c].  This makes the PK code
+          binary wise incompatible with previous releases while the API has not changed at all.
+
+January 22nd, 2002
+v0.36  -- Corrections to the manual
+       -- Made a modification to Twofish which lets you build a "small ram" variant.  It requires
+          about 190 bytes of ram for the key storage compared to the 4,200 bytes the normal 
+          variant requires.
+       -- Reduced the stack space used in all of the PK routines.
+
+January 19th, 2002
+v0.35  -- If you removed the first hash or cipher from the library it wouldn't return an error if 
+          you used an ID=0 [i.e blowfish or sha256] in any routine.  Now it checks for that and will
+          return an error like it should
+       -- Merged in new routines from Clay Culver.  These routines are for the PK code so you can easily 
+          encode a symmetric key for multiple recipients.
+       -- Made the ecc and DH make_key() routines make secret keys of the same size as the keysize listed.
+          Originally I wanted to ensure that the keys were smaller than the order of the field used
+          However, the bias is so insignifcant using full sizes.  For example, with a ECC-192 key the order
+          is about 2^191.99, so instead I rounded down and used a 184-bit secret key.  Now I simply use a full 192-bit
+          key the code will work just the same except that some 192-bit keys will be duplicates which is not a big
+          deal since 1/2^192 is a very small bias!
+       -- Made the configuration a bit simpler and more exacting.  You can for example now select which DH or ECC
+          key settings you wish to support without including the data for all other key settings.  I put the #defines
+          in a new file called "mycrypt_cfg.h"
+       -- Configured "mpi-config.h" so its a bit more conservative with the memory required and code space used
+       -- Jason Klapste submitted bug fixes to the yarrow, hash and various other issues.  The yarrow code will now
+          use what ever remaining hash/cipher combo is left [after you #undef them] at build time.   He also suggested
+          a fix to remove unused structures from the symmetric_key and hash_state unions.
+       -- Made the CTR code handle variable length blocks better. It will buffer the encryption pad so you can
+          encrypt messages any size block at a time.
+       -- Simplified the yarrow code to take advantage of the new CTR code.
+       -- Added a 4096-bit DH key setting.  That took me about 36 hours to find!
+       -- Changed the base64 routines to use a real base64 encoding scheme.
+       -- Added in DH and ECC "encrypt_key()" functions.  They are still rather "beta"ish.
+       -- Added **Twofish** to the list of ciphers!
+
+January 18th, 2002
+v0.34  -- Added "sha512" to the list of hashes.  Produces a 512-bit message digest.  Note that with the current
+          padding with the rsa_sign() function you cannot use sha512 with a key less than 1536 bits for signatures.
+       -- Cleaned up the other hash functions to use the LOAD and STORE macros...
+
+January 17th, 2002
+v0.33  -- Made the lower limit on keysizes for RSA 1024 bits again because I realized that 768 bit keys wouldn't
+          work with the padding scheme and large symmetric keys.
+       -- Added information concerning the Zlib license to the manual
+       -- Added a 3072-bit key setting for the DH code.
+       -- Made the "find_xyz()" routines take "const char *" as per Clay Culver's suggestion.
+       -- Fixed an embarassing typo in the manual concerning the hashes.  Thank's Clay for finding it!
+       -- Fixed rand_prime() so that it makes primes bigger than the setting you give.  For example,
+          if you want a 1024-bit prime it would make a 1023-bit one.  Now it ensures that the prime
+          it makes is always greater than 2^(8n) (n == bytes in prime).  This doesn't have a huge
+          impact on security but I corrected it just the same.
+       -- Fixed the CTR routine to work on platforms where char != 8-bits 
+       -- Fixed sha1/sha256/md5/blowfish to not assume "unsigned long == 32-bits", Basically any operation with carries
+          I "AND" with 0xFFFFFFFF.  That forces only the lower 32-bits to have information in it.  On x86 platforms
+          most compilers optimize out the AND operation since its a nop.
+
+January 16th, 2002
+v0.32  -- Made Rijndael's setup function fully static so it is thread safe
+       -- Svante Seleborg suggested a cosmetic style fixup for aes.c, 
+          basically to remove some of the #defines to clean it up
+       -- Made the PK routines not export the ASCII version of the names of ciphers/hashes which makes
+          the PK message formats *incompatible* with previous releases.
+       -- Merge in Zlib :-)
+ 
+  
+January 15th, 2002
+v0.31  -- The RSA routines can now use CRT to speed up decryption/signatures.  The routines are backwards 
+          compatible with previous releases.
+       -- Fixed another bug that Svante Seleborg found.  Basically you could buffer-overrun the 
+          rsa_exptmod() function itself if you're not careful.  That's fixed now.  Fixed another bug in
+          rsa_exptmod() where if it knows the buffer you passed is too small it wouldn't free all used 
+          memory.       
+       -- improved the readability of the PK import/export functions
+       -- Added a fix to RSA.C by Clay Culver
+       -- Changed the CONST64 macro for MSVC to use the "unsigned __int64" type, e.g. "ui64" instead of "i64".
+
+January 14th, 2002
+v0.30  -- Major change to the Yarrow PRNG code, fixed a bug that Eugene Starokoltsev found.
+          Basically if you added entropy to the pool in small increments it could in fact
+          cancel out.  Now I hash the pool with the new data which is way smarter.
+
+January 12th, 2002
+v0.29  -- Added MPI code written by Svante Seleborg to the library.  This will make the PK code much
+          easier to follow and debug.  Actually I've already fixed a memory leak in dh_shared_secret().
+       -- Memory leaks found and correct in all three PK routines.  The leaks would occur when a bignum
+          operation fails so it wouldn't normally turn up in the course of a program
+       -- Fixed bugs in dh_key_size and ecc_key_size which would return garbage for invalid key idx'es
+
+January 11th, 2002
+v0.28  -- Cleaned up some code so that it doesn't assume "char == 8bits".  Mainly SAFER+ has been 
+          changed.
+       -- ***HUGE*** changes in the PK code.  I check all return values in the bignum code so if there
+          are errors [insufficient memory, etc..] it will be reported.  This makes the code fairly more
+          robust and likely to catch any errors.
+       -- Updated the is_prime() function to use a new prototype [it can return errors now] and it also
+          does trial divisions against more primes before the Rabin Miller steps
+       -- Added OFB, CFB and ECB generic wrappers for the symmetric ciphers to round out the implementations.
+       -- Added Xtea to the list of ciphers, to the best of my ability I have verified this implementation.
+          I should note that there is not alot of concrete information about the cipher.  "Ansi C" versions
+          I found did not address endianess and were not even portable!.  This code is portable and to the
+          best of my knowledge implements the Xtea algorithm as per the [short] X-Tea paper.
+       -- Reformated the manual to include the **FULL** source code optimized to be pritable.
+
+January 9th, 2002
+v0.27  -- Changed the char constants to numerical values.  It is backwards compatible and should work on
+          platforms where 'd' != 100 [for example].
+       -- Made a change to rand_prime() which takes the input length as a signed type so you can pass
+          a negative len to get a "3 mod 4" style prime... oops
+       -- changed the MSVC makefile to build with a warning level of three, no warnings!
+
+January 8th, 2002
+v0.26  -- updated SHA-256 to use ROR() for a rotate so 64-bit machines won't corrupt
+          the output
+       -- Changed #include <> to #include "" for local .h files as per Richard Heathfields' suggestions.
+       -- Fixed bug in MPI [well bug in MSVC] that compiled code incorrectly in mp_set_int()
+          I added a work around that catches the error and continues normally.
+
+January 8th, 2002
+v0.25  -- Added a stupid define so MSVC 6.00 can build the library.
+       -- Big thanks to sci.crypt and "Ajay K. Agrawal" for helping me port this to MSVC
+
+January 7th, 2002
+v0.24  -- Sped up Blowfish by unrolling and removing the swaps.
+       -- Made the code comply with more traditional ANSI C standards
+          Should compile with MSVC with less errors
+       -- moved the demos and documentation into their own directories
+          so you can easily build the library with other tool chains
+          by compiling the files in the root
+       -- converted functions with length of outputs to use 
+          "unsigned long" so 16-bit platforms will like this library more.
+
+January 5th, 2002
+v0.23  -- Fixed a small error in the MPI config it should build fine anywhere.
+
+January 4th, 2002
+v0.22  -- faster gf_mul() code
+       -- gf_shl() and gf_shr() are safe on 64-bit platforms now
+       -- Fixed an error in the hashes that Brian Gladman found.  
+          Basically if the message has exactly 56 bytes left to be 
+          compressed I handled them incorrectly.
+
+January 4th, 2002
+v0.21  -- sped up the ECC code by removing redundant divisions in the 
+          point add and double routines.  I also extract the bits more
+          efficiently in "ecc_mulmod()" now.
+       -- sped up [and documented] the rand_prime() function.  Now it just
+          makes a random integer and increments by two until a prime is found
+          This is faster since it doesn't require alot of calls to the PRNG and
+          it doesn't require loading huge integers over and over.  rand_prime()
+          can also make primes congruent to 3 mod 4 [i.e for a blum integer]
+       -- added a gf_sqrt() function that finds square roots in a GF(2^w) field
+       -- fixed a bug in gf_div() that would return the wrong results if the divisor had a greator
+          divisor than the dividend.
+
+January 4th, 2002
+v0.20  -- Added the fixed MPI back in so RSA and DH are much faster again
+
+v0.19  -- Updated the manual to reflect the fact that Brian Gladman wrote the AES and Serpent code.
+       -- DH, ECC and RSA signature/decryption functions check if the key is private
+       -- new DH signature/verification code works just like the RSA/ECC versions
+
+January 3rd, 2002
+v0.18  -- Added way more comments to each .C file 
+       -- fixed a bug in cbc_decrypt(pt, ct, key) where pt == ct [i.e same buffer]
+       -- fixed RC5 so it reads the default rounds out of the cipher_descriptor table
+       -- cleaned up ecc_export()
+       -- Cleaned up dh_import() and ecc_import() which also perform more 
+          error checking now
+       -- Fixed a serious flaw in rsa_import() with private keys.
+
+January 2nd, 2002
+v0.17  -- Fixed a bug in the random prime generator that fixes the wrong bits to one
+       -- ECC and DH code verify that the moduli and orders are in fact prime.  That 
+          slows down the test routines alot but what are you gonna do? 
+       -- Fixed a huge bug in the mp_exptmod() function which incorrectly calculates g^x mod p for some
+          values of p.  I replaced it with a slow function.  Once the author of MPI fixes his faster routine
+          I will switch back.
+  
+January 1st, 2002 [whoa new year!]
+v0.16  -- Improved GF division code that is faster.
+       -- documented the GF code
+
+December 31st, 2001
+v0.15  -- A 1792-bit and 2048-bit DH setting was added.  Took me all night to 
+          find a 1792 and 2048-bit strong prime but what the heck
+       -- Library now has polynomial-basis GF(2^w) routines I wrote myself.  Can be used to perform
+          ECC over GF(2^w) later on....
+       -- Fixed a bug with the defines that allows it to build in windows
+       
+December 30th, 2001
+v0.14  -- Fixed the xxx_encrypt() packet routines to make an IV of appropriate size 
+          for the cipher used.  It was defaulting to making a 256-bit IV...
+       -- base64_encode() now appends a NULL byte, um "duh" stupid mistake now fixed...
+       -- spell checked the manual again... :-)
+
+December 30th, 2001
+v0.13  -- Switching back to older copy of MPI since it works! arrg..
+       -- Added sign/verify functions for ECC
+       -- all signature verification routines default to invalid signatures.
+       -- Changed all calls to memset to zeromem.  Fixed up some buffer problems 
+          in other routines.  All calls to zeromem let the compiler determine the size
+          of the data to wipe.
+
+December 29th, 2001
+v0.12  -- Imported a new version of MPI [the bignum library] that should
+          be a bit more stable [if you want to write your own bignum
+          routines with the library that is...]
+       -- Manual has way more info
+       -- hash_file() clears stack now [like it should]
+       -- The artificial cap on the hash input size of 2^32 bits has been
+          removed.  Basically I was too lazy todo 64-bit math before
+          [don't ask why... I can't remember].  Anyways the hashes
+          support the size of 2^64 bits [if you ever use that many bits in a message
+          that's just wierd...]
+       -- The hashes now wipe the "hash_state" after the digest is computed.  This helps
+          prevent the internal state of the hash being leaked accidently [i.e stack problems]
+
+December 29th, 2001
+v0.11  -- Made #define's so you can trim the library down by removing
+          ciphers, hashs, modes of operation, prngs, and even PK algorithms
+          For example, the library with rijndael+ctr+sha1+ECC is 91KB compared
+          to the 246kb the full library takes.
+       -- Added ECC packet routines for encrypt/decrypt/sign/verify much akin to
+          the RSA packet routines.
+       -- ECC now compresses the public key, a ECC-192 public key takes 33 bytes 
+          for example....
+
+December 28th, 2001
+v0.10  -- going to restart the manual from scratch to make it more 
+          clear and professional
+       -- Added ECC over Z/pZ.  Basically provides as much as DH
+          except its faster since the numbers are smaller.  For example,
+          A comparable 256-bit ECC key provides as much security as expected
+          from a DH key over 1024-bits.
+       -- Cleaned up the DH code to not export the symbol "sets[]"
+       -- Fixed a bug in the DH code that would not make the correct size 
+          random string if you made the key short.  For instance if you wanted 
+          a 512-bit DH key it would make a 768-bit one but only make up 512-bits 
+          for the exponent... now it makes the full 768 bits [or whatever the case 
+          is]
+       -- Fixed another ***SERIOUS*** bug in the DH code that would default to 768-bit
+          keys by mistake.
+
+December 25th, 2001
+v0.09  -- Includes a demo program called file_crypt which shows off
+          how to use the library to make a command line tool which
+          allows the user to encode/decode a file with any
+          hash (on the passphrase) and cipher in CTR mode.
+       -- Switched everything to use typedef's now to clear up the code.
+       -- Added AES (128/192 and 256 bit key modes)
+
+December 24th, 2001
+v0.08  -- fixed a typo in the manual. MPI stores its bignums in
+          BIG endian not little.
+       -- Started adding a RNG to the library.  Right now it tries
+          to open /dev/random and if that fails it uses either the 
+          MS CSP or the clock drift RNG.  It also allows callbacks 
+          since the drift RNG is slow (about 3.5 bytes/sec)
+       -- the RNG can also automatically setup a PRNG as well now
+
+v0.07  -- Added basic DH routines sufficient to 
+          negotiate shared secrets 
+          [see the manual for a complete example!]
+       -- Fixed rsa_import to detect when the input
+          could be corrupt.  
+       -- added more to the manual.
+
+December 22nd, 2001
+v0.06  -- Fixed some formatting errors in 
+          the hash functions [just source code cleaning]
+       -- Fixed a typo in the error message for sha256 :-)
+       -- Fixed an error in base64_encode() that 
+          would fail to catch all buffer overruns
+       -- Test program times the RSA and symmetric cipher 
+          routines for kicks...
+       -- Added the "const" modifier to alot of routines to 
+          clear up the purpose of each function.
+       -- Changed the name of the library to "TomCrypt" 
+          following a suggestion from a sci.crypt reader....
+
+v0.05  -- Fixed the ROL/ROR macro to be safe on platforms 
+          where unsigned long is not 32-bits
+       -- I have added a bit more to the documentation 
+          manual "crypt.pdf" provided.
+       -- I have added a makefile for LCC-Win32.  It should be 
+          easy to port to other LCC platforms by changing a few lines.
+       -- Ran a spell checker over the manual.
+       -- Changed the header and library from "crypt" to "mycrypt" to not
+          clash with the *nix package "crypt".
+
+v0.04  -- Fixed a bug in the RC5,RC6,Blowfish key schedules
+          where if the key was not a multiple of 4 bytes it would
+          not get loaded correctly.
+
+December 21st, 2001
+
+v0.03  -- Added Serpent to the list of ciphers.
+
+v0.02  -- Changed RC5 to only allow 12 to 24 rounds
+       -- Added more to the manual.
+
+v0.01  -- We will call this the first version.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,232 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+/* Dropbear doesn't need these 
+
+const char *crypt_build_settings =
+   "LibTomCrypt " SCRYPT "\n\n"
+   "Endianess: "
+#if defined(ENDIAN_NEUTRAL)
+   "neutral\n"
+#elif defined(ENDIAN_LITTLE)
+   "little"
+   #if defined(ENDIAN_32BITWORD)
+   " (32-bit words)\n"
+   #else
+   " (64-bit words)\n"
+   #endif
+#elif defined(ENDIAN_BIG)
+   "big"
+   #if defined(ENDIAN_32BITWORD)
+   " (32-bit words)\n"
+   #else
+   " (64-bit words)\n"
+   #endif
+#endif
+   "Clean stack: "
+#if defined(CLEAN_STACK)
+   "enabled\n"
+#else
+   "disabled\n"
+#endif
+   "Ciphers built-in:\n"
+#if defined(BLOWFISH)
+   "   Blowfish\n"
+#endif
+#if defined(RC2)
+   "   RC2\n"
+#endif
+#if defined(RC5)
+   "   RC5\n"
+#endif
+#if defined(RC6)
+   "   RC6\n"
+#endif
+#if defined(SAFERP)
+   "   Safer+\n"
+#endif
+#if defined(SAFER)
+   "   Safer\n"
+#endif
+#if defined(RIJNDAEL)
+   "   Rijndael\n"
+#endif
+#if defined(XTEA)
+   "   XTEA\n"
+#endif
+#if defined(TWOFISH)
+   "   Twofish "
+   #if defined(TWOFISH_SMALL) && defined(TWOFISH_TABLES)
+       "(small, tables)\n"
+   #elif defined(TWOFISH_SMALL)
+       "(small)\n"
+   #elif defined(TWOFISH_TABLES)
+       "(tables)\n"
+   #else
+       "\n"
+   #endif
+#endif
+#if defined(DES)
+   "   DES\n"
+#endif
+#if defined(CAST5)
+   "   CAST5\n"
+#endif
+#if defined(NOEKEON)
+   "   Noekeon\n"
+#endif
+#if defined(SKIPJACK)
+   "   Skipjack\n"
+#endif
+
+    "\nHashes built-in:\n"
+#if defined(SHA512)
+   "   SHA-512\n"
+#endif
+#if defined(SHA384)
+   "   SHA-384\n"
+#endif
+#if defined(SHA256)
+   "   SHA-256\n"
+#endif
+#if defined(SHA224)
+   "   SHA-224\n"
+#endif
+#if defined(TIGER)
+   "   TIGER\n"
+#endif
+#if defined(SHA1)
+   "   SHA1\n"
+#endif
+#if defined(MD5)
+   "   MD5\n"
+#endif
+#if defined(MD4)
+   "   MD4\n"
+#endif
+#if defined(MD2)
+   "   MD2\n"
+#endif
+#if defined(RIPEMD128)
+   "   RIPEMD128\n"
+#endif
+#if defined(RIPEMD160)
+   "   RIPEMD160\n"
+#endif
+
+    "\nBlock Chaining Modes:\n"
+#if defined(CFB)
+    "   CFB\n"
+#endif
+#if defined(OFB)
+    "   OFB\n"
+#endif
+#if defined(ECB)
+    "   ECB\n"
+#endif
+#if defined(CBC)
+    "   CBC\n"
+#endif
+#if defined(CTR)
+    "   CTR\n"
+#endif
+
+    "\nPRNG:\n"
+#if defined(YARROW)
+    "   Yarrow\n"
+#endif
+#if defined(SPRNG)
+    "   SPRNG\n"
+#endif
+#if defined(RC4)
+    "   RC4\n"
+#endif
+
+    "\nPK Algs:\n"
+#if defined(MRSA)
+    "   RSA\n"
+#endif
+#if defined(MDH)
+    "   DH\n"
+#endif
+#if defined(MECC)
+    "   ECC\n"
+#endif
+#if defined(MDSA)
+    "   DSA\n"
+#endif
+#if defined(KR)
+    "   KR\n"
+#endif
+
+    "\nCompiler:\n"
+#if defined(WIN32)
+    "   WIN32 platform detected.\n"
+#endif
+#if defined(__CYGWIN__)
+    "   CYGWIN Detected.\n"
+#endif
+#if defined(__DJGPP__)
+    "   DJGPP Detected.\n"
+#endif
+#if defined(_MSC_VER)
+    "   MSVC compiler detected.\n"
+#endif
+#if defined(__GNUC__)
+    "   GCC compiler detected.\n"
+#endif
+#if defined(INTEL_CC)
+    "   Intel C Compiler detected.\n"
+#endif
+
+    "\nVarious others: "
+#if defined(GF)
+    " GF "
+#endif
+#if defined(BASE64)
+    " BASE64 "
+#endif
+#if defined(MPI)
+    " MPI "
+#endif
+#if defined(HMAC)
+    " HMAC "
+#endif
+#if defined(OMAC)
+    " OMAC "
+#endif
+#if defined(PMAC)
+    " PMAC "
+#endif
+#if defined(EAX_MODE)
+    " EAX_MODE "
+#endif
+#if defined(OCB_MODE)
+    " OCB_MODE "
+#endif
+#if defined(TRY_UNRANDOM_FIRST)
+    " TRY_UNRANDOM_FIRST "
+#endif
+#if defined(LTC_TEST)
+    " LTC_TEST "
+#endif
+#if defined(PKCS_1)
+    " PKCS#1 "
+#endif
+#if defined(PKCS_5)
+    " PKCS#5 "
+#endif
+    "\n"
+    "\n\n\n"
+    ;
+	*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt.out	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,88 @@
+\BOOKMARK [0][-]{chapter.1}{Introduction}{}
+\BOOKMARK [1][-]{section.1.1}{What is the LibTomCrypt?}{chapter.1}
+\BOOKMARK [2][-]{subsection.1.1.1}{What the library IS for?}{section.1.1}
+\BOOKMARK [2][-]{subsection.1.1.2}{What the library IS NOT for?}{section.1.1}
+\BOOKMARK [1][-]{section.1.2}{Why did I write it?}{chapter.1}
+\BOOKMARK [2][-]{subsection.1.2.1}{Modular}{section.1.2}
+\BOOKMARK [1][-]{section.1.3}{License}{chapter.1}
+\BOOKMARK [1][-]{section.1.4}{Patent Disclosure}{chapter.1}
+\BOOKMARK [1][-]{section.1.5}{Building the library}{chapter.1}
+\BOOKMARK [1][-]{section.1.6}{Building against the library}{chapter.1}
+\BOOKMARK [1][-]{section.1.7}{Thanks}{chapter.1}
+\BOOKMARK [0][-]{chapter.2}{The Application Programming Interface \(API\)}{}
+\BOOKMARK [1][-]{section.2.1}{Introduction}{chapter.2}
+\BOOKMARK [1][-]{section.2.2}{Macros}{chapter.2}
+\BOOKMARK [1][-]{section.2.3}{Functions with Variable Length Output}{chapter.2}
+\BOOKMARK [1][-]{section.2.4}{Functions that need a PRNG}{chapter.2}
+\BOOKMARK [1][-]{section.2.5}{Functions that use Arrays of Octets}{chapter.2}
+\BOOKMARK [0][-]{chapter.3}{Symmetric Block Ciphers}{}
+\BOOKMARK [1][-]{section.3.1}{Core Functions}{chapter.3}
+\BOOKMARK [1][-]{section.3.2}{Key Sizes and Number of Rounds}{chapter.3}
+\BOOKMARK [1][-]{section.3.3}{The Cipher Descriptors}{chapter.3}
+\BOOKMARK [2][-]{subsection.3.3.1}{Notes}{section.3.3}
+\BOOKMARK [1][-]{section.3.4}{Symmetric Modes of Operations}{chapter.3}
+\BOOKMARK [2][-]{subsection.3.4.1}{Background}{section.3.4}
+\BOOKMARK [2][-]{subsection.3.4.2}{Choice of Mode}{section.3.4}
+\BOOKMARK [2][-]{subsection.3.4.3}{Implementation}{section.3.4}
+\BOOKMARK [1][-]{section.3.5}{Encrypt and Authenticate Modes}{chapter.3}
+\BOOKMARK [2][-]{subsection.3.5.1}{EAX Mode}{section.3.5}
+\BOOKMARK [2][-]{subsection.3.5.2}{OCB Mode}{section.3.5}
+\BOOKMARK [0][-]{chapter.4}{One-Way Cryptographic Hash Functions}{}
+\BOOKMARK [1][-]{section.4.1}{Core Functions}{chapter.4}
+\BOOKMARK [1][-]{section.4.2}{Hash Descriptors}{chapter.4}
+\BOOKMARK [2][-]{subsection.4.2.1}{Notice}{section.4.2}
+\BOOKMARK [0][-]{chapter.5}{Message Authentication Codes}{}
+\BOOKMARK [1][-]{section.5.1}{HMAC Protocol}{chapter.5}
+\BOOKMARK [1][-]{section.5.2}{OMAC Support}{chapter.5}
+\BOOKMARK [1][-]{section.5.3}{PMAC Support}{chapter.5}
+\BOOKMARK [0][-]{chapter.6}{Pseudo-Random Number Generators}{}
+\BOOKMARK [1][-]{section.6.1}{Core Functions}{chapter.6}
+\BOOKMARK [2][-]{subsection.6.1.1}{Remarks}{section.6.1}
+\BOOKMARK [2][-]{subsection.6.1.2}{Example}{section.6.1}
+\BOOKMARK [1][-]{section.6.2}{PRNG Descriptors}{chapter.6}
+\BOOKMARK [1][-]{section.6.3}{The Secure RNG}{chapter.6}
+\BOOKMARK [2][-]{subsection.6.3.1}{The Secure PRNG Interface}{section.6.3}
+\BOOKMARK [0][-]{chapter.7}{RSA Routines}{}
+\BOOKMARK [1][-]{section.7.1}{Background}{chapter.7}
+\BOOKMARK [1][-]{section.7.2}{Core Functions}{chapter.7}
+\BOOKMARK [1][-]{section.7.3}{Packet Routines}{chapter.7}
+\BOOKMARK [1][-]{section.7.4}{Remarks}{chapter.7}
+\BOOKMARK [0][-]{chapter.8}{Diffie-Hellman Key Exchange}{}
+\BOOKMARK [1][-]{section.8.1}{Background}{chapter.8}
+\BOOKMARK [1][-]{section.8.2}{Core Functions}{chapter.8}
+\BOOKMARK [2][-]{subsection.8.2.1}{Remarks on Usage}{section.8.2}
+\BOOKMARK [2][-]{subsection.8.2.2}{Remarks on The Snippet}{section.8.2}
+\BOOKMARK [1][-]{section.8.3}{Other Diffie-Hellman Functions}{chapter.8}
+\BOOKMARK [1][-]{section.8.4}{DH Packet}{chapter.8}
+\BOOKMARK [0][-]{chapter.9}{Elliptic Curve Cryptography}{}
+\BOOKMARK [1][-]{section.9.1}{Background}{chapter.9}
+\BOOKMARK [1][-]{section.9.2}{Core Functions}{chapter.9}
+\BOOKMARK [1][-]{section.9.3}{ECC Packet}{chapter.9}
+\BOOKMARK [1][-]{section.9.4}{ECC Keysizes}{chapter.9}
+\BOOKMARK [0][-]{chapter.10}{Digital Signature Algorithm}{}
+\BOOKMARK [1][-]{section.10.1}{Introduction}{chapter.10}
+\BOOKMARK [1][-]{section.10.2}{Key Generation}{chapter.10}
+\BOOKMARK [1][-]{section.10.3}{Key Verification}{chapter.10}
+\BOOKMARK [1][-]{section.10.4}{Signatures}{chapter.10}
+\BOOKMARK [1][-]{section.10.5}{Import and Export}{chapter.10}
+\BOOKMARK [0][-]{chapter.11}{Public Keyrings}{}
+\BOOKMARK [1][-]{section.11.1}{Introduction}{chapter.11}
+\BOOKMARK [1][-]{section.11.2}{The Keyring API}{chapter.11}
+\BOOKMARK [0][-]{chapter.12}{GF\(2w\) Math Routines}{}
+\BOOKMARK [0][-]{chapter.13}{Miscellaneous}{}
+\BOOKMARK [1][-]{section.13.1}{Base64 Encoding and Decoding}{chapter.13}
+\BOOKMARK [1][-]{section.13.2}{The Multiple Precision Integer Library \(MPI\)}{chapter.13}
+\BOOKMARK [2][-]{subsection.13.2.1}{Binary Forms of ``mp\137int'' Variables}{section.13.2}
+\BOOKMARK [2][-]{subsection.13.2.2}{Primality Testing}{section.13.2}
+\BOOKMARK [0][-]{chapter.14}{Programming Guidelines}{}
+\BOOKMARK [1][-]{section.14.1}{Secure Pseudo Random Number Generators}{chapter.14}
+\BOOKMARK [1][-]{section.14.2}{Preventing Trivial Errors}{chapter.14}
+\BOOKMARK [1][-]{section.14.3}{Registering Your Algorithms}{chapter.14}
+\BOOKMARK [1][-]{section.14.4}{Key Sizes}{chapter.14}
+\BOOKMARK [2][-]{subsection.14.4.1}{Symmetric Ciphers}{section.14.4}
+\BOOKMARK [2][-]{subsection.14.4.2}{Assymetric Ciphers}{section.14.4}
+\BOOKMARK [1][-]{section.14.5}{Thread Safety}{chapter.14}
+\BOOKMARK [0][-]{chapter.15}{Configuring the Library}{}
+\BOOKMARK [1][-]{section.15.1}{Introduction}{chapter.15}
+\BOOKMARK [1][-]{section.15.2}{mycrypt\137cfg.h}{chapter.15}
+\BOOKMARK [1][-]{section.15.3}{The Configure Script}{chapter.15}
Binary file crypt.pdf has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt.tex	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,3040 @@
+\documentclass[b5paper]{book}
+\usepackage{hyperref}
+\usepackage{makeidx}
+\usepackage{amssymb}
+\usepackage{color}
+\usepackage{alltt}
+\usepackage{graphicx}
+\usepackage{layout}
+\def\union{\cup}
+\def\intersect{\cap}
+\def\getsrandom{\stackrel{\rm R}{\gets}}
+\def\cross{\times}
+\def\cat{\hspace{0.5em} \| \hspace{0.5em}}
+\def\catn{$\|$}
+\def\divides{\hspace{0.3em} | \hspace{0.3em}}
+\def\nequiv{\not\equiv}
+\def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}}
+\def\lcm{{\rm lcm}}
+\def\gcd{{\rm gcd}}
+\def\log{{\rm log}}
+\def\ord{{\rm ord}}
+\def\abs{{\mathit abs}}
+\def\rep{{\mathit rep}}
+\def\mod{{\mathit\ mod\ }}
+\renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})}
+\newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor}
+\newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil}
+\def\Or{{\rm\ or\ }}
+\def\And{{\rm\ and\ }}
+\def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}}
+\def\implies{\Rightarrow}
+\def\undefined{{\rm ``undefined"}}
+\def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}}
+\let\oldphi\phi
+\def\phi{\varphi}
+\def\Pr{{\rm Pr}}
+\newcommand{\str}[1]{{\mathbf{#1}}}
+\def\F{{\mathbb F}}
+\def\N{{\mathbb N}}
+\def\Z{{\mathbb Z}}
+\def\R{{\mathbb R}}
+\def\C{{\mathbb C}}
+\def\Q{{\mathbb Q}}
+
+\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}}
+
+\def\gap{\vspace{0.5ex}}
+\makeindex
+\begin{document}
+\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.95}
+\author{Tom St Denis \\
+\\
[email protected] \\
+http://libtomcrypt.org \\ \\
+Phone: 1-613-836-3160\\
+111 Banning Rd \\
+Kanata, Ontario \\
+K2L 1C3 \\
+Canada
+}
+\maketitle
+This text and source code library are both hereby placed in the public domain.  This book has been 
+formatted for B5 [176x250] paper using the \LaTeX{} {\em book} macro package.
+
+\vspace{10cm}
+
+\begin{flushright}Open Source.  Open Academia.  Open Minds.
+
+\mbox{ }
+
+Tom St Denis,
+
+Ontario, Canada
+\end{flushright}
+\newpage
+\tableofcontents
+\chapter{Introduction}
+\section{What is the LibTomCrypt?}
+LibTomCrypt is a portable ANSI C cryptographic library that supports symmetric ciphers, one-way hashes, 
+pseudo-random number generators, public key cryptography (via RSA,DH or ECC/DH) and a plethora of support 
+routines.  It is designed to compile out of the box with the GNU C Compiler (GCC) version 2.95.3 (and higher) 
+and with MSVC version 6 in win32.
+
+The library has been successfully tested on quite a few other platforms ranging from the ARM7TDMI in a 
+Gameboy Advanced to various PowerPC processors and even the MIPS processor in the PlayStation 2.  Suffice it
+to say the code is portable.
+
+The library is designed so new ciphers/hashes/PRNGs can be added at runtime and the existing API (and helper API functions) will 
+be able to use the new designs automatically.  There exist self-check functions for each cipher and hash to ensure that
+they compile and execute to the published design specifications.  The library also performs extensive parameter error checking
+and will give verbose error messages when possible.
+
+Essentially the library saves the time of having to implement the ciphers, hashes, prngs yourself.  Typically implementing
+useful cryptography is an error prone business which means anything that can save considerable time and effort is a good
+thing.
+
+\subsection{What the library IS for?}
+
+The library typically serves as a basis for other protocols and message formats.  For example, it should be possible to 
+take the RSA routines out of this library, apply the appropriate message padding and get PKCS compliant RSA routines.  
+Similarly SSL protocols could be formed on top  of the low-level symmetric cipher functions.  The goal of this package is 
+to provide these low level core functions in a robust and easy to use fashion.
+
+The library also serves well as a toolkit for applications where they don't need to be OpenPGP, PKCS, etc. compliant.
+Included are fully operational public key routines for encryption, decryption, signature generation and verification.  
+These routines are fully portable but are not conformant to any known set of standards.  They are all based on established
+number theory and cryptography.  
+
+\subsection{What the library IS NOT for?}
+
+The library is not designed to be in anyway an implementation of the SSL or OpenPGP standards.  The library 
+is not designed to be compliant with any known form of API or programming hierarchy.  It is not a port of any other 
+library and it is not platform specific (like the MS CSP).  So if you're looking to drop in some buzzword 
+compliant crypto library this is not for you.  The library has been written from scratch to provide basic functions as 
+well as non-standard higher level functions.  
+
+This is not to say that the library is a ``homebrew'' project.  All of the symmetric ciphers and one-way hash functions
+conform to published test vectors.  The public key functions are derived from publicly available material and the majority
+of the code has been reviewed by a growing community of developers.
+
+\subsubsection{Why not?}
+You may be asking why I didn't choose to go all out and support standards like P1363, PKCS and the whole lot.  The reason
+is quite simple too much money gets in the way.  When I tried to access the P1363 draft documents and was denied (it 
+requires a password) I realized that they're just a business anyways.  See what happens is a company will sit down and
+invent a ``standard''.  Then they try to sell it to as many people as they can.  All of a sudden this ``standard'' is 
+everywhere.  Then the standard is updated every so often to keep people dependent.  Then you become RSA.  If people are 
+supposed to support these standards they had better make them more accessible.
+
+\section{Why did I write it?}
+You may be wondering, ``Tom, why did you write a crypto library.  I already have one.''.  Well the reason falls into
+two categories:
+\begin{enumerate}
+    \item I am too lazy to figure out someone else's API.  I'd rather invent my own simpler API and use that.
+    \item It was (still is) good coding practice.
+\end{enumerate}
+
+The idea is that I am not striving to replace OpenSSL or Crypto++ or Cryptlib or etc.  I'm trying to write my 
+{\bf own} crypto library and hopefully along the way others will appreciate the work.
+
+With this library all core functions (ciphers, hashes, prngs) have the {\bf exact} same prototype definition.  They all load
+and store data in a format independent of the platform.  This means if you encrypt with Blowfish on a PPC it should decrypt
+on an x86 with zero problems.  The consistent API also means that if you learn how to use blowfish with my library you 
+know how to use Safer+ or RC6 or Serpent or ... as well.  With all of the core functions there are central descriptor tables 
+that can be used to make a program automatically pick between ciphers, hashes and PRNGs at runtime.  That means your 
+application can support all ciphers/hashes/prngs without changing the source code.
+
+\subsection{Modular}
+The LibTomCrypt package has also been written to be very modular.  The block ciphers, one-way hashes and
+pseudo-random number generators (PRNG) are all used within the API through ``descriptor'' tables which 
+are essentially structures with pointers to functions.  While you can still call particular functions
+directly (\textit{e.g. sha256\_process()}) this descriptor interface allows the developer to customize their
+usage of the library.
+
+For example, consider a hardware platform with a specialized RNG device.  Obviously one would like to tap
+that for the PRNG needs within the library (\textit{e.g. making a RSA key}).  All the developer has todo
+is write a descriptor and the few support routines required for the device.  After that the rest of the 
+API can make use of it without change.  Similiarly imagine a few years down the road when AES2 (\textit{or whatever they call it}) is
+invented.  It can be added to the library and used within applications with zero modifications to the
+end applications provided they are written properly.
+
+This flexibility within the library means it can be used with any combination of primitive algorithms and 
+unlike libraries like OpenSSL is not tied to direct routines.  For instance, in OpenSSL there are CBC block
+mode routines for every single cipher.  That means every time you add or remove a cipher from the library
+you have to update the associated support code as well.  In LibTomCrypt the associated code (\textit{chaining modes in this case})
+are not directly tied to the ciphers.  That is a new cipher can be added to the library by simply providing 
+the key setup, ECB decrypt and encrypt and test vector routines.  After that all five chaining mode routines
+can make use of the cipher right away.
+
+
+\section{License}
+
+All of the source code except for the following files have been written by the author or donated to the project
+under a public domain license:
+
+\begin{enumerate}
+   \item rc2.c
+   \item safer.c
+\end{enumerate}
+
+`mpi.c'' was originally written by Michael Fromberger ([email protected]) but has since been replaced with my LibTomMath
+library.
+
+``rc2.c'' is based on publicly available code that is not attributed to a person from the given source.  ``safer.c''
+was written by Richard De Moliner ([email protected]) and is public domain.
+
+The project is hereby released as public domain.
+
+\section{Patent Disclosure}
+
+The author (Tom St Denis) is not a patent lawyer so this section is not to be treated as legal advice.  To the best
+of the authors knowledge the only patent related issues within the library are the RC5 and RC6 symmetric block ciphers.  
+They can be removed from a build by simply commenting out the two appropriate lines in the makefile script.  The rest
+of the ciphers and hashes are patent free or under patents that have since expired.
+
+The RC2 and RC4 symmetric ciphers are not under patents but are under trademark regulations.  This means you can use 
+the ciphers you just can't advertise that you are doing so.  
+
+\section{Building the library}
+
+To build the library on a GCC equipped platform simply type ``make'' at your command prompt.  It will build the library
+file ``libtomcrypt.a''.  
+
+To install the library copy all of the ``.h'' files into your ``\#include'' path and the single libtomcrypt.a file into 
+your library path.
+
+With MSVC you can build the library with ``nmake -f makefile.msvc''.  This will produce a ``tomcrypt.lib'' file which
+is the core library.  Copy the header files into your MSVC include path and the library in the lib path (typically
+under where VC98 is installed).
+
+\section{Building against the library}
+
+In the recent versions the build steps have changed.  The build options are now stored in ``mycrypt\_custom.h'' and
+no longer in the makefile.  If you change a build option in that file you must re-build the library from clean to
+ensure the build is intact.  The perl script ``config.pl'' will help setup the custom header and a custom makefile
+if you want one (the provided ``makefile'' will work with custom configs).
+
+\section{Thanks}
+I would like to give thanks to the following people (in no particular order) for helping me develop this project:
+\begin{enumerate}
+   \item Richard van de Laarschot
+   \item Richard Heathfield
+   \item Ajay K. Agrawal
+   \item Brian Gladman
+   \item Svante Seleborg
+   \item Clay Culver
+   \item Jason Klapste
+   \item Dobes Vandermeer
+   \item Daniel Richards
+   \item Wayne Scott
+   \item Andrew Tyler
+   \item Sky Schulz
+   \item Christopher Imes
+\end{enumerate}
+
+\chapter{The Application Programming Interface (API)}
+\section{Introduction}
+\index{CRYPT\_ERROR} \index{CRYPT\_OK}
+
+In general the API is very simple to memorize and use.  Most of the functions return either {\bf void} or {\bf int}.  Functions
+that return {\bf int} will return {\bf CRYPT\_OK} if the function was successful or one of the many error codes 
+if it failed.  Certain functions that return int will return $-1$ to indicate an error.  These functions will be explicitly
+commented upon.  When a function does return a CRYPT error code it can be translated into a string with
+
+\begin{verbatim}
+const char *error_to_string(int errno);
+\end{verbatim}
+
+An example of handling an error is:
+\begin{verbatim}
+void somefunc(void)
+{
+   int errno;
+   
+   /* call a cryptographic function */
+   if ((errno = some_crypto_function(...)) != CRYPT_OK) {
+      printf("A crypto error occured, %s\n", error_to_string(errno));
+      /* perform error handling */
+   }
+   /* continue on if no error occured */
+}
+\end{verbatim}
+
+There is no initialization routine for the library and for the most part the code is thread safe.  The only thread
+related issue is if you use the same symmetric cipher, hash or public key state data in multiple threads.  Normally
+that is not an issue.
+
+To include the prototypes for ``LibTomCrypt.a'' into your own program simply include ``mycrypt.h'' like so:
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void) {
+    return 0;
+}
+\end{verbatim}
+
+The header file ``mycrypt.h'' also includes ``stdio.h'', ``string.h'', ``stdlib.h'', ``time.h'', ``ctype.h'' and ``mpi.h''
+(the bignum library routines).
+
+\section{Macros}
+
+There are a few helper macros to make the coding process a bit easier.  The first set are related to loading and storing
+32/64-bit words in little/big endian format.  The macros are:
+
+\index{STORE32L} \index{STORE64L} \index{LOAD32L} \index{LOAD64L}
+\index{STORE32H} \index{STORE64H} \index{LOAD32H} \index{LOAD64H} \index{BSWAP}
+\begin{small}
+\begin{center}
+\begin{tabular}{|c|c|c|}
+     \hline STORE32L(x, y) & {\bf unsigned long} x, {\bf unsigned char} *y & $x \to y[0 \ldots 3]$ \\
+     \hline STORE64L(x, y) & {\bf unsigned long long} x, {\bf unsigned char} *y & $x \to y[0 \ldots 7]$ \\
+     \hline LOAD32L(x, y) & {\bf unsigned long} x, {\bf unsigned char} *y & $y[0 \ldots 3] \to x$ \\
+     \hline LOAD64L(x, y) & {\bf unsigned long long} x, {\bf unsigned char} *y & $y[0 \ldots 7] \to x$ \\
+     \hline STORE32H(x, y) & {\bf unsigned long} x, {\bf unsigned char} *y & $x \to y[3 \ldots 0]$ \\
+     \hline STORE64H(x, y) & {\bf unsigned long long} x, {\bf unsigned char} *y & $x \to y[7 \ldots 0]$ \\
+     \hline LOAD32H(x, y) & {\bf unsigned long} x, {\bf unsigned char} *y & $y[3 \ldots 0] \to x$ \\
+     \hline LOAD64H(x, y) & {\bf unsigned long long} x, {\bf unsigned char} *y & $y[7 \ldots 0] \to x$ \\
+     \hline BSWAP(x) & {\bf unsigned long} x & Swaps the byte order of x. \\
+     \hline
+\end{tabular}
+\end{center}
+\end{small}
+
+There are 32-bit cyclic rotations as well:
+\index{ROL} \index{ROR}
+\begin{center}
+\begin{tabular}{|c|c|c|}
+     \hline ROL(x, y) & {\bf unsigned long} x, {\bf unsigned long} y & $x << y$ \\
+     \hline ROR(x, y) & {\bf unsigned long} x, {\bf unsigned long} y & $x >> y$ \\
+     \hline
+\end{tabular}
+\end{center}
+
+\section{Functions with Variable Length Output}
+Certain functions such as (for example) ``rsa\_export()'' give an output that is variable length.  To prevent buffer overflows you
+must pass it the length of the buffer\footnote{Extensive error checking is not in place but it will be in future releases so it is a good idea to follow through with these guidelines.} where
+the output will be stored.  For example:
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void) {
+    rsa_key key;
+    unsigned char buffer[1024];
+    unsigned long x;
+    int errno;
+
+    /* ... Make up the RSA key somehow */
+
+    /* lets export the key, set x to the size of the output buffer */
+    x = sizeof(buffer);
+    if ((errno = rsa_export(buffer, &x, PK_PUBLIC, &key)) != CRYPT_OK) {
+       printf("Export error: %s\n", error_to_string(errno));
+       return -1;
+    }
+    
+    /* if rsa_export() was successful then x will have the size of the output */
+    printf("RSA exported key takes %d bytes\n", x);
+
+    /* ... do something with the buffer */
+
+    return 0;
+}
+\end{verbatim}
+\end{small}
+In the above example if the size of the RSA public key was more than 1024 bytes this function would not store anything in
+either ``buffer'' or ``x'' and simply return an error code.  If the function suceeds it stores the length of the output
+back into ``x'' so that the calling application will know how many bytes used.
+
+\section{Functions that need a PRNG}
+Certain functions such as ``rsa\_make\_key()'' require a PRNG.  These functions do not setup the PRNG themselves so it is 
+the responsibility of the calling function to initialize the PRNG before calling them.
+
+\section{Functions that use Arrays of Octets}
+Most functions require inputs that are arrays of the data type ``unsigned char''.  Whether it is a symmetric key, IV
+for a chaining mode or public key packet it is assumed that regardless of the actual size of ``unsigned char'' only the
+lower eight bits contain data.  For example, if you want to pass a 256 bit key to a symmetric ciphers setup routine
+you must pass it in (a pointer to) an array of 32 ``unsigned char'' variables.  Certain routines 
+(such as SAFER+) take special care to work properly on platforms where an ``unsigned char'' is not eight bits.
+
+For the purposes of this library the term ``byte'' will refer to an octet or eight bit word.  Typically an array of
+type ``byte'' will be synonymous with an array of type ``unsigned char''.
+
+\chapter{Symmetric Block Ciphers}
+\section{Core Functions}
+
+Libtomcrypt provides several block ciphers all in a plain vanilla ECB block mode.  Its important to first note that you 
+should never use the ECB modes directly to encrypt data.  Instead you should use the ECB functions to make a chaining mode
+or use one of the provided chaining modes.  All of the ciphers are written as ECB interfaces since it allows the rest of
+the API to grow in a modular fashion.
+
+All ciphers store their scheduled keys in a single data type called ``symmetric\_key''.  This allows all ciphers to 
+have the same prototype and store their keys as  naturally as possible.  All ciphers provide five visible functions which
+are (given that XXX is the name of the cipher):
+\index{Cipher Setup}
+\begin{verbatim}
+int XXX_setup(const unsigned char *key, int keylen, int rounds,
+              symmetric_key *skey);
+\end{verbatim}
+
+The XXX\_setup() routine will setup the cipher to be used with a given number of rounds and a given key length (in bytes).
+The number of rounds can be set to zero to use the default, which is generally a good idea.
+
+If the function returns successfully the variable ``skey'' will have a scheduled key stored in it.  Its important to note
+that you should only used this scheduled key with the intended cipher.  For example, if you call 
+``blowfish\_setup()'' do not pass the scheduled key onto ``rc5\_ecb\_encrypt()''.  All setup functions do not allocate 
+memory off the heap so when you are done with a key you can simply discard it (e.g. they can be on the stack).
+
+To encrypt or decrypt a block in ECB mode there are these two functions:
+\index{Cipher Encrypt} \index{Cipher Decrypt}
+\begin{verbatim}
+void XXX_ecb_encrypt(const unsigned char *pt, unsigned char *ct,
+                     symmetric_key *skey);
+
+void XXX_ecb_decrypt(const unsigned char *ct, unsigned char *pt,
+                     symmetric_key *skey);
+\end{verbatim}
+These two functions will encrypt or decrypt (respectively) a single block of text\footnote{The size of which depends on
+which cipher you are using.} and store the result where you want it.  It is possible that the input and output buffer are 
+the same buffer.  For the encrypt function ``pt''\footnote{pt stands for plaintext.} is the input and ``ct'' is the output.
+For the decryption function its the opposite.  To test a particular cipher against test vectors\footnote{As published in their design papers.} call: \index{Cipher Testing}
+\begin{verbatim}
+int XXX_test(void);
+\end{verbatim}
+This function will return {\bf CRYPT\_OK} if the cipher matches the test vectors from the design publication it is 
+based upon.  Finally for each cipher there is a function which will help find a desired key size:
+\begin{verbatim}
+int XXX_keysize(int *keysize);
+\end{verbatim}
+Essentially it will round the input keysize in ``keysize'' down to the next appropriate key size.  This function
+return {\bf CRYPT\_OK} if the key size specified is acceptable.  For example:
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   int keysize, errno;
+
+   /* now given a 20 byte key what keysize does Twofish want to use? */
+   keysize = 20;
+   if ((errno = twofish_keysize(&keysize)) != CRYPT_OK) {
+      printf("Error getting key size: %s\n", error_to_string(errno));
+      return -1;
+   }
+   printf("Twofish suggested a key size of %d\n", keysize);
+   return 0;
+}
+\end{verbatim}
+\end{small}
+This should indicate a keysize of sixteen bytes is suggested.  An example snippet that encodes a block with 
+Blowfish in ECB mode is below.
+
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{ 
+   unsigned char pt[8], ct[8], key[8];
+   symmetric_key skey;
+   int errno;
+
+   /* ... key is loaded appropriately in ``key'' ... */
+   /* ... load a block of plaintext in ``pt'' ... */
+
+   /* schedule the key */
+   if ((errno = blowfish_setup(key, 8, 0, &skey)) != CRYPT_OK) {
+      printf("Setup error: %s\n", error_to_string(errno));
+      return -1;
+   }
+
+   /* encrypt the block */
+   blowfish_ecb_encrypt(pt, ct, &skey);
+
+   /* decrypt the block */
+   blowfish_ecb_decrypt(ct, pt, &skey);
+
+   return 0;
+}
+\end{verbatim}
+\end{small}
+
+\section{Key Sizes and Number of Rounds}
+\index{Symmetric Keys}
+As a general rule of thumb do not use symmetric keys under 80 bits if you can.  Only a few of the ciphers support smaller
+keys (mainly for test vectors anyways).  Ideally your application should be making at least 256 bit keys.  This is not
+because you're supposed to be paranoid.  Its because if your PRNG has a bias of any sort the more bits the better.  For
+example, if you have $\mbox{Pr}\left[X = 1\right] = {1 \over 2} \pm \gamma$ where $\vert \gamma \vert > 0$ then the
+total amount of entropy in N bits is $N \cdot -log_2\left ({1 \over 2} + \vert \gamma \vert \right)$.  So if $\gamma$
+were $0.25$ (a severe bias) a 256-bit string would have about 106 bits of entropy whereas a 128-bit string would have
+only 53 bits of entropy.
+
+The number of rounds of most ciphers is not an option you can change.  Only RC5 allows you to change the number of
+rounds.  By passing zero as the number of rounds all ciphers will use their default number of rounds.  Generally the
+ciphers are configured such that the default number of rounds provide adequate security for the given block size.
+
+\section{The Cipher Descriptors}
+\index{Cipher Descriptor}
+To facilitate automatic routines an array of cipher descriptors is provided in the array ``cipher\_descriptor''.  An element
+of this array has the following format:
+
+\begin{verbatim}
+struct _cipher_descriptor {
+   char *name;
+   unsigned long min_key_length, max_key_length, 
+                 block_length, default_rounds;
+   int  (*setup)      (const unsigned char *key, int keylength, 
+                       int num_rounds, symmetric_key *skey);
+   void (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, 
+                       symmetric_key *key);
+   void (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt,
+                       symmetric_key *key);
+   int  (*test)       (void);
+   int  (*keysize)    (int *desired_keysize);
+};
+\end{verbatim}
+
+Where ``name'' is the lower case ASCII version of the name.  The fields ``min\_key\_length'', ``max\_key\_length'' and
+``block\_length'' are all the number of bytes not bits.  As a good rule of thumb it is assumed that the cipher supports
+the min and max key lengths but not always everything in between.  The ``default\_rounds'' field is the default number
+of rounds that will be used.
+
+The remaining fields are all pointers to the core functions for each cipher.  The end of the cipher\_descriptor array is
+marked when ``name'' equals {\bf NULL}.
+
+As of this release the current cipher\_descriptors elements are
+
+\begin{small}
+\begin{center}
+\begin{tabular}{|c|c|c|c|c|c|}
+     \hline Name & Descriptor Name & Block Size & Key Range & Rounds \\
+     \hline Blowfish & blowfish\_desc & 8 & 8 $\ldots$ 56 & 16 \\
+     \hline X-Tea & xtea\_desc & 8 & 16 & 32 \\
+     \hline RC2 & rc2\_desc & 8 & 8 $\ldots$ 128 & 16 \\
+     \hline RC5-32/12/b & rc5\_desc & 8 & 8 $\ldots$ 128 & 12 $\ldots$ 24 \\
+     \hline RC6-32/20/b & rc6\_desc & 16 & 8 $\ldots$ 128 & 20 \\
+     \hline SAFER+ & saferp\_desc &16 & 16, 24, 32 & 8, 12, 16 \\
+     \hline Safer K64   & safer\_k64\_desc & 8 & 8 & 6 $\ldots$ 13 \\
+     \hline Safer SK64  & safer\_sk64\_desc & 8 & 8 & 6 $\ldots$ 13 \\
+     \hline Safer K128  & safer\_k128\_desc & 8 & 16 & 6 $\ldots$ 13 \\
+     \hline Safer SK128 & safer\_sk128\_desc & 8 & 16 & 6 $\ldots$ 13 \\
+     \hline AES & aes\_desc & 16 & 16, 24, 32 & 10, 12, 14 \\
+     \hline Twofish & twofish\_desc & 16 & 16, 24, 32 & 16 \\
+     \hline DES & des\_desc & 8 & 7 & 16 \\
+     \hline 3DES (EDE mode) & des3\_desc & 8 & 21 & 16 \\
+     \hline CAST5 (CAST-128) & cast5\_desc & 8 & 5 $\ldots$ 16 & 12, 16 \\
+     \hline Noekeon & noekeon\_desc & 16 & 16 & 16 \\
+     \hline Skipjack & skipjack\_desc & 8 & 10 & 32 \\
+     \hline
+\end{tabular}
+\end{center}
+\end{small}
+
+\subsection{Notes}
+For the 64-bit SAFER famliy of ciphers (e.g K64, SK64, K128, SK128) the ecb\_encrypt() and ecb\_decrypt()
+functions are the same.  So if you want to use those functions directly just call safer\_ecb\_encrypt()
+or safer\_ecb\_decrypt() respectively.
+
+Note that for ``DES'' and ``3DES'' they use 8 and 24 byte keys but only 7 and 21 [respectively] bytes of the keys are in
+fact used for the purposes of encryption.  My suggestion is just to use random 8/24 byte keys instead of trying to make a 8/24
+byte string from the real 7/21 byte key.
+
+Note that ``Twofish'' has additional configuration options that take place at build time.  These options are found in
+the file ``mycrypt\_cfg.h''.  The first option is ``TWOFISH\_SMALL'' which when defined will force the Twofish code
+to not pre-compute the Twofish ``$g(X)$'' function as a set of four $8 \times 32$ s-boxes.  This means that a scheduled
+key will require less ram but the resulting cipher will be slower.  The second option is ``TWOFISH\_TABLES'' which when
+defined will force the Twofish code to use pre-computed tables for the two s-boxes $q_0, q_1$ as well as the multiplication
+by the polynomials 5B and EF used in the MDS multiplication.  As a result the code is faster and slightly larger.  The
+speed increase is useful when ``TWOFISH\_SMALL'' is defined since the s-boxes and MDS multiply form the heart of the
+Twofish round function.
+
+\begin{small}
+\begin{center}
+\begin{tabular}{|l|l|l|}
+\hline TWOFISH\_SMALL & TWOFISH\_TABLES & Speed and Memory (per key) \\
+\hline undefined & undefined & Very fast, 4.2KB of ram. \\
+\hline undefined & defined & As above, faster keysetup, larger code (1KB more). \\
+\hline defined & undefined & Very slow, 0.2KB of ram. \\
+\hline defined & defined & Somewhat faster, 0.2KB of ram, larger code. \\
+\hline
+\end{tabular}
+\end{center}
+\end{small}
+
+To work with the cipher\_descriptor array there is a function:
+\begin{verbatim}
+int find_cipher(char *name)
+\end{verbatim}
+Which will search for a given name in the array.  It returns negative one if the cipher is not found, otherwise it returns
+the location in the array where the cipher was found.  For example, to indirectly setup Blowfish you can also use:
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   unsigned char key[8];
+   symmetric_key skey;
+   int errno;
+
+   /* you must register a cipher before you use it */
+   if (register_cipher(&blowfish_desc)) == -1) {
+      printf("Unable to register Blowfish cipher.");
+      return -1;
+   }
+
+   /* generic call to function (assuming the key in key[] was already setup) */
+   if ((errno = cipher_descriptor[find_cipher("blowfish")].setup(key, 8, 0, &skey)) != CRYPT_OK) {
+      printf("Error setting up Blowfish: %s\n", error_to_string(errno));
+      return -1;
+   }
+
+   /* ... use cipher ... */
+}
+\end{verbatim}
+\end{small}
+
+A good safety would be to check the return value of ``find\_cipher()'' before accessing the desired function.  In order
+to use a cipher with the descriptor table you must register it first using:
+\begin{verbatim}
+int register_cipher(const struct _cipher_descriptor *cipher);
+\end{verbatim}
+Which accepts a pointer to a descriptor and returns the index into the global descriptor table.  If an error occurs such
+as there is no more room (it can have 32 ciphers at most) it will return {\bf{-1}}.  If you try to add the same cipher more
+than once it will just return the index of the first copy.  To remove a cipher call:
+\begin{verbatim}
+int unregister_cipher(const struct _cipher_descriptor *cipher);
+\end{verbatim}
+Which returns {\bf CRYPT\_OK} if it removes it otherwise it returns {\bf CRYPT\_ERROR}.  Consider:
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   int errno;
+   
+   /* register the cipher */
+   if (register_cipher(&rijndael_desc) == -1) {
+      printf("Error registering Rijndael\n");
+      return -1;
+   }
+
+   /* use Rijndael */
+
+   /* remove it */
+   if ((errno = unregister_cipher(&rijndael_desc)) != CRYPT_OK) {
+      printf("Error removing Rijndael: %s\n", error_to_string(errno));
+      return -1;
+   }
+
+   return 0;
+}
+\end{verbatim}
+\end{small}
+This snippet is a small program that registers only Rijndael only.  
+
+\section{Symmetric Modes of Operations}
+\subsection{Background}
+A typical symmetric block cipher can be used in chaining modes to effectively encrypt messages larger than the block
+size of the cipher.  Given a key $k$, a plaintext $P$ and a cipher $E$ we shall denote the encryption of the block
+$P$ under the key $k$ as $E_k(P)$.  In some modes there exists an initial vector denoted as $C_{-1}$.
+
+\subsubsection{ECB Mode}
+ECB or Electronic Codebook Mode is the simplest method to use.  It is given as:
+\begin{equation}
+C_i = E_k(P_i)
+\end{equation}
+This mode is very weak since it allows people to swap blocks and perform replay attacks if the same key is used more
+than once.
+
+\subsubsection{CBC Mode}
+CBC or Cipher Block Chaining mode is a simple mode designed to prevent trivial forms of replay and swap attacks on ciphers.
+It is given as:
+\begin{equation}
+C_i = E_k(P_i \oplus C_{i - 1})
+\end{equation}
+It is important that the initial vector be unique and preferably random for each message encrypted under the same key.
+
+\subsubsection{CTR Mode}
+CTR or Counter Mode is a mode which only uses the encryption function of the cipher.  Given a initial vector which is
+treated as a large binary counter the CTR mode is given as:
+\begin{eqnarray}
+C_{-1} = C_{-1} + 1\mbox{ }(\mbox{mod }2^W) \nonumber \\
+C_i = P_i \oplus E_k(C_{-1})
+\end{eqnarray}
+Where $W$ is the size of a block in bits (e.g. 64 for Blowfish).  As long as the initial vector is random for each message
+encrypted under the same key replay and swap attacks are infeasible.  CTR mode may look simple but it is as secure
+as the block cipher is under a chosen plaintext attack (provided the initial vector is unique).
+
+\subsubsection{CFB Mode}
+CFB or Ciphertext Feedback Mode is a mode akin to CBC.  It is given as:
+\begin{eqnarray}
+C_i = P_i \oplus C_{-1} \nonumber \\
+C_{-1} = E_k(C_i)
+\end{eqnarray}
+Note that in this library the output feedback width is equal to the size of the block cipher.  That is this mode is used
+to encrypt whole blocks at a time.  However, the library will buffer data allowing the user to encrypt or decrypt partial
+blocks without a delay.  When this mode is first setup it will initially encrypt the initial vector as required.
+
+\subsubsection{OFB Mode}
+OFB or Output Feedback Mode is a mode akin to CBC as well.  It is given as:
+\begin{eqnarray}
+C_{-1} = E_k(C_{-1}) \nonumber \\
+C_i = P_i \oplus C_{-1}
+\end{eqnarray}
+Like the CFB mode the output width in CFB mode is the same as the width of the block cipher.  OFB mode will also
+buffer the output which will allow you to encrypt or decrypt partial blocks without delay.
+
+\subsection{Choice of Mode}
+My personal preference is for the CTR mode since it has several key benefits:
+\begin{enumerate}
+   \item No short cycles which is possible in the OFB and CFB modes.
+   \item Provably as secure as the block cipher being used under a chosen plaintext attack.
+   \item Technically does not require the decryption routine of the cipher.
+   \item Allows random access to the plaintext.
+   \item Allows the encryption of block sizes that are not equal to the size of the block cipher.
+\end{enumerate}
+The CTR, CFB and OFB routines provided allow you to encrypt block sizes that differ from the ciphers block size.  They 
+accomplish this by buffering the data required to complete a block.  This allows you to encrypt or decrypt any size 
+block of memory with either of the three modes.
+
+The ECB and CBC modes process blocks of the same size as the cipher at a time.  Therefore they are less flexible than the
+other modes.
+
+\subsection{Implementation}
+\index{CBC Mode} \index{CTR Mode}
+\index{OFB Mode} \index{CFB Mode}
+The library provides simple support routines for handling CBC, CTR, CFB, OFB and ECB encoded messages.  Assuming the mode 
+you want is XXX there is a structure called ``symmetric\_XXX'' that will contain the information required to
+use that mode.  They have identical setup routines (except ECB mode for obvious reasons):
+\begin{verbatim}
+int XXX_start(int cipher, const unsigned char *IV, 
+              const unsigned char *key, int keylen, 
+              int num_rounds, symmetric_XXX *XXX);
+
+int ecb_start(int cipher, const unsigned char *key, int keylen, 
+              int num_rounds, symmetric_ECB *ecb);
+\end{verbatim}
+
+In each case ``cipher'' is the index into the cipher\_descriptor array of the cipher you want to use.  The ``IV'' value is 
+the initialization vector to be used with the cipher.  You must fill the IV yourself and it is assumed they are the same 
+length as the block size\footnote{In otherwords the size of a block of plaintext for the cipher, e.g. 8 for DES, 16 for AES, etc.} 
+of the cipher you choose.  It is important that the IV  be random for each unique message you want to encrypt.  The 
+parameters ``key'', ``keylen'' and ``num\_rounds'' are the same as in the XXX\_setup() function call.  The final parameter 
+is a pointer to the structure you want to hold the information for the mode of operation.
+
+Both routines return {\bf CRYPT\_OK} if the cipher initialized correctly, otherwise they return an error code.  To 
+actually encrypt or decrypt the following routines are provided:
+\begin{verbatim}
+int XXX_encrypt(const unsigned char *pt, unsigned char *ct, 
+                symmetric_XXX *XXX);
+int XXX_decrypt(const unsigned char *ct, unsigned char *pt,
+                symmetric_XXX *XXX);
+
+int YYY_encrypt(const unsigned char *pt, unsigned char *ct, 
+                unsigned long len, symmetric_YYY *YYY);
+int YYY_decrypt(const unsigned char *ct, unsigned char *pt, 
+                unsigned long len, symmetric_YYY *YYY);
+\end{verbatim}
+Where ``XXX'' is one of (ecb, cbc) and ``YYY'' is one of (ctr, ofb, cfb).  In the CTR, OFB and CFB cases ``len'' is the
+size of the buffer (as number of chars) to encrypt or decrypt.  The CTR, OFB and CFB modes are order sensitive but not
+chunk sensitive.  That is you can encrypt ``ABCDEF'' in three calls like ``AB'', ``CD'', ``EF'' or two like ``ABCDE'' and ``F''
+and end up with the same ciphertext.  However, encrypting ``ABC'' and ``DABC'' will result in different ciphertexts.  All
+five of the modes will return {\bf CRYPT\_OK} on success from the encrypt or decrypt functions.
+
+To decrypt in either mode you simply perform the setup like before (recall you have to fetch the IV value you used)
+and use the decrypt routine on all of the blocks.  When you are done working with either mode you should wipe the 
+memory (using ``zeromem()'') to help prevent the key from leaking.  For example:
+\newpage
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   unsigned char key[16], IV[16], buffer[512];
+   symmetric_CTR ctr;
+   int x, errno;
+
+   /* register twofish first */
+   if (register_cipher(&twofish_desc) == -1) {
+      printf("Error registering cipher.\n");
+      return -1;
+   }
+
+   /* somehow fill out key and IV */
+
+   /* start up CTR mode */
+   if ((errno = ctr_start(find_cipher("twofish"), IV, key, 16, 0, &ctr)) != CRYPT_OK) {
+      printf("ctr_start error: %s\n", error_to_string(errno));
+      return -1;
+   }
+
+   /* somehow fill buffer than encrypt it */
+   if ((errno = ctr_encrypt(buffer, buffer, sizeof(buffer), &ctr)) != CRYPT_OK) {
+      printf("ctr_encrypt error: %s\n", error_to_string(errno));
+      return -1;
+   }
+
+   /* make use of ciphertext... */
+
+   /* clear up and return */
+   zeromem(key, sizeof(key));
+   zeromem(&ctr, sizeof(ctr));
+
+   return 0;
+}
+\end{verbatim}
+\end{small}
+
+\section{Encrypt and Authenticate Modes}
+
+\subsection{EAX Mode}
+LibTomCrypt provides support for a mode called EAX\footnote{See 
+M. Bellare, P. Rogaway, D. Wagner, A Conventional Authenticated-Encryption Mode.} in a manner similar to the
+way it was intended to be used.
+
+First a short description of what EAX mode is before I explain how to use it.  EAX is a mode that requires a cipher,
+CTR and OMAC support and provides encryption and authentication.  It is initialized with a random ``nonce'' that can
+be shared publicly as well as a ``header'' which can be fixed and public as well as a random secret symmetric key.
+
+The ``header'' data is meant to be meta-data associated with a stream that isn't private (e.g. protocol messages).  It can
+be added at anytime during an EAX stream and is part of the authentication tag.  That is, changes in the meta-data can
+be detected by an invalid output tag.
+
+The mode can then process plaintext producing ciphertext as well as compute a partial checksum.  The actual checksum
+called a ``tag'' is only emitted when the message is finished.  In the interim though the user can process any arbitrary
+sized message block to send to the recipient as ciphertext.  This makes the EAX mode especially suited for streaming modes
+of operation.
+
+The mode is initialized with the following function.
+\begin{verbatim}
+int eax_init(eax_state *eax, int cipher, 
+             const unsigned char *key, unsigned long keylen,
+             const unsigned char *nonce, unsigned long noncelen,
+             const unsigned char *header, unsigned long headerlen);
+\end{verbatim}
+
+Where ``eax'' is the EAX state.  ``cipher'' is the index of the desired cipher in the descriptor table.  
+``key'' is the shared secret symmetric key of length ``keylen''.  ``nonce'' is the random public string of
+length ``noncelen''.  ``header'' is the random (or fixed or \textbf{NULL}) header for the message of length
+``headerlen''.
+
+When this function completes ``eax'' will be initialized such that you can now either have data decrypted or 
+encrypted in EAX mode.  Note that if ``headerlen'' is zero you may pass ``header'' as \textbf{NULL}.  It will still
+initialize the EAX ``H'' value to the correct value.  
+
+To encrypt or decrypt data in a streaming mode use the following.
+\begin{verbatim}
+int eax_encrypt(eax_state *eax, const unsigned char *pt, 
+                unsigned char *ct, unsigned long length);
+
+int eax_decrypt(eax_state *eax, const unsigned char *ct, 
+                unsigned char *pt, unsigned long length);
+\end{verbatim}
+The function ``eax\_encrypt'' will encrypt the bytes in ``pt'' of ``length'' bytes and store the ciphertext in
+``ct''.  Note that ``ct'' and ``pt'' may be the same region in memory.   This function will also send the ciphertext
+through the OMAC function.  The function ``eax\_decrypt'' decrypts ``ct'' and stores it in ``pt''.  This also allows 
+``pt'' and ``ct'' to be the same region in memory.  
+
+Note that both of these functions allow you to send the data in any granularity but the order is important.  While
+the eax\_init() function allows you to add initial header data to the stream you can also add header data during the
+EAX stream with the following.
+
+Also note that you cannot both encrypt or decrypt with the same ``eax'' context.  For bi-directional communication you
+will need to initialize two EAX contexts (preferably with different headers and nonces).  
+
+\begin{verbatim}
+int eax_addheader(eax_state *eax, 
+                  const unsigned char *header, unsigned long length);
+\end{verbatim}
+
+This will add the ``length'' bytes from ``header'' to the given ``eax'' stream.  Once the message is finished the 
+``tag'' (checksum) may be computed with the following function.
+
+\begin{verbatim}
+int eax_done(eax_state *eax, 
+             unsigned char *tag, unsigned long *taglen);
+\end{verbatim}
+This will terminate the EAX state ``eax'' and store upto ``taglen'' bytes of the message tag in ``tag''.  The function
+then stores how many bytes of the tag were written out back into ``taglen''.
+
+The EAX mode code can be tested to ensure it matches the test vectors by calling the following function.
+\begin{verbatim}
+int eax_test(void);
+\end{verbatim}
+This requires that the AES (or Rijndael) block cipher be registered with the cipher\_descriptor table first.
+
+\subsection{OCB Mode}
+LibTomCrypt provides support for a mode called OCB\footnote{See 
+P. Rogaway, M. Bellare, J. Black, T. Krovetz, ``OCB: A Block Cipher Mode of Operation for Efficient Authenticated Encryption''.}
+in a mode somewhat similar to as it was meant to be used.
+
+OCB is an encryption protocol that simultaneously provides authentication.  It is slightly faster to use than EAX mode
+but is less flexible.  Let's review how to initialize an OCB context.
+
+\begin{verbatim}
+int ocb_init(ocb_state *ocb, int cipher, 
+             const unsigned char *key, unsigned long keylen, 
+             const unsigned char *nonce);
+\end{verbatim}
+
+This will initialize the ``ocb'' context using cipher descriptor ``cipher''.  It will use a ``key'' of length ``keylen''
+and the random ``nonce''.  Note that ``nonce'' must be a random (public) string the same length as the block ciphers
+block size (e.g. 16 for AES).
+
+This mode has no ``Associated Data'' like EAX mode does which means you cannot authenticate metadata along with the stream.
+To encrypt or decrypt data use the following.
+
+\begin{verbatim}
+int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct);
+int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt);
+\end{verbatim}
+
+This will encrypt (or decrypt for the latter) a fixed length of data from ``pt'' to ``ct'' (vice versa for the latter).  
+They assume that ``pt'' and ``ct'' are the same size as the block cipher's block size.  Note that you cannot call 
+both functions given a single ``ocb'' state.  For bi-directional communication you will have to initialize two ``ocb''
+states (with different nonces).  Also ``pt'' and ``ct'' may point to the same location in memory.
+
+When you are finished encrypting the message you call the following function to compute the tag.
+
+\begin{verbatim}
+int ocb_done_encrypt(ocb_state *ocb, 
+                     const unsigned char *pt, unsigned long ptlen,
+                           unsigned char *ct, 
+                           unsigned char *tag, unsigned long *taglen);
+\end{verbatim}
+
+This will terminate an encrypt stream ``ocb''.  If you have trailing bytes of plaintext that will not complete a block 
+you can pass them here.  This will also encrypt the ``ptlen'' bytes in ``pt'' and store them in ``ct''.  It will also
+store upto ``taglen'' bytes of the tag into ``tag''.
+
+Note that ``ptlen'' must be less than or equal to the block size of block cipher chosen.  Also note that if you have 
+an input message equal to the length of the block size then you pass the data here (not to ocb\_encrypt()) only.  
+
+To terminate a decrypt stream and compared the tag you call the following.
+
+\begin{verbatim}
+int ocb_done_decrypt(ocb_state *ocb, 
+                     const unsigned char *ct,  unsigned long ctlen,
+                           unsigned char *pt, 
+                     const unsigned char *tag, unsigned long taglen, 
+                           int *res);
+\end{verbatim}
+
+Similarly to the previous function you can pass trailing message bytes into this function.  This will compute the 
+tag of the message (internally) and then compare it against the ``taglen'' bytes of ``tag'' provided.  By default
+``res'' is set to zero.  If all ``taglen'' bytes of ``tag'' can be verified then ``res'' is set to one (authenticated
+message).
+
+To make life simpler the following two functions are provided for memory bound OCB.
+
+\begin{verbatim}
+int ocb_encrypt_authenticate_memory(int cipher,
+    const unsigned char *key,    unsigned long keylen,
+    const unsigned char *nonce,  
+    const unsigned char *pt,     unsigned long ptlen,
+          unsigned char *ct,
+          unsigned char *tag,    unsigned long *taglen);
+\end{verbatim}
+
+This will OCB encrypt the message ``pt'' of length ``ptlen'' and store the ciphertext in ``ct''.  The length ``ptlen''
+can be any arbitrary length.  
+
+\begin{verbatim}
+int ocb_decrypt_verify_memory(int cipher,
+    const unsigned char *key,    unsigned long keylen,
+    const unsigned char *nonce,  
+    const unsigned char *ct,     unsigned long ctlen,
+          unsigned char *pt,
+    const unsigned char *tag,    unsigned long taglen,
+          int           *res);
+\end{verbatim}
+
+Similarly this will OCB decrypt and compare the internally computed tag against the tag provided. ``res'' is set 
+appropriately.
+
+
+
+\chapter{One-Way Cryptographic Hash Functions}
+\section{Core Functions}
+
+Like the ciphers there are hash core functions and a universal data type to hold the hash state called ``hash\_state''.  
+To initialize hash XXX (where XXX is the name) call:
+\index{Hash Functions}
+\begin{verbatim}
+void XXX_init(hash_state *md);
+\end{verbatim}
+
+This simply sets up the hash to the default state governed by the specifications of the hash.  To add data to the 
+message being hashed call:
+\begin{verbatim}
+int XXX_process(hash_state *md, const unsigned char *in, unsigned long len);
+\end{verbatim}
+
+Essentially all hash messages are virtually infinitely\footnote{Most hashes are limited to $2^{64}$ bits or 2,305,843,009,213,693,952 bytes.} long message which 
+are buffered.  The data can be passed in any sized chunks as long as the order of the bytes are the same the message digest
+(hash output) will be the same.  For example, this means that:
+\begin{verbatim}
+md5_process(&md, "hello ", 6);
+md5_process(&md, "world", 5);
+\end{verbatim}
+Will produce the same message digest as the single call:
+\index{Message Digest}
+\begin{verbatim}
+md5_process(&md, "hello world", 11);
+\end{verbatim}
+
+To finally get the message digest (the hash) call:
+\begin{verbatim}
+int XXX_done(hash_state *md, 
+              unsigned char *out);
+\end{verbatim}
+
+This function will finish up the hash and store the result in the ``out'' array.  You must ensure that ``out'' is long
+enough for the hash in question.  Often hashes are used to get keys for symmetric ciphers so the ``XXX\_done()'' functions
+will wipe the ``md'' variable before returning automatically.
+
+To test a hash function call:
+\begin{verbatim}
+int XXX_test(void);
+\end{verbatim}
+
+This will return {\bf CRYPTO\_OK} if the hash matches the test vectors, otherwise it returns an error code.  An
+example snippet that hashes a message with md5 is given below.
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+    hash_state md;
+    unsigned char *in = "hello world", out[16];
+
+    /* setup the hash */
+    md5_init(&md);
+
+    /* add the message */
+    md5_process(&md, in, strlen(in));
+
+    /* get the hash in out[0..15] */
+    md5_done(&md, out);
+
+    return 0;
+}
+\end{verbatim}
+\end{small}
+
+\section{Hash Descriptors}
+\index{Hash Descriptors}
+Like the set of ciphers the set of hashes have descriptors too.  They are stored in an array called ``hash\_descriptor'' and
+are defined by:
+\begin{verbatim}
+struct _hash_descriptor {
+    char *name;
+    unsigned long hashsize;    /* digest output size in bytes  */
+    unsigned long blocksize;   /* the block size the hash uses */
+    void (*init)   (hash_state *);
+    int  (*process)(hash_state *, const unsigned char *, unsigned long);
+    int  (*done)   (hash_state *, unsigned char *);
+    int  (*test)   (void);
+};
+\end{verbatim}
+
+Similarly ``name'' is the name of the hash function in ASCII (all lowercase).  ``hashsize'' is the size of the digest output
+in bytes.  The remaining fields are pointers to the functions that do the respective tasks.  There is a function to
+search the array as well called ``int find\_hash(char *name)''.  It returns -1 if the hash is not found, otherwise the
+position in the descriptor table of the hash.
+
+You can use the table to indirectly call a hash function that is chosen at runtime.  For example:
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   unsigned char buffer[100], hash[MAXBLOCKSIZE];
+   int idx, x;
+   hash_state md;
+
+   /* register hashes .... */
+   if (register_hash(&md5_desc) == -1) {
+      printf("Error registering MD5.\n");
+      return -1;
+   }
+
+   /* register other hashes ... */
+
+   /* prompt for name and strip newline */
+   printf("Enter hash name: \n");
+   fgets(buffer, sizeof(buffer), stdin);
+   buffer[strlen(buffer) - 1] = 0;
+
+   /* get hash index */
+   idx = find_hash(buffer);
+   if (idx == -1) {
+      printf("Invalid hash name!\n");
+      return -1;
+   }
+
+   /* hash input until blank line */
+   hash_descriptor[idx].init(&md);
+   while (fgets(buffer, sizeof(buffer), stdin) != NULL)
+         hash_descriptor[idx].process(&md, buffer, strlen(buffer));
+   hash_descriptor[idx].done(&md, hash);
+
+   /* dump to screen */
+   for (x = 0; x < hash_descriptor[idx].hashsize; x++)
+       printf("%02x ", hash[x]);
+   printf("\n");
+   return 0;
+}
+\end{verbatim}
+\end{small}
+
+Note the usage of ``MAXBLOCKSIZE''.  In Libtomcrypt no symmetric block, key or hash digest is larger than MAXBLOCKSIZE in
+length.  This provides a simple size you can set your automatic arrays to that will not get overrun.
+
+There are three helper functions as well:
+\index{hash\_memory()} \index{hash\_file()}
+\begin{verbatim}
+int hash_memory(int hash, const unsigned char *data, 
+                unsigned long len, unsigned char *dst,
+                unsigned long *outlen);
+
+int hash_file(int hash, const char *fname, 
+              unsigned char *dst,
+              unsigned long *outlen);
+
+int hash_filehandle(int hash, FILE *in, 
+                    unsigned char *dst, unsigned long *outlen);
+\end{verbatim}
+
+The ``hash'' parameter is the location in the descriptor table of the hash (\textit{e.g. the return of find\_hash()}).  
+The ``*outlen'' variable is used to keep track of the output size.  You
+must set it to the size of your output buffer before calling the functions.  When they complete succesfully they store
+the length of the message digest back in it.  The functions are otherwise straightforward.  The ``hash\_filehandle'' 
+function assumes that ``in'' is an file handle opened in binary mode.  It will hash to the end of file and not reset
+the file position when finished.
+
+To perform the above hash with md5 the following code could be used:
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   int idx, errno;
+   unsigned long len;
+   unsigned char out[MAXBLOCKSIZE];
+
+   /* register the hash */
+   if (register_hash(&md5_desc) == -1) {
+      printf("Error registering MD5.\n");
+      return -1;
+   }
+
+   /* get the index of the hash  */
+   idx = find_hash("md5");
+
+   /* call the hash */
+   len = sizeof(out);
+   if ((errno = hash_memory(idx, "hello world", 11, out, &len)) != CRYPT_OK) {
+      printf("Error hashing data: %s\n", error_to_string(errno));
+      return -1;
+   }
+   return 0;
+}
+\end{verbatim}
+\end{small}
+
+The following hashes are provided as of this release:
+\begin{center}
+\begin{tabular}{|c|c|c|}
+      \hline Name & Descriptor Name & Size of Message Digest (bytes) \\
+      \hline WHIRLPOOL & whirlpool\_desc & 64 \\
+      \hline SHA-512 & sha512\_desc & 64 \\
+      \hline SHA-384 & sha384\_desc & 48 \\
+      \hline SHA-256 & sha256\_desc & 32 \\
+      \hline SHA-224 & sha224\_desc & 28 \\
+      \hline TIGER-192 & tiger\_desc & 24 \\
+      \hline SHA-1 & sha1\_desc & 20 \\
+      \hline RIPEMD-160 & rmd160\_desc & 20 \\
+      \hline RIPEMD-128 & rmd128\_desc & 16 \\
+      \hline MD5 & md5\_desc & 16 \\
+      \hline MD4 & md4\_desc & 16 \\
+      \hline MD2 & md2\_desc & 16 \\
+      \hline
+\end{tabular}
+\end{center}
+
+Similar to the cipher descriptor table you must register your hash algorithms before you can use them.  These functions
+work exactly like those of the cipher registration code.  The functions are:
+\begin{verbatim}
+int register_hash(const struct _hash_descriptor *hash);
+int unregister_hash(const struct _hash_descriptor *hash);
+\end{verbatim}
+
+\subsection{Notice}
+It is highly recommended that you \textbf{not} use the MD4 or MD5 hashes for the purposes of digital signatures or authentication codes.  
+These hashes are provided for completeness and they still can be used for the purposes of password hashing or one-way accumulators
+(e.g. Yarrow).
+
+The other hashes such as the SHA-1, SHA-2 (that includes SHA-512, SHA-384 and SHA-256) and TIGER-192 are still considered secure
+for all purposes you would normally use a hash for.
+
+\chapter{Message Authentication Codes}
+\section{HMAC Protocol}
+Thanks to Dobes Vandermeer the library now includes support for hash based message authenication codes or HMAC for short.  An HMAC
+of a message is a keyed authenication code that only the owner of a private symmetric key will be able to verify.  The purpose is
+to allow an owner of a private symmetric key to produce an HMAC on a message then later verify if it is correct.  Any impostor or
+eavesdropper will not be able to verify the authenticity of a message.  
+
+The HMAC support works much like the normal hash functions except that the initialization routine requires you to pass a key 
+and its length.  The key is much like a key you would pass to a cipher.  That is, it is simply an array of octets stored in
+chars.  The initialization routine is:
+\begin{verbatim}
+int hmac_init(hmac_state *hmac, int hash, 
+              const unsigned char *key, unsigned long keylen);
+\end{verbatim}
+The ``hmac'' parameter is the state for the HMAC code.  ``hash'' is the index into the descriptor table of the hash you want
+to use to authenticate the message.  ``key'' is the pointer to the array of chars that make up the key.  ``keylen'' is the
+length (in octets) of the key you want to use to authenticate the message.  To send octets of a message through the HMAC system you must use the following function:
+\begin{verbatim}
+int hmac_process(hmac_state *hmac, const unsigned char *buf,
+                  unsigned long len);
+\end{verbatim}
+``hmac'' is the HMAC state you are working with. ``buf'' is the array of octets to send into the HMAC process.  ``len'' is the
+number of octets to process.  Like the hash process routines you can send the data in arbitrarly sized chunks. When you 
+are finished with the HMAC process you must call the following function to get the HMAC code:
+\begin{verbatim}
+int hmac_done(hmac_state *hmac, unsigned char *hashOut,
+              unsigned long *outlen);
+\end{verbatim}
+``hmac'' is the HMAC state you are working with.  ``hashOut'' is the array of octets where the HMAC code should be stored.  You must
+set ``outlen'' to the size of the destination buffer before calling this function.  It is updated with the length of the HMAC code
+produced (depending on which hash was picked).  If ``outlen'' is less than the size of the message digest (and ultimately
+the HMAC code) then the HMAC code is truncated as per FIPS-198 specifications (e.g. take the first ``outlen'' bytes).
+
+There are two  utility functions provided to make using HMACs easier todo.  They accept the key and information about the
+message (file pointer, address in memory) and produce the HMAC result in one shot.  These are useful if you want to avoid
+calling the three step process yourself.
+
+\begin{verbatim}
+int hmac_memory(int hash, const unsigned char *key, unsigned long keylen,
+                const unsigned char *data, unsigned long len, 
+                unsigned char *dst, unsigned long *dstlen);
+\end{verbatim}
+This will produce an HMAC code for the array of octets in ``data'' of length ``len''.  The index into the hash descriptor 
+table must be provided in ``hash''.  It uses the key from ``key'' with a key length of ``keylen''.  
+The result is stored in the array of octets ``dst'' and the length in ``dstlen''.  The value of ``dstlen'' must be set
+to the size of the destination buffer before calling this function.  Similarly for files there is the  following function:
+\begin{verbatim}
+int hmac_file(int hash, const char *fname, const unsigned char *key,
+              unsigned long keylen, 
+              unsigned char *dst, unsigned long *dstlen);
+\end{verbatim}
+``hash'' is the index into the hash descriptor table of the hash you want to use.  ``fname'' is the filename to process.  
+``key'' is the array of octets to use as the key of length ``keylen''.  ``dst'' is the array of octets where the 
+result should be stored.
+
+To test if the HMAC code is working there is the following function:
+\begin{verbatim}
+int hmac_test(void);
+\end{verbatim}
+Which returns {\bf CRYPT\_OK} if the code passes otherwise it returns an error code.  Some example code for using the 
+HMAC system is given below.
+
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   int idx, errno;
+   hmac_state hmac;
+   unsigned char key[16], dst[MAXBLOCKSIZE];
+   unsigned long dstlen;
+
+   /* register SHA-1 */
+   if (register_hash(&sha1_desc) == -1) {
+      printf("Error registering SHA1\n");
+      return -1;
+   }
+
+   /* get index of SHA1 in hash descriptor table */
+   idx = find_hash("sha1");
+
+   /* we would make up our symmetric key in "key[]" here */
+
+   /* start the HMAC */
+   if ((errno = hmac_init(&hmac, idx, key, 16)) != CRYPT_OK) {
+      printf("Error setting up hmac: %s\n", error_to_string(errno));
+      return -1;
+   }
+
+   /* process a few octets */
+   if((errno = hmac_process(&hmac, "hello", 5) != CRYPT_OK) {
+      printf("Error processing hmac: %s\n", error_to_string(errno));
+      return -1;
+   }
+
+   /* get result (presumably to use it somehow...) */
+   dstlen = sizeof(dst);
+   if ((errno = hmac_done(&hmac, dst, &dstlen)) != CRYPT_OK) {
+      printf("Error finishing hmac: %s\n", error_to_string(errno));
+      return -1;
+   }
+   printf("The hmac is %lu bytes long\n", dstlen);
+  
+   /* return */
+   return 0;
+}
+\end{verbatim}
+\end{small}
+
+\section{OMAC Support}
+OMAC\footnote{\url{http://crypt.cis.ibaraki.ac.jp/omac/omac.html}}, which stands for \textit{One-Key CBC MAC} is an 
+algorithm which produces a Message Authentication Code (MAC) using only a block cipher such as AES.  From an API 
+standpoint the OMAC routines work much like the HMAC routines do.  Instead in this case a cipher is used instead of a hash.  
+
+To start an OMAC state you call
+
+\begin{verbatim}
+int omac_init(omac_state *omac, int cipher, 
+              const unsigned char *key, unsigned long keylen);
+\end{verbatim}
+The ``omac'' variable is the state for the OMAC algorithm.  ``cipher'' is the index into the cipher\_descriptor table
+of the cipher\footnote{The cipher must have a 64 or 128 bit block size.  Such as CAST5, Blowfish, DES, AES, Twofish, etc.} you
+wish to use.  ``key'' and ``keylen'' are the keys used to authenticate the data.
+
+To send data through the algorithm call
+\begin{verbatim}
+int omac_process(omac_state *state, 
+                 const unsigned char *buf, unsigned long len);
+\end{verbatim}
+This will send ``len'' bytes from ``buf'' through the active OMAC state ``state''.  Returns \textbf{CRYPT\_OK} if the 
+function succeeds.  The function is not sensitive to the granularity of the data.  For example,
+
+\begin{verbatim}
+omac_process(&mystate, "hello",  5);
+omac_process(&mystate, " world", 6);
+\end{verbatim}
+
+Would produce the same result as,
+
+\begin{verbatim}
+omac_process(&mystate, "hello world",  11);
+\end{verbatim}
+
+When you are done processing the message you can call the following to compute the message tag.
+
+\begin{verbatim}
+int omac_done(omac_state *state, 
+              unsigned char *out, unsigned long *outlen);
+\end{verbatim}
+Which will terminate the OMAC and output the \textit{tag} (MAC) to ``out''.  Note that unlike the HMAC and other code 
+``outlen'' can be smaller than the default MAC size (for instance AES would make a 16-byte tag).  Part of the OMAC 
+specification states that the output may be truncated.  So if you pass in $outlen = 5$ and use AES as your cipher than
+the output MAC code will only be five bytes long.  If ``outlen'' is larger than the default size it is set to the default
+size to show how many bytes were actually used.
+
+Similar to the HMAC code the file and memory functions are also provided.  To OMAC a buffer of memory in one shot use the 
+following function.
+
+\begin{verbatim}
+int omac_memory(int cipher, 
+                const unsigned char *key, unsigned long keylen,
+                const unsigned char *msg, unsigned long msglen,
+                unsigned char *out, unsigned long *outlen);
+\end{verbatim}
+This will compute the OMAC of ``msglen'' bytes of ``msg'' using the key ``key'' of length ``keylen'' bytes and the cipher
+specified by the ``cipher'''th entry in the cipher\_descriptor table.  It will store the MAC in ``out'' with the same
+rules as omac\_done.
+
+To OMAC a file use
+\begin{verbatim}
+int omac_file(int cipher, 
+              const unsigned char *key, unsigned long keylen,
+              const char *filename, 
+              unsigned char *out, unsigned long *outlen);
+\end{verbatim}
+
+Which will OMAC the entire contents of the file specified by ``filename'' using the key ``key'' of length ``keylen'' bytes
+and the cipher specified by the ``cipher'''th entry in the cipher\_descriptor table.  It will store the MAC in ``out'' with 
+the same rules as omac\_done.
+
+To test if the OMAC code is working there is the following function:
+\begin{verbatim}
+int omac_test(void);
+\end{verbatim}
+Which returns {\bf CRYPT\_OK} if the code passes otherwise it returns an error code.  Some example code for using the 
+OMAC system is given below.
+
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   int idx, err;
+   omac_state omac;
+   unsigned char key[16], dst[MAXBLOCKSIZE];
+   unsigned long dstlen;
+
+   /* register Rijndael */
+   if (register_cipher(&rijndael_desc) == -1) {
+      printf("Error registering Rijndael\n");
+      return -1;
+   }
+
+   /* get index of Rijndael in cipher descriptor table */
+   idx = find_cipher("rijndael");
+
+   /* we would make up our symmetric key in "key[]" here */
+
+   /* start the OMAC */
+   if ((err = omac_init(&omac, idx, key, 16)) != CRYPT_OK) {
+      printf("Error setting up omac: %s\n", error_to_string(err));
+      return -1;
+   }
+
+   /* process a few octets */
+   if((err = omac_process(&omac, "hello", 5) != CRYPT_OK) {
+      printf("Error processing omac: %s\n", error_to_string(err));
+      return -1;
+   }
+
+   /* get result (presumably to use it somehow...) */
+   dstlen = sizeof(dst);
+   if ((err = omac_done(&omac, dst, &dstlen)) != CRYPT_OK) {
+      printf("Error finishing omac: %s\n", error_to_string(err));
+      return -1;
+   }
+   printf("The omac is %lu bytes long\n", dstlen);
+  
+   /* return */
+   return 0;
+}
+\end{verbatim}
+\end{small}
+
+\section{PMAC Support}
+The PMAC\footnote{J.Black, P.Rogaway, ``A Block--Cipher Mode of Operation for Parallelizable Message Authentication''} 
+protocol is another MAC algorithm that relies solely on a symmetric-key block cipher.  It uses essentially the same
+API as the provided OMAC code.  
+
+A PMAC state is initialized with the following.
+
+\begin{verbatim}
+int pmac_init(pmac_state *pmac, int cipher, 
+              const unsigned char *key, unsigned long keylen);
+\end{verbatim}
+Which initializes the ``pmac'' state with the given ``cipher'' and ``key'' of length ``keylen'' bytes.  The chosen cipher
+must have a 64 or 128 bit block size (e.x. AES).
+
+To MAC data simply send it through the process function.
+
+\begin{verbatim}
+int pmac_process(pmac_state *state, 
+                 const unsigned char *buf, unsigned long len);
+\end{verbatim}
+This will process ``len'' bytes of ``buf'' in the given ``state''.  The function is not sensitive to the granularity of the
+data.  For example,
+
+\begin{verbatim}
+pmac_process(&mystate, "hello",  5);
+pmac_process(&mystate, " world", 6);
+\end{verbatim}
+
+Would produce the same result as,
+
+\begin{verbatim}
+pmac_process(&mystate, "hello world",  11);
+\end{verbatim}
+
+When a complete message has been processed the following function can be called to compute the message tag.
+
+\begin{verbatim}
+int pmac_done(pmac_state *state, 
+              unsigned char *out, unsigned long *outlen);
+\end{verbatim}
+This will store upto ``outlen'' bytes of the tag for the given ``state'' into ``out''.  Note that if ``outlen'' is larger
+than the size of the tag it is set to the amount of bytes stored in ``out''.
+
+Similar to the PMAC code the file and memory functions are also provided.  To PMAC a buffer of memory in one shot use the 
+following function.
+
+\begin{verbatim}
+int pmac_memory(int cipher, 
+                const unsigned char *key, unsigned long keylen,
+                const unsigned char *msg, unsigned long msglen,
+                unsigned char *out, unsigned long *outlen);
+\end{verbatim}
+This will compute the PMAC of ``msglen'' bytes of ``msg'' using the key ``key'' of length ``keylen'' bytes and the cipher
+specified by the ``cipher'''th entry in the cipher\_descriptor table.  It will store the MAC in ``out'' with the same
+rules as omac\_done.
+
+To PMAC a file use
+\begin{verbatim}
+int pmac_file(int cipher, 
+              const unsigned char *key, unsigned long keylen,
+              const char *filename, 
+              unsigned char *out, unsigned long *outlen);
+\end{verbatim}
+
+Which will PMAC the entire contents of the file specified by ``filename'' using the key ``key'' of length ``keylen'' bytes
+and the cipher specified by the ``cipher'''th entry in the cipher\_descriptor table.  It will store the MAC in ``out'' with 
+the same rules as omac\_done.
+
+To test if the PMAC code is working there is the following function:
+\begin{verbatim}
+int pmac_test(void);
+\end{verbatim}
+Which returns {\bf CRYPT\_OK} if the code passes otherwise it returns an error code.
+
+
+\chapter{Pseudo-Random Number Generators}
+\section{Core Functions}
+
+The library provides an array of core functions for Pseudo-Random Number Generators (PRNGs) as well.  A cryptographic PRNG is
+used to expand a shorter bit string into a longer bit string.  PRNGs are used wherever random data is required such as Public Key (PK)
+key generation.  There is a universal structure called ``prng\_state''.  To initialize a PRNG call:
+\begin{verbatim}
+int XXX_start(prng_state *prng);
+\end{verbatim}
+
+This will setup the PRNG for future use and not seed it.  In order 
+for the PRNG to be cryptographically useful you must give it entropy.  Ideally you'd have some OS level source to tap 
+like in UNIX (see section 5.3).  To add entropy to the PRNG call:
+\begin{verbatim}
+int XXX_add_entropy(const unsigned char *in, unsigned long len, 
+                    prng_state *prng);
+\end{verbatim}
+
+Which returns {\bf CRYPTO\_OK} if the entropy was accepted.  Once you think you have enough entropy you call another
+function to put the entropy into action.
+\begin{verbatim}
+int XXX_ready(prng_state *prng);
+\end{verbatim}
+
+Which returns {\bf CRYPTO\_OK} if it is ready.  Finally to actually read bytes call:
+\begin{verbatim}
+unsigned long XXX_read(unsigned char *out, unsigned long len,
+                       prng_state *prng);
+\end{verbatim}
+
+Which returns the number of bytes read from the PRNG.
+
+\subsection{Remarks}
+
+It is possible to be adding entropy and reading from a PRNG at the same time.  For example, if you first seed the PRNG
+and call ready() you can now read from it.  You can also keep adding new entropy to it.  The new entropy will not be used
+in the PRNG until ready() is called again.  This allows the PRNG to be used and re-seeded at the same time.  No real error 
+checking is guaranteed to see if the entropy is sufficient or if the PRNG is even in a ready state before reading.
+
+\subsection{Example}
+
+Below is a simple snippet to read 10 bytes from yarrow.  Its important to note that this snippet is {\bf NOT} secure since
+the entropy added is not random.
+
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   prng_state prng;
+   unsigned char buf[10];
+   int err;
+   
+   /* start it */
+   if ((err = yarrow_start(&prng)) != CRYPT_OK) {
+      printf("Start error: %s\n", error_to_string(err));
+   }
+   /* add entropy */
+   if ((err = yarrow_add_entropy("hello world", 11, &prng)) != CRYPT_OK) {
+      printf("Add_entropy error: %s\n", error_to_string(err));
+   }
+   /* ready and read */
+   if ((err = yarrow_ready(&prng)) != CRYPT_OK) {
+      printf("Ready error: %s\n", error_to_string(err));
+   }
+   printf("Read %lu bytes from yarrow\n", yarrow_read(buf, 10, &prng));
+   return 0;
+}
+\end{verbatim}
+
+\section{PRNG Descriptors}
+\index{PRNG Descriptor}
+PRNGs have descriptors too (surprised?). Stored in the structure ``prng\_descriptor''.  The format of an element is:
+\begin{verbatim}
+struct _prng_descriptor {
+    char *name;
+    int (*start)      (prng_state *);
+    int (*add_entropy)(const unsigned char *, unsigned long, prng_state *);
+    int (*ready)      (prng_state *);
+    unsigned long (*read)(unsigned char *, unsigned long len, prng_state *);
+};
+\end{verbatim}
+
+There is a ``int find\_prng(char *name)'' function as well.  Returns -1 if the PRNG is not found, otherwise it returns
+the position in the prng\_descriptor array.
+
+Just like the ciphers and hashes you must register your prng before you can use it.  The two functions provided work
+exactly as those for the cipher registry functions.  They are:
+\begin{verbatim}
+int register_prng(const struct _prng_descriptor *prng);
+int unregister_prng(const struct _prng_descriptor *prng);
+\end{verbatim}
+
+\subsubsection{PRNGs Provided}
+Currently Yarrow (yarrow\_desc), RC4 (rc4\_desc) and the secure RNG (sprng\_desc) are provided as PRNGs within the 
+library.  
+
+RC4 is provided with a PRNG interface because it is a stream cipher and not well suited for the symmetric block cipher
+interface.  You provide the key for RC4 via the rc4\_add\_entropy() function.  By calling rc4\_ready() the key will be used
+to setup the RC4 state for encryption or decryption.  The rc4\_read() function has been modified from RC4 since it will 
+XOR the output of the RC4 keystream generator against the input buffer you provide.  The following snippet will demonstrate
+how to encrypt a buffer with RC4:
+
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   prng_state prng;
+   unsigned char buf[32];
+   int err;
+
+   if ((err = rc4_start(&prng)) != CRYPT_OK) {
+      printf("RC4 init error: %s\n", error_to_string(err));
+      exit(-1);
+   }
+
+   /* use ``key'' as the key */
+   if ((err = rc4_add_entropy("key", 3, &prng)) != CRYPT_OK) {
+      printf("RC4 add entropy error: %s\n", error_to_string(err));
+      exit(-1);
+   }
+
+   /* setup RC4 for use */
+   if ((err = rc4_ready(&prng)) != CRYPT_OK) {
+      printf("RC4 ready error: %s\n", error_to_string(err));
+      exit(-1);
+   }
+
+   /* encrypt buffer */
+   strcpy(buf,"hello world");
+   if (rc4_read(buf, 11, &prng) != 11) {
+      printf("RC4 read error\n");
+      exit(-1);
+   }
+   return 0;
+}   
+\end{verbatim}
+\end{small}
+To decrypt you have to do the exact same steps.  
+
+\section{The Secure RNG}
+\index{Secure RNG}
+An RNG is related to a PRNG except that it doesn't expand a smaller seed to get the data.  They generate their random bits
+by performing some computation on fresh input bits.  Possibly the hardest thing to get correctly in a cryptosystem is the 
+PRNG.  Computers are deterministic beasts that try hard not to stray from pre-determined paths.  That makes gathering 
+entropy needed to seed the PRNG a hard task.  
+
+There is one small function that may help on certain platforms:
+\index{rng\_get\_bytes()}
+\begin{verbatim}
+unsigned long rng_get_bytes(unsigned char *buf, unsigned long len, 
+                  void (*callback)(void));
+\end{verbatim}
+
+Which will try one of three methods of getting random data.  The first is to open the popular ``/dev/random'' device which 
+on most *NIX platforms provides cryptographic random bits\footnote{This device is available in Windows through the Cygwin compiler suite.  It emulates ``/dev/random'' via the Microsoft CSP.}.  
+The second method is to try the Microsoft Cryptographic Service Provider and read the RNG.  The third method is an ANSI C 
+clock drift method that is also somewhat popular but gives bits of lower entropy.  The ``callback'' parameter is a pointer to a function that returns void.  Its used when the slower ANSI C RNG must be 
+used so the calling application can still work.  This is useful since the ANSI C RNG has a throughput of three 
+bytes a second.  The callback pointer may be set to {\bf NULL} to avoid using it if you don't want to.  The function 
+returns the number of bytes actually read from any RNG source.  There is a function to help setup a PRNG as well:
+\index{rng\_make\_prng()}
+\begin{verbatim}
+int rng_make_prng(int bits, int wprng, prng_state *prng, 
+                  void (*callback)(void));
+\end{verbatim}
+This will try to setup the prng with a state of at least ``bits'' of entropy.  The ``callback'' parameter works much like
+the callback in ``rng\_get\_bytes()''.  It is highly recommended that you use this function to setup your PRNGs unless you have a
+platform where the RNG doesn't work well.  Example usage of this function is given below.
+
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   ecc_key mykey;
+   prng_state prng;
+   int err;
+
+   /* register yarrow */
+   if (register_prng(&yarrow_desc) == -1) {
+      printf("Error registering Yarrow\n");
+      return -1;
+   }
+
+   /* setup the PRNG */
+   if ((err = rng_make_prng(128, find_prng("yarrow"), &prng, NULL)) != CRYPT_OK) {
+      printf("Error setting up PRNG, %s\n", error_to_string(err));
+      return -1;
+   }
+
+   /* make a 192-bit ECC key */
+   if ((err = ecc_make_key(&prng, find_prng("yarrow"), 24, &mykey)) != CRYPT_OK) {
+      printf("Error making key: %s\n", error_to_string(err));
+      return -1;
+   }
+   return 0;
+}
+\end{verbatim}
+\end{small}
+
+\subsection{The Secure PRNG Interface}
+It is possible to access the secure RNG through the PRNG interface and in turn use it within dependent functions such
+as the PK API.  This simplifies the cryptosystem on platforms where the secure RNG is fast.  The secure PRNG never 
+requires to be started, that is you need not call the start, add\_entropy or ready functions.  For example, consider
+the previous example using this PRNG.
+
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   ecc_key mykey;
+   int err;
+
+   /* register SPRNG */
+   if (register_prng(&sprng_desc) == -1) {
+      printf("Error registering SPRNG\n");
+      return -1;
+   }
+
+   /* make a 192-bit ECC key */
+   if ((err = ecc_make_key(NULL, find_prng("sprng"), 24, &mykey)) != CRYPT_OK) {
+      printf("Error making key: %s\n", error_to_string(err));
+      return -1;
+   }
+   return 0;
+}
+\end{verbatim}
+\end{small}
+
+\chapter{RSA Public Key Cryptography}
+\textbf{Note: } \textit{This chapter on PKCS \#1 RSA will replace the older chapter on RSA (The current chapter nine) in subsequent 
+releases of the library.  Users are encouraged to stop using the LibTomCrypt style padding functions.}
+
+\section{PKCS \#1 Encryption}
+
+PKCS \#1 RSA Encryption amounts to OAEP padding of the input message followed by the modular exponentiation.  As far as this portion of
+the library is concerned we are only dealing with th OAEP padding of the message.
+
+\subsection{OAEP Encoding}
+
+\begin{alltt}
+int pkcs_1_oaep_encode(const unsigned char *msg,    unsigned long msglen,
+                       const unsigned char *lparam, unsigned long lparamlen,
+                             unsigned long modulus_bitlen, int hash_idx,
+                             int           prng_idx,    prng_state *prng,
+                             unsigned char *out,    unsigned long *outlen);
+\end{alltt}
+
+This accepts ``msg'' as input of length ``msglen'' which will be OAEP padded.  The ``lparam'' variable is an additional system specific
+tag that can be applied to the encoding.  This is useful to identify which system encoded the message.  If no variance is desired then
+``lparam'' can be set to \textbf{NULL}.  
+
+OAEP encoding requires the length of the modulus in bits in order to calculate the size of the output.  This is passed as the parameter
+``modulus\_bitlen''.  ``hash\_idx'' is the index into the hash descriptor table of the hash desired.  PKCS \#1 allows any hash to be 
+used but both the encoder and decoder must use the same hash in order for this to succeed.  The size of hash output affects the maximum
+ sized input message.  ``prng\_idx'' and ``prng'' are the random number generator arguments required to randomize the padding process.  
+The padded message is stored in ``out'' along with the length in ``outlen''.
+
+If $h$ is the length of the hash and $m$ the length of the modulus (both in octets) then the maximum payload for ``msg'' is 
+$m - 2h - 2$.  For example, with a $1024$--bit RSA key and SHA--1 as the hash the maximum payload is $86$ bytes.  
+
+Note that when the message is padded it still has not been RSA encrypted.  You must pass the output of this function to 
+rsa\_exptmod() to encrypt it. 
+
+\subsection{OAEP Decoding}
+
+\begin{alltt}
+int pkcs_1_oaep_decode(const unsigned char *msg,    unsigned long msglen,
+                       const unsigned char *lparam, unsigned long lparamlen,
+                             unsigned long modulus_bitlen, int hash_idx,
+                             unsigned char *out,    unsigned long *outlen);
+\end{alltt}
+
+This function decodes an OAEP encoded message and outputs the original message that was passed to the OAEP encoder.  ``msg'' is the 
+output of pkcs\_1\_oaep\_encode() of length ``msglen''.  ``lparam'' is the same system variable passed to the OAEP encoder.  If it does not
+match what was used during encoding this function will not decode the packet.  ``modulus\_bitlen'' is the size of the RSA modulus in bits
+and must match what was used during encoding.  Similarly the ``hash\_idx'' index into the hash descriptor table must match what was used
+during encoding.
+
+If the function succeeds it decodes the OAEP encoded message into ``out'' of length ``outlen''.  
+
+\section{PKCS \#1 Digital Signatures}
+
+\subsection{PSS Encoding}
+PSS encoding is the second half of the PKCS \#1 standard which is padding to be applied to messages that are signed.  
+
+\begin{alltt}
+int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
+                            unsigned long saltlen,  int           hash_idx,
+                            int           prng_idx, prng_state   *prng,
+                            unsigned long modulus_bitlen,
+                            unsigned char *out,     unsigned long *outlen);
+\end{alltt}
+
+This function assumes the message to be PSS encoded has previously been hashed.  The input hash ``msghash'' is of length 
+``msghashlen''.  PSS allows a variable length random salt (it can be zero length) to be introduced in the signature process.  
+``hash\_idx'' is the index into the hash descriptor table of the hash to use.  ``prng\_idx'' and ``prng'' are the random
+number generator information required for the salt.
+
+Similar to OAEP encoding ``modulus\_bitlen'' is the size of the RSA modulus.  It limits the size of the salt.  If $m$ is the length
+of the modulus $h$ the length of the hash output (in octets) then there can be $m - h - 2$ bytes of salt.  
+
+This function does not actually sign the data it merely pads the hash of a message so that it can be processed by rsa\_exptmod().
+
+\subsection{PSS Decoding}
+
+To decode a PSS encoded signature block you have to use the following.
+
+\begin{alltt}
+int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
+                      const unsigned char *sig,     unsigned long siglen,
+                            unsigned long saltlen,  int           hash_idx,
+                            unsigned long modulus_bitlen, int    *res);
+\end{alltt}
+This will decode the PSS encoded message in ``sig'' of length ``siglen'' and compare it to values in ``msghash'' of length
+``msghashlen''.  If the block is a valid PSS block and the decoded hash equals the hash supplied ``res'' is set to non--zero.  Otherwise, 
+it is set to zero.  The rest of the parameters are as in the PSS encode call.
+
+It's important to use the same ``saltlen'' and hash for both encoding and decoding as otherwise the procedure will not work.
+
+\chapter{Password Based Cryptography}
+\section{PKCS \#5}
+In order to securely handle user passwords for the purposes of creating session keys and chaining IVs the PKCS \#5 was drafted.   PKCS \#5
+is made up of two algorithms, Algorithm One and Algorithm Two.  Algorithm One is the older fairly limited algorithm which has been implemented
+for completeness.  Algorithm Two is a bit more modern and more flexible to work with.
+
+\section{Algorithm One}
+Algorithm One accepts as input a password, an 8--byte salt and an iteration counter.  The iteration counter is meant to act as delay for
+people trying to brute force guess the password.  The higher the iteration counter the longer the delay.  This algorithm also requires a hash 
+algorithm and produces an output no longer than the output of the hash.  
+
+\begin{alltt}
+int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, 
+                const unsigned char *salt, 
+                int iteration_count,  int hash_idx,
+                unsigned char *out,   unsigned long *outlen)
+\end{alltt}
+Where ``password'' is the users password.  Since the algorithm allows binary passwords you must also specify the length in ``password\_len''.  
+The ``salt'' is a fixed size 8--byte array which should be random for each user and session.  The ``iteration\_count'' is the delay desired
+on the password.  The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table.  
+
+The output of length upto ``outlen'' is stored in ``out''.  If ``outlen'' is initially larger than the size of the hash functions output
+it is set to the number of bytes stored.  If it is smaller than not all of the hash output is stored in ``out''.
+
+\section{Algorithm Two}
+
+Algorithm Two is the recommended algorithm for this task.  It allows variable length salts and can produce outputs larger than the 
+hash functions output.  As such it can easily be used to derive session keys for ciphers and MACs as well initial vectors as required
+from a single password and invokation of this algorithm.
+
+\begin{alltt}
+int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, 
+                const unsigned char *salt,     unsigned long salt_len,
+                int iteration_count,           int hash_idx,
+                unsigned char *out,            unsigned long *outlen)
+\end{alltt}
+Where ``password'' is the users password.  Since the algorithm allows binary passwords you must also specify the length in ``password\_len''.  
+The ``salt'' is an array of size ``salt\_len''.  It should be random for each user and session.  The ``iteration\_count'' is the delay desired
+on the password.  The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table.   The output of length upto 
+``outlen'' is stored in ``out''.
+
+\begin{alltt}
+/* demo to show how to make session state material from a password */
+#include <mycrypt.h>
+int main(void)
+\{
+    unsigned char password[100], salt[100],
+                  cipher_key[16], cipher_iv[16],
+                  mac_key[16], outbuf[48];
+    int           err, hash_idx;
+    unsigned long outlen, password_len, salt_len;
+
+    /* register hash and get it's idx .... */
+
+    /* get users password and make up a salt ... */
+
+    /* create the material (100 iterations in algorithm) */
+    outlen = sizeof(outbuf);
+    if ((err = pkcs_5_alg2(password, password_len, salt, salt_len, 
+                           100, hash_idx, outbuf, &outlen)) != CRYPT_OK) \{
+       /* error handle */
+    \}
+
+    /* now extract it */
+    memcpy(cipher_key, outbuf, 16);
+    memcpy(cipher_iv,  outbuf+16, 16);
+    memcpy(mac_key,    outbuf+32, 16);
+
+    /* use material (recall to store the salt in the output) */
+\}
+\end{alltt}
+
+\chapter{RSA Routines}
+
+\textbf{Note: } \textit{This chapter has been marked for removal.  In particular any function that uses the LibTomCrypt style 
+RSA padding (e.g. rsa\_pad() rsa\_signpad())  will be removed in the v0.96 release cycle.  The functions like rsa\_make\_key() and
+rsa\_exptmod() will stay but may be slightly modified. }
+
+\section{Background}
+
+RSA is a public key algorithm that is based on the inability to find the ``e-th'' root modulo a composite of unknown 
+factorization.  Normally the difficulty of breaking RSA is associated with the integer factoring problem but they are
+not strictly equivalent.
+
+The system begins with with two primes $p$ and $q$ and their product $N = pq$.  The order or ``Euler totient'' of the
+multiplicative sub-group formed modulo $N$ is given as $\phi(N) = (p - 1)(q - 1)$ which can be reduced to 
+$\mbox{lcm}(p - 1, q - 1)$.  The public key consists of the composite $N$ and some integer $e$ such that 
+$\mbox{gcd}(e, \phi(N)) = 1$.  The private key consists of the composite $N$ and the inverse of $e$ modulo $\phi(N)$ 
+often simply denoted as $de \equiv 1\mbox{ }(\mbox{mod }\phi(N))$.
+
+A person who wants to encrypt with your public key simply forms an integer (the plaintext) $M$ such that 
+$1 < M < N-2$ and computes the ciphertext $C = M^e\mbox{ }(\mbox{mod }N)$.  Since finding the inverse exponent $d$
+given only $N$ and $e$ appears to be intractable only the owner of the private key can decrypt the ciphertext and compute
+$C^d \equiv \left (M^e \right)^d \equiv M^1 \equiv M\mbox{ }(\mbox{mod }N)$.  Similarly the owner of the private key 
+can sign a message by ``decrypting'' it.  Others can verify it by ``encrypting'' it.  
+
+Currently RSA is a difficult system to cryptanalyze provided that both primes are large and not close to each other.  
+Ideally $e$ should be larger than $100$ to prevent direct analysis.  For example, if $e$ is three and you do not pad
+the plaintext to be encrypted than it is possible that $M^3 < N$ in which case finding the cube-root would be trivial.  
+The most often suggested value for $e$ is $65537$ since it is large enough to make such attacks impossible and also well 
+designed for fast exponentiation (requires 16 squarings and one multiplication).
+
+It is important to pad the input to RSA since it has particular mathematical structure.  For instance  
+$M_1^dM_2^d = (M_1M_2)^d$ which can be used to forge a signature.  Suppose $M_3 = M_1M_2$ is a message you want
+to have a forged signature for.  Simply get the signatures for $M_1$ and $M_2$ on their own and multiply the result
+together.  Similar tricks can be used to deduce plaintexts from ciphertexts.  It is important not only to sign 
+the hash of documents only but also to pad the inputs with data to remove such structure.  
+
+\section{Core Functions}
+
+For RSA routines a single ``rsa\_key'' structure is used.  To make a new RSA key call:
+\index{rsa\_make\_key()}
+\begin{verbatim}
+int rsa_make_key(prng_state *prng, 
+                 int wprng, int size, 
+                 long e, rsa_key *key);
+\end{verbatim}
+
+Where ``wprng'' is the index into the PRNG descriptor array.  ``size'' is the size in bytes of the RSA modulus desired.
+``e'' is the encryption exponent desired, typical values are 3, 17, 257 and 65537.  I suggest you stick with 65537 since its big
+enough to prevent trivial math attacks and not super slow.  ``key'' is where the key is placed.  All keys must be at 
+least 128 bytes and no more than 512 bytes in size (\textit{that is from 1024 to 4096 bits}).
+
+Note that the ``rsa\_make\_key()'' function allocates memory at runtime when you make the key.  Make sure to call 
+``rsa\_free()'' (see below) when you are finished with the key.  If ``rsa\_make\_key()'' fails it will automatically 
+free the ram allocated itself.
+
+There are three types of RSA keys.  The types are {\bf PK\_PRIVATE\_OPTIMIZED}, {\bf PK\_PRIVATE} and {\bf PK\_PUBLIC}.  The first
+two are private keys where the ``optimized'' type uses the Chinese Remainder Theorem to speed up decryption/signatures.  By 
+default all new keys are of the ``optimized'' type.  The non-optimized private type is provided for backwards compatibility
+as well as to save space since the optimized key requires about four times as much memory.
+
+To do raw work with the RSA function call:
+\index{rsa\_exptmod()}
+\begin{verbatim}
+int rsa_exptmod(const unsigned char *in, unsigned long inlen, 
+                unsigned char *out, unsigned long *outlen, 
+                int which, rsa_key *key);
+\end{verbatim}
+This loads the bignum from ``in'' as a big endian word in the format PKCS specifies, raises it to either ``e'' or ``d'' and stores the result
+in ``out'' and the size of the result in ``outlen''. ``which'' is set to {\bf PK\_PUBLIC} to use ``e'' 
+(i.e. for encryption/verifying) and set to {\bf PK\_PRIVATE} to use ``d'' as the exponent (i.e. for decrypting/signing).
+
+Note that this function does not perform padding on the input (as per PKCS).  So if you send in ``0000001'' you will
+get ``01'' back (when you do the opposite operation).  Make sure you pad properly which usually involves setting the msb to
+a non-zero value.
+
+\section{Packet Routines}
+To encrypt or decrypt a symmetric key using RSA the following functions are provided.  The idea is that you make up
+a random symmetric key and use that to encode your message.  By RSA encrypting the symmetric key you can send it to a
+recipient who can RSA decrypt it and symmetrically decrypt the message.
+\begin{verbatim}
+int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen,
+                          unsigned char *outkey, unsigned long *outlen,
+                          prng_state *prng, int wprng, rsa_key *key);
+\end{verbatim}
+This function is used to RSA encrypt a symmetric to share with another user.  The symmetric key and its length are
+passed as ``inkey'' and ``inlen'' respectively.  The symmetric key is limited to a range of 8 to 32 bytes 
+(\textit{64 to 256 bits}).  The RSA encrypted packet is stored in ``outkey'' and will be of length ``outlen'' bytes.  The
+value of ``outlen'' must be originally set to the size of the output buffer. 
+
+\begin{verbatim}
+int rsa_decrypt_key(const unsigned char *in, unsigned long inlen, 
+                          unsigned char *outkey, unsigned long *keylen, 
+                          rsa_key *key);
+\end{verbatim}
+
+This function will decrypt an RSA packet to retrieve the original symmetric key encrypted with rsa\_encrypt\_key().  
+Similarly to sign or verify a hash of a message the following two messages are provided.  The idea is to hash your message 
+then use these functions to RSA sign the hash.  
+\begin{verbatim}
+int rsa_sign_hash(const unsigned char *in,  unsigned long inlen, 
+                        unsigned char *out, unsigned long *outlen, 
+                        rsa_key *key);
+
+int rsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+                    const unsigned char *hash, int *stat, rsa_key *key);
+\end{verbatim}
+For ``rsa\_sign\_hash'' the input is intended to be the hash of a message the user wants to sign.  The output is the 
+RSA signed packet which ``rsa\_verify\_hash'' can verify.  For the verification function ``sig'' is the RSA signature
+and ``hash'' is the hash of the message.  The integer ``stat'' is set to non-zero if the signature is valid or zero 
+otherwise.
+
+To import/export RSA keys as a memory buffer (e.g. to store them to disk) call:
+\begin{verbatim}
+int rsa_export(unsigned char *out, unsigned long *outlen, 
+               int type, rsa_key *key);
+
+int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key);
+\end{verbatim}
+
+The ``type'' parameter is {\bf PK\_PUBLIC}, {\bf PK\_PRIVATE} or {\bf PK\_PRIVATE\_OPTIMIZED} to export either a public or 
+private key.  The latter type will export a key with the optimized parameters.  To free the memory used by an RSA key call:
+\index{rsa\_free()}
+\begin{verbatim}
+void rsa_free(rsa_key *key);
+\end{verbatim}
+
+Note that if the key fails to ``rsa\_import()'' you do not have to free the memory allocated for it.
+
+\section{Remarks}
+It is important that you match your RSA key size with the function you are performing.  The internal padding for both
+signatures and encryption triple the size of the plaintext.  This means to encrypt or sign
+a message of N bytes you must have a modulus of 1+3N bytes.  Note that this doesn't affect the length of the plaintext 
+you pass into functions like rsa\_encrypt().  This restriction applies only to data that is passed through the
+internal RSA routines directly directly.
+
+The following table gives the size requirements for various hashes.
+\begin{center}
+\begin{tabular}{|c|c|c|}
+      \hline Name & Size of Message Digest (bytes) & RSA Key Size (bits)\\
+      \hline SHA-512 & 64 & 1544\\
+      \hline SHA-384 & 48 & 1160 \\
+      \hline SHA-256 & 32 & 776\\
+      \hline TIGER-192 & 24 & 584\\
+      \hline SHA-1 & 20 & 488\\
+      \hline MD5 & 16 & 392\\
+      \hline MD4 & 16 & 392\\
+      \hline
+\end{tabular}
+\end{center}
+
+The symmetric ciphers will use at a maximum a 256-bit key which means at the least a 776-bit RSA key is 
+required to use all of the symmetric ciphers with the RSA routines. If you want to use any of the large size 
+message digests (SHA-512 or SHA-384) you will have to use a larger key.  Or to be simple just make 2048-bit or larger
+keys.  None of the hashes will have problems with such key sizes.
+
+\chapter{Diffie-Hellman Key Exchange}
+
+\section{Background}
+
+Diffie-Hellman was the original public key system proposed.  The system is based upon the group structure
+of finite fields.  For Diffie-Hellman a prime $p$ is chosen and a ``base'' $b$ such that $b^x\mbox{ }(\mbox{mod }p)$ 
+generates a large sub-group of prime order (for unique values of $x$).
+
+A secret key is an exponent $x$ and a public key is the value of $y \equiv g^x\mbox{ }(\mbox{mod }p)$.  The term
+``discrete logarithm'' denotes the action of finding $x$ given only $y$, $g$ and $p$.  The key exchange part of
+Diffie-Hellman arises from the fact that two users A and B with keys $(A_x, A_y)$ and $(B_x, B_y)$ can exchange 
+a shared key $K \equiv B_y^{A_x} \equiv A_y^{B_x} \equiv g^{A_xB_x}\mbox{ }(\mbox{mod }p)$.
+
+From this public encryption and signatures can be developed.  The trivial way to encrypt (for example) using a public key 
+$y$ is to perform the key exchange offline.  The sender invents a key $k$ and its public copy 
+$k' \equiv g^k\mbox{ }(\mbox{mod }p)$ and uses $K \equiv k'^{A_x}\mbox{ }(\mbox{mod }p)$ as a key to encrypt
+the message with.  Typically $K$ would be sent to a one-way hash and the message digested used as a key in a 
+symmetric cipher.
+
+It is important that the order of the sub-group that $g$ generates not only be large but also prime.  There are
+discrete logarithm algorithms that take $\sqrt r$ time given the order $r$.  The discrete logarithm can be computed
+modulo each prime factor of $r$ and the results combined using the Chinese Remainder Theorem.  In the cases where 
+$r$ is ``B-Smooth'' (e.g. all small factors or powers of small prime factors) the solution is trivial to find.
+
+To thwart such attacks the primes and bases in the library have been designed and fixed.  Given a prime $p$ the order of
+ the sub-group generated is a large prime namely ${p - 1} \over 2$.  Such primes are known as ``strong primes'' and the 
+smaller prime (e.g. the order of the base) are known as Sophie-Germaine primes.
+
+\section{Core Functions}
+
+This library also provides core Diffie-Hellman functions so you can negotiate keys over insecure mediums.  The routines 
+provided are relatively easy to use and only take two function calls to negotiate a shared key.  There is a structure
+called ``dh\_key'' which stores the Diffie-Hellman key in a format these routines can use.  The first routine is to
+make a Diffie-Hellman private key pair:
+\index{dh\_make\_key()}
+\begin{verbatim}
+int dh_make_key(prng_state *prng, int wprng, 
+                int keysize, dh_key *key);
+\end{verbatim}
+The ``keysize'' is the size of the modulus you want in bytes.  Currently support sizes are 96 to 512 bytes which correspond 
+to key sizes of 768 to 4096 bits. The smaller the key the faster it is to use however it will be less secure.  When 
+specifying a size not explicitly supported by the library it will round {\em up} to the next key size.  If the size is 
+above 512 it will return an error.  So if you pass ``keysize == 32'' it will use a 768 bit key but if you pass 
+``keysize == 20000'' it will return an error.  The primes and generators used are built-into the library and were designed 
+to meet very specific goals.  The primes are strong primes which means that if $p$ is the prime then
+$p-1$ is equal to $2r$ where $r$ is a large prime.  The bases are chosen to generate a group of order $r$ to prevent
+leaking a bit of the key.  This means the bases generate a very large prime order group which is good to make cryptanalysis
+hard.
+
+The next two routines are for exporting/importing Diffie-Hellman keys in a binary format.  This is useful for transport
+over communication mediums.  
+
+\index{dh\_export()} \index{dh\_import()}
+\begin{verbatim}
+int dh_export(unsigned char *out, unsigned long *outlen, 
+              int type, dh_key *key);
+
+int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key);
+\end{verbatim}
+
+These two functions work just like the ``rsa\_export()'' and ``rsa\_import()'' functions except these work with 
+Diffie-Hellman keys. Its important to note you do not have to free the ram for a ``dh\_key'' if an import fails.  You can free a 
+``dh\_key'' using:
+\begin{verbatim}
+void dh_free(dh_key *key);
+\end{verbatim}
+After you have exported a copy of your public key (using {\bf PK\_PUBLIC} as ``type'') you can now create a shared secret 
+with the other user using:
+\index{dh\_shared\_secret()}
+\begin{verbatim}
+int dh_shared_secret(dh_key *private_key, 
+                     dh_key *public_key, 
+                     unsigned char *out, unsigned long *outlen);
+\end{verbatim}
+
+Where ``private\_key'' is the key you made and ``public\_key'' is the copy of the public key the other user sent you.  The result goes
+into ``out'' and the length into ``outlen''.  If all went correctly the data in ``out'' should be identical for both parties.  It is important to
+note that the two keys have to be the same size in order for this to work.  There is a function to get the size of a
+key:
+\index{dh\_get\_size()}
+\begin{verbatim}
+int dh_get_size(dh_key *key);
+\end{verbatim}
+This returns the size in bytes of the modulus chosen for that key.
+
+\subsection{Remarks on Usage}
+Its important that you hash the shared key before trying to use it as a key for a symmetric cipher or something.  An 
+example program that communicates over sockets, using MD5 and 1024-bit DH keys is\footnote{This function is a small example.  It is suggested that proper packaging be used.  For example, if the public key sent is truncated these routines will not detect that.}:
+\newpage
+\begin{small}
+\begin{verbatim}
+int establish_secure_socket(int sock, int mode, unsigned char *key, 
+                            prng_state *prng, int wprng)
+{
+   unsigned char buf[4096], buf2[4096];
+   unsigned long x, len;
+   int res, err, inlen;
+   dh_key mykey, theirkey;
+
+   /* make up our private key */
+   if ((err = dh_make_key(prng, wprng, 128, &mykey)) != CRYPT_OK)  {
+      return err;
+   }
+
+   /* export our key as public */ 
+   x = sizeof(buf);
+   if ((err = dh_export(buf, &x, PK_PUBLIC, &mykey)) != CRYPT_OK) {
+      res = err;
+      goto done2;
+   }
+
+   if (mode == 0) {
+      /* mode 0 so we send first */
+      if (send(sock, buf, x, 0) != x) {
+         res = CRYPT_ERROR;
+         goto done2;
+      }          
+
+      /* get their key */
+      if ((inlen = recv(sock, buf2, sizeof(buf2), 0)) <= 0) {
+         res = CRYPT_ERROR;
+         goto done2;
+      }
+   } else {
+      /* mode >0 so we send second */
+      if ((inlen = recv(sock, buf2, sizeof(buf2), 0)) <= 0) {
+         res = CRYPT_ERROR;
+         goto done2;
+      }
+
+      if (send(sock, buf, x, 0) != x) {
+         res = CRYPT_ERROR;
+         goto done2;
+      }
+   }
+
+   if ((err = dh_import(buf2, inlen, &theirkey)) != CRYPT_OK) { 
+      res = err;
+      goto done2;
+   }
+
+   /* make shared secret */
+   x = sizeof(buf);
+   if ((err = dh_shared_secret(&mykey, &theirkey, buf, &x)) != CRYPT_OK) {
+      res = err;
+      goto done;
+   }
+ 
+   /* hash it */
+   len = 16;        /* default is MD5 so "key" must be at least 16 bytes long */
+   if ((err = hash_memory(find_hash("md5"), buf, x, key, &len)) != CRYPT_OK) {
+      res = err;
+      goto done;
+   }
+
+   /* clean up and return */
+   res = CRYPT_OK;
+done:
+   dh_free(&theirkey);
+done2:
+   dh_free(&mykey);
+   zeromem(buf,  sizeof(buf));
+   zeromem(buf2, sizeof(buf2));
+   return res;
+}
+\end{verbatim}
+\end{small}
+\newpage
+\subsection{Remarks on The Snippet}
+When the above code snippet is done (assuming all went well) their will be a shared 128-bit key in the ``key'' array
+passed to ``establish\_secure\_socket()''.
+
+\section{Other Diffie-Hellman Functions}
+In order to test the Diffie-Hellman function internal workings (e.g. the primes and bases) their is a test function made
+available:
+\index{dh\_test()}
+\begin{verbatim}
+int dh_test(void);
+\end{verbatim}
+
+This function returns {\bf CRYPT\_OK} if the bases and primes in the library are correct.  There is one last helper 
+function:
+\index{dh\_sizes()}
+\begin{verbatim}
+void dh_sizes(int *low, int *high);
+\end{verbatim}
+Which stores the smallest and largest key sizes support into the two variables.
+
+\section{DH Packet}
+Similar to the RSA related functions there are functions to encrypt or decrypt symmetric keys using the DH public key
+algorithms.  
+\begin{verbatim}
+int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
+                         unsigned char *out,  unsigned long *len, 
+                         prng_state *prng, int wprng, int hash, 
+                         dh_key *key);
+
+int dh_decrypt_key(const unsigned char *in, unsigned long inlen,
+                         unsigned char *outkey, unsigned long *keylen, 
+                         dh_key *key);
+\end{verbatim}
+Where ``inkey'' is an input symmetric key of no more than 32 bytes.  Essentially these routines created a random public key
+and find the hash of the shared secret.  The message digest is than XOR'ed against the symmetric key.  All of the 
+required data is placed in ``out'' by ``dh\_encrypt\_key()''.   The hash must produce a message digest at least as large
+as the symmetric key you are trying to share.
+
+Similar to the RSA system you can sign and verify a hash of a message.
+\begin{verbatim}
+int dh_sign_hash(const unsigned char *in,  unsigned long inlen,
+                       unsigned char *out, unsigned long *outlen,
+                       prng_state *prng, int wprng, dh_key *key);
+
+int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
+                         const unsigned char *hash, unsigned long hashlen, 
+                         int *stat, dh_key *key);
+\end{verbatim}
+
+The ``dh\_sign\_hash'' function signs the message hash in ``in'' of length ``inlen'' and forms a DH packet in ``out''.  
+The ``dh\_verify\_hash'' function verifies the DH signature in ``sig'' against the hash in ``hash''.  It sets ``stat''
+to non-zero if the signature passes or zero if it fails.
+
+\chapter{Elliptic Curve Cryptography}
+
+\section{Background}
+The library provides a set of core ECC functions as well that are designed to be the Elliptic Curve analogy of all of the 
+Diffie-Hellman routines in the previous chapter.  Elliptic curves (of certain forms) have the benefit that they are harder
+to attack (no sub-exponential attacks exist unlike normal DH crypto) in fact the fastest attack requires the square root
+of the order of the base point in time.  That means if you use a base point of order $2^{192}$ (which would represent a
+192-bit key) then the work factor is $2^{96}$ in order to find the secret key.
+
+The curves in this library are taken from the following website:
+\begin{verbatim}
+http://csrc.nist.gov/cryptval/dss.htm
+\end{verbatim}
+
+They are all curves over the integers modulo a prime.  The curves have the basic equation that is:
+\begin{equation}
+y^2 = x^3 - 3x + b\mbox{ }(\mbox{mod }p)
+\end{equation}
+
+The variable $b$ is chosen such that the number of points is nearly maximal.  In fact the order of the base points $\beta$ 
+provided are very close to $p$ that is $\vert \vert \phi(\beta) \vert \vert \approx \vert \vert p \vert \vert$.  The curves
+range in order from $\approx 2^{192}$ points to $\approx 2^{521}$.  According to the source document any key size greater
+than or equal to 256-bits is sufficient for long term security.  
+
+\section{Core Functions}
+
+Like the DH routines there is a key structure ``ecc\_key'' used by the functions.  There is a function to make a key:
+\index{ecc\_make\_key()}
+\begin{verbatim}
+int ecc_make_key(prng_state *prng, int wprng, 
+                 int keysize, ecc_key *key);
+\end{verbatim}
+
+The ``keysize'' is the size of the modulus in bytes desired.  Currently directly supported values are 20, 24, 28, 32, 48 and 65 bytes which
+correspond to key sizes of 160, 192, 224, 256, 384 and 521 bits respectively.  If you pass a key size that is between any key size
+it will round the keysize up to the next available one.  The rest of the parameters work like they do in the ``dh\_make\_key()'' function.  
+To free the ram allocated by a key call:
+\index{ecc\_free()}
+\begin{verbatim}
+void ecc_free(ecc_key *key);
+\end{verbatim}
+
+To import and export a key there are: 
+\index{ecc\_export()}
+\index{ecc\_import()}
+\begin{verbatim}
+int ecc_export(unsigned char *out, unsigned long *outlen, 
+               int type, ecc_key *key);
+
+int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
+\end{verbatim}
+These two work exactly like there DH counterparts.  Finally when you share your public key you can make a shared secret
+with:
+\index{ecc\_shared\_secret()}
+\begin{verbatim}
+int ecc_shared_secret(ecc_key *private_key, 
+                      ecc_key *public_key, 
+                      unsigned char *out, unsigned long *outlen);
+\end{verbatim}
+Which works exactly like the DH counterpart, the ``private\_key'' is your own key and ``public\_key'' is the key the other
+user sent you.   Note that this function stores both $x$ and $y$ co-ordinates of the shared
+elliptic point.  You should hash the output to get a shared key in a more compact and useful form (most of the entropy is 
+in $x$ anyways).  Both keys have to be the same size for this to work, to help there is a function to get the size in bytes
+ of a key.
+\index{ecc\_get\_size()}
+\begin{verbatim}
+int ecc_get_size(ecc_key *key);
+\end{verbatim}
+
+To test the ECC routines and to get the minimum and maximum key sizes there are these two functions:
+\index{ecc\_test()}
+\begin{verbatim}
+int ecc_test(void);
+void ecc_sizes(int *low, int *high);
+\end{verbatim}
+Which both work like their DH counterparts.
+
+\section{ECC Packet}
+Similar to the RSA API there are two functions which encrypt and decrypt symmetric keys using the ECC public key
+algorithms.
+\begin{verbatim}
+int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
+                          unsigned char *out,  unsigned long *len, 
+                          prng_state *prng, int wprng, int hash, 
+                          ecc_key *key);
+
+int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
+                          unsigned char *outkey, unsigned long *keylen, 
+                          ecc_key *key);
+\end{verbatim}
+
+Where ``inkey'' is an input symmetric key of no more than 32 bytes.  Essentially these routines created a random public key
+and find the hash of the shared secret.  The message digest is than XOR'ed against the symmetric key.  All of the required
+data is placed in ``out'' by ``ecc\_encrypt\_key()''.   The hash chosen must produce a message digest at least as large
+as the symmetric key you are trying to share.
+
+There are also functions to sign and verify the hash of a message.
+\begin{verbatim}
+int ecc_sign_hash(const unsigned char *in,  unsigned long inlen,
+                        unsigned char *out, unsigned long *outlen,
+                        prng_state *prng, int wprng, ecc_key *key);
+
+int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
+                    const unsigned char *hash, unsigned long hashlen, 
+                          int *stat, ecc_key *key);
+\end{verbatim}
+
+The ``ecc\_sign\_hash'' function signs the message hash in ``in'' of length ``inlen'' and forms a ECC packet in ``out''.  
+The ``ecc\_verify\_hash'' function verifies the ECC signature in ``sig'' against the hash in ``hash''.  It sets ``stat''
+to non-zero if the signature passes or zero if it fails.
+
+
+\section{ECC Keysizes}
+With ECC if you try and sign a hash that is bigger than your ECC key you can run into problems.  The math will still work
+and in effect the signature will still work.  With ECC keys the strength of the signature is limited by the size of
+the hash or the size of they key, whichever is smaller.  For example, if you sign with SHA256 and a ECC-160 key in effect
+you have 160-bits of security (e.g. as if you signed with SHA-1).  
+
+The library will not warn you if you make this mistake so it is important to check yourself before using the 
+signatures.
+
+\chapter{Digital Signature Algorithm}
+\section{Introduction}
+The Digital Signature Algorithm (or DSA) is a variant of the ElGamal Signature scheme which has been modified to 
+reduce the bandwidth of a signature.  For example, to have ``80-bits of security'' with ElGamal you need a group of 
+order at least 1024-bits.  With DSA you need a group of order at least 160-bits.  By comparison the ElGamal signature
+would require at least 256 bytes where as the DSA signature would require only at least 40 bytes.  
+
+The API for the DSA is essentially the same as the other PK algorithms.  Except in the case of DSA no encryption or
+decryption routines are provided.  
+
+\section{Key Generation}
+To make a DSA key you must call the following function
+\begin{verbatim}
+int dsa_make_key(prng_state *prng, int wprng, 
+                 int group_size, int modulus_size, 
+                 dsa_key *key);
+\end{verbatim}
+The variable ``prng'' is an active PRNG state and ``wprng'' the index to the descriptor.  ``group\_size'' and 
+``modulus\_size'' control the difficulty of forging a signature.  Both parameters are in bytes.  The larger the
+``group\_size'' the more difficult a forgery becomes upto a limit.  The value of $group\_size$ is limited by 
+$15 < group\_size < 1024$ and $modulus\_size - group\_size < 512$.  Suggested values for the pairs are as follows.
+
+\begin{center}
+\begin{tabular}{|c|c|c|}
+\hline \textbf{Bits of Security} & \textbf{group\_size} & \textbf{modulus\_size} \\
+\hline 80  & 20 & 128 \\
+\hline 120 & 30 & 256 \\
+\hline 140 & 35 & 384 \\
+\hline 160 & 40 & 512 \\
+\hline
+\end{tabular}
+\end{center}
+
+When you are finished with a DSA key you can call the following function to free the memory used.
+\begin{verbatim}
+void dsa_free(dsa_key *key);
+\end{verbatim}
+
+\section{Key Verification}
+Each DSA key is composed of the following variables.
+
+\begin{enumerate}
+  \item $q$ a small prime of magnitude $256^{group\_size}$.  
+  \item $p = qr + 1$ a large prime of magnitude $256^{modulus\_size}$ where $r$ is a random even integer.
+  \item $g = h^r \mbox{ (mod }p\mbox{)}$ a generator of order $q$ modulo $p$.  $h$ can be any non-trivial random 
+        value.  For this library they start at $h = 2$ and step until $g$ is not $1$.
+  \item $x$ a random secret (the secret key) in the range $1 < x < q$ 
+  \item $y = g^x \mbox{ (mod }p\mbox{)}$ the public key.
+\end{enumerate}
+
+A DSA key is considered valid if it passes all of the following tests.
+
+\begin{enumerate}
+   \item $q$ must be prime.
+   \item $p$ must be prime.
+   \item $g$ cannot be one of $\lbrace -1, 0, 1 \rbrace$ (modulo $p$).
+   \item $g$ must be less than $p$.
+   \item $(p-1) \equiv 0 \mbox{ (mod }q\mbox{)}$.
+   \item $g^q \equiv 1 \mbox{ (mod }p\mbox{)}$.
+   \item $1 < y < p - 1$
+   \item $y^q \equiv 1 \mbox{ (mod }p\mbox{)}$.
+\end{enumerate}
+
+Tests one and two ensure that the values will at least form a field which is required for the signatures to  
+function.  Tests three and four ensure that the generator $g$ is not set to a trivial value which would make signature
+forgery easier.  Test five ensures that $q$ divides the order of multiplicative sub-group of $\Z/p\Z$. Test six
+ensures that the generator actually generates a prime order group.  Tests seven and eight ensure that the public key
+is within range and belongs to a group of prime order.  Note that test eight does not prove that $g$ generated $y$ only
+that $y$ belongs to a multiplicative sub-group of order $q$. 
+
+The following function will perform these tests.
+
+\begin{verbatim}
+int dsa_verify_key(dsa_key *key, int *stat);
+\end{verbatim}
+
+This will test ``key'' and store the result in ``stat''.  If the result is $stat = 0$ the DSA key failed one of the tests
+and should not be used at all.  If the result is $stat = 1$ the DSA key is valid (as far as valid mathematics are concerned).
+
+
+
+\section{Signatures}
+To generate a DSA signature call the following function
+
+\begin{verbatim}
+int dsa_sign_hash(const unsigned char *in,  unsigned long inlen,
+                        unsigned char *out, unsigned long *outlen,
+                        prng_state *prng, int wprng, dsa_key *key);
+\end{verbatim}
+
+Which will sign the data in ``in'' of length ``inlen'' bytes.  The signature is stored in ``out'' and the size
+of the signature in ``outlen''.  If the signature is longer than the size you initially specify in ``outlen'' nothing
+is stored and the function returns an error code.  The DSA ``key'' must be of the \textbf{PK\_PRIVATE} persuasion.
+
+To verify a hash created with that function use the following function
+
+\begin{verbatim}
+int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+                    const unsigned char *hash, unsigned long inlen, 
+                    int *stat, dsa_key *key);
+\end{verbatim}
+Which will verify the data in ``hash'' of length ``inlen'' against the signature stored in ``sig'' of length ``siglen''.  
+It will set ``stat'' to $1$ if the signature is valid, otherwise it sets ``stat'' to $0$.  
+
+\section{Import and Export}
+
+To export a DSA key so that it can be transported use the following function
+\begin{verbatim}
+int dsa_export(unsigned char *out, unsigned long *outlen, 
+               int type, 
+               dsa_key *key);
+\end{verbatim}
+This will export the DSA ``key'' to the buffer ``out'' and set the length in ``outlen'' (which must have been previously
+initialized to the maximum buffer size).  The ``type`` variable may be either \textbf{PK\_PRIVATE} or \textbf{PK\_PUBLIC}
+depending on whether you want to export a private or public copy of the DSA key.
+
+To import an exported DSA key use the following function
+
+\begin{verbatim}
+int dsa_import(const unsigned char *in, unsigned long inlen, 
+               dsa_key *key);
+\end{verbatim}
+
+This will import the DSA key from the buffer ``in'' of length ``inlen'' to the ``key''.  If the process fails the function
+will automatically free all of the heap allocated in the process (you don't have to call dsa\_free()).  
+
+\chapter{Public Keyrings}
+\section{Introduction}
+In order to simplify the usage of the public key algorithms a set of keyring routines have been developed.  They let the 
+developer manage asymmetric keys by providing load, save, export, import routines as well as encrypt, decrypt, sign, verify
+routines in a unified API.  That is all three types of PK systems can be used within the same keyring with the same API.
+
+To define types of keys there are four enumerations used globaly:
+\begin{verbatim}
+enum {
+   NON_KEY=0,
+   RSA_KEY,
+   DH_KEY,
+   ECC_KEY
+};
+\end{verbatim}
+
+To make use of the system the developer has to know how link-lists work.  The main structure that the keyring routines use 
+is the ``pk\_key'' defined as:
+\begin{small}
+\begin{verbatim}
+typedef struct Pk_key {
+    int     key_type,             /* PUBLIC, PRIVATE, PRIVATE_OPTIMIZED */
+            system;               /* RSA, ECC or DH ?   */
+
+    char    name[MAXLEN],         /* various info's about this key */
+            email[MAXLEN],
+            description[MAXLEN];
+
+    unsigned long ID;             /* CRC32 of the name/email/description together */
+
+    _pk_key key;
+
+    struct Pk_key  *next;         /* linked list chain */
+} pk_key;
+\end{verbatim}
+\end{small}
+
+The list is chained via the ``next'' member and terminated with the node of the list that has ``system'' equal to 
+{\bf NON\_KEY}.
+
+\section{The Keyring API}
+To initialize a blank keyring the function ``kr\_init()'' is used.
+\begin{verbatim}
+int kr_init(pk_key **pk);
+\end{verbatim}
+You pass it a pointer to a pointer of type ``pk\_key'' where it will allocate ram for one node of the keyring and sets the
+pointer.
+
+Now instead of calling the PK specific ``make\_key'' functions there is one function that can make all three types of keys.
+\begin{verbatim}
+int kr_make_key(pk_key *pk, prng_state *prng, int wprng, 
+                int system, int keysize, const char *name,
+                const char *email, const char *description);
+\end{verbatim}
+The ``name'', ``email'' and ``description'' parameters are simply little pieces of information that you can tag along with a
+key.  They can each be either blank or any string less than 256 bytes.  ``system'' is one of the enumeration elements, that
+is {\bf RSA\_KEY}, {\bf DH\_KEY} or {\bf ECC\_KEY}.  ``keysize'' is the size of the key you desire which is regulated by
+the individual systems, for example, RSA keys are limited in keysize from 128 to 512 bytes.
+
+To find keys along a keyring there are two functions provided:
+\begin{verbatim}
+pk_key *kr_find(pk_key *pk, unsigned long ID);
+
+pk_key *kr_find_name(pk_key *pk, const char *name);
+\end{verbatim}
+The first searches by the 32-bit ID provided and the latter checks the name against the keyring.  They both return a pointer
+to the node in the ring of a match or {\bf NULL} if no match is found.
+
+To export or import a single node of a keyring the two functions are provided:
+\begin{verbatim}
+int kr_export(pk_key *pk, unsigned long ID, int key_type, 
+              unsigned char *out, unsigned long *outlen);
+
+int kr_import(pk_key *pk, const unsigned char *in);
+\end{verbatim}
+The export function exports the key with an ID provided and of a specific type much like the normal PK export routines.  The
+``key\_type'' is one of {\bf PK\_PUBLIC} or {\bf PK\_PRIVATE}.  In this function with RSA keys the type 
+{\bf PK\_PRIVATE\_OPTIMIZED} is the same as the {\bf PK\_PRIVATE} type.  The import function will read in a packet and 
+add it to the keyring.  
+
+To load and save whole keyrings from disk:
+\begin{verbatim}
+int kr_load(pk_key **pk, FILE *in, symmetric_CTR *ctr);
+
+int kr_save(pk_key *pk, FILE *out, symmetric_CTR *ctr);
+\end{verbatim}
+Both take file pointers to allow the user to pre-append data to the stream.  The ``ctr'' parameter should be setup with 
+``ctr\_start'' or set to NULL.  This parameter lets the user encrypt the keyring as its written to disk, if it is set
+to NULL the data is written without being encrypted.  The load function assumes the list has not been initialized yet 
+and will reset the pointer given to it.
+
+There are the four encrypt, decrypt, sign and verify functions as well
+\begin{verbatim}
+int kr_encrypt_key(pk_key *pk, unsigned long ID, 
+                   const unsigned char *in, unsigned long inlen,
+                   unsigned char *out, unsigned long *outlen,
+                   prng_state *prng, int wprng, int hash);
+
+int kr_decrypt_key(pk_key *pk, const unsigned char *in,
+                   unsigned char *out, unsigned long *outlen);
+\end{verbatim}
+
+The kr\_encrypt\_key() routine is designed to encrypt a symmetric key with a specified users public key.  The symmetric
+key is then used with a block cipher to encode the message.  The recipient can call kr\_decrypt\_key() to get the original
+symmetric key back and decode the message.  The hash specified must produce a message digest longer than symmetric key 
+provided.  
+
+\begin{verbatim}
+int kr_sign_hash(pk_key *pk, unsigned long ID, 
+                 const unsigned char *in, unsigned long inlen,
+                 unsigned char *out, unsigned long *outlen,
+                 prng_state *prng, int wprng);
+
+int kr_verify_hash(pk_key *pk, const unsigned char *in, 
+                   const unsigned char *hash, unsigned long hashlen,
+                   int *stat);
+\end{verbatim}
+
+Similar to the two previous these are used to sign a message digest or verify one.  This requires hashing the message
+first then passing the output in. 
+
+To delete keys and clear rings there are:
+\begin{verbatim}
+int kr_del(pk_key **_pk, unsigned long ID);
+int kr_clear(pk_key **pk);
+\end{verbatim}
+``kr\_del'' will try to remove a key with a given ID from the ring and ``kr\_clear'' will completely empty a list and free
+the memory associated with it.  Below is small example using the keyring API:
+
+\begin{small}
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   pk_key *kr;
+   unsigned char buf[4096], buf2[4096];
+   unsigned long len;
+   int err;
+
+   /* make a new list */
+   if ((err = kr_init(&kr)) != CRYPT_OK) {
+      printf("kr_init: %s\n", error_to_string(err));
+      exit(-1);
+   }
+
+   /* add a key to it */
+   register_prng(&sprng_desc);
+   if ((err = kr_make_key(kr, NULL, find_prng("sprng"), RSA_KEY, 128, 
+                "TomBot", "t[email protected]", "test key")) == CRYPT_OK) {
+      printf("kr_make_key: %s\n", error_to_string(err));
+      exit(-1);
+   }
+
+   /* export the first key */
+   len = sizeof(buf);
+   if ((err = kr_export(kr, kr->ID, PK_PRIVATE, buf, &len)) != CRYPT_OK) {
+      printf("kr_export: %s\n", error_to_string(err));
+      exit(-1);
+   }
+
+   /* ... */
+}  
+\end{verbatim}
+\end{small}
+
+\chapter{$GF(2^w)$ Math Routines}
+
+The library provides a set of polynomial-basis $GF(2^w)$ routines to help facilitate algorithms such as ECC over such
+fields.  Note that the current implementation of ECC in the library is strictly over the integers only.  The routines
+are simple enough to use for other purposes outside of ECC.  
+
+At the heart of all of the GF routines is the data type ``gf\_int'.  It is simply a type definition for an array of 
+$L$ 32-bit words.  You can configure the maximum size $L$ of the ``gf\_int'' type by opening the file ``mycrypt.h'' and 
+changing ``LSIZE''.  Note that if you set it to $n$ then you can only multiply upto two $n \over 2$ bit polynomials without
+an overflow.  The type ``gf\_intp'' is associated with a pointer to an ``unsigned long'' as required in the algorithms.
+
+There are no initialization routines for ``gf\_int'' variables and you can simply use them after declaration.  There are five
+low level functions:
+\index{gf\_copy()} \index{gf\_zero()} \index{gf\_iszero()} \index{gf\_isone()} 
+\index{gf\_deg()} 
+\begin{verbatim}
+void gf_copy(gf_intp a, gf_intp b);
+void gf_zero(gf_intp a);
+int gf_iszero(gf_intp a);
+int gf_isone(gf_intp a);
+int gf_deg(gf_intp a);
+\end{verbatim}
+There are all fairly self-explanatory.  ``gf\_copy(a, b)'' copies the contents of ``a'' into ``b''.  ``gf\_zero()'' simply
+zeroes the entire polynomial.  ``gf\_iszero()'' tests to see if the polynomial is all zero and ``gf\_isone()'' tests to see
+if the polynomial is equal to the multiplicative identity.  ``gf\_deg()'' returns the degree of the polynomial or $-1$ if its
+a zero polynomial.
+
+There are five core math routines as well:
+\index{gf\_shl()} \index{gf\_shr()} \index{gf\_add()} \index{gf\_mul()} \index{gf\_div()} 
+\begin{verbatim}
+void gf_shl(gf_intp a, gf_intp b);
+void gf_shr(gf_intp a, gf_intp b);
+void gf_add(gf_intp a, gf_intp b, gf_intp c);
+void gf_mul(gf_intp a, gf_intp b, gf_intp c);
+void gf_div(gf_intp a, gf_intp b, gf_intp q, gf_intp r);
+\end{verbatim}
+
+Which are all fairly obvious.  ``gf\_shl(a,b)'' multiplies the polynomial ``a'' by $x$ and stores it in ``b''.  
+``gf\_shl(a,b)'' divides the polynomial ``a'' by $x$ and stores it in ``b''.  ``gf\_add(a,b,c)'' adds the polynomial
+``a'' to ``b'' and stores the sum in ``c''.  Similarly for ``gf\_mul(a,b,c)''.  The ``gf\_div(a,b,q,r)'' function divides
+``a'' by ``b'' and stores the quotient in ``q'' and the remainder in ``r''.
+
+There are six number theoretic functions as well:
+\index{gf\_mod()} \index{gf\_mulmod()} \index{gf\_invmod()} \index{gf\_gcd()} \index{gf\_is\_prime()} 
+\index{gf\_sqrt()}
+\begin{verbatim}
+void gf_mod(gf_intp a, gf_intp m, gf_intp b);
+void gf_mulmod(gf_intp a, gf_intp b, gf_intp m, gf_intp c);
+void gf_invmod(gf_intp A, gf_intp M, gf_intp B);
+void gf_sqrt(gf_intp a, gf_intp m, gf_intp b);
+void gf_gcd(gf_intp A, gf_intp B, gf_intp c);
+int gf_is_prime(gf_intp a);
+\end{verbatim}
+
+Which all work similarly except for  ``gf\_mulmod(a,b,m,c)'' which computes $c = ab\mbox{ }(\mbox{mod }m)$.  The 
+``gf\_is\_prime()'' function returns one if the polynomial is primitive, otherwise it returns zero.
+
+Finally to read/store a ``gf\_int'' in a binary string use:
+\index{gf\_size()} \index{gf\_toraw()} \index{gf\_readraw()} 
+\begin{verbatim}
+int gf_size(gf_intp a);
+void gf_toraw(gf_intp a, unsigned char *dst);
+void gf_readraw(gf_intp a, unsigned char *str, int len);
+\end{verbatim}
+Where ``gf\_size()'' returns the size in bytes required for the data.  ``gf\_toraw(a,b)'' stores the polynomial in ``b''
+in binary format (endian neutral).  ``gf\_readraw(a,b,c)'' reads the binary string in ``b'' back.  Note that the length 
+you pass it must be the same as returned by ``gf\_size()'' or it will not load correctly.
+
+\chapter{Miscellaneous}
+\section{Base64 Encoding and Decoding}
+The library provides functions to encode and decode a RFC1521 base64 coding scheme.  This means that it can decode what it 
+encodes but the format used does not comply to any known standard.  The characters used in the mappings are:
+\begin{verbatim}
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
+\end{verbatim}
+Those characters should are supported in virtually any 7-bit ASCII system which means they can be used for transport over
+common e-mail, usenet and HTTP mediums.  The format of an encoded stream is just a literal sequence of ASCII characters
+where a group of four represent 24-bits of input.  The first four chars of the encoders output is the length of the 
+original input.  After the first four characters is the rest of the message.
+
+Often it is desirable to line wrap the output to fit nicely in an e-mail or usenet posting.  The decoder allows you to
+put any character (that is not in the above sequence) in between any character of the encoders output.  You may not however,
+break up the first four characters.
+
+To encode a binary string in base64 call:
+\index{base64\_encode()}  \index{base64\_decode()} 
+\begin{verbatim}
+int base64_encode(const unsigned char *in, unsigned long len, 
+                  unsigned char *out, unsigned long *outlen);
+\end{verbatim}
+Where ``in'' is the binary string and ``out'' is where the ASCII output is placed.  You must set the value of ``outlen'' prior
+to calling this function and it sets the length of the base64 output in ``outlen'' when it is done.  To decode a base64 
+string call:
+\begin{verbatim}
+int base64_decode(const unsigned char *in, unsigned long len, 
+                  unsigned char *out, unsigned long *outlen);
+\end{verbatim}
+
+\section{The Multiple Precision Integer Library (MPI)}
+The library comes with a copy of LibTomMath  which is a multiple precision integer library written by the
+author of LibTomCrypt.  LibTomMath is a trivial to use ANSI C compatible large integer library which is free 
+for all uses and is distributed freely.
+
+At the heart of all the functions is the data type ``mp\_int'' (defined in tommath.h).  This data type is what 
+will hold all large integers.  In order to use an mp\_int one must initialize it first, for example:
+\begin{verbatim}
+#include <mycrypt.h> /* mycrypt.h includes mpi.h automatically */
+int main(void)
+{ 
+   mp_int bignum;
+   
+   /* initialize it */
+   mp_init(&bignum);
+
+   return 0;
+}
+\end{verbatim}
+If you are unfamiliar with the syntax of C the \& symbol is used to pass the address of ``bignum'' to the function.  All
+LibTomMath functions require the address of the parameters.  To free the memory of a mp\_int use (for example):
+\begin{verbatim}
+mp_clear(&bignum);
+\end{verbatim}
+
+The functions also have the basic form of one of the following:
+\begin{verbatim}
+mp_XXX(mp_int *a);
+mp_XXX(mp_int *a, mp_int *b, mp_int *c);
+mp_XXX(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+\end{verbatim}
+
+Where they perform some operation and store the result in the mp\_int variable passed on the far right.  
+For example, to compute $c = a + b \mbox{ }(\mbox{mod }m)$ you would call:
+\begin{verbatim}
+mp_addmod(&a, &b, &m, &c);
+\end{verbatim}
+
+\subsection{Binary Forms of ``mp\_int'' Variables}
+
+Often it is required to store a ``mp\_int'' in binary form for transport (e.g. exporting a key, packet 
+encryption, etc.).  LibTomMath includes two functions to help when exporting numbers:
+\begin{verbatim}
+int mp_raw_size(mp_int *num);
+mp_toraw(&num, buf);
+\end{verbatim}
+
+The former function gives the size in bytes of the raw format and the latter function actually stores the raw data.  All
+``mp\_int'' numbers are stored in big endian form (like PKCS demands) with the first byte being the sign of the number.  The
+``rsa\_exptmod()'' function differs slightly since it will take the input in the form exactly as PKCS demands (without the
+leading sign byte).  All other functions include the sign byte (since its much simpler just to include it).  The sign byte
+must be zero for positive numbers and non-zero for negative numbers.  For example,
+the sequence:
+\begin{verbatim}
+00 FF 30 04
+\end{verbatim}
+Represents the integer $255 \cdot 256^2 + 48 \cdot 256^1 + 4 \cdot 256^0$ or 16,723,972.
+
+To read a binary string back into a ``mp\_int'' call:
+\begin{verbatim}
+mp_read_raw(mp_int *num, unsigned char *str, int len);
+\end{verbatim}
+Where ``num'' is where to store it, ``str'' is the binary string (including the leading sign byte) and ``len'' is the 
+length of the binary string.
+
+\subsection{Primality Testing}
+\index{Primality Testing}
+The library includes primality testing and random prime functions as well.  The primality tester will perform the test in
+two phases.  First it will perform trial division by the first few primes.  Second it will perform eight rounds of the 
+Rabin-Miller primality testing algorithm.  If the candidate passes both phases it is declared prime otherwise it is declared
+composite.  No prime number will fail the two phases but composites can.  Each round of the Rabin-Miller algorithm reduces
+the probability of a pseudo-prime by $1 \over 4$ therefore after sixteen rounds the probability is no more than 
+$\left ( { 1 \over 4 } \right )^{8} = 2^{-16}$.  In practice the probability of error is in fact much lower than that.
+
+When making random primes the trial division step is in fact an optimized implementation of ``Implementation of Fast RSA Key Generation on Smart Cards''\footnote{Chenghuai Lu, Andre L. M. dos Santos and Francisco R. Pimentel}.
+In essence a table of machine-word sized residues are kept of a candidate modulo a set of primes.  When the candiate
+is rejected and ultimately incremented to test the next number the residues are updated without using multi-word precision
+math operations.  As a result the routine can scan ahead to the next number required for testing with very little work
+involved.
+
+In the event that a composite did make it through it would most likely cause the the algorithm trying to use it to fail.  For 
+instance, in RSA two primes $p$ and $q$ are required.  The order of the multiplicative sub-group (modulo $pq$) is given 
+as $\phi(pq)$ or $(p - 1)(q - 1)$.  The decryption exponent $d$ is found as $de \equiv 1\mbox{ }(\mbox{mod } \phi(pq))$.  If either $p$ or $q$ is composite the value of $d$ will be incorrect and the user
+will not be able to sign or decrypt messages at all.  Suppose $p$ was prime and $q$ was composite this is just a variation of 
+the multi-prime RSA.  Suppose $q = rs$ for two primes $r$ and $s$ then $\phi(pq) = (p - 1)(r - 1)(s - 1)$ which clearly is 
+not equal to $(p - 1)(rs - 1)$.
+
+These are not technically part of the LibTomMath library but this is the best place to document them.  
+To test if a ``mp\_int'' is prime call:
+\begin{verbatim}
+int is_prime(mp_int *N, int *result);
+\end{verbatim}
+This puts a one in ``result'' if the number is probably prime, otherwise it places a zero in it.  It is assumed that if 
+it returns an error that the value in ``result'' is undefined.  To make 
+a random prime call:
+\begin{verbatim}
+int rand_prime(mp_int *N, unsigned long len, prng_state *prng, int wprng);
+\end{verbatim}
+Where ``len'' is the size of the prime in bytes ($2 \le len \le 256$).  You can set ``len'' to the negative size you want
+to get a prime of the form $p \equiv 3\mbox{ }(\mbox{mod } 4)$.  So if you want a 1024-bit prime of this sort pass 
+``len = -128'' to the function.  Upon success it will return {\bf CRYPT\_OK} and ``N'' will contain an integer which
+is very likely prime.
+
+\chapter{Programming Guidelines}
+
+\section{Secure Pseudo Random Number Generators}
+Probably the singal most vulnerable point of any cryptosystem is the PRNG.  Without one generating and protecting secrets
+would be impossible.  The requirement that one be setup correctly is vitally important and to address this point the library
+does provide two RNG sources that will address the largest amount of end users as possible.  The ``sprng'' PRNG provided 
+provides and easy to access source of entropy for any application on a *NIX or Windows computer.  
+
+However, when the end user is not on one of these platforms the application developer must address the issue of finding
+entropy.  This manual is not designed to be a text on cryptography.  I would just like to highlight that when you design
+a cryptosystem make sure the first problem you solve is getting a fresh source of entropy.  
+
+\section{Preventing Trivial Errors}
+Two simple ways to prevent trivial errors is to prevent overflows and to check the return values.  All of the functions
+which output variable length strings will require you to pass the length of the destination.  If the size of your output
+buffer is smaller than the output it will report an error.  Therefore, make sure the size you pass is correct!
+
+Also virtually all of the functions return an error code or {\bf CRYPT\_OK}.  You should detect all errors as simple 
+typos or such can cause algorithms to fail to work as desired.
+
+\section{Registering Your Algorithms}
+To avoid linking and other runtime errors it is important to register the ciphers, hashes and PRNGs you intend to use 
+before you try to use them.  This includes any function which would use an algorithm indirectly through a descriptor table.
+
+A neat bonus to the registry system is that you can add external algorithms that are not part of the library without 
+having to hack the library.  For example, suppose you have a hardware specific PRNG on your system.  You could easily 
+write the few functions required plus a descriptor.  After registering your PRNG all of the library functions that 
+need a PRNG can instantly take advantage of it.
+
+\section{Key Sizes}
+
+\subsection{Symmetric Ciphers}
+For symmetric ciphers use as large as of a key as possible.  For the most part ``bits are cheap'' so using a 256-bit key
+is not a hard thing todo.  
+
+\subsection{Assymetric Ciphers}
+The following chart gives the work factor for solving a DH/RSA public key using the NFS.  The work factor for a key of order
+$n$ is estimated to be
+\begin{equation}
+e^{1.923 \cdot ln(n)^{1 \over 3} \cdot ln(ln(n))^{2 \over 3}} 
+\end{equation}
+
+Note that $n$ is not the bit-length but the magnitude.  For example, for a 1024-bit key $n = 2^{1024}$.  The work required 
+is:
+\begin{center}
+\begin{tabular}{|c|c|}
+    \hline RSA/DH Key Size (bits) & Work Factor ($log_2$) \\
+    \hline 512 & 63.92 \\
+    \hline 768 & 76.50 \\
+    \hline 1024 & 86.76 \\
+    \hline 1536 & 103.37 \\
+    \hline 2048 & 116.88 \\
+    \hline 2560 & 128.47 \\
+    \hline 3072 & 138.73 \\
+    \hline 4096 & 156.49 \\
+    \hline 
+\end{tabular}
+\end{center}
+
+The work factor for ECC keys is much higher since the best attack is still fully exponentional.  Given a key of magnitude
+$n$ it requires $\sqrt n$ work.  The following table sumarizes the work required:
+\begin{center}
+\begin{tabular}{|c|c|}
+    \hline ECC Key Size (bits) & Work Factor ($log_2$) \\
+    \hline 160 & 80  \\
+    \hline 192 & 96  \\
+    \hline 224 & 112 \\
+    \hline 256 & 128 \\
+    \hline 384 & 192 \\
+    \hline 521 & 260.5 \\
+    \hline
+\end{tabular}
+\end{center}
+
+Using the above tables the following suggestions for key sizes seems appropriate:
+\begin{center}
+\begin{tabular}{|c|c|c|}
+    \hline Security Goal & RSA/DH Key Size (bits) & ECC Key Size (bits) \\
+    \hline Short term (less than a year) & 1024 & 160 \\
+    \hline Short term (less than five years) & 1536 & 192 \\
+    \hline Long Term (less than ten years) & 2560 & 256 \\
+    \hline 
+\end{tabular}
+\end{center}
+
+\section{Thread Safety}
+The library is not thread safe but several simple precautions can be taken to avoid any problems.  The registry functions
+such as register\_cipher() are not thread safe no matter what you do.  Its best to call them from your programs initializtion
+code before threads are initiated.
+
+The rest of the code uses state variables you must pass it such as hash\_state, hmac\_state, etc.  This means that if each
+thread has its own state variables then they will not affect each other.  This is fairly simple with symmetric ciphers
+and hashes.  However, the keyring and PRNG support is something the threads will want to share.  The simplest workaround 
+is create semaphores or mutexes around calls to those functions.  
+
+Since C does not have standard semaphores this support is not native to Libtomcrypt.  Even a C based semaphore is not entire
+possible as some compilers may ignore the ``volatile'' keyword or have multiple processors.  Provide your host application
+is modular enough putting the locks in the right place should not bloat the code significantly and will solve all thread
+safety issues within the library.
+
+\chapter{Configuring the Library}
+\section{Introduction}
+The library is fairly flexible about how it can be built, used and generally distributed.  Additions are being made with
+each new release that will make the library even more flexible.  Most options are placed in the makefile and others
+are in ``mycrypt\_cfg.h''.  All are used when the library is built from scratch.
+
+For GCC platforms the file ``makefile'' is the makefile to be used.  On MSVC platforms ``makefile.vc'' and on PS2 platforms
+``makefile.ps2''.
+
+\section{mycrypt\_cfg.h}
+The file ``mycrypt\_cfg.h'' is what lets you control what functionality you want to remove from the library.  By default,
+everything the library has to offer it built.  
+
+\subsubsection{ARGTYPE}
+This lets you control how the \_ARGCHK macro will behave.  The macro is used to check pointers inside the functions against
+NULL.  There are three settings for ARGTYPE.  When set to 0 it will have the default behaviour of printing a message to 
+stderr and raising a SIGABRT signal.  This is provided so all platforms that use libtomcrypt can have an error that functions
+similarly.  When set to 1 it will simply pass on to the assert() macro.  When set to 2 it will resolve to a empty macro
+and no error checking will be performed.
+
+\subsubsection{Endianess}
+There are five macros related to endianess issues.  For little endian platforms define, ENDIAN\_LITTLE.  For big endian
+platforms define ENDIAN\_BIG.  Similarly when the default word size of an ``unsigned long'' is 32-bits define ENDIAN\_32BITWORD
+or define ENDIAN\_64BITWORD when its 64-bits.  If you do not define any of them the library will automatically use ENDIAN\_NEUTRAL
+which will work on all platforms.  Currently the system will automatically detect GCC or MSVC on a windows platform as well
+as GCC on a PS2 platform.
+
+\section{The Configure Script}
+There are also options you can specify from the configure script or ``mycrypt\_config.h''.  
+
+\subsubsection{X memory routines}
+The makefiles must define three macros denoted as XMALLOC, XCALLOC and XFREE which resolve to the name of the respective
+functions.  This lets you substitute in your own memory routines.  If you substitute in your own functions they must behave
+like the standard C library functions in terms of what they expect as input and output.  By default the library uses the
+standard C routines.
+
+\subsubsection{X clock routines}
+The rng\_get\_bytes() function can call a function that requires the clock() function.  These macros let you override
+the default clock() used with a replacement.  By default the standard C library clock() function is used.
+
+\subsubsection{NO\_FILE}
+During the build if NO\_FILE is defined then any function in the library that uses file I/O will not call the file I/O 
+functions and instead simply return CRYPT\_ERROR.  This should help resolve any linker errors stemming from a lack of
+file I/O on embedded platforms.
+
+\subsubsection{CLEAN\_STACK}
+When this functions is defined the functions that store key material on the stack will clean up afterwards.  Assumes that
+you have no memory paging with the stack.
+
+\subsubsection{Symmetric Ciphers, One-way Hashes, PRNGS and Public Key Functions}
+There are a plethora of macros for the ciphers, hashes, PRNGs and public key functions which are fairly self-explanatory.  
+When they are defined the functionality is included otherwise it is not.  There are some dependency issues which are
+noted in the file.  For instance, Yarrow requires CTR chaining mode, a block cipher and a hash function.
+
+\subsubsection{TWOFISH\_SMALL and TWOFISH\_TABLES}
+Twofish is a 128-bit symmetric block cipher that is provided within the library.  The cipher itself is flexible enough
+to allow some tradeoffs in the implementation.  When TWOFISH\_SMALL is defined the scheduled symmetric key for Twofish 
+requires only 200 bytes of memory.  This is achieved by not pre-computing the substitution boxes.  Having this 
+defined will also greatly slow down the cipher.  When this macro is not defined Twofish will pre-compute the 
+tables at a cost of 4KB of memory.  The cipher will be much faster as a result.  
+
+When TWOFISH\_TABLES is defined the cipher will use pre-computed (and fixed in code) tables required to work.  This is
+useful when TWOFISH\_SMALL is defined as the table values are computed on the fly.  When this is defined the code size
+will increase by approximately 500 bytes.  If this is defined but TWOFISH\_SMALL is not the cipher will still work but
+it will not speed up the encryption or decryption functions.
+
+\subsubsection{SMALL\_CODE}
+When this is defined some of the code such as the Rijndael and SAFER+ ciphers are replaced with smaller code variants.
+These variants are slower but can save quite a bit of code space.
+
+\end{document}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_argchk.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,21 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+#include <signal.h>
+
+#if (ARGTYPE == 0)
+void crypt_argchk(char *v, char *s, int d)
+{
+ fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n",
+         v, d, s);
+ (void)raise(SIGABRT);
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_cipher_descriptor.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,18 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+struct _cipher_descriptor cipher_descriptor[TAB_SIZE] = {
+{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL } };
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_cipher_is_valid.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,19 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int cipher_is_valid(int idx)
+{
+   if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) {
+      return CRYPT_INVALID_CIPHER;
+   }
+   return CRYPT_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_find_cipher.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,24 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int find_cipher(const char *name)
+{
+   int x;
+   _ARGCHK(name != NULL);
+   for (x = 0; x < TAB_SIZE; x++) {
+       if (cipher_descriptor[x].name != NULL && !strcmp(cipher_descriptor[x].name, name)) {
+          return x;
+       }
+   }
+   return -1;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_find_cipher_any.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,32 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+/* idea from Wayne Scott */
+int find_cipher_any(const char *name, int blocklen, int keylen)
+{
+   int x;
+
+   _ARGCHK(name != NULL);
+
+   x = find_cipher(name);
+   if (x != -1) return x;
+
+   for (x = 0; x < TAB_SIZE; x++) {
+       if (cipher_descriptor[x].name == NULL) {
+          continue;
+       }
+       if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) {
+          return x;
+       }
+   }
+   return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_find_cipher_id.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,22 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int find_cipher_id(unsigned char ID)
+{
+   int x;
+   for (x = 0; x < TAB_SIZE; x++) {
+       if (cipher_descriptor[x].ID == ID) {
+          return (cipher_descriptor[x].name == NULL) ? -1 : x;
+       }
+   }
+   return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_find_hash.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,23 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int find_hash(const char *name)
+{
+   int x;
+   _ARGCHK(name != NULL);
+   for (x = 0; x < TAB_SIZE; x++) {
+       if (hash_descriptor[x].name != NULL && strcmp(hash_descriptor[x].name, name) == 0) {
+          return x;
+       }
+   }
+   return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_find_hash_any.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+/* return first hash with at least [amount over] digestlen bytes of output */
+int find_hash_any(const char *name, int digestlen)
+{
+   int x, y, z;
+   _ARGCHK(name != NULL);
+
+   x = find_hash(name);
+   if (x != -1) return x;
+
+   y = MAXBLOCKSIZE+1;
+   z = -1;
+   for (x = 0; x < TAB_SIZE; x++) {
+       if (hash_descriptor[x].name == NULL) {
+          continue;
+       }
+       if ((int)hash_descriptor[x].hashsize >= digestlen && (int)hash_descriptor[x].hashsize < y) {
+          z = x;
+          y = hash_descriptor[x].hashsize;
+       }
+   }
+   return z;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_find_hash_id.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,22 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int find_hash_id(unsigned char ID)
+{
+   int x;
+   for (x = 0; x < TAB_SIZE; x++) {
+       if (hash_descriptor[x].ID == ID) {
+          return (hash_descriptor[x].name == NULL) ? -1 : x;
+       }
+   }
+   return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_find_prng.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,24 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int find_prng(const char *name)
+{
+   int x;
+   _ARGCHK(name != NULL);
+   for (x = 0; x < TAB_SIZE; x++) {
+       if ((prng_descriptor[x].name != NULL) && strcmp(prng_descriptor[x].name, name) == 0) {
+          return x;
+       }
+   }
+   return -1;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_hash_descriptor.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,17 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+struct _hash_descriptor hash_descriptor[TAB_SIZE] = {
+{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL } };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_hash_is_valid.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,19 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int hash_is_valid(int idx)
+{
+   if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) {
+      return CRYPT_INVALID_HASH;
+   }
+   return CRYPT_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_prng_descriptor.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,18 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+struct _prng_descriptor prng_descriptor[TAB_SIZE] = {
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL } };
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_prng_is_valid.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,19 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int prng_is_valid(int idx)
+{
+   if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) {
+      return CRYPT_INVALID_PRNG;
+   }
+   return CRYPT_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_register_cipher.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,36 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int register_cipher(const struct _cipher_descriptor *cipher)
+{
+   int x;
+
+   _ARGCHK(cipher != NULL);
+
+   /* is it already registered? */
+   for (x = 0; x < TAB_SIZE; x++) {
+       if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) {
+          return x;
+       }
+   }
+
+   /* find a blank spot */
+   for (x = 0; x < TAB_SIZE; x++) {
+       if (cipher_descriptor[x].name == NULL) {
+          memcpy(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor));
+          return x;
+       }
+   }
+
+   /* no spot */
+   return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_register_hash.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,36 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int register_hash(const struct _hash_descriptor *hash)
+{
+   int x;
+
+   _ARGCHK(hash != NULL);
+
+   /* is it already registered? */
+   for (x = 0; x < TAB_SIZE; x++) {
+       if (memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor)) == 0) {
+          return x;
+       }
+   }
+
+   /* find a blank spot */
+   for (x = 0; x < TAB_SIZE; x++) {
+       if (hash_descriptor[x].name == NULL) {
+          memcpy(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor));
+          return x;
+       }
+   }
+
+   /* no spot */
+   return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_register_prng.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,36 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int register_prng(const struct _prng_descriptor *prng)
+{
+   int x;
+
+   _ARGCHK(prng != NULL);
+
+   /* is it already registered? */
+   for (x = 0; x < TAB_SIZE; x++) {
+       if (memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor)) == 0) {
+          return x;
+       }
+   }
+
+   /* find a blank spot */
+   for (x = 0; x < TAB_SIZE; x++) {
+       if (prng_descriptor[x].name == NULL) {
+          memcpy(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor));
+          return x;
+       }
+   }
+
+   /* no spot */
+   return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_unregister_cipher.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,28 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int unregister_cipher(const struct _cipher_descriptor *cipher)
+{
+   int x;
+
+   _ARGCHK(cipher != NULL);
+
+   /* is it already registered? */
+   for (x = 0; x < TAB_SIZE; x++) {
+       if (memcmp(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor)) == 0) {
+          cipher_descriptor[x].name = NULL;
+          cipher_descriptor[x].ID   = 255;
+          return CRYPT_OK;
+       }
+   }
+   return CRYPT_ERROR;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_unregister_hash.c	Mon May 31 18:21:40 2004 +0000
@@ -0,0 +1,27 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email