changeset 3:7faae8f46238 libtomcrypt-orig

Branch renaming
author Matt Johnston <matt@ucc.asn.au>
date Mon, 31 May 2004 18:25:41 +0000
parents
children 6362d3854bb4
files LICENSE PLAN aes.c aes_tab.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 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 196 files changed, 49251 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE	Mon May 31 18:25:41 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:25:41 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:25:41 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:25:41 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/authors	Mon May 31 18:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 2004 +0000
@@ -0,0 +1,229 @@
+/* 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"
+
+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:25:41 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:25:41 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", "[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:25:41 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:25:41 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"
+
+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 },
+{ 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 },
+{ 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 },
+{ 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 },
+{ 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 },
+{ 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 },
+{ 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 },
+{ 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 2004 +0000
@@ -0,0 +1,45 @@
+/* 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 },
+{ 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 },
+{ 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 },
+{ 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 },
+{ 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 },
+{ 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 },
+{ 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 },
+{ 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:25:41 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:25:41 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"
+
+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 },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ NULL, NULL, NULL, NULL, NULL },
+{ 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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:25:41 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 protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int unregister_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) {
+          hash_descriptor[x].name = NULL;
+          return CRYPT_OK;
+       }
+   }
+   return CRYPT_ERROR;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt_unregister_prng.c	Mon May 31 18:25:41 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 protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+int unregister_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) {
+          prng_descriptor[x].name = NULL;
+          return CRYPT_OK;
+       }
+   }
+   return CRYPT_ERROR;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ctr_decrypt.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,25 @@
+/* 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 CTR
+
+int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr)
+{
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(ctr != NULL);
+
+   return ctr_encrypt(ct, pt, len, ctr);
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ctr_encrypt.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,64 @@
+/* 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 CTR
+
+int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr)
+{
+   int x, err;
+
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(ctr != NULL);
+
+   if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
+       return err;
+   }
+   
+   /* is blocklen/padlen valid? */
+   if (ctr->blocklen < 0 || ctr->blocklen > (int)sizeof(ctr->ctr) ||
+       ctr->padlen   < 0 || ctr->padlen   > (int)sizeof(ctr->pad)) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   while (len-- > 0) {
+      /* is the pad empty? */
+      if (ctr->padlen == ctr->blocklen) {
+         /* increment counter */
+         if (ctr->mode == 0) {
+            /* little-endian */
+            for (x = 0; x < ctr->blocklen; x++) {
+               ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
+               if (ctr->ctr[x] != (unsigned char)0) {
+                  break;
+               }
+            }
+         } else {
+            /* big-endian */
+            for (x = ctr->blocklen-1; x >= 0; x--) {
+               ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
+               if (ctr->ctr[x] != (unsigned char)0) {
+                  break;
+               }
+            }
+         }
+
+         /* encrypt it */
+         cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key);
+         ctr->padlen = 0;
+      }
+      *ct++ = *pt++ ^ ctr->pad[ctr->padlen++];
+   }
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ctr_start.c	Mon May 31 18:25:41 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 CTR
+
+int ctr_start(int cipher, const unsigned char *count, const unsigned char *key, int keylen, 
+              int num_rounds, symmetric_CTR *ctr)
+{
+   int x, err;
+
+   _ARGCHK(count != NULL);
+   _ARGCHK(key != NULL);
+   _ARGCHK(ctr != 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, &ctr->key)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* copy ctr */
+   ctr->blocklen = cipher_descriptor[cipher].block_length;
+   ctr->cipher   = cipher;
+   ctr->padlen   = 0;
+   ctr->mode     = 0;
+   for (x = 0; x < ctr->blocklen; x++) {
+       ctr->ctr[x] = count[x];
+   }
+   cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key);
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/encrypt.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,231 @@
+/* encrypt V1.1 Fri Oct 18 04:28:03 NZDT 2002 */
+/* File de/encryption, using libtomcrypt */
+/* Written by Daniel Richards <[email protected]> */
+/* Help from Tom St Denis with various bits */
+/* This code is public domain, no rights reserved. */
+/* Encrypts by default, -d flag enables decryption */
+/* ie: ./encrypt blowfish story.txt story.ct */
+/* ./encrypt -d blowfish story.ct story.pt */
+
+#include <mycrypt.h>
+
+int errno;
+
+int usage(char *name) 
+{
+   int x;
+
+   printf("Usage: %s [-d](ecrypt) cipher infile outfile\nCiphers:\n", name);
+   for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+      printf("%s\n",cipher_descriptor[x].name);
+   }
+   exit(1);
+}
+
+void register_algs(void)
+{
+   int x;
+   
+#ifdef RIJNDAEL
+  register_cipher (&aes_desc);
+#endif
+#ifdef BLOWFISH
+  register_cipher (&blowfish_desc);
+#endif
+#ifdef XTEA
+  register_cipher (&xtea_desc);
+#endif
+#ifdef RC5
+  register_cipher (&rc5_desc);
+#endif
+#ifdef RC6
+  register_cipher (&rc6_desc);
+#endif
+#ifdef SAFERP
+  register_cipher (&saferp_desc);
+#endif
+#ifdef TWOFISH
+  register_cipher (&twofish_desc);
+#endif
+#ifdef SAFER
+  register_cipher (&safer_k64_desc);
+  register_cipher (&safer_sk64_desc);
+  register_cipher (&safer_k128_desc);
+  register_cipher (&safer_sk128_desc);
+#endif
+#ifdef RC2
+  register_cipher (&rc2_desc);
+#endif
+#ifdef DES
+  register_cipher (&des_desc);
+  register_cipher (&des3_desc);
+#endif
+#ifdef CAST5
+  register_cipher (&cast5_desc);
+#endif
+#ifdef NOEKEON
+  register_cipher (&noekeon_desc);
+#endif
+#ifdef SKIPJACK
+  register_cipher (&skipjack_desc);
+#endif
+
+   if (register_hash(&sha256_desc) == -1) {
+      printf("Error registering SHA256\n");
+      exit(-1);
+   } 
+
+   if (register_prng(&yarrow_desc) == -1) {
+      printf("Error registering yarrow PRNG\n");
+      exit(-1);
+   }
+
+   if (register_prng(&sprng_desc) == -1) {
+      printf("Error registering sprng PRNG\n");
+      exit(-1);
+   }
+}
+
+int main(int argc, char *argv[]) 
+{
+   unsigned char plaintext[512],ciphertext[512];
+   unsigned char tmpkey[512], key[MAXBLOCKSIZE], IV[MAXBLOCKSIZE];
+   unsigned char inbuf[512]; /* i/o block size */
+   unsigned long outlen, y, ivsize, x, decrypt;
+   symmetric_CTR ctr;
+   int cipher_idx, hash_idx, ks;
+   char *infile, *outfile, *cipher;
+   prng_state prng;
+   FILE *fdin, *fdout;
+
+   /* register algs, so they can be printed */
+   register_algs();
+
+   if (argc < 4) {
+      return usage(argv[0]);
+   }
+
+   if (!strcmp(argv[1], "-d")) {
+      decrypt = 1;
+      cipher  = argv[2];
+      infile  = argv[3];
+      outfile = argv[4];
+   } else {
+      decrypt = 0;
+      cipher  = argv[1];
+      infile  = argv[2];
+      outfile = argv[3];
+   }   
+
+   /* file handles setup */
+   fdin = fopen(infile,"rb");
+   if (fdin == NULL) {
+      perror("Can't open input for reading");
+      exit(-1);
+   }
+
+   fdout = fopen(outfile,"wb");
+   if (fdout == NULL) { 
+      perror("Can't open output for writing");
+      exit(-1);
+   }
+ 
+   cipher_idx = find_cipher(cipher);
+   if (cipher_idx == -1) {
+      printf("Invalid cipher entered on command line.\n");
+      exit(-1);
+   }
+
+   hash_idx = find_hash("sha256");
+   if (hash_idx == -1) {
+      printf("SHA256 not found...?\n");
+      exit(-1);
+   }
+
+   ivsize = cipher_descriptor[cipher_idx].block_length;
+   ks = hash_descriptor[hash_idx].hashsize;
+   if (cipher_descriptor[cipher_idx].keysize(&ks) != CRYPT_OK) { 
+      printf("Invalid keysize???\n");
+      exit(-1);
+   }
+
+   printf("\nEnter key: ");
+   fgets((char *)tmpkey,sizeof(tmpkey), stdin);
+   outlen = sizeof(key);
+   if ((errno = hash_memory(hash_idx,tmpkey,strlen((char *)tmpkey),key,&outlen)) != CRYPT_OK) {
+      printf("Error hashing key: %s\n", error_to_string(errno));
+      exit(-1);
+   }
+   
+   if (decrypt) {
+      /* Need to read in IV */
+      if (fread(IV,1,ivsize,fdin) != ivsize) {
+         printf("Error reading IV from input.\n");
+         exit(-1);
+      }
+   
+      if ((errno = ctr_start(cipher_idx,IV,key,ks,0,&ctr)) != CRYPT_OK) {
+         printf("ctr_start error: %s\n",error_to_string(errno));
+         exit(-1);
+      }
+
+      /* IV done */
+      do {
+         y = fread(inbuf,1,sizeof(inbuf),fdin);
+
+         if ((errno = ctr_decrypt(inbuf,plaintext,y,&ctr)) != CRYPT_OK) {
+            printf("ctr_decrypt error: %s\n", error_to_string(errno));
+            exit(-1);
+         }
+
+         if (fwrite(plaintext,1,y,fdout) != y) {
+            printf("Error writing to file.\n");
+            exit(-1);
+         }
+      } while (y == sizeof(inbuf));
+      fclose(fdin);
+      fclose(fdout);
+
+   } else {  /* encrypt */
+      /* Setup yarrow for random bytes for IV */
+      
+      if ((errno = rng_make_prng(128, find_prng("yarrow"), &prng, NULL)) != CRYPT_OK) {
+         printf("Error setting up PRNG, %s\n", error_to_string(errno));
+      }      
+
+      /* You can use rng_get_bytes on platforms that support it */
+      /* x = rng_get_bytes(IV,ivsize,NULL);*/
+      x = yarrow_read(IV,ivsize,&prng);
+      if (x != ivsize) {
+         printf("Error reading PRNG for IV required.\n");
+         exit(-1);
+      }
+   
+      if (fwrite(IV,1,ivsize,fdout) != ivsize) {
+         printf("Error writing IV to output.\n");
+         exit(-1);
+      }
+
+      if ((errno = ctr_start(cipher_idx,IV,key,ks,0,&ctr)) != CRYPT_OK) {
+         printf("ctr_start error: %s\n",error_to_string(errno));
+         exit(-1);
+      }
+
+      do {
+         y = fread(inbuf,1,sizeof(inbuf),fdin);
+
+         if ((errno = ctr_encrypt(inbuf,ciphertext,y,&ctr)) != CRYPT_OK) {
+            printf("ctr_encrypt error: %s\n", error_to_string(errno));
+            exit(-1);
+         }
+
+         if (fwrite(ciphertext,1,y,fdout) != y) {
+            printf("Error writing to output.\n");
+            exit(-1);
+         }
+      } while (y == sizeof(inbuf));   
+      fclose(fdout);
+      fclose(fdin);
+   }
+   return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/hashsum.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,106 @@
+/*
+ * Written by Daniel Richards <[email protected]> 6/7/2002
+ * hash.c: This app uses libtomcrypt to hash either stdin or a file
+ * This file is Public Domain. No rights are reserved.
+ * Compile with 'gcc hashsum.c -o hashsum -ltomcrypt'
+ * This example isn't really big enough to warrent splitting into
+ * more functions ;)
+*/
+
+#include <mycrypt_custom.h>
+
+int errno;
+
+void register_algs();
+
+int main(int argc, char **argv)
+{
+   int idx, x, z;
+   unsigned long w;
+   unsigned char hash_buffer[MAXBLOCKSIZE];
+   hash_state md;
+
+   /* You need to register algorithms before using them */
+   register_algs();
+   if (argc < 2) {
+      printf("usage: ./hash algorithm file [file ...]\n");
+      printf("Algorithms:\n");
+      for (x = 0; hash_descriptor[x].name != NULL; x++) {
+         printf(" %s\n", hash_descriptor[x].name);
+      }
+      exit(EXIT_SUCCESS);
+   }
+
+   idx = find_hash(argv[1]);
+   if (idx == -1) {
+      fprintf(stderr, "\nInvalid hash specified on command line.\n");
+      return -1;
+   }
+
+   if (argc == 2) {
+      hash_descriptor[idx].init(&md);
+      do {
+         x = fread(hash_buffer, 1, sizeof(hash_buffer), stdin);
+         hash_descriptor[idx].process(&md, hash_buffer, x);
+      } while (x == sizeof(hash_buffer));
+      hash_descriptor[idx].done(&md, hash_buffer);
+      for (x = 0; x < (int)hash_descriptor[idx].hashsize; x++) {
+          printf("%02x",hash_buffer[x]);
+      }
+      printf("  (stdin)\n");
+   } else {
+      for (z = 2; z < argc; z++) {
+         w = sizeof(hash_buffer);
+         if ((errno = hash_file(idx,argv[z],hash_buffer,&w)) != CRYPT_OK) {
+            printf("File hash error: %s\n", error_to_string(errno));
+         } else {
+             for (x = 0; x < (int)hash_descriptor[idx].hashsize; x++) {
+                 printf("%02x",hash_buffer[x]);
+             }
+             printf("  %s\n", argv[z]);
+         }
+      }
+   }
+   return EXIT_SUCCESS;
+}
+
+void register_algs(void)
+{
+#ifdef TIGER
+  register_hash (&tiger_desc);
+#endif
+#ifdef MD2
+  register_hash (&md2_desc);
+#endif
+#ifdef MD4
+  register_hash (&md4_desc);
+#endif
+#ifdef MD5
+  register_hash (&md5_desc);
+#endif
+#ifdef SHA1
+  register_hash (&sha1_desc);
+#endif
+#ifdef SHA224
+  register_hash (&sha224_desc);
+#endif
+#ifdef SHA256
+  register_hash (&sha256_desc);
+#endif
+#ifdef SHA384
+  register_hash (&sha384_desc);
+#endif
+#ifdef SHA512
+  register_hash (&sha512_desc);
+#endif
+#ifdef RIPEMD128
+  register_hash (&rmd128_desc);
+#endif
+#ifdef RIPEMD160
+  register_hash (&rmd160_desc);
+#endif
+#ifdef WHIRLPOOL
+  register_hash (&whirlpool_desc);
+#endif
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/small.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,11 @@
+// small demo app that just includes a cipher/hash/prng
+
+#include <mycrypt.h>
+
+int main(void)
+{
+   register_cipher(&rijndael_desc);
+   register_prng(&yarrow_desc);
+   register_hash(&sha256_desc);
+   return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,1982 @@
+/* This is the worst code you have ever seen written on purpose.... this code is just a big hack to test
+out the functionality of the library */
+
+#ifdef SONY_PS2
+#include <eetypes.h>
+#include <eeregs.h>
+#include "timer.h"
+#endif
+
+#include <mycrypt.h>
+
+int     errnum;
+
+
+int
+null_setup (const unsigned char *key, int keylen, int num_rounds,
+        symmetric_key * skey)
+{
+  return CRYPT_OK;
+}
+
+void
+null_ecb_encrypt (const unsigned char *pt, unsigned char *ct,
+          symmetric_key * key)
+{
+  memcpy (ct, pt, 8);
+}
+
+void
+null_ecb_decrypt (const unsigned char *ct, unsigned char *pt,
+          symmetric_key * key)
+{
+  memcpy (pt, ct, 8);
+}
+
+int
+null_test (void)
+{
+  return CRYPT_OK;
+}
+
+int
+null_keysize (int *desired_keysize)
+{
+  return CRYPT_OK;
+}
+
+const struct _cipher_descriptor null_desc = {
+  "memcpy()",
+  255,
+  8, 8, 8, 1,
+  &null_setup,
+  &null_ecb_encrypt,
+  &null_ecb_decrypt,
+  &null_test,
+  &null_keysize
+};
+
+
+prng_state prng;
+
+void
+store_tests (void)
+{
+  unsigned char buf[8];
+  unsigned long L;
+  ulong64 LL;
+
+  printf ("LOAD32/STORE32 tests\n");
+  L = 0x12345678UL;
+  STORE32L (L, &buf[0]);
+  L = 0;
+  LOAD32L (L, &buf[0]);
+  if (L != 0x12345678UL) {
+    printf ("LOAD/STORE32 Little don't work\n");
+    exit (-1);
+  }
+  LL = CONST64 (0x01020304050607);
+  STORE64L (LL, &buf[0]);
+  LL = 0;
+  LOAD64L (LL, &buf[0])
+    if (LL != CONST64 (0x01020304050607)) {
+    printf ("LOAD/STORE64 Little don't work\n");
+    exit (-1);
+  }
+
+  L = 0x12345678UL;
+  STORE32H (L, &buf[0]);
+  L = 0;
+  LOAD32H (L, &buf[0]);
+  if (L != 0x12345678UL) {
+    printf ("LOAD/STORE32 High don't work, %08lx\n", L);
+    exit (-1);
+  }
+  LL = CONST64 (0x01020304050607);
+  STORE64H (LL, &buf[0]);
+  LL = 0;
+  LOAD64H (LL, &buf[0])
+    if (LL != CONST64 (0x01020304050607)) {
+    printf ("LOAD/STORE64 High don't work\n");
+    exit (-1);
+  }
+}
+
+void
+cipher_tests (void)
+{
+  int     x;
+
+  printf ("Ciphers compiled in\n");
+  for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+    printf
+      (" %12s (%2d) Key Size: %4d to %4d, Block Size: %3d, Default # of rounds: %2d\n",
+       cipher_descriptor[x].name, cipher_descriptor[x].ID,
+       cipher_descriptor[x].min_key_length * 8,
+       cipher_descriptor[x].max_key_length * 8,
+       cipher_descriptor[x].block_length * 8,
+       cipher_descriptor[x].default_rounds);
+  }
+
+}
+
+void
+ecb_tests (void)
+{
+  int     x;
+
+  printf ("ECB tests\n");
+  for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+    printf (" %12s: ", cipher_descriptor[x].name);
+    if ((errnum = cipher_descriptor[x].test ()) != CRYPT_OK) {
+      printf (" **failed** Reason: %s\n", error_to_string (errnum));
+      exit (-1);
+    } else {
+      printf ("passed\n");
+    }
+  }
+}
+
+#ifdef CBC
+void
+cbc_tests (void)
+{
+  symmetric_CBC cbc;
+  int     x, y;
+  unsigned char blk[32], ct[32], key[32], IV[32];
+  const unsigned char test[] =
+    { 0XFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+  printf ("CBC tests\n");
+  /* ---- CBC ENCODING ---- */
+  /* make up a block and IV */
+  for (x = 0; x < 32; x++)
+    blk[x] = IV[x] = x;
+
+  /* now lets start a cbc session */
+  if ((errnum =
+       cbc_start (find_cipher ("blowfish"), IV, key, 16, 0,
+          &cbc)) != CRYPT_OK) {
+    printf ("CBC Setup: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* now lets encode 32 bytes */
+  for (x = 0; x < 4; x++) {
+    if ((errnum = cbc_encrypt (blk + 8 * x, ct + 8 * x, &cbc)) != CRYPT_OK) {
+      printf ("CBC encrypt: %s\n", error_to_string (errnum));
+      exit (-1);
+    }
+  }
+
+  zeromem (blk, sizeof (blk));
+
+  /* ---- CBC DECODING ---- */
+  /* make up a IV */
+  for (x = 0; x < 32; x++)
+    IV[x] = x;
+
+  /* now lets start a cbc session */
+  if ((errnum =
+       cbc_start (find_cipher ("blowfish"), IV, key, 16, 0,
+          &cbc)) != CRYPT_OK) {
+    printf ("CBC Setup: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* now lets decode 32 bytes */
+  for (x = 0; x < 4; x++) {
+    if ((errnum = cbc_decrypt (ct + 8 * x, blk + 8 * x, &cbc)) != CRYPT_OK) {
+      printf ("CBC decrypt: %s\n", error_to_string (errnum));
+      exit (-1);
+    }
+  }
+
+
+  /* print output */
+  for (x = y = 0; x < 32; x++)
+    if (blk[x] != x)
+      y = 1;
+  printf ("  %s\n", y ? "failed" : "passed");
+
+  /* lets actually check the bytes */
+  memset (IV, 0, 8);
+  IV[0] = 0xFF;         /* IV  = FF 00 00 00 00 00 00 00 */
+  memset (blk, 0, 32);
+  blk[8] = 0xFF;        /* BLK = 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 */
+  cbc_start (find_cipher ("memcpy()"), IV, key, 8, 0, &cbc);
+  cbc_encrypt (blk, ct, &cbc);  /* expect: FF 00 00 00 00 00 00 00 */
+  cbc_encrypt (blk + 8, ct + 8, &cbc);  /* expect: 00 00 00 00 00 00 00 00 */
+  if (memcmp (ct, test, 16)) {
+    printf ("CBC failed logical testing.\n");
+    for (x = 0; x < 16; x++)
+      printf ("%02x ", ct[x]);
+    printf ("\n");
+    exit (-1);
+  } else {
+    printf ("CBC passed logical testing.\n");
+  }
+}
+#else
+void
+cbc_tests (void)
+{
+  printf ("CBC not compiled in\n");
+}
+#endif
+
+#ifdef OFB
+void
+ofb_tests (void)
+{
+  symmetric_OFB ofb;
+  int     x, y;
+  unsigned char blk[32], ct[32], key[32], IV[32];
+
+  printf ("OFB tests\n");
+  /* ---- ofb ENCODING ---- */
+  /* make up a block and IV */
+  for (x = 0; x < 32; x++)
+    blk[x] = IV[x] = x;
+
+  /* now lets start a ofb session */
+  if ((errnum =
+       ofb_start (find_cipher ("cast5"), IV, key, 16, 0, &ofb)) != CRYPT_OK) {
+    printf ("OFB Setup: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* now lets encode 32 bytes */
+  for (x = 0; x < 4; x++) {
+    if ((errnum = ofb_encrypt (blk + 8 * x, ct + 8 * x, 8, &ofb)) != CRYPT_OK) {
+      printf ("OFB encrypt: %s\n", error_to_string (errnum));
+      exit (-1);
+    }
+  }
+
+  zeromem (blk, sizeof (blk));
+
+  /* ---- ofb DECODING ---- */
+  /* make up a IV */
+  for (x = 0; x < 32; x++)
+    IV[x] = x;
+
+  /* now lets start a ofb session */
+  if ((errnum =
+       ofb_start (find_cipher ("cast5"), IV, key, 16, 0, &ofb)) != CRYPT_OK) {
+    printf ("OFB setup: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* now lets decode 32 bytes */
+  for (x = 0; x < 4; x++) {
+    if ((errnum = ofb_decrypt (ct + 8 * x, blk + 8 * x, 8, &ofb)) != CRYPT_OK) {
+      printf ("OFB decrypt: %s\n", error_to_string (errnum));
+      exit (-1);
+    }
+  }
+
+  /* print output */
+  for (x = y = 0; x < 32; x++)
+    if (blk[x] != x)
+      y = 1;
+  printf ("  %s\n", y ? "failed" : "passed");
+  if (y)
+    exit (-1);
+}
+#else
+void
+ofb_tests (void)
+{
+  printf ("OFB not compiled in\n");
+}
+#endif
+
+#ifdef CFB
+void
+cfb_tests (void)
+{
+  symmetric_CFB cfb;
+  int     x, y;
+  unsigned char blk[32], ct[32], key[32], IV[32];
+
+  printf ("CFB tests\n");
+  /* ---- cfb ENCODING ---- */
+  /* make up a block and IV */
+  for (x = 0; x < 32; x++)
+    blk[x] = IV[x] = x;
+
+  /* now lets start a cfb session */
+  if ((errnum =
+       cfb_start (find_cipher ("blowfish"), IV, key, 16, 0,
+          &cfb)) != CRYPT_OK) {
+    printf ("CFB setup: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* now lets encode 32 bytes */
+  for (x = 0; x < 4; x++) {
+    if ((errnum = cfb_encrypt (blk + 8 * x, ct + 8 * x, 8, &cfb)) != CRYPT_OK) {
+      printf ("CFB encrypt: %s\n", error_to_string (errnum));
+      exit (-1);
+    }
+  }
+
+  zeromem (blk, sizeof (blk));
+
+  /* ---- cfb DECODING ---- */
+  /* make up ahash_descriptor[prng->yarrow.hash].hashsize IV */
+  for (x = 0; x < 32; x++)
+    IV[x] = x;
+
+  /* now lets start a cfb session */
+  if ((errnum =
+       cfb_start (find_cipher ("blowfish"), IV, key, 16, 0,
+          &cfb)) != CRYPT_OK) {
+    printf ("CFB Setup: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* now lets decode 32 bytes */
+  for (x = 0; x < 4; x++) {
+    if ((errnum = cfb_decrypt (ct + 8 * x, blk + 8 * x, 8, &cfb)) != CRYPT_OK) {
+      printf ("CFB decrypt: %s\n", error_to_string (errnum));
+      exit (-1);
+    }
+  }
+
+  /* print output */
+  for (x = y = 0; x < 32; x++)
+    if (blk[x] != x)
+      y = 1;
+  printf ("  %s\n", y ? "failed" : "passed");
+  if (y)
+    exit (-1);
+}
+#else
+void
+cfb_tests (void)
+{
+  printf ("CFB not compiled in\n");
+}
+#endif
+
+#ifdef CTR
+void
+ctr_tests (void)
+{
+  symmetric_CTR ctr;
+  int     x, y;
+  unsigned char blk[32], ct[32], key[32], count[32];
+  const unsigned char test[] =
+    { 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0 };
+
+  printf ("CTR tests\n");
+  /* ---- CTR ENCODING ---- */
+  /* make up a block and IV */
+  for (x = 0; x < 32; x++)
+    blk[x] = count[x] = x;
+
+  /* now lets start a ctr session */
+  if ((errnum =
+       ctr_start (find_cipher ("xtea"), count, key, 16, 0,
+          &ctr)) != CRYPT_OK) {
+    printf ("CTR Setup: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* now lets encode 32 bytes */
+  for (x = 0; x < 4; x++) {
+    if ((errnum = ctr_encrypt (blk + 8 * x, ct + 8 * x, 8, &ctr)) != CRYPT_OK) {
+      printf ("CTR encrypt: %s\n", error_to_string (errnum));
+      exit (-1);
+    }
+  }
+
+  zeromem (blk, sizeof (blk));
+
+  /* ---- CTR DECODING ---- */
+  /* make up a IV */
+  for (x = 0; x < 32; x++)
+    count[x] = x;
+
+  /* now lets start a cbc session */
+  if ((errnum =
+       ctr_start (find_cipher ("xtea"), count, key, 16, 0,
+          &ctr)) != CRYPT_OK) {
+    printf ("CTR Setup: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* now lets decode 32 bytes */
+  for (x = 0; x < 4; x++) {
+    if ((errnum = ctr_decrypt (ct + 8 * x, blk + 8 * x, 8, &ctr)) != CRYPT_OK) {
+      printf ("CTR decrypt: %s\n", error_to_string (errnum));
+      exit (-1);
+    }
+  }
+
+  /* print output */
+  for (x = y = 0; x < 32; x++)
+    if (blk[x] != x)
+      y = 1;
+  printf ("  %s\n", y ? "failed" : "passed");
+  if (y)
+    exit (-1);
+
+  /* lets actually check the bytes */
+  memset (count, 0, 8);
+  count[0] = 0xFF;      /* IV  = FF 00 00 00 00 00 00 00 */
+  memset (blk, 0, 32);
+  blk[9] = 2;           /* BLK = 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 */
+  ctr_start (find_cipher ("memcpy()"), count, key, 8, 0, &ctr);
+  ctr_encrypt (blk, ct, 8, &ctr);   /* expect: FF 00 00 00 00 00 00 00 */
+  ctr_encrypt (blk + 8, ct + 8, 8, &ctr);   /* expect: 00 03 00 00 00 00 00 00 */
+  if (memcmp (ct, test, 16)) {
+    printf ("CTR failed logical testing.\n");
+    for (x = 0; x < 16; x++)
+      printf ("%02x ", ct[x]);
+    printf ("\n");
+  } else {
+    printf ("CTR passed logical testing.\n");
+  }
+
+}
+#else
+void
+ctr_tests (void)
+{
+  printf ("CTR not compiled in\n");
+}
+#endif
+
+void
+hash_tests (void)
+{
+  int     x;
+  printf ("Hash tests\n");
+  for (x = 0; hash_descriptor[x].name != NULL; x++) {
+    printf (" %10s (%2d) ", hash_descriptor[x].name, hash_descriptor[x].ID);
+    if ((errnum = hash_descriptor[x].test ()) != CRYPT_OK) {
+      printf ("**failed** Reason: %s\n", error_to_string (errnum));
+      exit(-1);
+    } else {
+      printf ("passed\n");
+    }
+  }
+}
+
+#ifdef MRSA
+void
+pad_test (void)
+{
+  unsigned char in[100], out[100];
+  unsigned long x, y;
+
+  /* make a dummy message */
+  for (x = 0; x < 16; x++)
+    in[x] = (unsigned char) x;
+
+  /* pad the message so that random filler is placed before and after it */
+  y = 100;
+  if ((errnum =
+       rsa_pad (in, 16, out, &y, find_prng ("yarrow"), &prng)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* depad the message to get the original content */
+  memset (in, 0, sizeof (in));
+  x = 100;
+  if ((errnum = rsa_depad (out, y, in, &x)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* check outcome */
+  printf ("rsa_pad: ");
+  if (x != 16) {
+    printf ("Failed.  Wrong size.\n");
+    exit (-1);
+  }
+  for (x = 0; x < 16; x++)
+    if (in[x] != x) {
+      printf ("Failed.  Expected %02lx and got %02x.\n", x, in[x]);
+      exit (-1);
+    }
+  printf ("passed.\n");
+}
+void
+rsa_test (void)
+{
+  unsigned char in[520], out[520];
+  unsigned long x, y, z, limit;
+  int     stat;
+  rsa_key key;
+  clock_t t;
+
+  /* ---- SINGLE ENCRYPT ---- */
+  /* encrypt a short 8 byte string */
+  if ((errnum =
+       rsa_make_key (&prng, find_prng ("yarrow"), 1024 / 8, 65537,
+             &key)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  for (x = 0; x < 8; x++)
+    in[x] = (unsigned char) (x + 1);
+  y = sizeof (in);
+  if ((errnum = rsa_exptmod (in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* decrypt it */
+  zeromem (in, sizeof (in));
+  x = sizeof (out);
+  if ((errnum = rsa_exptmod (out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* compare */
+  printf ("RSA    : ");
+  for (x = 0; x < 8; x++)
+    if (in[x] != (x + 1)) {
+      printf ("Failed.  x==%02lx, in[%ld]==%02x\n", x, x, in[x]);
+      exit (-1);
+    }
+  printf ("passed.\n");
+
+  /* test the rsa_encrypt_key functions */
+  for (x = 0; x < 16; x++)
+    in[x] = x;
+  y = sizeof (out);
+  if ((errnum =
+       rsa_encrypt_key (in, 16, out, &y, &prng, find_prng ("yarrow"),
+            &key)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  zeromem (in, sizeof (in));
+  x = sizeof (in);
+  if ((errnum = rsa_decrypt_key (out, y, in, &x, &key)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  printf ("RSA en/de crypt key routines: ");
+  if (x != 16) {
+    printf ("Failed (length)\n");
+    exit (-1);
+  }
+  for (x = 0; x < 16; x++)
+    if (in[x] != x) {
+      printf ("Failed (contents)\n");
+      exit (-1);
+    }
+  printf ("Passed\n");
+
+  /* test sign_hash functions */
+  for (x = 0; x < 16; x++)
+    in[x] = x;
+  x = sizeof (in);
+  if ((errnum = rsa_sign_hash (in, 16, out, &x, &key)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  printf ("RSA signed hash: %lu bytes\n", x);
+  if ((errnum = rsa_verify_hash (out, x, in, &stat, &key)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  printf ("Verify hash: %s, ", stat ? "passed" : "failed");
+  in[0] ^= 1;
+  if ((errnum = rsa_verify_hash (out, x, in, &stat, &key)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  printf ("%s\n", (!stat) ? "passed" : "failed");
+  if (stat)
+    exit (-1);
+  rsa_free (&key);
+
+  /* make a RSA key */
+#ifdef SONY_PS2_NOPE
+  limit = 1024;
+#else
+  limit = 2048;
+#endif
+
+  {
+    int     tt;
+
+    for (z = 1024; z <= limit; z += 512) {
+      t = XCLOCK ();
+      for (tt = 0; tt < 3; tt++) {
+         if ((errnum = rsa_make_key (&prng, find_prng ("yarrow"), z / 8, 65537, &key)) != CRYPT_OK) {
+            printf ("Error: %s\n", error_to_string (errnum));
+            exit (-1);
+         }
+
+         /* check modulus size */
+         if (mp_unsigned_bin_size(&key.N) != (int)(z/8)) { 
+            printf("\nRSA key supposed to be %lu bits but was %d bits\n", z, mp_count_bits(&key.N));
+            exit(EXIT_FAILURE);
+         }
+
+         if (tt < 2) {
+            rsa_free (&key);
+         }
+      }
+      t = XCLOCK () - t;
+      printf ("Took %.0f ms to make a %ld-bit RSA key.\n", 1000.0 * (((double) t / 3.0) / (double) XCLOCKS_PER_SEC), z);
+
+      /* time encryption */
+      t = XCLOCK ();
+
+      for (tt = 0; tt < 20; tt++) {
+         y = sizeof (in);
+         if ((errnum = rsa_exptmod (in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) {
+            printf ("Error: %s\n", error_to_string (errnum));
+            exit (-1);
+         }
+      }
+      t = XCLOCK () - t;
+      printf ("Took %.0f ms to encrypt with a %ld-bit RSA key.\n",
+              1000.0 * (((double) t / 20.0) / (double) XCLOCKS_PER_SEC), z);
+
+      /* time decryption */
+      t = XCLOCK ();
+      for (tt = 0; tt < 20; tt++) {
+          x = sizeof (out);
+          if ((errnum = rsa_exptmod (out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) {
+             printf ("Error: %s\n", error_to_string (errnum));
+             exit (-1);
+          }
+      }
+      t = XCLOCK () - t;
+      printf ("Took %.0f ms to decrypt with a %ld-bit RSA key.\n",
+      1000.0 * (((double) t / 20.0) / (double) XCLOCKS_PER_SEC), z);
+      rsa_free (&key);
+    }
+  }
+}
+#else
+void
+pad_test (void)
+{
+  printf ("MRSA not compiled in\n");
+}
+
+void
+rsa_test (void)
+{
+  printf ("MRSA not compiled in\n");
+}
+#endif
+
+#ifdef BASE64
+void
+base64_test (void)
+{
+  unsigned char buf[2][100];
+  unsigned long x, y;
+
+  printf ("Base64 tests\n");
+  zeromem (buf, sizeof (buf));
+  for (x = 0; x < 16; x++)
+    buf[0][x] = (unsigned char) x;
+
+  x = 100;
+  if (base64_encode (buf[0], 16, buf[1], &x) != CRYPT_OK) {
+    printf ("  error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  printf ("  encoded 16 bytes to %ld bytes...[%s]\n", x, buf[1]);
+  memset (buf[0], 0, 100);
+  y = 100;
+  if (base64_decode (buf[1], x, buf[0], &y) != CRYPT_OK) {
+    printf ("  error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  printf ("  decoded %ld bytes to %ld bytes\n", x, y);
+  for (x = 0; x < 16; x++)
+    if (buf[0][x] != x) {
+      printf (" **failed**\n");
+      exit (-1);
+    }
+  printf ("  passed\n");
+}
+#else
+void
+base64_test (void)
+{
+  printf ("Base64 not compiled in\n");
+}
+#endif
+
+void
+time_hash (void)
+{
+  clock_t t1;
+  int     x, y;
+  unsigned long z;
+  unsigned char input[4096], out[MAXBLOCKSIZE];
+  printf ("Hash Time Trials (4KB blocks):\n");
+  for (x = 0; hash_descriptor[x].name != NULL; x++) {
+    t1 = XCLOCK ();
+    z = sizeof (out);
+    y = 0;
+    while (XCLOCK () - t1 < (5 * XCLOCKS_PER_SEC)) {
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      hash_memory (x, input, 4096, out, &z);
+      y += 32;
+    }
+    t1 = XCLOCK () - t1;
+    printf ("%-20s: Hash at %5.2f Mbit/sec\n", hash_descriptor[x].name,
+        ((8.0 * 4096.0) *
+         ((double) y / ((double) t1 / (double) XCLOCKS_PER_SEC))) /
+        1000000.0);
+  }
+}
+
+void
+time_ecb (void)
+{
+  clock_t t1, t2;
+  long    x, y1, y2;
+  unsigned char pt[32], key[32];
+  symmetric_key skey;
+  void    (*func) (const unsigned char *, unsigned char *, symmetric_key *);
+
+  printf ("ECB Time Trials for the Symmetric Ciphers:\n");
+  for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+    cipher_descriptor[x].setup (key, cipher_descriptor[x].min_key_length, 0,
+                &skey);
+
+#define DO1   func(pt,pt,&skey);
+#define DO2   DO1 DO1
+#define DO4   DO2 DO2
+#define DO8   DO4 DO4
+#define DO16  DO8 DO8
+#define DO32  DO16 DO16
+#define DO64  DO32 DO32
+#define DO128 DO64 DO64
+#define DO256 DO128 DO128
+
+    func = cipher_descriptor[x].ecb_encrypt;
+    y1 = 0;
+    t1 = XCLOCK ();
+    while (XCLOCK () - t1 < 3 * XCLOCKS_PER_SEC) {
+      DO256;
+      y1 += 256;
+    }
+    t1 = XCLOCK () - t1;
+
+    func = cipher_descriptor[x].ecb_decrypt;
+    y2 = 0;
+    t2 = XCLOCK ();
+    while (XCLOCK () - t2 < 3 * XCLOCKS_PER_SEC) {
+      DO256;
+      y2 += 256;
+    }
+    t2 = XCLOCK () - t2;
+    printf
+      ("%-20s: Encrypt at %5.2f Mbit/sec and Decrypt at %5.2f Mbit/sec\n",
+       cipher_descriptor[x].name,
+       ((8.0 * (double) cipher_descriptor[x].block_length) *
+    ((double) y1 / ((double) t1 / (double) XCLOCKS_PER_SEC))) / 1000000.0,
+       ((8.0 * (double) cipher_descriptor[x].block_length) *
+    ((double) y2 / ((double) t2 / (double) XCLOCKS_PER_SEC))) /
+       1000000.0);
+
+#undef DO256
+#undef DO128
+#undef DO64
+#undef DO32
+#undef DO16
+#undef DO8
+#undef DO4
+#undef DO2
+#undef DO1
+  }
+}
+
+#ifdef MDH
+void
+dh_tests (void)
+{
+  unsigned char buf[3][4096];
+  unsigned long x, y, z;
+  int     low, high, stat, stat2;
+  dh_key  usera, userb;
+  clock_t t1;
+
+  printf("Testing builting DH parameters...."); fflush(stdout);
+  if ((errnum = dh_test()) != CRYPT_OK) {
+     printf("DH Error: %s\n", error_to_string(errnum));
+     exit(-1);
+  }
+  printf("Passed.\n");
+
+  dh_sizes (&low, &high);
+  printf ("DH Keys from %d to %d supported.\n", low * 8, high * 8);
+
+  /* make up two keys */
+  if ((errnum =
+       dh_make_key (&prng, find_prng ("yarrow"), 96, &usera)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  if ((errnum =
+       dh_make_key (&prng, find_prng ("yarrow"), 96, &userb)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* make the shared secret */
+  x = 4096;
+  if ((errnum = dh_shared_secret (&usera, &userb, buf[0], &x)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  y = 4096;
+  if ((errnum = dh_shared_secret (&userb, &usera, buf[1], &y)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  if (y != x) {
+    printf ("DH Shared keys are not same size.\n");
+    exit (-1);
+  }
+  if (memcmp (buf[0], buf[1], x)) {
+    printf ("DH Shared keys not same contents.\n");
+    exit (-1);
+  }
+
+  /* now export userb */
+  y = 4096;
+  if ((errnum = dh_export (buf[1], &y, PK_PUBLIC, &userb)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  dh_free (&userb);
+
+  /* import and make the shared secret again */
+  if ((errnum = dh_import (buf[1], y, &userb)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  z = 4096;
+  if ((errnum = dh_shared_secret (&usera, &userb, buf[2], &z)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  printf ("DH routines: ");
+  if (z != x) {
+    printf ("failed.  Size don't match?\n");
+    exit (-1);
+  }
+  if (memcmp (buf[0], buf[2], x)) {
+    printf ("Failed.  Content didn't match.\n");
+    exit (-1);
+  }
+  printf ("Passed\n");
+  dh_free (&usera);
+  dh_free (&userb);
+
+/* time stuff */
+  {
+    static int sizes[] = { 96, 128, 160, 192, 224, 256, 320, 384, 512 };
+    int     ii, tt;
+
+    for (ii = 0; ii < (int) (sizeof (sizes) / sizeof (sizes[0])); ii++) {
+      t1 = XCLOCK ();
+      for (tt = 0; tt < 25; tt++) {
+    dh_make_key (&prng, find_prng ("yarrow"), sizes[ii], &usera);
+    dh_free (&usera);
+      }
+      t1 = XCLOCK () - t1;
+      printf ("Make dh-%d key took %f msec\n", sizes[ii] * 8,
+          1000.0 * (((double) t1 / 25.0) / (double) XCLOCKS_PER_SEC));
+    }
+  }
+
+/* test encrypt_key */
+  dh_make_key (&prng, find_prng ("yarrow"), 128, &usera);
+  for (x = 0; x < 16; x++)
+    buf[0][x] = x;
+  y = sizeof (buf[1]);
+  if ((errnum =
+       dh_encrypt_key (buf[0], 16, buf[1], &y, &prng, find_prng ("yarrow"),
+               find_hash ("md5"), &usera)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  zeromem (buf[0], sizeof (buf[0]));
+  x = sizeof (buf[0]);
+  if ((errnum = dh_decrypt_key (buf[1], y, buf[0], &x, &usera)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  printf ("DH en/de crypt key routines: ");
+  if (x != 16) {
+    printf ("Failed (length)\n");
+    exit (-1);
+  }
+  for (x = 0; x < 16; x++)
+    if (buf[0][x] != x) {
+      printf ("Failed (contents)\n");
+      exit (-1);
+    }
+  printf ("Passed (size %lu)\n", y);
+
+/* test sign_hash */
+  for (x = 0; x < 16; x++)
+    buf[0][x] = x;
+  x = sizeof (buf[1]);
+  if ((errnum =
+       dh_sign_hash (buf[0], 16, buf[1], &x, &prng, find_prng ("yarrow"),
+             &usera)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  if ((errnum = dh_verify_hash (buf[1], x, buf[0], 16, &stat, &usera)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  buf[0][0] ^= 1;
+  if ((errnum = dh_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  printf ("dh_sign/verify_hash: %s (%d,%d), %lu\n",
+      ((stat == 1)
+       && (stat2 == 0)) ? "passed" : "failed", stat, stat2, x);
+  dh_free (&usera);
+}
+#else
+void
+dh_tests (void)
+{
+  printf ("MDH not compiled in\n");
+}
+#endif
+
+int     callback_x = 0;
+void
+callback (void)
+{
+  printf ("%c\x08", "-\\|/"[++callback_x & 3]);
+#ifndef SONY_PS2
+  fflush (stdout);
+#endif
+}
+
+void
+rng_tests (void)
+{
+  unsigned char buf[16];
+  clock_t t1;
+  int     x, y;
+
+  printf ("RNG tests\n");
+  t1 = XCLOCK ();
+  x = rng_get_bytes (buf, sizeof (buf), &callback);
+  t1 = XCLOCK () - t1;
+  printf ("  %f bytes per second...",
+      (double) x / ((double) t1 / (double) XCLOCKS_PER_SEC));
+  printf ("read %d bytes.\n  ", x);
+  for (y = 0; y < x; y++)
+    printf ("%02x ", buf[y]);
+  printf ("\n");
+
+#ifdef YARROW
+  if ((errnum =
+       rng_make_prng (128, find_prng ("yarrow"), &prng,
+              &callback)) != CRYPT_OK) {
+    printf (" starting yarrow error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+#endif
+}
+
+#ifdef MECC
+void
+ecc_tests (void)
+{
+  unsigned char buf[4][4096];
+  unsigned long x, y, z;
+  int     stat, stat2, low, high;
+  ecc_key usera, userb;
+  clock_t t1;
+
+  if ((errnum = ecc_test ()) != CRYPT_OK) {
+    printf ("ecc Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  ecc_sizes (&low, &high);
+  printf ("ecc Keys from %d to %d supported.\n", low * 8, high * 8);
+
+  /* make up two keys */
+  if ((errnum =
+       ecc_make_key (&prng, find_prng ("yarrow"), 24, &usera)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  if ((errnum =
+       ecc_make_key (&prng, find_prng ("yarrow"), 24, &userb)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* make the shared secret */
+  x = 4096;
+  if ((errnum = ecc_shared_secret (&usera, &userb, buf[0], &x)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  y = 4096;
+  if ((errnum = ecc_shared_secret (&userb, &usera, buf[1], &y)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  if (y != x) {
+    printf ("ecc Shared keys are not same size.\n");
+    exit (-1);
+  }
+
+  if (memcmp (buf[0], buf[1], x)) {
+    printf ("ecc Shared keys not same contents.\n");
+    exit (-1);
+  }
+
+  /* now export userb */
+  y = 4096;
+  if ((errnum = ecc_export (buf[1], &y, PK_PUBLIC, &userb)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  ecc_free (&userb);
+  printf ("ECC-192 export took %ld bytes\n", y);
+
+  /* import and make the shared secret again */
+  if ((errnum = ecc_import (buf[1], y, &userb)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  z = 4096;
+  if ((errnum = ecc_shared_secret (&usera, &userb, buf[2], &z)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  printf ("ecc routines: ");
+  if (z != x) {
+    printf ("failed.  Size don't match?\n");
+    exit (-1);
+  }
+  if (memcmp (buf[0], buf[2], x)) {
+    printf ("Failed.  Content didn't match.\n");
+    exit (-1);
+  }
+  printf ("Passed\n");
+  ecc_free (&usera);
+  ecc_free (&userb);
+
+/* time stuff */
+  {
+    static int sizes[] = { 20, 24, 28, 32, 48, 65 };
+    int     ii, tt;
+
+    for (ii = 0; ii < (int) (sizeof (sizes) / sizeof (sizes[0])); ii++) {
+      t1 = XCLOCK ();
+      for (tt = 0; tt < 10; tt++) {
+    if ((errnum =
+         ecc_make_key (&prng, find_prng ("yarrow"), sizes[ii],
+               &usera)) != CRYPT_OK) {
+      printf ("Error: %s\n", error_to_string (errnum));
+      exit (-1);
+    }
+    ecc_free (&usera);
+      }
+      t1 = XCLOCK () - t1;
+      printf ("Make ECC-%d key took %f msec\n", sizes[ii] * 8,
+          1000.0 * (((double) t1 / 10.0) / (double) XCLOCKS_PER_SEC));
+    }
+  }
+
+/* test encrypt_key */
+  ecc_make_key (&prng, find_prng ("yarrow"), 20, &usera);
+  for (x = 0; x < 32; x++)
+    buf[0][x] = x;
+  y = sizeof (buf[1]);
+  if ((errnum =
+       ecc_encrypt_key (buf[0], 32, buf[1], &y, &prng, find_prng ("yarrow"),
+            find_hash ("sha256"), &usera)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  zeromem (buf[0], sizeof (buf[0]));
+  x = sizeof (buf[0]);
+  if ((errnum = ecc_decrypt_key (buf[1], y, buf[0], &x, &usera)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  printf ("ECC en/de crypt key routines: ");
+  if (x != 32) {
+    printf ("Failed (length)\n");
+    exit (-1);
+  }
+  for (x = 0; x < 32; x++)
+    if (buf[0][x] != x) {
+      printf ("Failed (contents)\n");
+      exit (-1);
+    }
+  printf ("Passed (size: %lu)\n", y);
+/* test sign_hash */
+  for (x = 0; x < 16; x++)
+    buf[0][x] = x;
+  x = sizeof (buf[1]);
+  if ((errnum =
+       ecc_sign_hash (buf[0], 16, buf[1], &x, &prng, find_prng ("yarrow"),
+              &usera)) != CRYPT_OK) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  printf("Signature size: %lu\n", x);
+  if (ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &usera)) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  buf[0][0] ^= 1;
+  if (ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera)) {
+    printf ("Error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  printf ("ecc_sign/verify_hash: %s (%d,%d)\n",
+      ((stat == 1) && (stat2 == 0)) ? "passed" : "failed", stat, stat2);
+  ecc_free (&usera);
+}
+#else
+void
+ecc_tests (void)
+{
+  printf ("MECC not compiled in\n");
+}
+#endif
+
+#ifdef GF
+void
+gf_tests (void)
+{
+  gf_int  a, b, c, d;
+  int     n;
+  unsigned char buf[1024];
+
+  printf ("GF tests\n");
+  gf_zero (a);
+  gf_zero (b);
+  gf_zero (c);
+  gf_zero (d);
+
+  /* a == 0x18000000b */
+  a[1] = 1;
+  a[0] = 0x8000000bUL;
+
+  /* b == 0x012345678 */
+  b[0] = 0x012345678UL;
+
+  /* find 1/b mod a */
+  gf_invmod (b, a, c);
+
+  /* find 1/1/b mod a */
+  gf_invmod (c, a, d);
+
+  /* display them */
+  printf ("  %08lx %08lx\n", c[0], d[0]);
+
+  /* store as binary string */
+  n = gf_size (a);
+  printf ("  a takes %d bytes\n", n);
+  gf_toraw (a, buf);
+  gf_readraw (a, buf, n);
+  printf ("  a == %08lx%08lx\n", a[1], a[0]);
+
+  /* primality testing */
+  gf_zero (a);
+  a[0] = 0x169;
+  printf ("  GF prime: %s, ", gf_is_prime (a) ? "passed" : "failed");
+  a[0] = 0x168;
+  printf ("  %s\n", gf_is_prime (a) ? "failed" : "passed");
+
+  /* test sqrt code */
+  gf_zero (a);
+  a[1] = 0x00000001;
+  a[0] = 0x8000000bUL;
+  gf_zero (b);
+  b[0] = 0x12345678UL;
+
+  gf_sqrt (b, a, c);
+  gf_mulmod (c, c, a, b);
+  printf ("  (%08lx)^2 = %08lx (mod %08lx%08lx) \n", c[0], b[0], a[1], a[0]);
+}
+#else
+void
+gf_tests (void)
+{
+  printf ("GF not compiled in\n");
+}
+#endif
+
+#ifdef MPI
+void
+test_prime (void)
+{
+  char buf[1024];
+  mp_int  a;
+  int     x;
+
+  /* make a 1024 bit prime */
+  mp_init (&a);
+  rand_prime (&a, 128*8, &prng, find_prng ("yarrow"));
+
+  /* dump it */
+  mp_todecimal (&a, buf);
+  printf ("1024-bit prime:\n");
+  for (x = 0; x < (int) strlen (buf);) {
+    printf ("%c", buf[x]);
+    if (!(++x % 60))
+      printf ("\\ \n");
+  }
+  printf ("\n\n");
+
+  mp_clear (&a);
+}
+#else
+void
+test_prime (void)
+{
+  printf ("MPI not compiled in\n");
+}
+#endif
+
+void
+register_all_algs (void)
+{
+#ifdef RIJNDAEL
+  register_cipher (&aes_desc);
+#endif
+#ifdef BLOWFISH
+  register_cipher (&blowfish_desc);
+#endif
+#ifdef XTEA
+  register_cipher (&xtea_desc);
+#endif
+#ifdef RC5
+  register_cipher (&rc5_desc);
+#endif
+#ifdef RC6
+  register_cipher (&rc6_desc);
+#endif
+#ifdef SAFERP
+  register_cipher (&saferp_desc);
+#endif
+#ifdef TWOFISH
+  register_cipher (&twofish_desc);
+#endif
+#ifdef SAFER
+  register_cipher (&safer_k64_desc);
+  register_cipher (&safer_sk64_desc);
+  register_cipher (&safer_k128_desc);
+  register_cipher (&safer_sk128_desc);
+#endif
+#ifdef RC2
+  register_cipher (&rc2_desc);
+#endif
+#ifdef DES
+  register_cipher (&des_desc);
+  register_cipher (&des3_desc);
+#endif
+#ifdef CAST5
+  register_cipher (&cast5_desc);
+#endif
+#ifdef NOEKEON
+  register_cipher (&noekeon_desc);
+#endif
+#ifdef SKIPJACK
+  register_cipher (&skipjack_desc);
+#endif
+  register_cipher (&null_desc);
+
+#ifdef TIGER
+  register_hash (&tiger_desc);
+#endif
+#ifdef MD2
+  register_hash (&md2_desc);
+#endif
+#ifdef MD4
+  register_hash (&md4_desc);
+#endif
+#ifdef MD5
+  register_hash (&md5_desc);
+#endif
+#ifdef SHA1
+  register_hash (&sha1_desc);
+#endif
+#ifdef SHA256
+  register_hash (&sha256_desc);
+#endif
+#ifdef SHA224
+  register_hash (&sha224_desc);
+#endif
+#ifdef SHA384
+  register_hash (&sha384_desc);
+#endif
+#ifdef SHA512
+  register_hash (&sha512_desc);
+#endif
+#ifdef RIPEMD128
+  register_hash (&rmd128_desc);
+#endif
+#ifdef RIPEMD160
+  register_hash (&rmd160_desc);
+#endif
+#ifdef WHIRLPOOL
+  register_hash (&whirlpool_desc);
+#endif
+
+#ifdef YARROW
+  register_prng (&yarrow_desc);
+#endif
+#ifdef SPRNG
+  register_prng (&sprng_desc);
+#endif
+}
+
+#ifdef KR
+void
+kr_display (pk_key * kr)
+{
+  static const char *sys[] = { "NON-KEY", "RSA", "DH", "ECC" };
+  static const char *type[] = { "PRIVATE", "PUBLIC", "PRIVATE_OPTIMIZED" };
+
+  while (kr->system != NON_KEY) {
+    printf ("CRC [%08lx], System [%10s], Type [%20s], %s, %s, %s\n", kr->ID,
+        sys[kr->system], type[kr->key_type], kr->name, kr->email,
+        kr->description);
+    kr = kr->next;
+  }
+  printf ("\n");
+}
+
+void
+kr_test_makekeys (pk_key ** kr)
+{
+  if ((errnum = kr_init (kr)) != CRYPT_OK) {
+    printf ("KR init error %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* make a DH key */
+  printf ("KR: Making DH key...\n");
+  if ((errnum =
+       kr_make_key (*kr, &prng, find_prng ("yarrow"), DH_KEY, 128, "dhkey",
+            "[email protected]", "dhkey one")) != CRYPT_OK) {
+    printf ("Make key error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* make a ECC key */
+  printf ("KR: Making ECC key...\n");
+  if ((errnum =
+       kr_make_key (*kr, &prng, find_prng ("yarrow"), ECC_KEY, 20, "ecckey",
+            "[email protected]", "ecckey one")) != CRYPT_OK) {
+    printf ("Make key error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* make a RSA key */
+  printf ("KR: Making RSA key...\n");
+  if ((errnum =
+       kr_make_key (*kr, &prng, find_prng ("yarrow"), RSA_KEY, 128, "rsakey",
+            "[email protected]", "rsakey one")) != CRYPT_OK) {
+    printf ("Make key error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+}
+
+void
+kr_test (void)
+{
+  pk_key *kr, *_kr;
+  unsigned char buf[8192], buf2[8192], buf3[8192];
+  unsigned long len;
+  int     i, j, stat;
+#ifndef NO_FILE
+  FILE   *f;
+#endif
+
+  kr_test_makekeys (&kr);
+
+  printf ("The original list:\n");
+  kr_display (kr);
+
+  for (i = 0; i < 3; i++) {
+    len = sizeof (buf);
+    if ((errnum = kr_export (kr, kr->ID, kr->key_type, buf, &len)) != CRYPT_OK) {
+      printf ("Error exporting key %d, %s\n", i, error_to_string (errnum));
+      exit (-1);
+    }
+    printf ("Exported key was: %lu bytes\n", len);
+    if ((errnum = kr_del (&kr, kr->ID)) != CRYPT_OK) {
+      printf ("Error deleting key %d, %s\n", i, error_to_string (errnum));
+      exit (-1);
+    }
+    kr_display (kr);
+    if ((errnum = kr_import (kr, buf, len)) != CRYPT_OK) {
+      printf ("Error importing key %d, %s\n", i, error_to_string (errnum));
+      exit (-1);
+    }
+    kr_display (kr);
+  }
+
+  for (i = 0; i < 3; i++) {
+    len = sizeof (buf);
+    if ((errnum = kr_export (kr, kr->ID, PK_PUBLIC, buf, &len)) != CRYPT_OK) {
+      printf ("Error exporting key %d, %s\n", i, error_to_string (errnum));
+      exit (-1);
+    }
+    printf ("Exported key was: %lu bytes\n", len);
+    if ((errnum = kr_del (&kr, kr->ID)) != CRYPT_OK) {
+      printf ("Error deleting key %d, %s\n", i, error_to_string (errnum));
+      exit (-1);
+    }
+    kr_display (kr);
+    if ((errnum = kr_import (kr, buf, len)) != CRYPT_OK) {
+      printf ("Error importing key %d, %s\n", i, error_to_string (errnum));
+      exit (-1);
+    }
+    kr_display (kr);
+  }
+
+  if ((errnum = kr_clear (&kr)) != CRYPT_OK) {
+    printf ("Error clearing ring: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+
+/* TEST output to file */
+#ifndef NO_FILE
+
+  if ((errnum = kr_init (&kr)) != CRYPT_OK) {
+    printf ("KR init error %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  kr_test_makekeys (&kr);
+
+  /* save to file */
+  f = fopen ("ring.dat", "wb");
+  if ((errnum = kr_save (kr, f, NULL)) != CRYPT_OK) {
+    printf ("kr_save error %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  fclose (f);
+
+  /* delete and load */
+  if ((errnum = kr_clear (&kr)) != CRYPT_OK) {
+    printf ("clear error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  f = fopen ("ring.dat", "rb");
+  if ((errnum = kr_load (&kr, f, NULL)) != CRYPT_OK) {
+    printf ("kr_load error %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  fclose (f);
+  remove ("ring.dat");
+  printf ("After load and save...\n");
+  kr_display (kr);
+
+  if ((errnum = kr_clear (&kr)) != CRYPT_OK) {
+    printf ("clear error: %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+#endif
+
+/* test the packet encryption/sign stuff */
+  for (i = 0; i < 32; i++)
+    buf[i] = i;
+  kr_test_makekeys (&kr);
+  _kr = kr;
+  for (i = 0; i < 3; i++) {
+    printf ("Testing a key with system %d, type %d:\t", _kr->system,
+        _kr->key_type);
+    len = sizeof (buf2);
+    if ((errnum =
+     kr_encrypt_key (kr, _kr->ID, buf, 16, buf2, &len, &prng,
+             find_prng ("yarrow"),
+             find_hash ("md5"))) != CRYPT_OK) {
+      printf ("Encrypt error, %d, %s\n", i, error_to_string (errnum));
+      exit (-1);
+    }
+    len = sizeof (buf3);
+    if ((errnum = kr_decrypt_key (kr, buf2, buf3, &len)) != CRYPT_OK) {
+      printf ("decrypt error, %d, %s\n", i, error_to_string (errnum));
+      exit (-1);
+    }
+    if (len != 16 || memcmp (buf3, buf, 16)) {
+      printf ("kr_decrypt_key failed, %i, %lu\n", i, len);
+      exit (-1);
+    }
+    printf ("kr_encrypt_key passed, ");
+
+    len = sizeof (buf2);
+    if ((errnum =
+     kr_sign_hash (kr, _kr->ID, buf, 32, buf2, &len, &prng,
+               find_prng ("yarrow"))) != CRYPT_OK) {
+      printf ("kr_sign_hash failed, %i, %s\n", i, error_to_string (errnum));
+      exit (-1);
+    }
+    printf ("kr_sign_hash: ");
+    if ((errnum = kr_verify_hash (kr, buf2, buf, 32, &stat)) != CRYPT_OK) {
+      printf ("kr_sign_hash failed, %i, %s\n", i, error_to_string (errnum));
+      exit (-1);
+    }
+    printf ("%s, ", stat ? "passed" : "failed");
+    buf[15] ^= 1;
+    if ((errnum = kr_verify_hash (kr, buf2, buf, 32, &stat)) != CRYPT_OK) {
+      printf ("kr_sign_hash failed, %i, %s\n", i, error_to_string (errnum));
+      exit (-1);
+    }
+    printf ("%s\n", (!stat) ? "passed" : "failed");
+    buf[15] ^= 1;
+
+    len = sizeof (buf);
+    if ((errnum =
+     kr_fingerprint (kr, _kr->ID, find_hash ("sha1"), buf,
+             &len)) != CRYPT_OK) {
+      printf ("kr_fingerprint failed, %i, %lu\n", i, len);
+      exit (-1);
+    }
+    printf ("Fingerprint:  ");
+    for (j = 0; j < 20; j++) {
+      printf ("%02x", buf[j]);
+      if (j < 19)
+    printf (":");
+    }
+    printf ("\n\n");
+
+    _kr = _kr->next;
+  }
+
+/* Test encrypting/decrypting to a public key */
+/* first dump the other two keys */
+  kr_del (&kr, kr->ID);
+  kr_del (&kr, kr->ID);
+  kr_display (kr);
+
+  /* now export it as public and private */
+  len = sizeof (buf);
+  if ((errnum = kr_export (kr, kr->ID, PK_PUBLIC, buf, &len)) != CRYPT_OK) {
+    printf ("Error exporting key %d, %s\n", i, error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* check boundaries */
+  memset (buf + len, 0, sizeof (buf) - len);
+
+  len = sizeof (buf2);
+  if ((errnum = kr_export (kr, kr->ID, PK_PRIVATE, buf2, &len)) != CRYPT_OK) {
+    printf ("Error exporting key  %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* check boundaries */
+  memset (buf2 + len, 0, sizeof (buf2) - len);
+
+  /* delete the key and import the public */
+  kr_clear (&kr);
+  kr_init (&kr);
+  kr_display (kr);
+  if ((errnum = kr_import (kr, buf, len)) != CRYPT_OK) {
+    printf ("Error importing key %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  kr_display (kr);
+
+  /* now encrypt a buffer */
+  for (i = 0; i < 16; i++)
+    buf[i] = i;
+  len = sizeof (buf3);
+  if ((errnum =
+       kr_encrypt_key (kr, kr->ID, buf, 16, buf3, &len, &prng,
+               find_prng ("yarrow"),
+               find_hash ("md5"))) != CRYPT_OK) {
+    printf ("Encrypt error, %d, %s\n", i, error_to_string (errnum));
+    exit (-1);
+  }
+
+  /* now delete the key and import the private one */
+  kr_clear (&kr);
+  kr_init (&kr);
+  kr_display (kr);
+  if ((errnum = kr_import (kr, buf2, len)) != CRYPT_OK) {
+    printf ("Error importing key %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+  kr_display (kr);
+
+  /* now decrypt */
+  len = sizeof (buf2);
+  if ((errnum = kr_decrypt_key (kr, buf3, buf2, &len)) != CRYPT_OK) {
+    printf ("decrypt error, %s\n", error_to_string (errnum));
+    exit (-1);
+  }
+
+  printf ("KR encrypt to public, decrypt with private: ");
+  if (len == 16 && !memcmp (buf2, buf, 16)) {
+    printf ("passed\n");
+  } else {
+    printf ("failed\n");
+  }
+
+  kr_clear (&kr);
+}
+#endif
+
+void
+test_errs (void)
+{
+#define ERR(x)  printf("%25s => %s\n", #x, error_to_string(x));
+
+  ERR (CRYPT_OK);
+  ERR (CRYPT_ERROR);
+
+  ERR (CRYPT_INVALID_KEYSIZE);
+  ERR (CRYPT_INVALID_ROUNDS);
+  ERR (CRYPT_FAIL_TESTVECTOR);
+
+  ERR (CRYPT_BUFFER_OVERFLOW);
+  ERR (CRYPT_INVALID_PACKET);
+
+  ERR (CRYPT_INVALID_PRNGSIZE);
+  ERR (CRYPT_ERROR_READPRNG);
+
+  ERR (CRYPT_INVALID_CIPHER);
+  ERR (CRYPT_INVALID_HASH);
+  ERR (CRYPT_INVALID_PRNG);
+
+  ERR (CRYPT_MEM);
+
+  ERR (CRYPT_PK_TYPE_MISMATCH);
+  ERR (CRYPT_PK_NOT_PRIVATE);
+
+  ERR (CRYPT_INVALID_ARG);
+  ERR (CRYPT_FILE_NOTFOUND);
+
+  ERR (CRYPT_PK_INVALID_TYPE);
+  ERR (CRYPT_PK_INVALID_SYSTEM);
+  ERR (CRYPT_PK_DUP);
+  ERR (CRYPT_PK_NOT_FOUND);
+  ERR (CRYPT_PK_INVALID_SIZE);
+
+  ERR (CRYPT_INVALID_PRIME_SIZE);
+}
+
+
+void dsa_tests(void)
+{
+   unsigned char msg[16], out[1024], out2[1024];
+   unsigned long x, y;
+   int err, stat1, stat2;
+   dsa_key key, key2;
+
+   /* make a random key */
+   if ((err = dsa_make_key(&prng, find_prng("yarrow"), 20, 128, &key)) != CRYPT_OK) {
+      printf("Error making DSA key: %s\n", error_to_string(err));
+      exit(-1);
+   }
+   printf("DSA Key Made\n");
+
+   /* verify it */
+   if ((err = dsa_verify_key(&key, &stat1)) != CRYPT_OK) {
+      printf("Error verifying DSA key: %s\n", error_to_string(err));
+      exit(-1);
+   }
+   printf("DSA key verification: %s\n", stat1 == 1 ? "passed" : "failed");
+   if (stat1 == 0) exit(-1);     
+
+   /* sign the message */
+   x = sizeof(out);
+   if ((err = dsa_sign_hash(msg, sizeof(msg), out, &x, &prng, find_prng("yarrow"), &key)) != CRYPT_OK) {
+      printf("Error signing with DSA key: %s\n", error_to_string(err));
+      exit(-1);
+   }
+   printf("DSA 160/1024 signature is %lu bytes long\n", x);
+
+   /* verify it once */
+   if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key)) != CRYPT_OK) {
+      printf("Error verifying with DSA key 1: %s\n", error_to_string(err));
+      exit(-1);
+   }
+
+   /* Modify and verify again */
+   msg[0] ^= 1;
+   if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat2, &key)) != CRYPT_OK) {
+      printf("Error verifying with DSA key 2: %s\n", error_to_string(err));
+      exit(-1);
+   }
+   msg[0] ^= 1;
+   printf("DSA Verification: %d, %d, %s\n", stat1, stat2, (stat1 == 1 && stat2 == 0) ? "passed" : "failed");
+   if (!(stat1 == 1 && stat2 == 0)) exit(-1);
+
+   /* test exporting it */
+   x = sizeof(out2);
+   if ((err = dsa_export(out2, &x, PK_PRIVATE, &key)) != CRYPT_OK) {
+      printf("Error export PK_PRIVATE DSA key: %s\n", error_to_string(err));
+      exit(-1);
+   }
+   printf("Exported PK_PRIVATE DSA key in %lu bytes\n", x);
+   if ((err = dsa_import(out2, x, &key2)) != CRYPT_OK) {
+      printf("Error importing PK_PRIVATE DSA key: %s\n", error_to_string(err));
+      exit(-1);
+   }
+   /* verify a signature with it */
+   if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)) != CRYPT_OK) {
+      printf("Error verifying with DSA key 3: %s\n", error_to_string(err));
+      exit(-1);
+   }
+   printf("PRIVATE Import Test: %s\n", stat1 == 1 ? "passed" : "failed");
+   if (stat1 == 0) exit(-1);
+   dsa_free(&key2);
+
+   /* export as public now */
+   x = sizeof(out2);
+   if ((err = dsa_export(out2, &x, PK_PUBLIC, &key)) != CRYPT_OK) {
+      printf("Error export PK_PUBLIC DSA key: %s\n", error_to_string(err));
+      exit(-1);
+   }
+   printf("Exported PK_PUBLIC DSA key in %lu bytes\n", x);
+   if ((err = dsa_import(out2, x, &key2)) != CRYPT_OK) {
+      printf("Error importing PK_PUBLIC DSA key: %s\n", error_to_string(err));
+      exit(-1);
+   }
+   /* verify a signature with it */
+   if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)) != CRYPT_OK) {
+      printf("Error verifying with DSA key 4: %s\n", error_to_string(err));
+      exit(-1);
+   }
+   printf("PUBLIC Import Test: %s\n", stat1 == 1 ? "passed" : "failed");
+   if (stat1 == 0) exit(-1);
+
+   dsa_free(&key2);
+   dsa_free(&key);
+}
+
+#ifdef PKCS_1
+void pkcs1_test(void)
+{
+   unsigned char buf[3][128];
+   int err, res1, res2, res3, prng_idx, hash_idx;
+   unsigned long x, y, l1, l2, l3, i1, i2;
+
+   /* get hash/prng  */
+   hash_idx = find_hash("sha1");
+   prng_idx = find_prng("yarrow");
+
+   /* do many tests */
+   for (x = 0; x < 10000; x++) {
+      zeromem(buf, sizeof(buf));
+
+      /* make a dummy message (of random length) */
+      l3 = (rand() & 31) + 8;
+      for (y = 0; y < l3; y++) buf[0][y] = rand() & 255;
+
+      /* encode it */
+      l1 = sizeof(buf[1]);
+      if ((err = pkcs_1_oaep_encode(buf[0], l3, NULL, 0, 1024, hash_idx, prng_idx, &prng, buf[1], &l1)) != CRYPT_OK) {
+         printf("OAEP encode: %s\n", error_to_string(err));
+         exit(-1);
+      }
+
+      /* decode it */
+      l2 = sizeof(buf[2]);
+      if ((err = pkcs_1_oaep_decode(buf[1], l1, NULL, 0, 1024, hash_idx, buf[2], &l2)) != CRYPT_OK) {
+         printf("OAEP decode: %s\n", error_to_string(err));
+         exit(-1);
+      }
+
+      if (l2 != l3 || memcmp(buf[2], buf[0], l3) != 0) {
+         printf("Outsize == %lu, should have been %lu, msg contents follow.\n", l2, l3);
+         printf("ORIGINAL:\n");
+         for (x = 0; x < l3; x++) {
+             printf("%02x ", buf[0][x]);
+         }
+         printf("\nRESULT:\n");
+         for (x = 0; x < l2; x++) {
+             printf("%02x ", buf[2][x]);
+         }
+         printf("\n\n");
+         exit(-1);
+      }
+
+      /* test PSS */
+      l1 = sizeof(buf[1]);
+      if ((err = pkcs_1_pss_encode(buf[0], l3, l3>>2, hash_idx, prng_idx, &prng, 1024, buf[1], &l1)) != CRYPT_OK) {
+         printf("PSS encode: %s\n", error_to_string(err));
+         exit(-1); 
+      }
+      
+      if ((err = pkcs_1_pss_decode(buf[0], l3, buf[1], l1, l3>>2, hash_idx, 1024, &res1)) != CRYPT_OK) {
+         printf("PSS decode1: %s\n", error_to_string(err));
+         exit(-1); 
+      }
+      
+      buf[0][i1 = abs(rand()) % l3] ^= 1;
+      if ((err = pkcs_1_pss_decode(buf[0], l3, buf[1], l1, l3>>2, hash_idx, 1024, &res2)) != CRYPT_OK) {
+         printf("PSS decode2: %s\n", error_to_string(err));
+         exit(-1); 
+      }
+
+      buf[0][i1] ^= 1;
+      buf[1][i2 = abs(rand()) % l1] ^= 1;
+      if ((err = pkcs_1_pss_decode(buf[0], l3, buf[1], l1, l3>>2, hash_idx, 1024, &res3)) != CRYPT_OK) {
+         printf("PSS decode3: %s\n", error_to_string(err));
+         exit(-1); 
+      }
+
+      if (!(res1 == 1 && res2 == 0 && res3 == 0)) {
+         printf("PSS failed: %d, %d, %d, %lu\n", res1, res2, res3, l3);
+         exit(-1);
+      }
+   }
+   printf("PKCS #1: Passed\n");
+}
+
+#endif /* PKCS_1 */
+
+int
+main (void)
+{
+#ifdef SONY_PS2
+  TIMER_Init ();
+#endif
+  srand(time(NULL));
+
+  register_all_algs ();
+   
+  if ((errnum = yarrow_start (&prng)) != CRYPT_OK) {
+    printf ("yarrow_start: %s\n", error_to_string (errnum));
+  }
+  if ((errnum = yarrow_add_entropy ((unsigned char *)"hello", 5, &prng)) != CRYPT_OK) {
+    printf ("yarrow_add_entropy: %s\n", error_to_string (errnum));
+  }
+  if ((errnum = yarrow_ready (&prng)) != CRYPT_OK) {
+    printf ("yarrow_ready: %s\n", error_to_string (errnum));
+  }
+
+  printf (crypt_build_settings);
+  test_errs ();
+
+#ifdef HMAC
+  printf ("HMAC: %s\n", hmac_test () == CRYPT_OK ? "passed" : "failed");
+  if (hmac_test() != CRYPT_OK) exit(EXIT_FAILURE);
+#endif
+
+#ifdef OMAC
+  printf ("OMAC: %s\n", omac_test () == CRYPT_OK ? "passed" : "failed");
+  if (omac_test() != CRYPT_OK) exit(EXIT_FAILURE);
+#endif
+
+#ifdef PMAC
+  printf ("PMAC: %s\n", pmac_test () == CRYPT_OK ? "passed" : "failed");
+  if (pmac_test() != CRYPT_OK) exit(EXIT_FAILURE);
+#endif
+
+#ifdef EAX_MODE
+  printf ("EAX : %s\n", eax_test () == CRYPT_OK ? "passed" : "failed");
+  if (eax_test() != CRYPT_OK) exit(EXIT_FAILURE);
+#endif
+
+#ifdef OCB_MODE
+  printf ("OCB : %s\n", ocb_test () == CRYPT_OK ? "passed" : "failed");
+  if (ocb_test() != CRYPT_OK) exit(EXIT_FAILURE);
+#endif
+
+  store_tests ();
+  cipher_tests ();
+  hash_tests ();
+
+#ifdef PKCS_1
+  pkcs1_test();
+#endif
+
+  ecb_tests ();
+  cbc_tests ();
+  ctr_tests ();
+  ofb_tests ();
+  cfb_tests ();
+
+  rng_tests ();
+  test_prime();
+
+#ifdef KR
+  kr_test ();
+#endif
+  dsa_tests();
+  rsa_test ();
+  pad_test ();
+  ecc_tests ();
+  dh_tests ();
+
+  gf_tests ();
+  base64_test ();
+
+  time_ecb ();
+  time_hash ();
+
+#ifdef SONY_PS2
+  TIMER_Shutdown ();
+#endif
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/tv_gen.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,492 @@
+#include <mycrypt.h>
+
+void reg_algs(void)
+{
+#ifdef RIJNDAEL
+  register_cipher (&aes_desc);
+#endif
+#ifdef BLOWFISH
+  register_cipher (&blowfish_desc);
+#endif
+#ifdef XTEA
+  register_cipher (&xtea_desc);
+#endif
+#ifdef RC5
+  register_cipher (&rc5_desc);
+#endif
+#ifdef RC6
+  register_cipher (&rc6_desc);
+#endif
+#ifdef SAFERP
+  register_cipher (&saferp_desc);
+#endif
+#ifdef TWOFISH
+  register_cipher (&twofish_desc);
+#endif
+#ifdef SAFER
+  register_cipher (&safer_k64_desc);
+  register_cipher (&safer_sk64_desc);
+  register_cipher (&safer_k128_desc);
+  register_cipher (&safer_sk128_desc);
+#endif
+#ifdef RC2
+  register_cipher (&rc2_desc);
+#endif
+#ifdef DES
+  register_cipher (&des_desc);
+  register_cipher (&des3_desc);
+#endif
+#ifdef CAST5
+  register_cipher (&cast5_desc);
+#endif
+#ifdef NOEKEON
+  register_cipher (&noekeon_desc);
+#endif
+#ifdef SKIPJACK
+  register_cipher (&skipjack_desc);
+#endif
+
+#ifdef TIGER
+  register_hash (&tiger_desc);
+#endif
+#ifdef MD2
+  register_hash (&md2_desc);
+#endif
+#ifdef MD4
+  register_hash (&md4_desc);
+#endif
+#ifdef MD5
+  register_hash (&md5_desc);
+#endif
+#ifdef SHA1
+  register_hash (&sha1_desc);
+#endif
+#ifdef SHA224
+  register_hash (&sha224_desc);
+#endif
+#ifdef SHA256
+  register_hash (&sha256_desc);
+#endif
+#ifdef SHA384
+  register_hash (&sha384_desc);
+#endif
+#ifdef SHA512
+  register_hash (&sha512_desc);
+#endif
+#ifdef RIPEMD128
+  register_hash (&rmd128_desc);
+#endif
+#ifdef RIPEMD160
+  register_hash (&rmd160_desc);
+#endif
+#ifdef WHIRLPOOL
+  register_hash (&whirlpool_desc);
+#endif
+}
+
+void hash_gen(void)
+{
+   unsigned char md[MAXBLOCKSIZE], buf[MAXBLOCKSIZE*2+2];
+   unsigned long outlen, x, y, z;
+   FILE *out;
+   
+   out = fopen("hash_tv.txt", "w");
+   
+   fprintf(out, "Hash Test Vectors:\n\nThese are the hashes of nn bytes '00 01 02 03 .. (nn-1)'\n\n");
+   for (x = 0; hash_descriptor[x].name != NULL; x++) {
+      fprintf(out, "Hash: %s\n", hash_descriptor[x].name);
+      
+      for (y = 0; y <= (hash_descriptor[x].blocksize * 2); y++) {
+         for (z = 0; z < y; z++) {
+            buf[z] = (unsigned char)(z & 255);
+         }
+         outlen = sizeof(md);
+         hash_memory(x, buf, y, md, &outlen);
+         fprintf(out, "%3lu: ", y);
+         for (z = 0; z < outlen; z++) {
+            fprintf(out, "%02X", md[z]);
+         }
+         fprintf(out, "\n");
+      }
+      fprintf(out, "\n");
+   }
+   fclose(out);
+}
+
+void cipher_gen(void)
+{
+   unsigned char key[MAXBLOCKSIZE], pt[MAXBLOCKSIZE];
+   unsigned long x, y, z, w;
+   int kl, lastkl;
+   FILE *out;
+   symmetric_key skey;
+   
+   out = fopen("cipher_tv.txt", "w");
+   
+   fprintf(out, 
+"Cipher Test Vectors\n\nThese are test encryptions with key of nn bytes '00 01 02 03 .. (nn-1)' and original PT of the same style.\n"
+"The output of step N is used as the key and plaintext for step N+1 (key bytes repeated as required to fill the key)\n\n");
+                   
+   for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+      fprintf(out, "Cipher: %s\n", cipher_descriptor[x].name);
+      
+      /* three modes, smallest, medium, large keys */
+      lastkl = 10000;
+      for (y = 0; y < 3; y++) {
+         switch (y) {
+            case 0: kl = cipher_descriptor[x].min_key_length; break;
+            case 1: kl = (cipher_descriptor[x].min_key_length + cipher_descriptor[x].max_key_length)/2; break;
+            case 2: kl = cipher_descriptor[x].max_key_length; break;
+         }
+         cipher_descriptor[x].keysize(&kl);
+         if (kl == lastkl) break;
+         lastkl = kl;
+         fprintf(out, "Key Size: %d bytes\n", kl);
+
+         for (z = 0; (int)z < kl; z++) {
+             key[z] = (unsigned char)z;
+         }
+         cipher_descriptor[x].setup(key, kl, 0, &skey);
+         
+         for (z = 0; (int)z < cipher_descriptor[x].block_length; z++) {
+            pt[z] = (unsigned char)z;
+         }
+         for (w = 0; w < 50; w++) {
+             cipher_descriptor[x].ecb_encrypt(pt, pt, &skey);
+             fprintf(out, "%2lu: ", w);
+             for (z = 0; (int)z < cipher_descriptor[x].block_length; z++) {
+                fprintf(out, "%02X", pt[z]);
+             }
+             fprintf(out, "\n");
+
+             /* reschedule a new key */
+             for (z = 0; z < (unsigned long)kl; z++) {
+                 key[z] = pt[z % cipher_descriptor[x].block_length];
+             }
+             cipher_descriptor[x].setup(key, kl, 0, &skey);
+         }
+         fprintf(out, "\n");
+     }
+     fprintf(out, "\n");
+  }
+  fclose(out);
+}  
+
+void hmac_gen(void)
+{
+   unsigned char key[MAXBLOCKSIZE], output[MAXBLOCKSIZE], input[MAXBLOCKSIZE*2+2];
+   int x, y, z, kl, err;
+   FILE *out;
+   unsigned long len;
+  
+   out = fopen("hmac_tv.txt", "w");
+
+   fprintf(out, 
+"HMAC Tests.  In these tests messages of N bytes long (00,01,02,...,NN-1) are HMACed.  The initial key is\n"
+"of the same format (the same length as the HASH output size).  The HMAC key in step N+1 is the HMAC output of\n"
+"step N.\n\n");
+
+   for (x = 0; hash_descriptor[x].name != NULL; x++) {
+      fprintf(out, "HMAC-%s\n", hash_descriptor[x].name);
+      
+      /* initial key */
+      for (y = 0; y < (int)hash_descriptor[x].hashsize; y++) {
+          key[y] = (y&255);
+      }
+      
+      for (y = 0; y <= (int)(hash_descriptor[x].blocksize * 2); y++) {
+         for (z = 0; z < y; z++) {
+            input[z] = (unsigned char)(z & 255);
+         }
+         len = sizeof(output);
+         if ((err = hmac_memory(x, key, hash_descriptor[x].hashsize, input, y, output, &len)) != CRYPT_OK) {
+            printf("Error hmacing: %s\n", error_to_string(err));
+            exit(EXIT_FAILURE);
+         }
+         fprintf(out, "%3d: ", y);
+         for (z = 0; z <(int) len; z++) {
+            fprintf(out, "%02X", output[z]);
+         }
+         fprintf(out, "\n");
+
+         /* forward the key */
+         memcpy(key, output, hash_descriptor[x].hashsize);
+      }
+      fprintf(out, "\n");
+   }
+   fclose(out);
+}
+   
+void omac_gen(void)
+{
+   unsigned char key[MAXBLOCKSIZE], output[MAXBLOCKSIZE], input[MAXBLOCKSIZE*2+2];
+   int err, x, y, z, kl;
+   FILE *out;
+   unsigned long len;
+  
+   out = fopen("omac_tv.txt", "w");
+
+   fprintf(out, 
+"OMAC Tests.  In these tests messages of N bytes long (00,01,02,...,NN-1) are OMAC'ed.  The initial key is\n"
+"of the same format (length specified per cipher).  The OMAC key in step N+1 is the OMAC output of\n"
+"step N (repeated as required to fill the array).\n\n");
+
+   for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+      kl = cipher_descriptor[x].block_length;
+
+      /* skip ciphers which do not have 64 or 128 bit block sizes */
+      if (kl != 8 && kl != 16) continue;
+
+      if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) {
+         kl = cipher_descriptor[x].max_key_length;
+      }
+      fprintf(out, "OMAC-%s (%d byte key)\n", cipher_descriptor[x].name, kl);
+      
+      /* initial key/block */
+      for (y = 0; y < kl; y++) {
+          key[y] = (y & 255);
+      }
+      
+      for (y = 0; y <= (int)(cipher_descriptor[x].block_length*2); y++) {
+         for (z = 0; z < y; z++) {
+            input[z] = (unsigned char)(z & 255);
+         }
+         len = sizeof(output);
+         if ((err = omac_memory(x, key, kl, input, y, output, &len)) != CRYPT_OK) {
+            printf("Error omacing: %s\n", error_to_string(err));
+            exit(EXIT_FAILURE);
+         }
+         fprintf(out, "%3d: ", y);
+         for (z = 0; z <(int)len; z++) {
+            fprintf(out, "%02X", output[z]);
+         }
+         fprintf(out, "\n");
+
+         /* forward the key */
+         for (z = 0; z < kl; z++) {
+             key[z] = output[z % len];
+         }
+      }
+      fprintf(out, "\n");
+   }
+   fclose(out);
+}
+
+void pmac_gen(void)
+{
+   unsigned char key[MAXBLOCKSIZE], output[MAXBLOCKSIZE], input[MAXBLOCKSIZE*2+2];
+   int err, x, y, z, kl;
+   FILE *out;
+   unsigned long len;
+  
+   out = fopen("pmac_tv.txt", "w");
+
+   fprintf(out, 
+"PMAC Tests.  In these tests messages of N bytes long (00,01,02,...,NN-1) are OMAC'ed.  The initial key is\n"
+"of the same format (length specified per cipher).  The OMAC key in step N+1 is the OMAC output of\n"
+"step N (repeated as required to fill the array).\n\n");
+
+   for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+      kl = cipher_descriptor[x].block_length;
+
+      /* skip ciphers which do not have 64 or 128 bit block sizes */
+      if (kl != 8 && kl != 16) continue;
+
+      if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) {
+         kl = cipher_descriptor[x].max_key_length;
+      }
+      fprintf(out, "PMAC-%s (%d byte key)\n", cipher_descriptor[x].name, kl);
+      
+      /* initial key/block */
+      for (y = 0; y < kl; y++) {
+          key[y] = (y & 255);
+      }
+      
+      for (y = 0; y <= (int)(cipher_descriptor[x].block_length*2); y++) {
+         for (z = 0; z < y; z++) {
+            input[z] = (unsigned char)(z & 255);
+         }
+         len = sizeof(output);
+         if ((err = pmac_memory(x, key, kl, input, y, output, &len)) != CRYPT_OK) {
+            printf("Error omacing: %s\n", error_to_string(err));
+            exit(EXIT_FAILURE);
+         }
+         fprintf(out, "%3d: ", y);
+         for (z = 0; z <(int)len; z++) {
+            fprintf(out, "%02X", output[z]);
+         }
+         fprintf(out, "\n");
+
+         /* forward the key */
+         for (z = 0; z < kl; z++) {
+             key[z] = output[z % len];
+         }
+      }
+      fprintf(out, "\n");
+   }
+   fclose(out);
+}
+
+void eax_gen(void)
+{
+   int err, kl, x, y1, z;
+   FILE *out;
+   unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], header[MAXBLOCKSIZE*2], 
+                 plaintext[MAXBLOCKSIZE*2], tag[MAXBLOCKSIZE];
+   unsigned long len;
+
+   out = fopen("eax_tv.txt", "w");
+   fprintf(out, "EAX Test Vectors.  Uses the 00010203...NN-1 pattern for header/nonce/plaintext/key.  The outputs\n"
+                "are of the form ciphertext,tag for a given NN.  The key for step N>1 is the tag of the previous\n"
+                "step repeated sufficiently.\n\n");
+
+   for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+      kl = cipher_descriptor[x].block_length;
+
+      /* skip ciphers which do not have 64 or 128 bit block sizes */
+      if (kl != 8 && kl != 16) continue;
+
+      if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) {
+         kl = cipher_descriptor[x].max_key_length;
+      }
+      fprintf(out, "EAX-%s (%d byte key)\n", cipher_descriptor[x].name, kl);
+
+      /* the key */
+      for (z = 0; z < kl; z++) {
+          key[z] = (z & 255);
+      }
+      
+      for (y1 = 0; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){
+         for (z = 0; z < y1; z++) {
+            plaintext[z] = (unsigned char)(z & 255);
+            nonce[z]     = (unsigned char)(z & 255);
+            header[z]    = (unsigned char)(z & 255);
+         }
+         len = sizeof(tag);
+         if ((err = eax_encrypt_authenticate_memory(x, key, kl, nonce, y1, header, y1, plaintext, y1, plaintext, tag, &len)) != CRYPT_OK) {
+            printf("Error EAX'ing: %s\n", error_to_string(err));
+            exit(EXIT_FAILURE);
+         }
+         fprintf(out, "%3d: ", y1);
+         for (z = 0; z < y1; z++) {
+            fprintf(out, "%02X", plaintext[z]);
+         }
+         fprintf(out, ", ");
+         for (z = 0; z <(int)len; z++) {
+            fprintf(out, "%02X", tag[z]);
+         }
+         fprintf(out, "\n");
+
+         /* forward the key */
+         for (z = 0; z < kl; z++) {
+             key[z] = tag[z % len];
+         }
+      }
+      fprintf(out, "\n");
+   }
+   fclose(out);
+}
+
+void ocb_gen(void)
+{
+   int err, kl, x, y1, z;
+   FILE *out;
+   unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], 
+                 plaintext[MAXBLOCKSIZE*2], tag[MAXBLOCKSIZE];
+   unsigned long len;
+
+   out = fopen("ocb_tv.txt", "w");
+   fprintf(out, "OCB Test Vectors.  Uses the 00010203...NN-1 pattern for nonce/plaintext/key.  The outputs\n"
+                "are of the form ciphertext,tag for a given NN.  The key for step N>1 is the tag of the previous\n"
+                "step repeated sufficiently.  The nonce is fixed throughout.\n\n");
+
+   for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+      kl = cipher_descriptor[x].block_length;
+
+      /* skip ciphers which do not have 64 or 128 bit block sizes */
+      if (kl != 8 && kl != 16) continue;
+
+      if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) {
+         kl = cipher_descriptor[x].max_key_length;
+      }
+      fprintf(out, "OCB-%s (%d byte key)\n", cipher_descriptor[x].name, kl);
+
+      /* the key */
+      for (z = 0; z < kl; z++) {
+          key[z] = (z & 255);
+      }
+
+      /* fixed nonce */
+      for (z = 0; z < cipher_descriptor[x].block_length; z++) {
+          nonce[z] = z;
+      }
+      
+      for (y1 = 0; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){
+         for (z = 0; z < y1; z++) {
+            plaintext[z] = (unsigned char)(z & 255);
+         }
+         len = sizeof(tag);
+         if ((err = ocb_encrypt_authenticate_memory(x, key, kl, nonce, plaintext, y1, plaintext, tag, &len)) != CRYPT_OK) {
+            printf("Error OCB'ing: %s\n", error_to_string(err));
+            exit(EXIT_FAILURE);
+         }
+         fprintf(out, "%3d: ", y1);
+         for (z = 0; z < y1; z++) {
+            fprintf(out, "%02X", plaintext[z]);
+         }
+         fprintf(out, ", ");
+         for (z = 0; z <(int)len; z++) {
+            fprintf(out, "%02X", tag[z]);
+         }
+         fprintf(out, "\n");
+
+         /* forward the key */
+         for (z = 0; z < kl; z++) {
+             key[z] = tag[z % len];
+         }
+      }
+      fprintf(out, "\n");
+   }
+   fclose(out);
+}
+
+void base64_gen(void)
+{
+   FILE *out;
+   unsigned char dst[256], src[32];
+   unsigned long x, y, len;
+   
+   out = fopen("base64_tv.txt", "w");
+   fprintf(out, "Base64 vectors.  These are the base64 encodings of the strings 00,01,02...NN-1\n\n");
+   for (x = 0; x <= 32; x++) {
+       for (y = 0; y < x; y++) {
+           src[y] = y;
+       }
+       len = sizeof(dst);
+       base64_encode(src, x, dst, &len);
+       fprintf(out, "%2lu: %s\n", x, dst);
+   }
+   fclose(out);
+}
+
+int main(void)
+{
+   reg_algs();
+   printf("Generating hash   vectors..."); fflush(stdout); hash_gen(); printf("done\n");
+   printf("Generating cipher vectors..."); fflush(stdout); cipher_gen(); printf("done\n");
+   printf("Generating HMAC   vectors..."); fflush(stdout); hmac_gen(); printf("done\n");
+   printf("Generating OMAC   vectors..."); fflush(stdout); omac_gen(); printf("done\n");
+   printf("Generating PMAC   vectors..."); fflush(stdout); pmac_gen(); printf("done\n");
+   printf("Generating EAX    vectors..."); fflush(stdout); eax_gen(); printf("done\n");
+   printf("Generating OCB    vectors..."); fflush(stdout); ocb_gen(); printf("done\n");
+   printf("Generating BASE64 vectors..."); fflush(stdout); base64_gen(); printf("done\n");
+   return 0;
+}
+
+
+         
+      
+      
+      
+    
+   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/x86_prof.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,358 @@
+#include <mycrypt.h>
+
+#define KTIMES  25
+#define TIMES   100000
+
+struct list {
+    int id;
+    unsigned long spd1, spd2, avg;
+} results[100];
+
+int no_results;
+
+int sorter(const void *a, const void *b)
+{
+   const struct list *A, *B;
+   A = a;
+   B = b;
+   if (A->avg < B->avg) return -1;
+   if (A->avg > B->avg) return 1;
+   return 0;
+}
+
+void tally_results(int type)
+{
+   int x;
+
+   // qsort the results
+   qsort(results, no_results, sizeof(struct list), &sorter);
+
+   printf("\n");
+   if (type == 0) {
+      for (x = 0; x < no_results; x++) {
+         printf("%-20s: Schedule at %6lu\n", cipher_descriptor[results[x].id].name, (unsigned long)results[x].spd1);
+      } 
+   } else if (type == 1) {
+      for (x = 0; x < no_results; x++) {
+        printf
+          ("%-20s: Encrypt at %5lu, Decrypt at %5lu\n", cipher_descriptor[results[x].id].name, results[x].spd1, results[x].spd2);
+      }
+   } else {
+      for (x = 0; x < no_results; x++) {
+        printf
+          ("%-20s: Process at %5lu\n", hash_descriptor[results[x].id].name, results[x].spd1 / 1000);
+      }
+   }
+}
+
+
+
+
+/* RDTSC from Scott Duplichan */
+static ulong64 rdtsc (void)
+   {
+   #if defined __GNUC__
+      #ifdef __i386__
+         ulong64 a;
+         __asm__ __volatile__ ("rdtsc ":"=A" (a));
+         return a;
+      #else /* gcc-IA64 version */
+         unsigned long result;
+         __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
+         while (__builtin_expect ((int) result == -1, 0))
+         __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
+         return result;
+      #endif
+
+   // Microsoft and Intel Windows compilers
+   #elif defined _M_IX86
+     __asm rdtsc
+   #elif defined _M_AMD64
+     return __rdtsc ();
+   #elif defined _M_IA64
+     #if defined __INTEL_COMPILER
+       #include <ia64intrin.h>
+     #endif
+      return __getReg (3116);
+   #else
+     #error need rdtsc function for this build
+   #endif
+   }
+
+ulong64 timer, skew = 0;
+prng_state prng;
+
+void t_start(void)
+{
+   timer = rdtsc();
+}
+
+ulong64 t_read(void)
+{
+   return rdtsc() - timer;
+}
+
+void init_timer(void)
+{
+   ulong64 c1, c2, t1, t2, t3;
+   unsigned long y1;
+
+   c1 = c2 = (ulong64)-1;
+   for (y1 = 0; y1 < TIMES*100; y1++) {
+      t_start();
+      t1 = t_read();
+      t3 = t_read();
+      t2 = t_read() - t1;
+
+      c1 = (c1 > t1) ? t1 : c1;
+      c2 = (c2 > t2) ? t2 : c2;
+   }
+   skew = c2 - c1;
+   printf("Clock Skew: %lu\n", (unsigned long)skew);
+}
+
+void reg_algs(void)
+{
+#ifdef RIJNDAEL
+  register_cipher (&aes_desc);
+#endif
+#ifdef BLOWFISH
+  register_cipher (&blowfish_desc);
+#endif
+#ifdef XTEA
+  register_cipher (&xtea_desc);
+#endif
+#ifdef RC5
+  register_cipher (&rc5_desc);
+#endif
+#ifdef RC6
+  register_cipher (&rc6_desc);
+#endif
+#ifdef SAFERP
+  register_cipher (&saferp_desc);
+#endif
+#ifdef TWOFISH
+  register_cipher (&twofish_desc);
+#endif
+#ifdef SAFER
+  register_cipher (&safer_k64_desc);
+  register_cipher (&safer_sk64_desc);
+  register_cipher (&safer_k128_desc);
+  register_cipher (&safer_sk128_desc);
+#endif
+#ifdef RC2
+  register_cipher (&rc2_desc);
+#endif
+#ifdef DES
+  register_cipher (&des_desc);
+  register_cipher (&des3_desc);
+#endif
+#ifdef CAST5
+  register_cipher (&cast5_desc);
+#endif
+#ifdef NOEKEON
+  register_cipher (&noekeon_desc);
+#endif
+#ifdef SKIPJACK
+  register_cipher (&skipjack_desc);
+#endif
+
+#ifdef TIGER
+  register_hash (&tiger_desc);
+#endif
+#ifdef MD2
+  register_hash (&md2_desc);
+#endif
+#ifdef MD4
+  register_hash (&md4_desc);
+#endif
+#ifdef MD5
+  register_hash (&md5_desc);
+#endif
+#ifdef SHA1
+  register_hash (&sha1_desc);
+#endif
+#ifdef SHA224
+  register_hash (&sha224_desc);
+#endif
+#ifdef SHA256
+  register_hash (&sha256_desc);
+#endif
+#ifdef SHA384
+  register_hash (&sha384_desc);
+#endif
+#ifdef SHA512
+  register_hash (&sha512_desc);
+#endif
+#ifdef RIPEMD128
+  register_hash (&rmd128_desc);
+#endif
+#ifdef RIPEMD160
+  register_hash (&rmd160_desc);
+#endif
+#ifdef WHIRLPOOL
+  register_hash (&whirlpool_desc);
+#endif
+
+register_prng(&yarrow_desc);
+rng_make_prng(128, find_prng("yarrow"), &prng, NULL);
+}
+
+int time_keysched(void)
+{
+  unsigned long x, i, y1;
+  ulong64 t1, c1;
+  symmetric_key skey;
+  int kl;
+  int    (*func) (const unsigned char *, int , int , symmetric_key *);
+  unsigned char key[MAXBLOCKSIZE];
+
+  printf ("\n\nKey Schedule Time Trials for the Symmetric Ciphers:\n(Times are cycles per key)\n");
+  no_results = 0; 
+ for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+#define DO1(k)   func(k, kl, 0, &skey);
+
+    func = cipher_descriptor[x].setup;
+    kl   = cipher_descriptor[x].min_key_length;
+    c1 = (ulong64)-1;
+    for (y1 = 0; y1 < KTIMES; y1++) {
+       yarrow_read(key, kl, &prng);
+       t_start();
+       DO1(key);
+       t1 = t_read();
+       c1 = (t1 > c1) ? c1 : t1;
+    }
+    t1 = c1 - skew;
+    results[no_results].spd1 = results[no_results].avg = t1;
+    results[no_results++].id = x;
+    printf("."); fflush(stdout);
+
+#undef DO1
+   }
+   tally_results(0);
+
+   return 0;
+}
+
+int time_cipher(void)
+{
+  unsigned long x, y1;
+  ulong64  t1, t2, c1, c2, a1, a2;
+  symmetric_key skey;
+  void    (*func) (const unsigned char *, unsigned char *, symmetric_key *);
+  unsigned char key[MAXBLOCKSIZE], pt[MAXBLOCKSIZE];
+
+
+  printf ("\n\nECB Time Trials for the Symmetric Ciphers:\n");
+  no_results = 0;
+  for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+    cipher_descriptor[x].setup (key, cipher_descriptor[x].min_key_length, 0,
+                &skey);
+
+#define DO1   func(pt,pt,&skey);
+#define DO2   DO1 DO1
+
+    func = cipher_descriptor[x].ecb_encrypt;
+    c1 = c2 = (ulong64)-1;
+    for (y1 = 0; y1 < TIMES; y1++) {
+        t_start();
+        DO1;
+        t1 = t_read();
+        DO2;
+        t2 = t_read();
+        t2 -= t1;
+
+        c1 = (t1 > c1 ? c1 : t1);
+        c2 = (t2 > c2 ? c2 : t2);
+    }
+    a1 = c2 - c1 - skew;
+
+
+    func = cipher_descriptor[x].ecb_decrypt;
+    c1 = c2 = (ulong64)-1;
+    for (y1 = 0; y1 < TIMES; y1++) {
+        t_start();
+        DO1;
+        t1 = t_read();
+        DO2;
+        t2 = t_read();
+        t2 -= t1;
+
+        c1 = (t1 > c1 ? c1 : t1);
+        c2 = (t2 > c2 ? c2 : t2);
+    }
+    a2 = c2 - c1 - skew;
+    
+    results[no_results].id = x;
+    results[no_results].spd1 = a1/cipher_descriptor[x].block_length;
+    results[no_results].spd2 = a2/cipher_descriptor[x].block_length;;
+    results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2;
+    ++no_results;
+    printf("."); fflush(stdout);
+    
+#undef DO2
+#undef DO1
+   }
+   tally_results(1);
+
+   return 0;
+}
+
+int time_hash(void)
+{
+  unsigned long x, y1, len;
+  ulong64 t1, t2, c1, c2;
+  hash_state md;
+  int    (*func)(hash_state *, const unsigned char *, unsigned long);
+  unsigned char pt[MAXBLOCKSIZE];
+
+
+  printf ("\n\nHASH Time Trials for:\n");
+  no_results = 0;
+  for (x = 0; hash_descriptor[x].name != NULL; x++) {
+    hash_descriptor[x].init(&md);
+
+#define DO1   func(&md,pt,len);
+#define DO2   DO1 DO1
+
+    func = hash_descriptor[x].process;
+    len  = hash_descriptor[x].blocksize;
+
+    c1 = c2 = (ulong64)-1;
+    for (y1 = 0; y1 < TIMES; y1++) {
+       t_start();
+       DO1;
+       t1 = t_read();
+       DO2;
+       t2 = t_read() - t1;
+       c1 = (t1 > c1) ? c1 : t1;
+       c2 = (t2 > c2) ? c2 : t2;
+    }
+    t1 = c2 - c1 - skew;
+    t1 = ((t1 * CONST64(1000))) / ((ulong64)hash_descriptor[x].blocksize);
+    results[no_results].id = x;
+    results[no_results].spd1 = results[no_results].avg = t1;
+    ++no_results;
+    printf("."); fflush(stdout);
+#undef DO2
+#undef DO1
+   }
+   tally_results(2);
+
+   return 0;
+}
+
+int main(void)
+{
+  reg_algs();
+
+  printf("Timings for ciphers and hashes.  Times are listed as cycles per byte processed.\n\n");
+
+//  init_timer();
+  time_cipher();
+  time_keysched();
+  time_hash();
+
+  return EXIT_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/des.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,1813 @@
+/* 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
+ */
+/* DES code submitted by Dobes Vandermeer */
+#include "mycrypt.h"
+
+#ifdef DES
+
+#define EN0 0 
+#define DE1 1
+
+const struct _cipher_descriptor des_desc =
+{
+    "des",
+    13,
+    8, 8, 8, 16,
+    &des_setup,
+    &des_ecb_encrypt,
+    &des_ecb_decrypt,
+    &des_test,
+    &des_keysize
+};
+
+const struct _cipher_descriptor des3_desc =
+{
+    "3des",
+    14,
+    24, 24, 8, 16,
+    &des3_setup,
+    &des3_ecb_encrypt,
+    &des3_ecb_decrypt,
+    &des3_test,
+    &des3_keysize
+};
+
+static const ulong32 bytebit[8] =
+{
+    0200, 0100, 040, 020, 010, 04, 02, 01 
+};
+
+static const ulong32 bigbyte[24] =
+{
+    0x800000UL,  0x400000UL,  0x200000UL,  0x100000UL,
+    0x80000UL,   0x40000UL,   0x20000UL,   0x10000UL,
+    0x8000UL,    0x4000UL,    0x2000UL,    0x1000UL,
+    0x800UL,     0x400UL,     0x200UL,     0x100UL,
+    0x80UL,      0x40UL,      0x20UL,      0x10UL,
+    0x8UL,       0x4UL,       0x2UL,       0x1L 
+};
+
+/* Use the key schedule specific in the standard (ANSI X3.92-1981) */
+
+static const unsigned char pc1[56] = {
+    56, 48, 40, 32, 24, 16,  8,  0, 57, 49, 41, 33, 25, 17,  
+     9,  1, 58, 50, 42, 34, 26, 18, 10,  2, 59, 51, 43, 35, 
+    62, 54, 46, 38, 30, 22, 14,  6, 61, 53, 45, 37, 29, 21,
+    13,  5, 60, 52, 44, 36, 28, 20, 12,  4, 27, 19, 11,  3 
+};
+
+static const unsigned char totrot[16] = {
+    1,   2,  4,  6,
+    8,  10, 12, 14, 
+    15, 17, 19, 21, 
+    23, 25, 27, 28
+};
+
+static const unsigned char pc2[48] = {
+    13, 16, 10, 23,  0,  4,      2, 27, 14,  5, 20,  9,
+    22, 18, 11,  3, 25,  7,     15,  6, 26, 19, 12,  1,
+    40, 51, 30, 36, 46, 54,     29, 39, 50, 44, 32, 47,
+    43, 48, 38, 55, 33, 52,     45, 41, 49, 35, 28, 31
+};
+
+
+static const ulong32 SP1[64] =
+{
+    0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL,
+    0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL,
+    0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL,
+    0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL,
+    0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL,
+    0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL,
+    0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL,
+    0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL,
+    0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL,
+    0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL,
+    0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL,
+    0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL,
+    0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL,
+    0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL,
+    0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL,
+    0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL
+};
+
+static const ulong32 SP2[64] =
+{
+    0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL,
+    0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL,
+    0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL,
+    0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL,
+    0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL,
+    0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL,
+    0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL,
+    0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL,
+    0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL,
+    0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL,
+    0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL,
+    0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL,
+    0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL,
+    0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL,
+    0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL,
+    0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL
+};
+
+static const ulong32 SP3[64] =
+{
+    0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL,
+    0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL,
+    0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL,
+    0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL,
+    0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL,
+    0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL,
+    0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL,
+    0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL,
+    0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL,
+    0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL,
+    0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL,
+    0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL,
+    0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL,
+    0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL,
+    0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL,
+    0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL
+};
+
+static const ulong32 SP4[64] =
+{
+    0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
+    0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL,
+    0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL,
+    0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL,
+    0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL,
+    0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL,
+    0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL,
+    0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL,
+    0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL,
+    0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL,
+    0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL,
+    0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
+    0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL,
+    0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL,
+    0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL,
+    0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL
+};
+
+static const ulong32 SP5[64] =
+{
+    0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL,
+    0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL,
+    0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL,
+    0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL,
+    0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL,
+    0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL,
+    0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL,
+    0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL,
+    0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL,
+    0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL,
+    0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL,
+    0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL,
+    0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL,
+    0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL,
+    0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL,
+    0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL
+};
+
+static const ulong32 SP6[64] =
+{
+    0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL,
+    0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL,
+    0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL,
+    0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
+    0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL,
+    0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL,
+    0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL,
+    0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL,
+    0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL,
+    0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL,
+    0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
+    0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL,
+    0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL,
+    0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL,
+    0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL,
+    0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL
+};
+
+static const ulong32 SP7[64] =
+{
+    0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL,
+    0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL,
+    0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL,
+    0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL,
+    0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL,
+    0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL,
+    0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL,
+    0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL,
+    0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL,
+    0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL,
+    0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL,
+    0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL,
+    0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL,
+    0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL,
+    0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL,
+    0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL
+};
+
+static const ulong32 SP8[64] =
+{
+    0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL,
+    0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL,
+    0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL,
+    0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL,
+    0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL,
+    0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL,
+    0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL,
+    0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL,
+    0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL,
+    0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL,
+    0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL,
+    0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL,
+    0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL,
+    0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL,
+    0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL,
+    0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL
+};
+
+#ifndef SMALL_CODE
+
+static const ulong64 des_ip[8][256] = {
+
+{ CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000000000010), CONST64(0x0000001000000010), 
+  CONST64(0x0000100000000000), CONST64(0x0000101000000000), CONST64(0x0000100000000010), CONST64(0x0000101000000010), 
+  CONST64(0x0000000000001000), CONST64(0x0000001000001000), CONST64(0x0000000000001010), CONST64(0x0000001000001010), 
+  CONST64(0x0000100000001000), CONST64(0x0000101000001000), CONST64(0x0000100000001010), CONST64(0x0000101000001010), 
+  CONST64(0x0010000000000000), CONST64(0x0010001000000000), CONST64(0x0010000000000010), CONST64(0x0010001000000010), 
+  CONST64(0x0010100000000000), CONST64(0x0010101000000000), CONST64(0x0010100000000010), CONST64(0x0010101000000010), 
+  CONST64(0x0010000000001000), CONST64(0x0010001000001000), CONST64(0x0010000000001010), CONST64(0x0010001000001010), 
+  CONST64(0x0010100000001000), CONST64(0x0010101000001000), CONST64(0x0010100000001010), CONST64(0x0010101000001010), 
+  CONST64(0x0000000000100000), CONST64(0x0000001000100000), CONST64(0x0000000000100010), CONST64(0x0000001000100010), 
+  CONST64(0x0000100000100000), CONST64(0x0000101000100000), CONST64(0x0000100000100010), CONST64(0x0000101000100010), 
+  CONST64(0x0000000000101000), CONST64(0x0000001000101000), CONST64(0x0000000000101010), CONST64(0x0000001000101010), 
+  CONST64(0x0000100000101000), CONST64(0x0000101000101000), CONST64(0x0000100000101010), CONST64(0x0000101000101010), 
+  CONST64(0x0010000000100000), CONST64(0x0010001000100000), CONST64(0x0010000000100010), CONST64(0x0010001000100010), 
+  CONST64(0x0010100000100000), CONST64(0x0010101000100000), CONST64(0x0010100000100010), CONST64(0x0010101000100010), 
+  CONST64(0x0010000000101000), CONST64(0x0010001000101000), CONST64(0x0010000000101010), CONST64(0x0010001000101010), 
+  CONST64(0x0010100000101000), CONST64(0x0010101000101000), CONST64(0x0010100000101010), CONST64(0x0010101000101010), 
+  CONST64(0x1000000000000000), CONST64(0x1000001000000000), CONST64(0x1000000000000010), CONST64(0x1000001000000010), 
+  CONST64(0x1000100000000000), CONST64(0x1000101000000000), CONST64(0x1000100000000010), CONST64(0x1000101000000010), 
+  CONST64(0x1000000000001000), CONST64(0x1000001000001000), CONST64(0x1000000000001010), CONST64(0x1000001000001010), 
+  CONST64(0x1000100000001000), CONST64(0x1000101000001000), CONST64(0x1000100000001010), CONST64(0x1000101000001010), 
+  CONST64(0x1010000000000000), CONST64(0x1010001000000000), CONST64(0x1010000000000010), CONST64(0x1010001000000010), 
+  CONST64(0x1010100000000000), CONST64(0x1010101000000000), CONST64(0x1010100000000010), CONST64(0x1010101000000010), 
+  CONST64(0x1010000000001000), CONST64(0x1010001000001000), CONST64(0x1010000000001010), CONST64(0x1010001000001010), 
+  CONST64(0x1010100000001000), CONST64(0x1010101000001000), CONST64(0x1010100000001010), CONST64(0x1010101000001010), 
+  CONST64(0x1000000000100000), CONST64(0x1000001000100000), CONST64(0x1000000000100010), CONST64(0x1000001000100010), 
+  CONST64(0x1000100000100000), CONST64(0x1000101000100000), CONST64(0x1000100000100010), CONST64(0x1000101000100010), 
+  CONST64(0x1000000000101000), CONST64(0x1000001000101000), CONST64(0x1000000000101010), CONST64(0x1000001000101010), 
+  CONST64(0x1000100000101000), CONST64(0x1000101000101000), CONST64(0x1000100000101010), CONST64(0x1000101000101010), 
+  CONST64(0x1010000000100000), CONST64(0x1010001000100000), CONST64(0x1010000000100010), CONST64(0x1010001000100010), 
+  CONST64(0x1010100000100000), CONST64(0x1010101000100000), CONST64(0x1010100000100010), CONST64(0x1010101000100010), 
+  CONST64(0x1010000000101000), CONST64(0x1010001000101000), CONST64(0x1010000000101010), CONST64(0x1010001000101010), 
+  CONST64(0x1010100000101000), CONST64(0x1010101000101000), CONST64(0x1010100000101010), CONST64(0x1010101000101010), 
+  CONST64(0x0000000010000000), CONST64(0x0000001010000000), CONST64(0x0000000010000010), CONST64(0x0000001010000010), 
+  CONST64(0x0000100010000000), CONST64(0x0000101010000000), CONST64(0x0000100010000010), CONST64(0x0000101010000010), 
+  CONST64(0x0000000010001000), CONST64(0x0000001010001000), CONST64(0x0000000010001010), CONST64(0x0000001010001010), 
+  CONST64(0x0000100010001000), CONST64(0x0000101010001000), CONST64(0x0000100010001010), CONST64(0x0000101010001010), 
+  CONST64(0x0010000010000000), CONST64(0x0010001010000000), CONST64(0x0010000010000010), CONST64(0x0010001010000010), 
+  CONST64(0x0010100010000000), CONST64(0x0010101010000000), CONST64(0x0010100010000010), CONST64(0x0010101010000010), 
+  CONST64(0x0010000010001000), CONST64(0x0010001010001000), CONST64(0x0010000010001010), CONST64(0x0010001010001010), 
+  CONST64(0x0010100010001000), CONST64(0x0010101010001000), CONST64(0x0010100010001010), CONST64(0x0010101010001010), 
+  CONST64(0x0000000010100000), CONST64(0x0000001010100000), CONST64(0x0000000010100010), CONST64(0x0000001010100010), 
+  CONST64(0x0000100010100000), CONST64(0x0000101010100000), CONST64(0x0000100010100010), CONST64(0x0000101010100010), 
+  CONST64(0x0000000010101000), CONST64(0x0000001010101000), CONST64(0x0000000010101010), CONST64(0x0000001010101010), 
+  CONST64(0x0000100010101000), CONST64(0x0000101010101000), CONST64(0x0000100010101010), CONST64(0x0000101010101010), 
+  CONST64(0x0010000010100000), CONST64(0x0010001010100000), CONST64(0x0010000010100010), CONST64(0x0010001010100010), 
+  CONST64(0x0010100010100000), CONST64(0x0010101010100000), CONST64(0x0010100010100010), CONST64(0x0010101010100010), 
+  CONST64(0x0010000010101000), CONST64(0x0010001010101000), CONST64(0x0010000010101010), CONST64(0x0010001010101010), 
+  CONST64(0x0010100010101000), CONST64(0x0010101010101000), CONST64(0x0010100010101010), CONST64(0x0010101010101010), 
+  CONST64(0x1000000010000000), CONST64(0x1000001010000000), CONST64(0x1000000010000010), CONST64(0x1000001010000010), 
+  CONST64(0x1000100010000000), CONST64(0x1000101010000000), CONST64(0x1000100010000010), CONST64(0x1000101010000010), 
+  CONST64(0x1000000010001000), CONST64(0x1000001010001000), CONST64(0x1000000010001010), CONST64(0x1000001010001010), 
+  CONST64(0x1000100010001000), CONST64(0x1000101010001000), CONST64(0x1000100010001010), CONST64(0x1000101010001010), 
+  CONST64(0x1010000010000000), CONST64(0x1010001010000000), CONST64(0x1010000010000010), CONST64(0x1010001010000010), 
+  CONST64(0x1010100010000000), CONST64(0x1010101010000000), CONST64(0x1010100010000010), CONST64(0x1010101010000010), 
+  CONST64(0x1010000010001000), CONST64(0x1010001010001000), CONST64(0x1010000010001010), CONST64(0x1010001010001010), 
+  CONST64(0x1010100010001000), CONST64(0x1010101010001000), CONST64(0x1010100010001010), CONST64(0x1010101010001010), 
+  CONST64(0x1000000010100000), CONST64(0x1000001010100000), CONST64(0x1000000010100010), CONST64(0x1000001010100010), 
+  CONST64(0x1000100010100000), CONST64(0x1000101010100000), CONST64(0x1000100010100010), CONST64(0x1000101010100010), 
+  CONST64(0x1000000010101000), CONST64(0x1000001010101000), CONST64(0x1000000010101010), CONST64(0x1000001010101010), 
+  CONST64(0x1000100010101000), CONST64(0x1000101010101000), CONST64(0x1000100010101010), CONST64(0x1000101010101010), 
+  CONST64(0x1010000010100000), CONST64(0x1010001010100000), CONST64(0x1010000010100010), CONST64(0x1010001010100010), 
+  CONST64(0x1010100010100000), CONST64(0x1010101010100000), CONST64(0x1010100010100010), CONST64(0x1010101010100010), 
+  CONST64(0x1010000010101000), CONST64(0x1010001010101000), CONST64(0x1010000010101010), CONST64(0x1010001010101010), 
+  CONST64(0x1010100010101000), CONST64(0x1010101010101000), CONST64(0x1010100010101010), CONST64(0x1010101010101010)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000000000008), CONST64(0x0000000800000008), 
+  CONST64(0x0000080000000000), CONST64(0x0000080800000000), CONST64(0x0000080000000008), CONST64(0x0000080800000008), 
+  CONST64(0x0000000000000800), CONST64(0x0000000800000800), CONST64(0x0000000000000808), CONST64(0x0000000800000808), 
+  CONST64(0x0000080000000800), CONST64(0x0000080800000800), CONST64(0x0000080000000808), CONST64(0x0000080800000808), 
+  CONST64(0x0008000000000000), CONST64(0x0008000800000000), CONST64(0x0008000000000008), CONST64(0x0008000800000008), 
+  CONST64(0x0008080000000000), CONST64(0x0008080800000000), CONST64(0x0008080000000008), CONST64(0x0008080800000008), 
+  CONST64(0x0008000000000800), CONST64(0x0008000800000800), CONST64(0x0008000000000808), CONST64(0x0008000800000808), 
+  CONST64(0x0008080000000800), CONST64(0x0008080800000800), CONST64(0x0008080000000808), CONST64(0x0008080800000808), 
+  CONST64(0x0000000000080000), CONST64(0x0000000800080000), CONST64(0x0000000000080008), CONST64(0x0000000800080008), 
+  CONST64(0x0000080000080000), CONST64(0x0000080800080000), CONST64(0x0000080000080008), CONST64(0x0000080800080008), 
+  CONST64(0x0000000000080800), CONST64(0x0000000800080800), CONST64(0x0000000000080808), CONST64(0x0000000800080808), 
+  CONST64(0x0000080000080800), CONST64(0x0000080800080800), CONST64(0x0000080000080808), CONST64(0x0000080800080808), 
+  CONST64(0x0008000000080000), CONST64(0x0008000800080000), CONST64(0x0008000000080008), CONST64(0x0008000800080008), 
+  CONST64(0x0008080000080000), CONST64(0x0008080800080000), CONST64(0x0008080000080008), CONST64(0x0008080800080008), 
+  CONST64(0x0008000000080800), CONST64(0x0008000800080800), CONST64(0x0008000000080808), CONST64(0x0008000800080808), 
+  CONST64(0x0008080000080800), CONST64(0x0008080800080800), CONST64(0x0008080000080808), CONST64(0x0008080800080808), 
+  CONST64(0x0800000000000000), CONST64(0x0800000800000000), CONST64(0x0800000000000008), CONST64(0x0800000800000008), 
+  CONST64(0x0800080000000000), CONST64(0x0800080800000000), CONST64(0x0800080000000008), CONST64(0x0800080800000008), 
+  CONST64(0x0800000000000800), CONST64(0x0800000800000800), CONST64(0x0800000000000808), CONST64(0x0800000800000808), 
+  CONST64(0x0800080000000800), CONST64(0x0800080800000800), CONST64(0x0800080000000808), CONST64(0x0800080800000808), 
+  CONST64(0x0808000000000000), CONST64(0x0808000800000000), CONST64(0x0808000000000008), CONST64(0x0808000800000008), 
+  CONST64(0x0808080000000000), CONST64(0x0808080800000000), CONST64(0x0808080000000008), CONST64(0x0808080800000008), 
+  CONST64(0x0808000000000800), CONST64(0x0808000800000800), CONST64(0x0808000000000808), CONST64(0x0808000800000808), 
+  CONST64(0x0808080000000800), CONST64(0x0808080800000800), CONST64(0x0808080000000808), CONST64(0x0808080800000808), 
+  CONST64(0x0800000000080000), CONST64(0x0800000800080000), CONST64(0x0800000000080008), CONST64(0x0800000800080008), 
+  CONST64(0x0800080000080000), CONST64(0x0800080800080000), CONST64(0x0800080000080008), CONST64(0x0800080800080008), 
+  CONST64(0x0800000000080800), CONST64(0x0800000800080800), CONST64(0x0800000000080808), CONST64(0x0800000800080808), 
+  CONST64(0x0800080000080800), CONST64(0x0800080800080800), CONST64(0x0800080000080808), CONST64(0x0800080800080808), 
+  CONST64(0x0808000000080000), CONST64(0x0808000800080000), CONST64(0x0808000000080008), CONST64(0x0808000800080008), 
+  CONST64(0x0808080000080000), CONST64(0x0808080800080000), CONST64(0x0808080000080008), CONST64(0x0808080800080008), 
+  CONST64(0x0808000000080800), CONST64(0x0808000800080800), CONST64(0x0808000000080808), CONST64(0x0808000800080808), 
+  CONST64(0x0808080000080800), CONST64(0x0808080800080800), CONST64(0x0808080000080808), CONST64(0x0808080800080808), 
+  CONST64(0x0000000008000000), CONST64(0x0000000808000000), CONST64(0x0000000008000008), CONST64(0x0000000808000008), 
+  CONST64(0x0000080008000000), CONST64(0x0000080808000000), CONST64(0x0000080008000008), CONST64(0x0000080808000008), 
+  CONST64(0x0000000008000800), CONST64(0x0000000808000800), CONST64(0x0000000008000808), CONST64(0x0000000808000808), 
+  CONST64(0x0000080008000800), CONST64(0x0000080808000800), CONST64(0x0000080008000808), CONST64(0x0000080808000808), 
+  CONST64(0x0008000008000000), CONST64(0x0008000808000000), CONST64(0x0008000008000008), CONST64(0x0008000808000008), 
+  CONST64(0x0008080008000000), CONST64(0x0008080808000000), CONST64(0x0008080008000008), CONST64(0x0008080808000008), 
+  CONST64(0x0008000008000800), CONST64(0x0008000808000800), CONST64(0x0008000008000808), CONST64(0x0008000808000808), 
+  CONST64(0x0008080008000800), CONST64(0x0008080808000800), CONST64(0x0008080008000808), CONST64(0x0008080808000808), 
+  CONST64(0x0000000008080000), CONST64(0x0000000808080000), CONST64(0x0000000008080008), CONST64(0x0000000808080008), 
+  CONST64(0x0000080008080000), CONST64(0x0000080808080000), CONST64(0x0000080008080008), CONST64(0x0000080808080008), 
+  CONST64(0x0000000008080800), CONST64(0x0000000808080800), CONST64(0x0000000008080808), CONST64(0x0000000808080808), 
+  CONST64(0x0000080008080800), CONST64(0x0000080808080800), CONST64(0x0000080008080808), CONST64(0x0000080808080808), 
+  CONST64(0x0008000008080000), CONST64(0x0008000808080000), CONST64(0x0008000008080008), CONST64(0x0008000808080008), 
+  CONST64(0x0008080008080000), CONST64(0x0008080808080000), CONST64(0x0008080008080008), CONST64(0x0008080808080008), 
+  CONST64(0x0008000008080800), CONST64(0x0008000808080800), CONST64(0x0008000008080808), CONST64(0x0008000808080808), 
+  CONST64(0x0008080008080800), CONST64(0x0008080808080800), CONST64(0x0008080008080808), CONST64(0x0008080808080808), 
+  CONST64(0x0800000008000000), CONST64(0x0800000808000000), CONST64(0x0800000008000008), CONST64(0x0800000808000008), 
+  CONST64(0x0800080008000000), CONST64(0x0800080808000000), CONST64(0x0800080008000008), CONST64(0x0800080808000008), 
+  CONST64(0x0800000008000800), CONST64(0x0800000808000800), CONST64(0x0800000008000808), CONST64(0x0800000808000808), 
+  CONST64(0x0800080008000800), CONST64(0x0800080808000800), CONST64(0x0800080008000808), CONST64(0x0800080808000808), 
+  CONST64(0x0808000008000000), CONST64(0x0808000808000000), CONST64(0x0808000008000008), CONST64(0x0808000808000008), 
+  CONST64(0x0808080008000000), CONST64(0x0808080808000000), CONST64(0x0808080008000008), CONST64(0x0808080808000008), 
+  CONST64(0x0808000008000800), CONST64(0x0808000808000800), CONST64(0x0808000008000808), CONST64(0x0808000808000808), 
+  CONST64(0x0808080008000800), CONST64(0x0808080808000800), CONST64(0x0808080008000808), CONST64(0x0808080808000808), 
+  CONST64(0x0800000008080000), CONST64(0x0800000808080000), CONST64(0x0800000008080008), CONST64(0x0800000808080008), 
+  CONST64(0x0800080008080000), CONST64(0x0800080808080000), CONST64(0x0800080008080008), CONST64(0x0800080808080008), 
+  CONST64(0x0800000008080800), CONST64(0x0800000808080800), CONST64(0x0800000008080808), CONST64(0x0800000808080808), 
+  CONST64(0x0800080008080800), CONST64(0x0800080808080800), CONST64(0x0800080008080808), CONST64(0x0800080808080808), 
+  CONST64(0x0808000008080000), CONST64(0x0808000808080000), CONST64(0x0808000008080008), CONST64(0x0808000808080008), 
+  CONST64(0x0808080008080000), CONST64(0x0808080808080000), CONST64(0x0808080008080008), CONST64(0x0808080808080008), 
+  CONST64(0x0808000008080800), CONST64(0x0808000808080800), CONST64(0x0808000008080808), CONST64(0x0808000808080808), 
+  CONST64(0x0808080008080800), CONST64(0x0808080808080800), CONST64(0x0808080008080808), CONST64(0x0808080808080808)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000000000004), CONST64(0x0000000400000004), 
+  CONST64(0x0000040000000000), CONST64(0x0000040400000000), CONST64(0x0000040000000004), CONST64(0x0000040400000004), 
+  CONST64(0x0000000000000400), CONST64(0x0000000400000400), CONST64(0x0000000000000404), CONST64(0x0000000400000404), 
+  CONST64(0x0000040000000400), CONST64(0x0000040400000400), CONST64(0x0000040000000404), CONST64(0x0000040400000404), 
+  CONST64(0x0004000000000000), CONST64(0x0004000400000000), CONST64(0x0004000000000004), CONST64(0x0004000400000004), 
+  CONST64(0x0004040000000000), CONST64(0x0004040400000000), CONST64(0x0004040000000004), CONST64(0x0004040400000004), 
+  CONST64(0x0004000000000400), CONST64(0x0004000400000400), CONST64(0x0004000000000404), CONST64(0x0004000400000404), 
+  CONST64(0x0004040000000400), CONST64(0x0004040400000400), CONST64(0x0004040000000404), CONST64(0x0004040400000404), 
+  CONST64(0x0000000000040000), CONST64(0x0000000400040000), CONST64(0x0000000000040004), CONST64(0x0000000400040004), 
+  CONST64(0x0000040000040000), CONST64(0x0000040400040000), CONST64(0x0000040000040004), CONST64(0x0000040400040004), 
+  CONST64(0x0000000000040400), CONST64(0x0000000400040400), CONST64(0x0000000000040404), CONST64(0x0000000400040404), 
+  CONST64(0x0000040000040400), CONST64(0x0000040400040400), CONST64(0x0000040000040404), CONST64(0x0000040400040404), 
+  CONST64(0x0004000000040000), CONST64(0x0004000400040000), CONST64(0x0004000000040004), CONST64(0x0004000400040004), 
+  CONST64(0x0004040000040000), CONST64(0x0004040400040000), CONST64(0x0004040000040004), CONST64(0x0004040400040004), 
+  CONST64(0x0004000000040400), CONST64(0x0004000400040400), CONST64(0x0004000000040404), CONST64(0x0004000400040404), 
+  CONST64(0x0004040000040400), CONST64(0x0004040400040400), CONST64(0x0004040000040404), CONST64(0x0004040400040404), 
+  CONST64(0x0400000000000000), CONST64(0x0400000400000000), CONST64(0x0400000000000004), CONST64(0x0400000400000004), 
+  CONST64(0x0400040000000000), CONST64(0x0400040400000000), CONST64(0x0400040000000004), CONST64(0x0400040400000004), 
+  CONST64(0x0400000000000400), CONST64(0x0400000400000400), CONST64(0x0400000000000404), CONST64(0x0400000400000404), 
+  CONST64(0x0400040000000400), CONST64(0x0400040400000400), CONST64(0x0400040000000404), CONST64(0x0400040400000404), 
+  CONST64(0x0404000000000000), CONST64(0x0404000400000000), CONST64(0x0404000000000004), CONST64(0x0404000400000004), 
+  CONST64(0x0404040000000000), CONST64(0x0404040400000000), CONST64(0x0404040000000004), CONST64(0x0404040400000004), 
+  CONST64(0x0404000000000400), CONST64(0x0404000400000400), CONST64(0x0404000000000404), CONST64(0x0404000400000404), 
+  CONST64(0x0404040000000400), CONST64(0x0404040400000400), CONST64(0x0404040000000404), CONST64(0x0404040400000404), 
+  CONST64(0x0400000000040000), CONST64(0x0400000400040000), CONST64(0x0400000000040004), CONST64(0x0400000400040004), 
+  CONST64(0x0400040000040000), CONST64(0x0400040400040000), CONST64(0x0400040000040004), CONST64(0x0400040400040004), 
+  CONST64(0x0400000000040400), CONST64(0x0400000400040400), CONST64(0x0400000000040404), CONST64(0x0400000400040404), 
+  CONST64(0x0400040000040400), CONST64(0x0400040400040400), CONST64(0x0400040000040404), CONST64(0x0400040400040404), 
+  CONST64(0x0404000000040000), CONST64(0x0404000400040000), CONST64(0x0404000000040004), CONST64(0x0404000400040004), 
+  CONST64(0x0404040000040000), CONST64(0x0404040400040000), CONST64(0x0404040000040004), CONST64(0x0404040400040004), 
+  CONST64(0x0404000000040400), CONST64(0x0404000400040400), CONST64(0x0404000000040404), CONST64(0x0404000400040404), 
+  CONST64(0x0404040000040400), CONST64(0x0404040400040400), CONST64(0x0404040000040404), CONST64(0x0404040400040404), 
+  CONST64(0x0000000004000000), CONST64(0x0000000404000000), CONST64(0x0000000004000004), CONST64(0x0000000404000004), 
+  CONST64(0x0000040004000000), CONST64(0x0000040404000000), CONST64(0x0000040004000004), CONST64(0x0000040404000004), 
+  CONST64(0x0000000004000400), CONST64(0x0000000404000400), CONST64(0x0000000004000404), CONST64(0x0000000404000404), 
+  CONST64(0x0000040004000400), CONST64(0x0000040404000400), CONST64(0x0000040004000404), CONST64(0x0000040404000404), 
+  CONST64(0x0004000004000000), CONST64(0x0004000404000000), CONST64(0x0004000004000004), CONST64(0x0004000404000004), 
+  CONST64(0x0004040004000000), CONST64(0x0004040404000000), CONST64(0x0004040004000004), CONST64(0x0004040404000004), 
+  CONST64(0x0004000004000400), CONST64(0x0004000404000400), CONST64(0x0004000004000404), CONST64(0x0004000404000404), 
+  CONST64(0x0004040004000400), CONST64(0x0004040404000400), CONST64(0x0004040004000404), CONST64(0x0004040404000404), 
+  CONST64(0x0000000004040000), CONST64(0x0000000404040000), CONST64(0x0000000004040004), CONST64(0x0000000404040004), 
+  CONST64(0x0000040004040000), CONST64(0x0000040404040000), CONST64(0x0000040004040004), CONST64(0x0000040404040004), 
+  CONST64(0x0000000004040400), CONST64(0x0000000404040400), CONST64(0x0000000004040404), CONST64(0x0000000404040404), 
+  CONST64(0x0000040004040400), CONST64(0x0000040404040400), CONST64(0x0000040004040404), CONST64(0x0000040404040404), 
+  CONST64(0x0004000004040000), CONST64(0x0004000404040000), CONST64(0x0004000004040004), CONST64(0x0004000404040004), 
+  CONST64(0x0004040004040000), CONST64(0x0004040404040000), CONST64(0x0004040004040004), CONST64(0x0004040404040004), 
+  CONST64(0x0004000004040400), CONST64(0x0004000404040400), CONST64(0x0004000004040404), CONST64(0x0004000404040404), 
+  CONST64(0x0004040004040400), CONST64(0x0004040404040400), CONST64(0x0004040004040404), CONST64(0x0004040404040404), 
+  CONST64(0x0400000004000000), CONST64(0x0400000404000000), CONST64(0x0400000004000004), CONST64(0x0400000404000004), 
+  CONST64(0x0400040004000000), CONST64(0x0400040404000000), CONST64(0x0400040004000004), CONST64(0x0400040404000004), 
+  CONST64(0x0400000004000400), CONST64(0x0400000404000400), CONST64(0x0400000004000404), CONST64(0x0400000404000404), 
+  CONST64(0x0400040004000400), CONST64(0x0400040404000400), CONST64(0x0400040004000404), CONST64(0x0400040404000404), 
+  CONST64(0x0404000004000000), CONST64(0x0404000404000000), CONST64(0x0404000004000004), CONST64(0x0404000404000004), 
+  CONST64(0x0404040004000000), CONST64(0x0404040404000000), CONST64(0x0404040004000004), CONST64(0x0404040404000004), 
+  CONST64(0x0404000004000400), CONST64(0x0404000404000400), CONST64(0x0404000004000404), CONST64(0x0404000404000404), 
+  CONST64(0x0404040004000400), CONST64(0x0404040404000400), CONST64(0x0404040004000404), CONST64(0x0404040404000404), 
+  CONST64(0x0400000004040000), CONST64(0x0400000404040000), CONST64(0x0400000004040004), CONST64(0x0400000404040004), 
+  CONST64(0x0400040004040000), CONST64(0x0400040404040000), CONST64(0x0400040004040004), CONST64(0x0400040404040004), 
+  CONST64(0x0400000004040400), CONST64(0x0400000404040400), CONST64(0x0400000004040404), CONST64(0x0400000404040404), 
+  CONST64(0x0400040004040400), CONST64(0x0400040404040400), CONST64(0x0400040004040404), CONST64(0x0400040404040404), 
+  CONST64(0x0404000004040000), CONST64(0x0404000404040000), CONST64(0x0404000004040004), CONST64(0x0404000404040004), 
+  CONST64(0x0404040004040000), CONST64(0x0404040404040000), CONST64(0x0404040004040004), CONST64(0x0404040404040004), 
+  CONST64(0x0404000004040400), CONST64(0x0404000404040400), CONST64(0x0404000004040404), CONST64(0x0404000404040404), 
+  CONST64(0x0404040004040400), CONST64(0x0404040404040400), CONST64(0x0404040004040404), CONST64(0x0404040404040404)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000000000002), CONST64(0x0000000200000002), 
+  CONST64(0x0000020000000000), CONST64(0x0000020200000000), CONST64(0x0000020000000002), CONST64(0x0000020200000002), 
+  CONST64(0x0000000000000200), CONST64(0x0000000200000200), CONST64(0x0000000000000202), CONST64(0x0000000200000202), 
+  CONST64(0x0000020000000200), CONST64(0x0000020200000200), CONST64(0x0000020000000202), CONST64(0x0000020200000202), 
+  CONST64(0x0002000000000000), CONST64(0x0002000200000000), CONST64(0x0002000000000002), CONST64(0x0002000200000002), 
+  CONST64(0x0002020000000000), CONST64(0x0002020200000000), CONST64(0x0002020000000002), CONST64(0x0002020200000002), 
+  CONST64(0x0002000000000200), CONST64(0x0002000200000200), CONST64(0x0002000000000202), CONST64(0x0002000200000202), 
+  CONST64(0x0002020000000200), CONST64(0x0002020200000200), CONST64(0x0002020000000202), CONST64(0x0002020200000202), 
+  CONST64(0x0000000000020000), CONST64(0x0000000200020000), CONST64(0x0000000000020002), CONST64(0x0000000200020002), 
+  CONST64(0x0000020000020000), CONST64(0x0000020200020000), CONST64(0x0000020000020002), CONST64(0x0000020200020002), 
+  CONST64(0x0000000000020200), CONST64(0x0000000200020200), CONST64(0x0000000000020202), CONST64(0x0000000200020202), 
+  CONST64(0x0000020000020200), CONST64(0x0000020200020200), CONST64(0x0000020000020202), CONST64(0x0000020200020202), 
+  CONST64(0x0002000000020000), CONST64(0x0002000200020000), CONST64(0x0002000000020002), CONST64(0x0002000200020002), 
+  CONST64(0x0002020000020000), CONST64(0x0002020200020000), CONST64(0x0002020000020002), CONST64(0x0002020200020002), 
+  CONST64(0x0002000000020200), CONST64(0x0002000200020200), CONST64(0x0002000000020202), CONST64(0x0002000200020202), 
+  CONST64(0x0002020000020200), CONST64(0x0002020200020200), CONST64(0x0002020000020202), CONST64(0x0002020200020202), 
+  CONST64(0x0200000000000000), CONST64(0x0200000200000000), CONST64(0x0200000000000002), CONST64(0x0200000200000002), 
+  CONST64(0x0200020000000000), CONST64(0x0200020200000000), CONST64(0x0200020000000002), CONST64(0x0200020200000002), 
+  CONST64(0x0200000000000200), CONST64(0x0200000200000200), CONST64(0x0200000000000202), CONST64(0x0200000200000202), 
+  CONST64(0x0200020000000200), CONST64(0x0200020200000200), CONST64(0x0200020000000202), CONST64(0x0200020200000202), 
+  CONST64(0x0202000000000000), CONST64(0x0202000200000000), CONST64(0x0202000000000002), CONST64(0x0202000200000002), 
+  CONST64(0x0202020000000000), CONST64(0x0202020200000000), CONST64(0x0202020000000002), CONST64(0x0202020200000002), 
+  CONST64(0x0202000000000200), CONST64(0x0202000200000200), CONST64(0x0202000000000202), CONST64(0x0202000200000202), 
+  CONST64(0x0202020000000200), CONST64(0x0202020200000200), CONST64(0x0202020000000202), CONST64(0x0202020200000202), 
+  CONST64(0x0200000000020000), CONST64(0x0200000200020000), CONST64(0x0200000000020002), CONST64(0x0200000200020002), 
+  CONST64(0x0200020000020000), CONST64(0x0200020200020000), CONST64(0x0200020000020002), CONST64(0x0200020200020002), 
+  CONST64(0x0200000000020200), CONST64(0x0200000200020200), CONST64(0x0200000000020202), CONST64(0x0200000200020202), 
+  CONST64(0x0200020000020200), CONST64(0x0200020200020200), CONST64(0x0200020000020202), CONST64(0x0200020200020202), 
+  CONST64(0x0202000000020000), CONST64(0x0202000200020000), CONST64(0x0202000000020002), CONST64(0x0202000200020002), 
+  CONST64(0x0202020000020000), CONST64(0x0202020200020000), CONST64(0x0202020000020002), CONST64(0x0202020200020002), 
+  CONST64(0x0202000000020200), CONST64(0x0202000200020200), CONST64(0x0202000000020202), CONST64(0x0202000200020202), 
+  CONST64(0x0202020000020200), CONST64(0x0202020200020200), CONST64(0x0202020000020202), CONST64(0x0202020200020202), 
+  CONST64(0x0000000002000000), CONST64(0x0000000202000000), CONST64(0x0000000002000002), CONST64(0x0000000202000002), 
+  CONST64(0x0000020002000000), CONST64(0x0000020202000000), CONST64(0x0000020002000002), CONST64(0x0000020202000002), 
+  CONST64(0x0000000002000200), CONST64(0x0000000202000200), CONST64(0x0000000002000202), CONST64(0x0000000202000202), 
+  CONST64(0x0000020002000200), CONST64(0x0000020202000200), CONST64(0x0000020002000202), CONST64(0x0000020202000202), 
+  CONST64(0x0002000002000000), CONST64(0x0002000202000000), CONST64(0x0002000002000002), CONST64(0x0002000202000002), 
+  CONST64(0x0002020002000000), CONST64(0x0002020202000000), CONST64(0x0002020002000002), CONST64(0x0002020202000002), 
+  CONST64(0x0002000002000200), CONST64(0x0002000202000200), CONST64(0x0002000002000202), CONST64(0x0002000202000202), 
+  CONST64(0x0002020002000200), CONST64(0x0002020202000200), CONST64(0x0002020002000202), CONST64(0x0002020202000202), 
+  CONST64(0x0000000002020000), CONST64(0x0000000202020000), CONST64(0x0000000002020002), CONST64(0x0000000202020002), 
+  CONST64(0x0000020002020000), CONST64(0x0000020202020000), CONST64(0x0000020002020002), CONST64(0x0000020202020002), 
+  CONST64(0x0000000002020200), CONST64(0x0000000202020200), CONST64(0x0000000002020202), CONST64(0x0000000202020202), 
+  CONST64(0x0000020002020200), CONST64(0x0000020202020200), CONST64(0x0000020002020202), CONST64(0x0000020202020202), 
+  CONST64(0x0002000002020000), CONST64(0x0002000202020000), CONST64(0x0002000002020002), CONST64(0x0002000202020002), 
+  CONST64(0x0002020002020000), CONST64(0x0002020202020000), CONST64(0x0002020002020002), CONST64(0x0002020202020002), 
+  CONST64(0x0002000002020200), CONST64(0x0002000202020200), CONST64(0x0002000002020202), CONST64(0x0002000202020202), 
+  CONST64(0x0002020002020200), CONST64(0x0002020202020200), CONST64(0x0002020002020202), CONST64(0x0002020202020202), 
+  CONST64(0x0200000002000000), CONST64(0x0200000202000000), CONST64(0x0200000002000002), CONST64(0x0200000202000002), 
+  CONST64(0x0200020002000000), CONST64(0x0200020202000000), CONST64(0x0200020002000002), CONST64(0x0200020202000002), 
+  CONST64(0x0200000002000200), CONST64(0x0200000202000200), CONST64(0x0200000002000202), CONST64(0x0200000202000202), 
+  CONST64(0x0200020002000200), CONST64(0x0200020202000200), CONST64(0x0200020002000202), CONST64(0x0200020202000202), 
+  CONST64(0x0202000002000000), CONST64(0x0202000202000000), CONST64(0x0202000002000002), CONST64(0x0202000202000002), 
+  CONST64(0x0202020002000000), CONST64(0x0202020202000000), CONST64(0x0202020002000002), CONST64(0x0202020202000002), 
+  CONST64(0x0202000002000200), CONST64(0x0202000202000200), CONST64(0x0202000002000202), CONST64(0x0202000202000202), 
+  CONST64(0x0202020002000200), CONST64(0x0202020202000200), CONST64(0x0202020002000202), CONST64(0x0202020202000202), 
+  CONST64(0x0200000002020000), CONST64(0x0200000202020000), CONST64(0x0200000002020002), CONST64(0x0200000202020002), 
+  CONST64(0x0200020002020000), CONST64(0x0200020202020000), CONST64(0x0200020002020002), CONST64(0x0200020202020002), 
+  CONST64(0x0200000002020200), CONST64(0x0200000202020200), CONST64(0x0200000002020202), CONST64(0x0200000202020202), 
+  CONST64(0x0200020002020200), CONST64(0x0200020202020200), CONST64(0x0200020002020202), CONST64(0x0200020202020202), 
+  CONST64(0x0202000002020000), CONST64(0x0202000202020000), CONST64(0x0202000002020002), CONST64(0x0202000202020002), 
+  CONST64(0x0202020002020000), CONST64(0x0202020202020000), CONST64(0x0202020002020002), CONST64(0x0202020202020002), 
+  CONST64(0x0202000002020200), CONST64(0x0202000202020200), CONST64(0x0202000002020202), CONST64(0x0202000202020202), 
+  CONST64(0x0202020002020200), CONST64(0x0202020202020200), CONST64(0x0202020002020202), CONST64(0x0202020202020202)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000010000000000), CONST64(0x0000000000000100), CONST64(0x0000010000000100), 
+  CONST64(0x0001000000000000), CONST64(0x0001010000000000), CONST64(0x0001000000000100), CONST64(0x0001010000000100), 
+  CONST64(0x0000000000010000), CONST64(0x0000010000010000), CONST64(0x0000000000010100), CONST64(0x0000010000010100), 
+  CONST64(0x0001000000010000), CONST64(0x0001010000010000), CONST64(0x0001000000010100), CONST64(0x0001010000010100), 
+  CONST64(0x0100000000000000), CONST64(0x0100010000000000), CONST64(0x0100000000000100), CONST64(0x0100010000000100), 
+  CONST64(0x0101000000000000), CONST64(0x0101010000000000), CONST64(0x0101000000000100), CONST64(0x0101010000000100), 
+  CONST64(0x0100000000010000), CONST64(0x0100010000010000), CONST64(0x0100000000010100), CONST64(0x0100010000010100), 
+  CONST64(0x0101000000010000), CONST64(0x0101010000010000), CONST64(0x0101000000010100), CONST64(0x0101010000010100), 
+  CONST64(0x0000000001000000), CONST64(0x0000010001000000), CONST64(0x0000000001000100), CONST64(0x0000010001000100), 
+  CONST64(0x0001000001000000), CONST64(0x0001010001000000), CONST64(0x0001000001000100), CONST64(0x0001010001000100), 
+  CONST64(0x0000000001010000), CONST64(0x0000010001010000), CONST64(0x0000000001010100), CONST64(0x0000010001010100), 
+  CONST64(0x0001000001010000), CONST64(0x0001010001010000), CONST64(0x0001000001010100), CONST64(0x0001010001010100), 
+  CONST64(0x0100000001000000), CONST64(0x0100010001000000), CONST64(0x0100000001000100), CONST64(0x0100010001000100), 
+  CONST64(0x0101000001000000), CONST64(0x0101010001000000), CONST64(0x0101000001000100), CONST64(0x0101010001000100), 
+  CONST64(0x0100000001010000), CONST64(0x0100010001010000), CONST64(0x0100000001010100), CONST64(0x0100010001010100), 
+  CONST64(0x0101000001010000), CONST64(0x0101010001010000), CONST64(0x0101000001010100), CONST64(0x0101010001010100), 
+  CONST64(0x0000000100000000), CONST64(0x0000010100000000), CONST64(0x0000000100000100), CONST64(0x0000010100000100), 
+  CONST64(0x0001000100000000), CONST64(0x0001010100000000), CONST64(0x0001000100000100), CONST64(0x0001010100000100), 
+  CONST64(0x0000000100010000), CONST64(0x0000010100010000), CONST64(0x0000000100010100), CONST64(0x0000010100010100), 
+  CONST64(0x0001000100010000), CONST64(0x0001010100010000), CONST64(0x0001000100010100), CONST64(0x0001010100010100), 
+  CONST64(0x0100000100000000), CONST64(0x0100010100000000), CONST64(0x0100000100000100), CONST64(0x0100010100000100), 
+  CONST64(0x0101000100000000), CONST64(0x0101010100000000), CONST64(0x0101000100000100), CONST64(0x0101010100000100), 
+  CONST64(0x0100000100010000), CONST64(0x0100010100010000), CONST64(0x0100000100010100), CONST64(0x0100010100010100), 
+  CONST64(0x0101000100010000), CONST64(0x0101010100010000), CONST64(0x0101000100010100), CONST64(0x0101010100010100), 
+  CONST64(0x0000000101000000), CONST64(0x0000010101000000), CONST64(0x0000000101000100), CONST64(0x0000010101000100), 
+  CONST64(0x0001000101000000), CONST64(0x0001010101000000), CONST64(0x0001000101000100), CONST64(0x0001010101000100), 
+  CONST64(0x0000000101010000), CONST64(0x0000010101010000), CONST64(0x0000000101010100), CONST64(0x0000010101010100), 
+  CONST64(0x0001000101010000), CONST64(0x0001010101010000), CONST64(0x0001000101010100), CONST64(0x0001010101010100), 
+  CONST64(0x0100000101000000), CONST64(0x0100010101000000), CONST64(0x0100000101000100), CONST64(0x0100010101000100), 
+  CONST64(0x0101000101000000), CONST64(0x0101010101000000), CONST64(0x0101000101000100), CONST64(0x0101010101000100), 
+  CONST64(0x0100000101010000), CONST64(0x0100010101010000), CONST64(0x0100000101010100), CONST64(0x0100010101010100), 
+  CONST64(0x0101000101010000), CONST64(0x0101010101010000), CONST64(0x0101000101010100), CONST64(0x0101010101010100), 
+  CONST64(0x0000000000000001), CONST64(0x0000010000000001), CONST64(0x0000000000000101), CONST64(0x0000010000000101), 
+  CONST64(0x0001000000000001), CONST64(0x0001010000000001), CONST64(0x0001000000000101), CONST64(0x0001010000000101), 
+  CONST64(0x0000000000010001), CONST64(0x0000010000010001), CONST64(0x0000000000010101), CONST64(0x0000010000010101), 
+  CONST64(0x0001000000010001), CONST64(0x0001010000010001), CONST64(0x0001000000010101), CONST64(0x0001010000010101), 
+  CONST64(0x0100000000000001), CONST64(0x0100010000000001), CONST64(0x0100000000000101), CONST64(0x0100010000000101), 
+  CONST64(0x0101000000000001), CONST64(0x0101010000000001), CONST64(0x0101000000000101), CONST64(0x0101010000000101), 
+  CONST64(0x0100000000010001), CONST64(0x0100010000010001), CONST64(0x0100000000010101), CONST64(0x0100010000010101), 
+  CONST64(0x0101000000010001), CONST64(0x0101010000010001), CONST64(0x0101000000010101), CONST64(0x0101010000010101), 
+  CONST64(0x0000000001000001), CONST64(0x0000010001000001), CONST64(0x0000000001000101), CONST64(0x0000010001000101), 
+  CONST64(0x0001000001000001), CONST64(0x0001010001000001), CONST64(0x0001000001000101), CONST64(0x0001010001000101), 
+  CONST64(0x0000000001010001), CONST64(0x0000010001010001), CONST64(0x0000000001010101), CONST64(0x0000010001010101), 
+  CONST64(0x0001000001010001), CONST64(0x0001010001010001), CONST64(0x0001000001010101), CONST64(0x0001010001010101), 
+  CONST64(0x0100000001000001), CONST64(0x0100010001000001), CONST64(0x0100000001000101), CONST64(0x0100010001000101), 
+  CONST64(0x0101000001000001), CONST64(0x0101010001000001), CONST64(0x0101000001000101), CONST64(0x0101010001000101), 
+  CONST64(0x0100000001010001), CONST64(0x0100010001010001), CONST64(0x0100000001010101), CONST64(0x0100010001010101), 
+  CONST64(0x0101000001010001), CONST64(0x0101010001010001), CONST64(0x0101000001010101), CONST64(0x0101010001010101), 
+  CONST64(0x0000000100000001), CONST64(0x0000010100000001), CONST64(0x0000000100000101), CONST64(0x0000010100000101), 
+  CONST64(0x0001000100000001), CONST64(0x0001010100000001), CONST64(0x0001000100000101), CONST64(0x0001010100000101), 
+  CONST64(0x0000000100010001), CONST64(0x0000010100010001), CONST64(0x0000000100010101), CONST64(0x0000010100010101), 
+  CONST64(0x0001000100010001), CONST64(0x0001010100010001), CONST64(0x0001000100010101), CONST64(0x0001010100010101), 
+  CONST64(0x0100000100000001), CONST64(0x0100010100000001), CONST64(0x0100000100000101), CONST64(0x0100010100000101), 
+  CONST64(0x0101000100000001), CONST64(0x0101010100000001), CONST64(0x0101000100000101), CONST64(0x0101010100000101), 
+  CONST64(0x0100000100010001), CONST64(0x0100010100010001), CONST64(0x0100000100010101), CONST64(0x0100010100010101), 
+  CONST64(0x0101000100010001), CONST64(0x0101010100010001), CONST64(0x0101000100010101), CONST64(0x0101010100010101), 
+  CONST64(0x0000000101000001), CONST64(0x0000010101000001), CONST64(0x0000000101000101), CONST64(0x0000010101000101), 
+  CONST64(0x0001000101000001), CONST64(0x0001010101000001), CONST64(0x0001000101000101), CONST64(0x0001010101000101), 
+  CONST64(0x0000000101010001), CONST64(0x0000010101010001), CONST64(0x0000000101010101), CONST64(0x0000010101010101), 
+  CONST64(0x0001000101010001), CONST64(0x0001010101010001), CONST64(0x0001000101010101), CONST64(0x0001010101010101), 
+  CONST64(0x0100000101000001), CONST64(0x0100010101000001), CONST64(0x0100000101000101), CONST64(0x0100010101000101), 
+  CONST64(0x0101000101000001), CONST64(0x0101010101000001), CONST64(0x0101000101000101), CONST64(0x0101010101000101), 
+  CONST64(0x0100000101010001), CONST64(0x0100010101010001), CONST64(0x0100000101010101), CONST64(0x0100010101010101), 
+  CONST64(0x0101000101010001), CONST64(0x0101010101010001), CONST64(0x0101000101010101), CONST64(0x0101010101010101)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000000000080), CONST64(0x0000008000000080), 
+  CONST64(0x0000800000000000), CONST64(0x0000808000000000), CONST64(0x0000800000000080), CONST64(0x0000808000000080), 
+  CONST64(0x0000000000008000), CONST64(0x0000008000008000), CONST64(0x0000000000008080), CONST64(0x0000008000008080), 
+  CONST64(0x0000800000008000), CONST64(0x0000808000008000), CONST64(0x0000800000008080), CONST64(0x0000808000008080), 
+  CONST64(0x0080000000000000), CONST64(0x0080008000000000), CONST64(0x0080000000000080), CONST64(0x0080008000000080), 
+  CONST64(0x0080800000000000), CONST64(0x0080808000000000), CONST64(0x0080800000000080), CONST64(0x0080808000000080), 
+  CONST64(0x0080000000008000), CONST64(0x0080008000008000), CONST64(0x0080000000008080), CONST64(0x0080008000008080), 
+  CONST64(0x0080800000008000), CONST64(0x0080808000008000), CONST64(0x0080800000008080), CONST64(0x0080808000008080), 
+  CONST64(0x0000000000800000), CONST64(0x0000008000800000), CONST64(0x0000000000800080), CONST64(0x0000008000800080), 
+  CONST64(0x0000800000800000), CONST64(0x0000808000800000), CONST64(0x0000800000800080), CONST64(0x0000808000800080), 
+  CONST64(0x0000000000808000), CONST64(0x0000008000808000), CONST64(0x0000000000808080), CONST64(0x0000008000808080), 
+  CONST64(0x0000800000808000), CONST64(0x0000808000808000), CONST64(0x0000800000808080), CONST64(0x0000808000808080), 
+  CONST64(0x0080000000800000), CONST64(0x0080008000800000), CONST64(0x0080000000800080), CONST64(0x0080008000800080), 
+  CONST64(0x0080800000800000), CONST64(0x0080808000800000), CONST64(0x0080800000800080), CONST64(0x0080808000800080), 
+  CONST64(0x0080000000808000), CONST64(0x0080008000808000), CONST64(0x0080000000808080), CONST64(0x0080008000808080), 
+  CONST64(0x0080800000808000), CONST64(0x0080808000808000), CONST64(0x0080800000808080), CONST64(0x0080808000808080), 
+  CONST64(0x8000000000000000), CONST64(0x8000008000000000), CONST64(0x8000000000000080), CONST64(0x8000008000000080), 
+  CONST64(0x8000800000000000), CONST64(0x8000808000000000), CONST64(0x8000800000000080), CONST64(0x8000808000000080), 
+  CONST64(0x8000000000008000), CONST64(0x8000008000008000), CONST64(0x8000000000008080), CONST64(0x8000008000008080), 
+  CONST64(0x8000800000008000), CONST64(0x8000808000008000), CONST64(0x8000800000008080), CONST64(0x8000808000008080), 
+  CONST64(0x8080000000000000), CONST64(0x8080008000000000), CONST64(0x8080000000000080), CONST64(0x8080008000000080), 
+  CONST64(0x8080800000000000), CONST64(0x8080808000000000), CONST64(0x8080800000000080), CONST64(0x8080808000000080), 
+  CONST64(0x8080000000008000), CONST64(0x8080008000008000), CONST64(0x8080000000008080), CONST64(0x8080008000008080), 
+  CONST64(0x8080800000008000), CONST64(0x8080808000008000), CONST64(0x8080800000008080), CONST64(0x8080808000008080), 
+  CONST64(0x8000000000800000), CONST64(0x8000008000800000), CONST64(0x8000000000800080), CONST64(0x8000008000800080), 
+  CONST64(0x8000800000800000), CONST64(0x8000808000800000), CONST64(0x8000800000800080), CONST64(0x8000808000800080), 
+  CONST64(0x8000000000808000), CONST64(0x8000008000808000), CONST64(0x8000000000808080), CONST64(0x8000008000808080), 
+  CONST64(0x8000800000808000), CONST64(0x8000808000808000), CONST64(0x8000800000808080), CONST64(0x8000808000808080), 
+  CONST64(0x8080000000800000), CONST64(0x8080008000800000), CONST64(0x8080000000800080), CONST64(0x8080008000800080), 
+  CONST64(0x8080800000800000), CONST64(0x8080808000800000), CONST64(0x8080800000800080), CONST64(0x8080808000800080), 
+  CONST64(0x8080000000808000), CONST64(0x8080008000808000), CONST64(0x8080000000808080), CONST64(0x8080008000808080), 
+  CONST64(0x8080800000808000), CONST64(0x8080808000808000), CONST64(0x8080800000808080), CONST64(0x8080808000808080), 
+  CONST64(0x0000000080000000), CONST64(0x0000008080000000), CONST64(0x0000000080000080), CONST64(0x0000008080000080), 
+  CONST64(0x0000800080000000), CONST64(0x0000808080000000), CONST64(0x0000800080000080), CONST64(0x0000808080000080), 
+  CONST64(0x0000000080008000), CONST64(0x0000008080008000), CONST64(0x0000000080008080), CONST64(0x0000008080008080), 
+  CONST64(0x0000800080008000), CONST64(0x0000808080008000), CONST64(0x0000800080008080), CONST64(0x0000808080008080), 
+  CONST64(0x0080000080000000), CONST64(0x0080008080000000), CONST64(0x0080000080000080), CONST64(0x0080008080000080), 
+  CONST64(0x0080800080000000), CONST64(0x0080808080000000), CONST64(0x0080800080000080), CONST64(0x0080808080000080), 
+  CONST64(0x0080000080008000), CONST64(0x0080008080008000), CONST64(0x0080000080008080), CONST64(0x0080008080008080), 
+  CONST64(0x0080800080008000), CONST64(0x0080808080008000), CONST64(0x0080800080008080), CONST64(0x0080808080008080), 
+  CONST64(0x0000000080800000), CONST64(0x0000008080800000), CONST64(0x0000000080800080), CONST64(0x0000008080800080), 
+  CONST64(0x0000800080800000), CONST64(0x0000808080800000), CONST64(0x0000800080800080), CONST64(0x0000808080800080), 
+  CONST64(0x0000000080808000), CONST64(0x0000008080808000), CONST64(0x0000000080808080), CONST64(0x0000008080808080), 
+  CONST64(0x0000800080808000), CONST64(0x0000808080808000), CONST64(0x0000800080808080), CONST64(0x0000808080808080), 
+  CONST64(0x0080000080800000), CONST64(0x0080008080800000), CONST64(0x0080000080800080), CONST64(0x0080008080800080), 
+  CONST64(0x0080800080800000), CONST64(0x0080808080800000), CONST64(0x0080800080800080), CONST64(0x0080808080800080), 
+  CONST64(0x0080000080808000), CONST64(0x0080008080808000), CONST64(0x0080000080808080), CONST64(0x0080008080808080), 
+  CONST64(0x0080800080808000), CONST64(0x0080808080808000), CONST64(0x0080800080808080), CONST64(0x0080808080808080), 
+  CONST64(0x8000000080000000), CONST64(0x8000008080000000), CONST64(0x8000000080000080), CONST64(0x8000008080000080), 
+  CONST64(0x8000800080000000), CONST64(0x8000808080000000), CONST64(0x8000800080000080), CONST64(0x8000808080000080), 
+  CONST64(0x8000000080008000), CONST64(0x8000008080008000), CONST64(0x8000000080008080), CONST64(0x8000008080008080), 
+  CONST64(0x8000800080008000), CONST64(0x8000808080008000), CONST64(0x8000800080008080), CONST64(0x8000808080008080), 
+  CONST64(0x8080000080000000), CONST64(0x8080008080000000), CONST64(0x8080000080000080), CONST64(0x8080008080000080), 
+  CONST64(0x8080800080000000), CONST64(0x8080808080000000), CONST64(0x8080800080000080), CONST64(0x8080808080000080), 
+  CONST64(0x8080000080008000), CONST64(0x8080008080008000), CONST64(0x8080000080008080), CONST64(0x8080008080008080), 
+  CONST64(0x8080800080008000), CONST64(0x8080808080008000), CONST64(0x8080800080008080), CONST64(0x8080808080008080), 
+  CONST64(0x8000000080800000), CONST64(0x8000008080800000), CONST64(0x8000000080800080), CONST64(0x8000008080800080), 
+  CONST64(0x8000800080800000), CONST64(0x8000808080800000), CONST64(0x8000800080800080), CONST64(0x8000808080800080), 
+  CONST64(0x8000000080808000), CONST64(0x8000008080808000), CONST64(0x8000000080808080), CONST64(0x8000008080808080), 
+  CONST64(0x8000800080808000), CONST64(0x8000808080808000), CONST64(0x8000800080808080), CONST64(0x8000808080808080), 
+  CONST64(0x8080000080800000), CONST64(0x8080008080800000), CONST64(0x8080000080800080), CONST64(0x8080008080800080), 
+  CONST64(0x8080800080800000), CONST64(0x8080808080800000), CONST64(0x8080800080800080), CONST64(0x8080808080800080), 
+  CONST64(0x8080000080808000), CONST64(0x8080008080808000), CONST64(0x8080000080808080), CONST64(0x8080008080808080), 
+  CONST64(0x8080800080808000), CONST64(0x8080808080808000), CONST64(0x8080800080808080), CONST64(0x8080808080808080)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000000000040), CONST64(0x0000004000000040), 
+  CONST64(0x0000400000000000), CONST64(0x0000404000000000), CONST64(0x0000400000000040), CONST64(0x0000404000000040), 
+  CONST64(0x0000000000004000), CONST64(0x0000004000004000), CONST64(0x0000000000004040), CONST64(0x0000004000004040), 
+  CONST64(0x0000400000004000), CONST64(0x0000404000004000), CONST64(0x0000400000004040), CONST64(0x0000404000004040), 
+  CONST64(0x0040000000000000), CONST64(0x0040004000000000), CONST64(0x0040000000000040), CONST64(0x0040004000000040), 
+  CONST64(0x0040400000000000), CONST64(0x0040404000000000), CONST64(0x0040400000000040), CONST64(0x0040404000000040), 
+  CONST64(0x0040000000004000), CONST64(0x0040004000004000), CONST64(0x0040000000004040), CONST64(0x0040004000004040), 
+  CONST64(0x0040400000004000), CONST64(0x0040404000004000), CONST64(0x0040400000004040), CONST64(0x0040404000004040), 
+  CONST64(0x0000000000400000), CONST64(0x0000004000400000), CONST64(0x0000000000400040), CONST64(0x0000004000400040), 
+  CONST64(0x0000400000400000), CONST64(0x0000404000400000), CONST64(0x0000400000400040), CONST64(0x0000404000400040), 
+  CONST64(0x0000000000404000), CONST64(0x0000004000404000), CONST64(0x0000000000404040), CONST64(0x0000004000404040), 
+  CONST64(0x0000400000404000), CONST64(0x0000404000404000), CONST64(0x0000400000404040), CONST64(0x0000404000404040), 
+  CONST64(0x0040000000400000), CONST64(0x0040004000400000), CONST64(0x0040000000400040), CONST64(0x0040004000400040), 
+  CONST64(0x0040400000400000), CONST64(0x0040404000400000), CONST64(0x0040400000400040), CONST64(0x0040404000400040), 
+  CONST64(0x0040000000404000), CONST64(0x0040004000404000), CONST64(0x0040000000404040), CONST64(0x0040004000404040), 
+  CONST64(0x0040400000404000), CONST64(0x0040404000404000), CONST64(0x0040400000404040), CONST64(0x0040404000404040), 
+  CONST64(0x4000000000000000), CONST64(0x4000004000000000), CONST64(0x4000000000000040), CONST64(0x4000004000000040), 
+  CONST64(0x4000400000000000), CONST64(0x4000404000000000), CONST64(0x4000400000000040), CONST64(0x4000404000000040), 
+  CONST64(0x4000000000004000), CONST64(0x4000004000004000), CONST64(0x4000000000004040), CONST64(0x4000004000004040), 
+  CONST64(0x4000400000004000), CONST64(0x4000404000004000), CONST64(0x4000400000004040), CONST64(0x4000404000004040), 
+  CONST64(0x4040000000000000), CONST64(0x4040004000000000), CONST64(0x4040000000000040), CONST64(0x4040004000000040), 
+  CONST64(0x4040400000000000), CONST64(0x4040404000000000), CONST64(0x4040400000000040), CONST64(0x4040404000000040), 
+  CONST64(0x4040000000004000), CONST64(0x4040004000004000), CONST64(0x4040000000004040), CONST64(0x4040004000004040), 
+  CONST64(0x4040400000004000), CONST64(0x4040404000004000), CONST64(0x4040400000004040), CONST64(0x4040404000004040), 
+  CONST64(0x4000000000400000), CONST64(0x4000004000400000), CONST64(0x4000000000400040), CONST64(0x4000004000400040), 
+  CONST64(0x4000400000400000), CONST64(0x4000404000400000), CONST64(0x4000400000400040), CONST64(0x4000404000400040), 
+  CONST64(0x4000000000404000), CONST64(0x4000004000404000), CONST64(0x4000000000404040), CONST64(0x4000004000404040), 
+  CONST64(0x4000400000404000), CONST64(0x4000404000404000), CONST64(0x4000400000404040), CONST64(0x4000404000404040), 
+  CONST64(0x4040000000400000), CONST64(0x4040004000400000), CONST64(0x4040000000400040), CONST64(0x4040004000400040), 
+  CONST64(0x4040400000400000), CONST64(0x4040404000400000), CONST64(0x4040400000400040), CONST64(0x4040404000400040), 
+  CONST64(0x4040000000404000), CONST64(0x4040004000404000), CONST64(0x4040000000404040), CONST64(0x4040004000404040), 
+  CONST64(0x4040400000404000), CONST64(0x4040404000404000), CONST64(0x4040400000404040), CONST64(0x4040404000404040), 
+  CONST64(0x0000000040000000), CONST64(0x0000004040000000), CONST64(0x0000000040000040), CONST64(0x0000004040000040), 
+  CONST64(0x0000400040000000), CONST64(0x0000404040000000), CONST64(0x0000400040000040), CONST64(0x0000404040000040), 
+  CONST64(0x0000000040004000), CONST64(0x0000004040004000), CONST64(0x0000000040004040), CONST64(0x0000004040004040), 
+  CONST64(0x0000400040004000), CONST64(0x0000404040004000), CONST64(0x0000400040004040), CONST64(0x0000404040004040), 
+  CONST64(0x0040000040000000), CONST64(0x0040004040000000), CONST64(0x0040000040000040), CONST64(0x0040004040000040), 
+  CONST64(0x0040400040000000), CONST64(0x0040404040000000), CONST64(0x0040400040000040), CONST64(0x0040404040000040), 
+  CONST64(0x0040000040004000), CONST64(0x0040004040004000), CONST64(0x0040000040004040), CONST64(0x0040004040004040), 
+  CONST64(0x0040400040004000), CONST64(0x0040404040004000), CONST64(0x0040400040004040), CONST64(0x0040404040004040), 
+  CONST64(0x0000000040400000), CONST64(0x0000004040400000), CONST64(0x0000000040400040), CONST64(0x0000004040400040), 
+  CONST64(0x0000400040400000), CONST64(0x0000404040400000), CONST64(0x0000400040400040), CONST64(0x0000404040400040), 
+  CONST64(0x0000000040404000), CONST64(0x0000004040404000), CONST64(0x0000000040404040), CONST64(0x0000004040404040), 
+  CONST64(0x0000400040404000), CONST64(0x0000404040404000), CONST64(0x0000400040404040), CONST64(0x0000404040404040), 
+  CONST64(0x0040000040400000), CONST64(0x0040004040400000), CONST64(0x0040000040400040), CONST64(0x0040004040400040), 
+  CONST64(0x0040400040400000), CONST64(0x0040404040400000), CONST64(0x0040400040400040), CONST64(0x0040404040400040), 
+  CONST64(0x0040000040404000), CONST64(0x0040004040404000), CONST64(0x0040000040404040), CONST64(0x0040004040404040), 
+  CONST64(0x0040400040404000), CONST64(0x0040404040404000), CONST64(0x0040400040404040), CONST64(0x0040404040404040), 
+  CONST64(0x4000000040000000), CONST64(0x4000004040000000), CONST64(0x4000000040000040), CONST64(0x4000004040000040), 
+  CONST64(0x4000400040000000), CONST64(0x4000404040000000), CONST64(0x4000400040000040), CONST64(0x4000404040000040), 
+  CONST64(0x4000000040004000), CONST64(0x4000004040004000), CONST64(0x4000000040004040), CONST64(0x4000004040004040), 
+  CONST64(0x4000400040004000), CONST64(0x4000404040004000), CONST64(0x4000400040004040), CONST64(0x4000404040004040), 
+  CONST64(0x4040000040000000), CONST64(0x4040004040000000), CONST64(0x4040000040000040), CONST64(0x4040004040000040), 
+  CONST64(0x4040400040000000), CONST64(0x4040404040000000), CONST64(0x4040400040000040), CONST64(0x4040404040000040), 
+  CONST64(0x4040000040004000), CONST64(0x4040004040004000), CONST64(0x4040000040004040), CONST64(0x4040004040004040), 
+  CONST64(0x4040400040004000), CONST64(0x4040404040004000), CONST64(0x4040400040004040), CONST64(0x4040404040004040), 
+  CONST64(0x4000000040400000), CONST64(0x4000004040400000), CONST64(0x4000000040400040), CONST64(0x4000004040400040), 
+  CONST64(0x4000400040400000), CONST64(0x4000404040400000), CONST64(0x4000400040400040), CONST64(0x4000404040400040), 
+  CONST64(0x4000000040404000), CONST64(0x4000004040404000), CONST64(0x4000000040404040), CONST64(0x4000004040404040), 
+  CONST64(0x4000400040404000), CONST64(0x4000404040404000), CONST64(0x4000400040404040), CONST64(0x4000404040404040), 
+  CONST64(0x4040000040400000), CONST64(0x4040004040400000), CONST64(0x4040000040400040), CONST64(0x4040004040400040), 
+  CONST64(0x4040400040400000), CONST64(0x4040404040400000), CONST64(0x4040400040400040), CONST64(0x4040404040400040), 
+  CONST64(0x4040000040404000), CONST64(0x4040004040404000), CONST64(0x4040000040404040), CONST64(0x4040004040404040), 
+  CONST64(0x4040400040404000), CONST64(0x4040404040404000), CONST64(0x4040400040404040), CONST64(0x4040404040404040)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000000000020), CONST64(0x0000002000000020), 
+  CONST64(0x0000200000000000), CONST64(0x0000202000000000), CONST64(0x0000200000000020), CONST64(0x0000202000000020), 
+  CONST64(0x0000000000002000), CONST64(0x0000002000002000), CONST64(0x0000000000002020), CONST64(0x0000002000002020), 
+  CONST64(0x0000200000002000), CONST64(0x0000202000002000), CONST64(0x0000200000002020), CONST64(0x0000202000002020), 
+  CONST64(0x0020000000000000), CONST64(0x0020002000000000), CONST64(0x0020000000000020), CONST64(0x0020002000000020), 
+  CONST64(0x0020200000000000), CONST64(0x0020202000000000), CONST64(0x0020200000000020), CONST64(0x0020202000000020), 
+  CONST64(0x0020000000002000), CONST64(0x0020002000002000), CONST64(0x0020000000002020), CONST64(0x0020002000002020), 
+  CONST64(0x0020200000002000), CONST64(0x0020202000002000), CONST64(0x0020200000002020), CONST64(0x0020202000002020), 
+  CONST64(0x0000000000200000), CONST64(0x0000002000200000), CONST64(0x0000000000200020), CONST64(0x0000002000200020), 
+  CONST64(0x0000200000200000), CONST64(0x0000202000200000), CONST64(0x0000200000200020), CONST64(0x0000202000200020), 
+  CONST64(0x0000000000202000), CONST64(0x0000002000202000), CONST64(0x0000000000202020), CONST64(0x0000002000202020), 
+  CONST64(0x0000200000202000), CONST64(0x0000202000202000), CONST64(0x0000200000202020), CONST64(0x0000202000202020), 
+  CONST64(0x0020000000200000), CONST64(0x0020002000200000), CONST64(0x0020000000200020), CONST64(0x0020002000200020), 
+  CONST64(0x0020200000200000), CONST64(0x0020202000200000), CONST64(0x0020200000200020), CONST64(0x0020202000200020), 
+  CONST64(0x0020000000202000), CONST64(0x0020002000202000), CONST64(0x0020000000202020), CONST64(0x0020002000202020), 
+  CONST64(0x0020200000202000), CONST64(0x0020202000202000), CONST64(0x0020200000202020), CONST64(0x0020202000202020), 
+  CONST64(0x2000000000000000), CONST64(0x2000002000000000), CONST64(0x2000000000000020), CONST64(0x2000002000000020), 
+  CONST64(0x2000200000000000), CONST64(0x2000202000000000), CONST64(0x2000200000000020), CONST64(0x2000202000000020), 
+  CONST64(0x2000000000002000), CONST64(0x2000002000002000), CONST64(0x2000000000002020), CONST64(0x2000002000002020), 
+  CONST64(0x2000200000002000), CONST64(0x2000202000002000), CONST64(0x2000200000002020), CONST64(0x2000202000002020), 
+  CONST64(0x2020000000000000), CONST64(0x2020002000000000), CONST64(0x2020000000000020), CONST64(0x2020002000000020), 
+  CONST64(0x2020200000000000), CONST64(0x2020202000000000), CONST64(0x2020200000000020), CONST64(0x2020202000000020), 
+  CONST64(0x2020000000002000), CONST64(0x2020002000002000), CONST64(0x2020000000002020), CONST64(0x2020002000002020), 
+  CONST64(0x2020200000002000), CONST64(0x2020202000002000), CONST64(0x2020200000002020), CONST64(0x2020202000002020), 
+  CONST64(0x2000000000200000), CONST64(0x2000002000200000), CONST64(0x2000000000200020), CONST64(0x2000002000200020), 
+  CONST64(0x2000200000200000), CONST64(0x2000202000200000), CONST64(0x2000200000200020), CONST64(0x2000202000200020), 
+  CONST64(0x2000000000202000), CONST64(0x2000002000202000), CONST64(0x2000000000202020), CONST64(0x2000002000202020), 
+  CONST64(0x2000200000202000), CONST64(0x2000202000202000), CONST64(0x2000200000202020), CONST64(0x2000202000202020), 
+  CONST64(0x2020000000200000), CONST64(0x2020002000200000), CONST64(0x2020000000200020), CONST64(0x2020002000200020), 
+  CONST64(0x2020200000200000), CONST64(0x2020202000200000), CONST64(0x2020200000200020), CONST64(0x2020202000200020), 
+  CONST64(0x2020000000202000), CONST64(0x2020002000202000), CONST64(0x2020000000202020), CONST64(0x2020002000202020), 
+  CONST64(0x2020200000202000), CONST64(0x2020202000202000), CONST64(0x2020200000202020), CONST64(0x2020202000202020), 
+  CONST64(0x0000000020000000), CONST64(0x0000002020000000), CONST64(0x0000000020000020), CONST64(0x0000002020000020), 
+  CONST64(0x0000200020000000), CONST64(0x0000202020000000), CONST64(0x0000200020000020), CONST64(0x0000202020000020), 
+  CONST64(0x0000000020002000), CONST64(0x0000002020002000), CONST64(0x0000000020002020), CONST64(0x0000002020002020), 
+  CONST64(0x0000200020002000), CONST64(0x0000202020002000), CONST64(0x0000200020002020), CONST64(0x0000202020002020), 
+  CONST64(0x0020000020000000), CONST64(0x0020002020000000), CONST64(0x0020000020000020), CONST64(0x0020002020000020), 
+  CONST64(0x0020200020000000), CONST64(0x0020202020000000), CONST64(0x0020200020000020), CONST64(0x0020202020000020), 
+  CONST64(0x0020000020002000), CONST64(0x0020002020002000), CONST64(0x0020000020002020), CONST64(0x0020002020002020), 
+  CONST64(0x0020200020002000), CONST64(0x0020202020002000), CONST64(0x0020200020002020), CONST64(0x0020202020002020), 
+  CONST64(0x0000000020200000), CONST64(0x0000002020200000), CONST64(0x0000000020200020), CONST64(0x0000002020200020), 
+  CONST64(0x0000200020200000), CONST64(0x0000202020200000), CONST64(0x0000200020200020), CONST64(0x0000202020200020), 
+  CONST64(0x0000000020202000), CONST64(0x0000002020202000), CONST64(0x0000000020202020), CONST64(0x0000002020202020), 
+  CONST64(0x0000200020202000), CONST64(0x0000202020202000), CONST64(0x0000200020202020), CONST64(0x0000202020202020), 
+  CONST64(0x0020000020200000), CONST64(0x0020002020200000), CONST64(0x0020000020200020), CONST64(0x0020002020200020), 
+  CONST64(0x0020200020200000), CONST64(0x0020202020200000), CONST64(0x0020200020200020), CONST64(0x0020202020200020), 
+  CONST64(0x0020000020202000), CONST64(0x0020002020202000), CONST64(0x0020000020202020), CONST64(0x0020002020202020), 
+  CONST64(0x0020200020202000), CONST64(0x0020202020202000), CONST64(0x0020200020202020), CONST64(0x0020202020202020), 
+  CONST64(0x2000000020000000), CONST64(0x2000002020000000), CONST64(0x2000000020000020), CONST64(0x2000002020000020), 
+  CONST64(0x2000200020000000), CONST64(0x2000202020000000), CONST64(0x2000200020000020), CONST64(0x2000202020000020), 
+  CONST64(0x2000000020002000), CONST64(0x2000002020002000), CONST64(0x2000000020002020), CONST64(0x2000002020002020), 
+  CONST64(0x2000200020002000), CONST64(0x2000202020002000), CONST64(0x2000200020002020), CONST64(0x2000202020002020), 
+  CONST64(0x2020000020000000), CONST64(0x2020002020000000), CONST64(0x2020000020000020), CONST64(0x2020002020000020), 
+  CONST64(0x2020200020000000), CONST64(0x2020202020000000), CONST64(0x2020200020000020), CONST64(0x2020202020000020), 
+  CONST64(0x2020000020002000), CONST64(0x2020002020002000), CONST64(0x2020000020002020), CONST64(0x2020002020002020), 
+  CONST64(0x2020200020002000), CONST64(0x2020202020002000), CONST64(0x2020200020002020), CONST64(0x2020202020002020), 
+  CONST64(0x2000000020200000), CONST64(0x2000002020200000), CONST64(0x2000000020200020), CONST64(0x2000002020200020), 
+  CONST64(0x2000200020200000), CONST64(0x2000202020200000), CONST64(0x2000200020200020), CONST64(0x2000202020200020), 
+  CONST64(0x2000000020202000), CONST64(0x2000002020202000), CONST64(0x2000000020202020), CONST64(0x2000002020202020), 
+  CONST64(0x2000200020202000), CONST64(0x2000202020202000), CONST64(0x2000200020202020), CONST64(0x2000202020202020), 
+  CONST64(0x2020000020200000), CONST64(0x2020002020200000), CONST64(0x2020000020200020), CONST64(0x2020002020200020), 
+  CONST64(0x2020200020200000), CONST64(0x2020202020200000), CONST64(0x2020200020200020), CONST64(0x2020202020200020), 
+  CONST64(0x2020000020202000), CONST64(0x2020002020202000), CONST64(0x2020000020202020), CONST64(0x2020002020202020), 
+  CONST64(0x2020200020202000), CONST64(0x2020202020202000), CONST64(0x2020200020202020), CONST64(0x2020202020202020)
+  }};
+  
+static const ulong64 des_fp[8][256] = {
+
+{ CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000002000000), CONST64(0x0000008002000000), 
+  CONST64(0x0000000000020000), CONST64(0x0000008000020000), CONST64(0x0000000002020000), CONST64(0x0000008002020000), 
+  CONST64(0x0000000000000200), CONST64(0x0000008000000200), CONST64(0x0000000002000200), CONST64(0x0000008002000200), 
+  CONST64(0x0000000000020200), CONST64(0x0000008000020200), CONST64(0x0000000002020200), CONST64(0x0000008002020200), 
+  CONST64(0x0000000000000002), CONST64(0x0000008000000002), CONST64(0x0000000002000002), CONST64(0x0000008002000002), 
+  CONST64(0x0000000000020002), CONST64(0x0000008000020002), CONST64(0x0000000002020002), CONST64(0x0000008002020002), 
+  CONST64(0x0000000000000202), CONST64(0x0000008000000202), CONST64(0x0000000002000202), CONST64(0x0000008002000202), 
+  CONST64(0x0000000000020202), CONST64(0x0000008000020202), CONST64(0x0000000002020202), CONST64(0x0000008002020202), 
+  CONST64(0x0200000000000000), CONST64(0x0200008000000000), CONST64(0x0200000002000000), CONST64(0x0200008002000000), 
+  CONST64(0x0200000000020000), CONST64(0x0200008000020000), CONST64(0x0200000002020000), CONST64(0x0200008002020000), 
+  CONST64(0x0200000000000200), CONST64(0x0200008000000200), CONST64(0x0200000002000200), CONST64(0x0200008002000200), 
+  CONST64(0x0200000000020200), CONST64(0x0200008000020200), CONST64(0x0200000002020200), CONST64(0x0200008002020200), 
+  CONST64(0x0200000000000002), CONST64(0x0200008000000002), CONST64(0x0200000002000002), CONST64(0x0200008002000002), 
+  CONST64(0x0200000000020002), CONST64(0x0200008000020002), CONST64(0x0200000002020002), CONST64(0x0200008002020002), 
+  CONST64(0x0200000000000202), CONST64(0x0200008000000202), CONST64(0x0200000002000202), CONST64(0x0200008002000202), 
+  CONST64(0x0200000000020202), CONST64(0x0200008000020202), CONST64(0x0200000002020202), CONST64(0x0200008002020202), 
+  CONST64(0x0002000000000000), CONST64(0x0002008000000000), CONST64(0x0002000002000000), CONST64(0x0002008002000000), 
+  CONST64(0x0002000000020000), CONST64(0x0002008000020000), CONST64(0x0002000002020000), CONST64(0x0002008002020000), 
+  CONST64(0x0002000000000200), CONST64(0x0002008000000200), CONST64(0x0002000002000200), CONST64(0x0002008002000200), 
+  CONST64(0x0002000000020200), CONST64(0x0002008000020200), CONST64(0x0002000002020200), CONST64(0x0002008002020200), 
+  CONST64(0x0002000000000002), CONST64(0x0002008000000002), CONST64(0x0002000002000002), CONST64(0x0002008002000002), 
+  CONST64(0x0002000000020002), CONST64(0x0002008000020002), CONST64(0x0002000002020002), CONST64(0x0002008002020002), 
+  CONST64(0x0002000000000202), CONST64(0x0002008000000202), CONST64(0x0002000002000202), CONST64(0x0002008002000202), 
+  CONST64(0x0002000000020202), CONST64(0x0002008000020202), CONST64(0x0002000002020202), CONST64(0x0002008002020202), 
+  CONST64(0x0202000000000000), CONST64(0x0202008000000000), CONST64(0x0202000002000000), CONST64(0x0202008002000000), 
+  CONST64(0x0202000000020000), CONST64(0x0202008000020000), CONST64(0x0202000002020000), CONST64(0x0202008002020000), 
+  CONST64(0x0202000000000200), CONST64(0x0202008000000200), CONST64(0x0202000002000200), CONST64(0x0202008002000200), 
+  CONST64(0x0202000000020200), CONST64(0x0202008000020200), CONST64(0x0202000002020200), CONST64(0x0202008002020200), 
+  CONST64(0x0202000000000002), CONST64(0x0202008000000002), CONST64(0x0202000002000002), CONST64(0x0202008002000002), 
+  CONST64(0x0202000000020002), CONST64(0x0202008000020002), CONST64(0x0202000002020002), CONST64(0x0202008002020002), 
+  CONST64(0x0202000000000202), CONST64(0x0202008000000202), CONST64(0x0202000002000202), CONST64(0x0202008002000202), 
+  CONST64(0x0202000000020202), CONST64(0x0202008000020202), CONST64(0x0202000002020202), CONST64(0x0202008002020202), 
+  CONST64(0x0000020000000000), CONST64(0x0000028000000000), CONST64(0x0000020002000000), CONST64(0x0000028002000000), 
+  CONST64(0x0000020000020000), CONST64(0x0000028000020000), CONST64(0x0000020002020000), CONST64(0x0000028002020000), 
+  CONST64(0x0000020000000200), CONST64(0x0000028000000200), CONST64(0x0000020002000200), CONST64(0x0000028002000200), 
+  CONST64(0x0000020000020200), CONST64(0x0000028000020200), CONST64(0x0000020002020200), CONST64(0x0000028002020200), 
+  CONST64(0x0000020000000002), CONST64(0x0000028000000002), CONST64(0x0000020002000002), CONST64(0x0000028002000002), 
+  CONST64(0x0000020000020002), CONST64(0x0000028000020002), CONST64(0x0000020002020002), CONST64(0x0000028002020002), 
+  CONST64(0x0000020000000202), CONST64(0x0000028000000202), CONST64(0x0000020002000202), CONST64(0x0000028002000202), 
+  CONST64(0x0000020000020202), CONST64(0x0000028000020202), CONST64(0x0000020002020202), CONST64(0x0000028002020202), 
+  CONST64(0x0200020000000000), CONST64(0x0200028000000000), CONST64(0x0200020002000000), CONST64(0x0200028002000000), 
+  CONST64(0x0200020000020000), CONST64(0x0200028000020000), CONST64(0x0200020002020000), CONST64(0x0200028002020000), 
+  CONST64(0x0200020000000200), CONST64(0x0200028000000200), CONST64(0x0200020002000200), CONST64(0x0200028002000200), 
+  CONST64(0x0200020000020200), CONST64(0x0200028000020200), CONST64(0x0200020002020200), CONST64(0x0200028002020200), 
+  CONST64(0x0200020000000002), CONST64(0x0200028000000002), CONST64(0x0200020002000002), CONST64(0x0200028002000002), 
+  CONST64(0x0200020000020002), CONST64(0x0200028000020002), CONST64(0x0200020002020002), CONST64(0x0200028002020002), 
+  CONST64(0x0200020000000202), CONST64(0x0200028000000202), CONST64(0x0200020002000202), CONST64(0x0200028002000202), 
+  CONST64(0x0200020000020202), CONST64(0x0200028000020202), CONST64(0x0200020002020202), CONST64(0x0200028002020202), 
+  CONST64(0x0002020000000000), CONST64(0x0002028000000000), CONST64(0x0002020002000000), CONST64(0x0002028002000000), 
+  CONST64(0x0002020000020000), CONST64(0x0002028000020000), CONST64(0x0002020002020000), CONST64(0x0002028002020000), 
+  CONST64(0x0002020000000200), CONST64(0x0002028000000200), CONST64(0x0002020002000200), CONST64(0x0002028002000200), 
+  CONST64(0x0002020000020200), CONST64(0x0002028000020200), CONST64(0x0002020002020200), CONST64(0x0002028002020200), 
+  CONST64(0x0002020000000002), CONST64(0x0002028000000002), CONST64(0x0002020002000002), CONST64(0x0002028002000002), 
+  CONST64(0x0002020000020002), CONST64(0x0002028000020002), CONST64(0x0002020002020002), CONST64(0x0002028002020002), 
+  CONST64(0x0002020000000202), CONST64(0x0002028000000202), CONST64(0x0002020002000202), CONST64(0x0002028002000202), 
+  CONST64(0x0002020000020202), CONST64(0x0002028000020202), CONST64(0x0002020002020202), CONST64(0x0002028002020202), 
+  CONST64(0x0202020000000000), CONST64(0x0202028000000000), CONST64(0x0202020002000000), CONST64(0x0202028002000000), 
+  CONST64(0x0202020000020000), CONST64(0x0202028000020000), CONST64(0x0202020002020000), CONST64(0x0202028002020000), 
+  CONST64(0x0202020000000200), CONST64(0x0202028000000200), CONST64(0x0202020002000200), CONST64(0x0202028002000200), 
+  CONST64(0x0202020000020200), CONST64(0x0202028000020200), CONST64(0x0202020002020200), CONST64(0x0202028002020200), 
+  CONST64(0x0202020000000002), CONST64(0x0202028000000002), CONST64(0x0202020002000002), CONST64(0x0202028002000002), 
+  CONST64(0x0202020000020002), CONST64(0x0202028000020002), CONST64(0x0202020002020002), CONST64(0x0202028002020002), 
+  CONST64(0x0202020000000202), CONST64(0x0202028000000202), CONST64(0x0202020002000202), CONST64(0x0202028002000202), 
+  CONST64(0x0202020000020202), CONST64(0x0202028000020202), CONST64(0x0202020002020202), CONST64(0x0202028002020202)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000008000000), CONST64(0x0000000208000000), 
+  CONST64(0x0000000000080000), CONST64(0x0000000200080000), CONST64(0x0000000008080000), CONST64(0x0000000208080000), 
+  CONST64(0x0000000000000800), CONST64(0x0000000200000800), CONST64(0x0000000008000800), CONST64(0x0000000208000800), 
+  CONST64(0x0000000000080800), CONST64(0x0000000200080800), CONST64(0x0000000008080800), CONST64(0x0000000208080800), 
+  CONST64(0x0000000000000008), CONST64(0x0000000200000008), CONST64(0x0000000008000008), CONST64(0x0000000208000008), 
+  CONST64(0x0000000000080008), CONST64(0x0000000200080008), CONST64(0x0000000008080008), CONST64(0x0000000208080008), 
+  CONST64(0x0000000000000808), CONST64(0x0000000200000808), CONST64(0x0000000008000808), CONST64(0x0000000208000808), 
+  CONST64(0x0000000000080808), CONST64(0x0000000200080808), CONST64(0x0000000008080808), CONST64(0x0000000208080808), 
+  CONST64(0x0800000000000000), CONST64(0x0800000200000000), CONST64(0x0800000008000000), CONST64(0x0800000208000000), 
+  CONST64(0x0800000000080000), CONST64(0x0800000200080000), CONST64(0x0800000008080000), CONST64(0x0800000208080000), 
+  CONST64(0x0800000000000800), CONST64(0x0800000200000800), CONST64(0x0800000008000800), CONST64(0x0800000208000800), 
+  CONST64(0x0800000000080800), CONST64(0x0800000200080800), CONST64(0x0800000008080800), CONST64(0x0800000208080800), 
+  CONST64(0x0800000000000008), CONST64(0x0800000200000008), CONST64(0x0800000008000008), CONST64(0x0800000208000008), 
+  CONST64(0x0800000000080008), CONST64(0x0800000200080008), CONST64(0x0800000008080008), CONST64(0x0800000208080008), 
+  CONST64(0x0800000000000808), CONST64(0x0800000200000808), CONST64(0x0800000008000808), CONST64(0x0800000208000808), 
+  CONST64(0x0800000000080808), CONST64(0x0800000200080808), CONST64(0x0800000008080808), CONST64(0x0800000208080808), 
+  CONST64(0x0008000000000000), CONST64(0x0008000200000000), CONST64(0x0008000008000000), CONST64(0x0008000208000000), 
+  CONST64(0x0008000000080000), CONST64(0x0008000200080000), CONST64(0x0008000008080000), CONST64(0x0008000208080000), 
+  CONST64(0x0008000000000800), CONST64(0x0008000200000800), CONST64(0x0008000008000800), CONST64(0x0008000208000800), 
+  CONST64(0x0008000000080800), CONST64(0x0008000200080800), CONST64(0x0008000008080800), CONST64(0x0008000208080800), 
+  CONST64(0x0008000000000008), CONST64(0x0008000200000008), CONST64(0x0008000008000008), CONST64(0x0008000208000008), 
+  CONST64(0x0008000000080008), CONST64(0x0008000200080008), CONST64(0x0008000008080008), CONST64(0x0008000208080008), 
+  CONST64(0x0008000000000808), CONST64(0x0008000200000808), CONST64(0x0008000008000808), CONST64(0x0008000208000808), 
+  CONST64(0x0008000000080808), CONST64(0x0008000200080808), CONST64(0x0008000008080808), CONST64(0x0008000208080808), 
+  CONST64(0x0808000000000000), CONST64(0x0808000200000000), CONST64(0x0808000008000000), CONST64(0x0808000208000000), 
+  CONST64(0x0808000000080000), CONST64(0x0808000200080000), CONST64(0x0808000008080000), CONST64(0x0808000208080000), 
+  CONST64(0x0808000000000800), CONST64(0x0808000200000800), CONST64(0x0808000008000800), CONST64(0x0808000208000800), 
+  CONST64(0x0808000000080800), CONST64(0x0808000200080800), CONST64(0x0808000008080800), CONST64(0x0808000208080800), 
+  CONST64(0x0808000000000008), CONST64(0x0808000200000008), CONST64(0x0808000008000008), CONST64(0x0808000208000008), 
+  CONST64(0x0808000000080008), CONST64(0x0808000200080008), CONST64(0x0808000008080008), CONST64(0x0808000208080008), 
+  CONST64(0x0808000000000808), CONST64(0x0808000200000808), CONST64(0x0808000008000808), CONST64(0x0808000208000808), 
+  CONST64(0x0808000000080808), CONST64(0x0808000200080808), CONST64(0x0808000008080808), CONST64(0x0808000208080808), 
+  CONST64(0x0000080000000000), CONST64(0x0000080200000000), CONST64(0x0000080008000000), CONST64(0x0000080208000000), 
+  CONST64(0x0000080000080000), CONST64(0x0000080200080000), CONST64(0x0000080008080000), CONST64(0x0000080208080000), 
+  CONST64(0x0000080000000800), CONST64(0x0000080200000800), CONST64(0x0000080008000800), CONST64(0x0000080208000800), 
+  CONST64(0x0000080000080800), CONST64(0x0000080200080800), CONST64(0x0000080008080800), CONST64(0x0000080208080800), 
+  CONST64(0x0000080000000008), CONST64(0x0000080200000008), CONST64(0x0000080008000008), CONST64(0x0000080208000008), 
+  CONST64(0x0000080000080008), CONST64(0x0000080200080008), CONST64(0x0000080008080008), CONST64(0x0000080208080008), 
+  CONST64(0x0000080000000808), CONST64(0x0000080200000808), CONST64(0x0000080008000808), CONST64(0x0000080208000808), 
+  CONST64(0x0000080000080808), CONST64(0x0000080200080808), CONST64(0x0000080008080808), CONST64(0x0000080208080808), 
+  CONST64(0x0800080000000000), CONST64(0x0800080200000000), CONST64(0x0800080008000000), CONST64(0x0800080208000000), 
+  CONST64(0x0800080000080000), CONST64(0x0800080200080000), CONST64(0x0800080008080000), CONST64(0x0800080208080000), 
+  CONST64(0x0800080000000800), CONST64(0x0800080200000800), CONST64(0x0800080008000800), CONST64(0x0800080208000800), 
+  CONST64(0x0800080000080800), CONST64(0x0800080200080800), CONST64(0x0800080008080800), CONST64(0x0800080208080800), 
+  CONST64(0x0800080000000008), CONST64(0x0800080200000008), CONST64(0x0800080008000008), CONST64(0x0800080208000008), 
+  CONST64(0x0800080000080008), CONST64(0x0800080200080008), CONST64(0x0800080008080008), CONST64(0x0800080208080008), 
+  CONST64(0x0800080000000808), CONST64(0x0800080200000808), CONST64(0x0800080008000808), CONST64(0x0800080208000808), 
+  CONST64(0x0800080000080808), CONST64(0x0800080200080808), CONST64(0x0800080008080808), CONST64(0x0800080208080808), 
+  CONST64(0x0008080000000000), CONST64(0x0008080200000000), CONST64(0x0008080008000000), CONST64(0x0008080208000000), 
+  CONST64(0x0008080000080000), CONST64(0x0008080200080000), CONST64(0x0008080008080000), CONST64(0x0008080208080000), 
+  CONST64(0x0008080000000800), CONST64(0x0008080200000800), CONST64(0x0008080008000800), CONST64(0x0008080208000800), 
+  CONST64(0x0008080000080800), CONST64(0x0008080200080800), CONST64(0x0008080008080800), CONST64(0x0008080208080800), 
+  CONST64(0x0008080000000008), CONST64(0x0008080200000008), CONST64(0x0008080008000008), CONST64(0x0008080208000008), 
+  CONST64(0x0008080000080008), CONST64(0x0008080200080008), CONST64(0x0008080008080008), CONST64(0x0008080208080008), 
+  CONST64(0x0008080000000808), CONST64(0x0008080200000808), CONST64(0x0008080008000808), CONST64(0x0008080208000808), 
+  CONST64(0x0008080000080808), CONST64(0x0008080200080808), CONST64(0x0008080008080808), CONST64(0x0008080208080808), 
+  CONST64(0x0808080000000000), CONST64(0x0808080200000000), CONST64(0x0808080008000000), CONST64(0x0808080208000000), 
+  CONST64(0x0808080000080000), CONST64(0x0808080200080000), CONST64(0x0808080008080000), CONST64(0x0808080208080000), 
+  CONST64(0x0808080000000800), CONST64(0x0808080200000800), CONST64(0x0808080008000800), CONST64(0x0808080208000800), 
+  CONST64(0x0808080000080800), CONST64(0x0808080200080800), CONST64(0x0808080008080800), CONST64(0x0808080208080800), 
+  CONST64(0x0808080000000008), CONST64(0x0808080200000008), CONST64(0x0808080008000008), CONST64(0x0808080208000008), 
+  CONST64(0x0808080000080008), CONST64(0x0808080200080008), CONST64(0x0808080008080008), CONST64(0x0808080208080008), 
+  CONST64(0x0808080000000808), CONST64(0x0808080200000808), CONST64(0x0808080008000808), CONST64(0x0808080208000808), 
+  CONST64(0x0808080000080808), CONST64(0x0808080200080808), CONST64(0x0808080008080808), CONST64(0x0808080208080808)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000020000000), CONST64(0x0000000820000000), 
+  CONST64(0x0000000000200000), CONST64(0x0000000800200000), CONST64(0x0000000020200000), CONST64(0x0000000820200000), 
+  CONST64(0x0000000000002000), CONST64(0x0000000800002000), CONST64(0x0000000020002000), CONST64(0x0000000820002000), 
+  CONST64(0x0000000000202000), CONST64(0x0000000800202000), CONST64(0x0000000020202000), CONST64(0x0000000820202000), 
+  CONST64(0x0000000000000020), CONST64(0x0000000800000020), CONST64(0x0000000020000020), CONST64(0x0000000820000020), 
+  CONST64(0x0000000000200020), CONST64(0x0000000800200020), CONST64(0x0000000020200020), CONST64(0x0000000820200020), 
+  CONST64(0x0000000000002020), CONST64(0x0000000800002020), CONST64(0x0000000020002020), CONST64(0x0000000820002020), 
+  CONST64(0x0000000000202020), CONST64(0x0000000800202020), CONST64(0x0000000020202020), CONST64(0x0000000820202020), 
+  CONST64(0x2000000000000000), CONST64(0x2000000800000000), CONST64(0x2000000020000000), CONST64(0x2000000820000000), 
+  CONST64(0x2000000000200000), CONST64(0x2000000800200000), CONST64(0x2000000020200000), CONST64(0x2000000820200000), 
+  CONST64(0x2000000000002000), CONST64(0x2000000800002000), CONST64(0x2000000020002000), CONST64(0x2000000820002000), 
+  CONST64(0x2000000000202000), CONST64(0x2000000800202000), CONST64(0x2000000020202000), CONST64(0x2000000820202000), 
+  CONST64(0x2000000000000020), CONST64(0x2000000800000020), CONST64(0x2000000020000020), CONST64(0x2000000820000020), 
+  CONST64(0x2000000000200020), CONST64(0x2000000800200020), CONST64(0x2000000020200020), CONST64(0x2000000820200020), 
+  CONST64(0x2000000000002020), CONST64(0x2000000800002020), CONST64(0x2000000020002020), CONST64(0x2000000820002020), 
+  CONST64(0x2000000000202020), CONST64(0x2000000800202020), CONST64(0x2000000020202020), CONST64(0x2000000820202020), 
+  CONST64(0x0020000000000000), CONST64(0x0020000800000000), CONST64(0x0020000020000000), CONST64(0x0020000820000000), 
+  CONST64(0x0020000000200000), CONST64(0x0020000800200000), CONST64(0x0020000020200000), CONST64(0x0020000820200000), 
+  CONST64(0x0020000000002000), CONST64(0x0020000800002000), CONST64(0x0020000020002000), CONST64(0x0020000820002000), 
+  CONST64(0x0020000000202000), CONST64(0x0020000800202000), CONST64(0x0020000020202000), CONST64(0x0020000820202000), 
+  CONST64(0x0020000000000020), CONST64(0x0020000800000020), CONST64(0x0020000020000020), CONST64(0x0020000820000020), 
+  CONST64(0x0020000000200020), CONST64(0x0020000800200020), CONST64(0x0020000020200020), CONST64(0x0020000820200020), 
+  CONST64(0x0020000000002020), CONST64(0x0020000800002020), CONST64(0x0020000020002020), CONST64(0x0020000820002020), 
+  CONST64(0x0020000000202020), CONST64(0x0020000800202020), CONST64(0x0020000020202020), CONST64(0x0020000820202020), 
+  CONST64(0x2020000000000000), CONST64(0x2020000800000000), CONST64(0x2020000020000000), CONST64(0x2020000820000000), 
+  CONST64(0x2020000000200000), CONST64(0x2020000800200000), CONST64(0x2020000020200000), CONST64(0x2020000820200000), 
+  CONST64(0x2020000000002000), CONST64(0x2020000800002000), CONST64(0x2020000020002000), CONST64(0x2020000820002000), 
+  CONST64(0x2020000000202000), CONST64(0x2020000800202000), CONST64(0x2020000020202000), CONST64(0x2020000820202000), 
+  CONST64(0x2020000000000020), CONST64(0x2020000800000020), CONST64(0x2020000020000020), CONST64(0x2020000820000020), 
+  CONST64(0x2020000000200020), CONST64(0x2020000800200020), CONST64(0x2020000020200020), CONST64(0x2020000820200020), 
+  CONST64(0x2020000000002020), CONST64(0x2020000800002020), CONST64(0x2020000020002020), CONST64(0x2020000820002020), 
+  CONST64(0x2020000000202020), CONST64(0x2020000800202020), CONST64(0x2020000020202020), CONST64(0x2020000820202020), 
+  CONST64(0x0000200000000000), CONST64(0x0000200800000000), CONST64(0x0000200020000000), CONST64(0x0000200820000000), 
+  CONST64(0x0000200000200000), CONST64(0x0000200800200000), CONST64(0x0000200020200000), CONST64(0x0000200820200000), 
+  CONST64(0x0000200000002000), CONST64(0x0000200800002000), CONST64(0x0000200020002000), CONST64(0x0000200820002000), 
+  CONST64(0x0000200000202000), CONST64(0x0000200800202000), CONST64(0x0000200020202000), CONST64(0x0000200820202000), 
+  CONST64(0x0000200000000020), CONST64(0x0000200800000020), CONST64(0x0000200020000020), CONST64(0x0000200820000020), 
+  CONST64(0x0000200000200020), CONST64(0x0000200800200020), CONST64(0x0000200020200020), CONST64(0x0000200820200020), 
+  CONST64(0x0000200000002020), CONST64(0x0000200800002020), CONST64(0x0000200020002020), CONST64(0x0000200820002020), 
+  CONST64(0x0000200000202020), CONST64(0x0000200800202020), CONST64(0x0000200020202020), CONST64(0x0000200820202020), 
+  CONST64(0x2000200000000000), CONST64(0x2000200800000000), CONST64(0x2000200020000000), CONST64(0x2000200820000000), 
+  CONST64(0x2000200000200000), CONST64(0x2000200800200000), CONST64(0x2000200020200000), CONST64(0x2000200820200000), 
+  CONST64(0x2000200000002000), CONST64(0x2000200800002000), CONST64(0x2000200020002000), CONST64(0x2000200820002000), 
+  CONST64(0x2000200000202000), CONST64(0x2000200800202000), CONST64(0x2000200020202000), CONST64(0x2000200820202000), 
+  CONST64(0x2000200000000020), CONST64(0x2000200800000020), CONST64(0x2000200020000020), CONST64(0x2000200820000020), 
+  CONST64(0x2000200000200020), CONST64(0x2000200800200020), CONST64(0x2000200020200020), CONST64(0x2000200820200020), 
+  CONST64(0x2000200000002020), CONST64(0x2000200800002020), CONST64(0x2000200020002020), CONST64(0x2000200820002020), 
+  CONST64(0x2000200000202020), CONST64(0x2000200800202020), CONST64(0x2000200020202020), CONST64(0x2000200820202020), 
+  CONST64(0x0020200000000000), CONST64(0x0020200800000000), CONST64(0x0020200020000000), CONST64(0x0020200820000000), 
+  CONST64(0x0020200000200000), CONST64(0x0020200800200000), CONST64(0x0020200020200000), CONST64(0x0020200820200000), 
+  CONST64(0x0020200000002000), CONST64(0x0020200800002000), CONST64(0x0020200020002000), CONST64(0x0020200820002000), 
+  CONST64(0x0020200000202000), CONST64(0x0020200800202000), CONST64(0x0020200020202000), CONST64(0x0020200820202000), 
+  CONST64(0x0020200000000020), CONST64(0x0020200800000020), CONST64(0x0020200020000020), CONST64(0x0020200820000020), 
+  CONST64(0x0020200000200020), CONST64(0x0020200800200020), CONST64(0x0020200020200020), CONST64(0x0020200820200020), 
+  CONST64(0x0020200000002020), CONST64(0x0020200800002020), CONST64(0x0020200020002020), CONST64(0x0020200820002020), 
+  CONST64(0x0020200000202020), CONST64(0x0020200800202020), CONST64(0x0020200020202020), CONST64(0x0020200820202020), 
+  CONST64(0x2020200000000000), CONST64(0x2020200800000000), CONST64(0x2020200020000000), CONST64(0x2020200820000000), 
+  CONST64(0x2020200000200000), CONST64(0x2020200800200000), CONST64(0x2020200020200000), CONST64(0x2020200820200000), 
+  CONST64(0x2020200000002000), CONST64(0x2020200800002000), CONST64(0x2020200020002000), CONST64(0x2020200820002000), 
+  CONST64(0x2020200000202000), CONST64(0x2020200800202000), CONST64(0x2020200020202000), CONST64(0x2020200820202000), 
+  CONST64(0x2020200000000020), CONST64(0x2020200800000020), CONST64(0x2020200020000020), CONST64(0x2020200820000020), 
+  CONST64(0x2020200000200020), CONST64(0x2020200800200020), CONST64(0x2020200020200020), CONST64(0x2020200820200020), 
+  CONST64(0x2020200000002020), CONST64(0x2020200800002020), CONST64(0x2020200020002020), CONST64(0x2020200820002020), 
+  CONST64(0x2020200000202020), CONST64(0x2020200800202020), CONST64(0x2020200020202020), CONST64(0x2020200820202020)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000080000000), CONST64(0x0000002080000000), 
+  CONST64(0x0000000000800000), CONST64(0x0000002000800000), CONST64(0x0000000080800000), CONST64(0x0000002080800000), 
+  CONST64(0x0000000000008000), CONST64(0x0000002000008000), CONST64(0x0000000080008000), CONST64(0x0000002080008000), 
+  CONST64(0x0000000000808000), CONST64(0x0000002000808000), CONST64(0x0000000080808000), CONST64(0x0000002080808000), 
+  CONST64(0x0000000000000080), CONST64(0x0000002000000080), CONST64(0x0000000080000080), CONST64(0x0000002080000080), 
+  CONST64(0x0000000000800080), CONST64(0x0000002000800080), CONST64(0x0000000080800080), CONST64(0x0000002080800080), 
+  CONST64(0x0000000000008080), CONST64(0x0000002000008080), CONST64(0x0000000080008080), CONST64(0x0000002080008080), 
+  CONST64(0x0000000000808080), CONST64(0x0000002000808080), CONST64(0x0000000080808080), CONST64(0x0000002080808080), 
+  CONST64(0x8000000000000000), CONST64(0x8000002000000000), CONST64(0x8000000080000000), CONST64(0x8000002080000000), 
+  CONST64(0x8000000000800000), CONST64(0x8000002000800000), CONST64(0x8000000080800000), CONST64(0x8000002080800000), 
+  CONST64(0x8000000000008000), CONST64(0x8000002000008000), CONST64(0x8000000080008000), CONST64(0x8000002080008000), 
+  CONST64(0x8000000000808000), CONST64(0x8000002000808000), CONST64(0x8000000080808000), CONST64(0x8000002080808000), 
+  CONST64(0x8000000000000080), CONST64(0x8000002000000080), CONST64(0x8000000080000080), CONST64(0x8000002080000080), 
+  CONST64(0x8000000000800080), CONST64(0x8000002000800080), CONST64(0x8000000080800080), CONST64(0x8000002080800080), 
+  CONST64(0x8000000000008080), CONST64(0x8000002000008080), CONST64(0x8000000080008080), CONST64(0x8000002080008080), 
+  CONST64(0x8000000000808080), CONST64(0x8000002000808080), CONST64(0x8000000080808080), CONST64(0x8000002080808080), 
+  CONST64(0x0080000000000000), CONST64(0x0080002000000000), CONST64(0x0080000080000000), CONST64(0x0080002080000000), 
+  CONST64(0x0080000000800000), CONST64(0x0080002000800000), CONST64(0x0080000080800000), CONST64(0x0080002080800000), 
+  CONST64(0x0080000000008000), CONST64(0x0080002000008000), CONST64(0x0080000080008000), CONST64(0x0080002080008000), 
+  CONST64(0x0080000000808000), CONST64(0x0080002000808000), CONST64(0x0080000080808000), CONST64(0x0080002080808000), 
+  CONST64(0x0080000000000080), CONST64(0x0080002000000080), CONST64(0x0080000080000080), CONST64(0x0080002080000080), 
+  CONST64(0x0080000000800080), CONST64(0x0080002000800080), CONST64(0x0080000080800080), CONST64(0x0080002080800080), 
+  CONST64(0x0080000000008080), CONST64(0x0080002000008080), CONST64(0x0080000080008080), CONST64(0x0080002080008080), 
+  CONST64(0x0080000000808080), CONST64(0x0080002000808080), CONST64(0x0080000080808080), CONST64(0x0080002080808080), 
+  CONST64(0x8080000000000000), CONST64(0x8080002000000000), CONST64(0x8080000080000000), CONST64(0x8080002080000000), 
+  CONST64(0x8080000000800000), CONST64(0x8080002000800000), CONST64(0x8080000080800000), CONST64(0x8080002080800000), 
+  CONST64(0x8080000000008000), CONST64(0x8080002000008000), CONST64(0x8080000080008000), CONST64(0x8080002080008000), 
+  CONST64(0x8080000000808000), CONST64(0x8080002000808000), CONST64(0x8080000080808000), CONST64(0x8080002080808000), 
+  CONST64(0x8080000000000080), CONST64(0x8080002000000080), CONST64(0x8080000080000080), CONST64(0x8080002080000080), 
+  CONST64(0x8080000000800080), CONST64(0x8080002000800080), CONST64(0x8080000080800080), CONST64(0x8080002080800080), 
+  CONST64(0x8080000000008080), CONST64(0x8080002000008080), CONST64(0x8080000080008080), CONST64(0x8080002080008080), 
+  CONST64(0x8080000000808080), CONST64(0x8080002000808080), CONST64(0x8080000080808080), CONST64(0x8080002080808080), 
+  CONST64(0x0000800000000000), CONST64(0x0000802000000000), CONST64(0x0000800080000000), CONST64(0x0000802080000000), 
+  CONST64(0x0000800000800000), CONST64(0x0000802000800000), CONST64(0x0000800080800000), CONST64(0x0000802080800000), 
+  CONST64(0x0000800000008000), CONST64(0x0000802000008000), CONST64(0x0000800080008000), CONST64(0x0000802080008000), 
+  CONST64(0x0000800000808000), CONST64(0x0000802000808000), CONST64(0x0000800080808000), CONST64(0x0000802080808000), 
+  CONST64(0x0000800000000080), CONST64(0x0000802000000080), CONST64(0x0000800080000080), CONST64(0x0000802080000080), 
+  CONST64(0x0000800000800080), CONST64(0x0000802000800080), CONST64(0x0000800080800080), CONST64(0x0000802080800080), 
+  CONST64(0x0000800000008080), CONST64(0x0000802000008080), CONST64(0x0000800080008080), CONST64(0x0000802080008080), 
+  CONST64(0x0000800000808080), CONST64(0x0000802000808080), CONST64(0x0000800080808080), CONST64(0x0000802080808080), 
+  CONST64(0x8000800000000000), CONST64(0x8000802000000000), CONST64(0x8000800080000000), CONST64(0x8000802080000000), 
+  CONST64(0x8000800000800000), CONST64(0x8000802000800000), CONST64(0x8000800080800000), CONST64(0x8000802080800000), 
+  CONST64(0x8000800000008000), CONST64(0x8000802000008000), CONST64(0x8000800080008000), CONST64(0x8000802080008000), 
+  CONST64(0x8000800000808000), CONST64(0x8000802000808000), CONST64(0x8000800080808000), CONST64(0x8000802080808000), 
+  CONST64(0x8000800000000080), CONST64(0x8000802000000080), CONST64(0x8000800080000080), CONST64(0x8000802080000080), 
+  CONST64(0x8000800000800080), CONST64(0x8000802000800080), CONST64(0x8000800080800080), CONST64(0x8000802080800080), 
+  CONST64(0x8000800000008080), CONST64(0x8000802000008080), CONST64(0x8000800080008080), CONST64(0x8000802080008080), 
+  CONST64(0x8000800000808080), CONST64(0x8000802000808080), CONST64(0x8000800080808080), CONST64(0x8000802080808080), 
+  CONST64(0x0080800000000000), CONST64(0x0080802000000000), CONST64(0x0080800080000000), CONST64(0x0080802080000000), 
+  CONST64(0x0080800000800000), CONST64(0x0080802000800000), CONST64(0x0080800080800000), CONST64(0x0080802080800000), 
+  CONST64(0x0080800000008000), CONST64(0x0080802000008000), CONST64(0x0080800080008000), CONST64(0x0080802080008000), 
+  CONST64(0x0080800000808000), CONST64(0x0080802000808000), CONST64(0x0080800080808000), CONST64(0x0080802080808000), 
+  CONST64(0x0080800000000080), CONST64(0x0080802000000080), CONST64(0x0080800080000080), CONST64(0x0080802080000080), 
+  CONST64(0x0080800000800080), CONST64(0x0080802000800080), CONST64(0x0080800080800080), CONST64(0x0080802080800080), 
+  CONST64(0x0080800000008080), CONST64(0x0080802000008080), CONST64(0x0080800080008080), CONST64(0x0080802080008080), 
+  CONST64(0x0080800000808080), CONST64(0x0080802000808080), CONST64(0x0080800080808080), CONST64(0x0080802080808080), 
+  CONST64(0x8080800000000000), CONST64(0x8080802000000000), CONST64(0x8080800080000000), CONST64(0x8080802080000000), 
+  CONST64(0x8080800000800000), CONST64(0x8080802000800000), CONST64(0x8080800080800000), CONST64(0x8080802080800000), 
+  CONST64(0x8080800000008000), CONST64(0x8080802000008000), CONST64(0x8080800080008000), CONST64(0x8080802080008000), 
+  CONST64(0x8080800000808000), CONST64(0x8080802000808000), CONST64(0x8080800080808000), CONST64(0x8080802080808000), 
+  CONST64(0x8080800000000080), CONST64(0x8080802000000080), CONST64(0x8080800080000080), CONST64(0x8080802080000080), 
+  CONST64(0x8080800000800080), CONST64(0x8080802000800080), CONST64(0x8080800080800080), CONST64(0x8080802080800080), 
+  CONST64(0x8080800000008080), CONST64(0x8080802000008080), CONST64(0x8080800080008080), CONST64(0x8080802080008080), 
+  CONST64(0x8080800000808080), CONST64(0x8080802000808080), CONST64(0x8080800080808080), CONST64(0x8080802080808080)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000001000000), CONST64(0x0000004001000000), 
+  CONST64(0x0000000000010000), CONST64(0x0000004000010000), CONST64(0x0000000001010000), CONST64(0x0000004001010000), 
+  CONST64(0x0000000000000100), CONST64(0x0000004000000100), CONST64(0x0000000001000100), CONST64(0x0000004001000100), 
+  CONST64(0x0000000000010100), CONST64(0x0000004000010100), CONST64(0x0000000001010100), CONST64(0x0000004001010100), 
+  CONST64(0x0000000000000001), CONST64(0x0000004000000001), CONST64(0x0000000001000001), CONST64(0x0000004001000001), 
+  CONST64(0x0000000000010001), CONST64(0x0000004000010001), CONST64(0x0000000001010001), CONST64(0x0000004001010001), 
+  CONST64(0x0000000000000101), CONST64(0x0000004000000101), CONST64(0x0000000001000101), CONST64(0x0000004001000101), 
+  CONST64(0x0000000000010101), CONST64(0x0000004000010101), CONST64(0x0000000001010101), CONST64(0x0000004001010101), 
+  CONST64(0x0100000000000000), CONST64(0x0100004000000000), CONST64(0x0100000001000000), CONST64(0x0100004001000000), 
+  CONST64(0x0100000000010000), CONST64(0x0100004000010000), CONST64(0x0100000001010000), CONST64(0x0100004001010000), 
+  CONST64(0x0100000000000100), CONST64(0x0100004000000100), CONST64(0x0100000001000100), CONST64(0x0100004001000100), 
+  CONST64(0x0100000000010100), CONST64(0x0100004000010100), CONST64(0x0100000001010100), CONST64(0x0100004001010100), 
+  CONST64(0x0100000000000001), CONST64(0x0100004000000001), CONST64(0x0100000001000001), CONST64(0x0100004001000001), 
+  CONST64(0x0100000000010001), CONST64(0x0100004000010001), CONST64(0x0100000001010001), CONST64(0x0100004001010001), 
+  CONST64(0x0100000000000101), CONST64(0x0100004000000101), CONST64(0x0100000001000101), CONST64(0x0100004001000101), 
+  CONST64(0x0100000000010101), CONST64(0x0100004000010101), CONST64(0x0100000001010101), CONST64(0x0100004001010101), 
+  CONST64(0x0001000000000000), CONST64(0x0001004000000000), CONST64(0x0001000001000000), CONST64(0x0001004001000000), 
+  CONST64(0x0001000000010000), CONST64(0x0001004000010000), CONST64(0x0001000001010000), CONST64(0x0001004001010000), 
+  CONST64(0x0001000000000100), CONST64(0x0001004000000100), CONST64(0x0001000001000100), CONST64(0x0001004001000100), 
+  CONST64(0x0001000000010100), CONST64(0x0001004000010100), CONST64(0x0001000001010100), CONST64(0x0001004001010100), 
+  CONST64(0x0001000000000001), CONST64(0x0001004000000001), CONST64(0x0001000001000001), CONST64(0x0001004001000001), 
+  CONST64(0x0001000000010001), CONST64(0x0001004000010001), CONST64(0x0001000001010001), CONST64(0x0001004001010001), 
+  CONST64(0x0001000000000101), CONST64(0x0001004000000101), CONST64(0x0001000001000101), CONST64(0x0001004001000101), 
+  CONST64(0x0001000000010101), CONST64(0x0001004000010101), CONST64(0x0001000001010101), CONST64(0x0001004001010101), 
+  CONST64(0x0101000000000000), CONST64(0x0101004000000000), CONST64(0x0101000001000000), CONST64(0x0101004001000000), 
+  CONST64(0x0101000000010000), CONST64(0x0101004000010000), CONST64(0x0101000001010000), CONST64(0x0101004001010000), 
+  CONST64(0x0101000000000100), CONST64(0x0101004000000100), CONST64(0x0101000001000100), CONST64(0x0101004001000100), 
+  CONST64(0x0101000000010100), CONST64(0x0101004000010100), CONST64(0x0101000001010100), CONST64(0x0101004001010100), 
+  CONST64(0x0101000000000001), CONST64(0x0101004000000001), CONST64(0x0101000001000001), CONST64(0x0101004001000001), 
+  CONST64(0x0101000000010001), CONST64(0x0101004000010001), CONST64(0x0101000001010001), CONST64(0x0101004001010001), 
+  CONST64(0x0101000000000101), CONST64(0x0101004000000101), CONST64(0x0101000001000101), CONST64(0x0101004001000101), 
+  CONST64(0x0101000000010101), CONST64(0x0101004000010101), CONST64(0x0101000001010101), CONST64(0x0101004001010101), 
+  CONST64(0x0000010000000000), CONST64(0x0000014000000000), CONST64(0x0000010001000000), CONST64(0x0000014001000000), 
+  CONST64(0x0000010000010000), CONST64(0x0000014000010000), CONST64(0x0000010001010000), CONST64(0x0000014001010000), 
+  CONST64(0x0000010000000100), CONST64(0x0000014000000100), CONST64(0x0000010001000100), CONST64(0x0000014001000100), 
+  CONST64(0x0000010000010100), CONST64(0x0000014000010100), CONST64(0x0000010001010100), CONST64(0x0000014001010100), 
+  CONST64(0x0000010000000001), CONST64(0x0000014000000001), CONST64(0x0000010001000001), CONST64(0x0000014001000001), 
+  CONST64(0x0000010000010001), CONST64(0x0000014000010001), CONST64(0x0000010001010001), CONST64(0x0000014001010001), 
+  CONST64(0x0000010000000101), CONST64(0x0000014000000101), CONST64(0x0000010001000101), CONST64(0x0000014001000101), 
+  CONST64(0x0000010000010101), CONST64(0x0000014000010101), CONST64(0x0000010001010101), CONST64(0x0000014001010101), 
+  CONST64(0x0100010000000000), CONST64(0x0100014000000000), CONST64(0x0100010001000000), CONST64(0x0100014001000000), 
+  CONST64(0x0100010000010000), CONST64(0x0100014000010000), CONST64(0x0100010001010000), CONST64(0x0100014001010000), 
+  CONST64(0x0100010000000100), CONST64(0x0100014000000100), CONST64(0x0100010001000100), CONST64(0x0100014001000100), 
+  CONST64(0x0100010000010100), CONST64(0x0100014000010100), CONST64(0x0100010001010100), CONST64(0x0100014001010100), 
+  CONST64(0x0100010000000001), CONST64(0x0100014000000001), CONST64(0x0100010001000001), CONST64(0x0100014001000001), 
+  CONST64(0x0100010000010001), CONST64(0x0100014000010001), CONST64(0x0100010001010001), CONST64(0x0100014001010001), 
+  CONST64(0x0100010000000101), CONST64(0x0100014000000101), CONST64(0x0100010001000101), CONST64(0x0100014001000101), 
+  CONST64(0x0100010000010101), CONST64(0x0100014000010101), CONST64(0x0100010001010101), CONST64(0x0100014001010101), 
+  CONST64(0x0001010000000000), CONST64(0x0001014000000000), CONST64(0x0001010001000000), CONST64(0x0001014001000000), 
+  CONST64(0x0001010000010000), CONST64(0x0001014000010000), CONST64(0x0001010001010000), CONST64(0x0001014001010000), 
+  CONST64(0x0001010000000100), CONST64(0x0001014000000100), CONST64(0x0001010001000100), CONST64(0x0001014001000100), 
+  CONST64(0x0001010000010100), CONST64(0x0001014000010100), CONST64(0x0001010001010100), CONST64(0x0001014001010100), 
+  CONST64(0x0001010000000001), CONST64(0x0001014000000001), CONST64(0x0001010001000001), CONST64(0x0001014001000001), 
+  CONST64(0x0001010000010001), CONST64(0x0001014000010001), CONST64(0x0001010001010001), CONST64(0x0001014001010001), 
+  CONST64(0x0001010000000101), CONST64(0x0001014000000101), CONST64(0x0001010001000101), CONST64(0x0001014001000101), 
+  CONST64(0x0001010000010101), CONST64(0x0001014000010101), CONST64(0x0001010001010101), CONST64(0x0001014001010101), 
+  CONST64(0x0101010000000000), CONST64(0x0101014000000000), CONST64(0x0101010001000000), CONST64(0x0101014001000000), 
+  CONST64(0x0101010000010000), CONST64(0x0101014000010000), CONST64(0x0101010001010000), CONST64(0x0101014001010000), 
+  CONST64(0x0101010000000100), CONST64(0x0101014000000100), CONST64(0x0101010001000100), CONST64(0x0101014001000100), 
+  CONST64(0x0101010000010100), CONST64(0x0101014000010100), CONST64(0x0101010001010100), CONST64(0x0101014001010100), 
+  CONST64(0x0101010000000001), CONST64(0x0101014000000001), CONST64(0x0101010001000001), CONST64(0x0101014001000001), 
+  CONST64(0x0101010000010001), CONST64(0x0101014000010001), CONST64(0x0101010001010001), CONST64(0x0101014001010001), 
+  CONST64(0x0101010000000101), CONST64(0x0101014000000101), CONST64(0x0101010001000101), CONST64(0x0101014001000101), 
+  CONST64(0x0101010000010101), CONST64(0x0101014000010101), CONST64(0x0101010001010101), CONST64(0x0101014001010101)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000000100000000), CONST64(0x0000000004000000), CONST64(0x0000000104000000), 
+  CONST64(0x0000000000040000), CONST64(0x0000000100040000), CONST64(0x0000000004040000), CONST64(0x0000000104040000), 
+  CONST64(0x0000000000000400), CONST64(0x0000000100000400), CONST64(0x0000000004000400), CONST64(0x0000000104000400), 
+  CONST64(0x0000000000040400), CONST64(0x0000000100040400), CONST64(0x0000000004040400), CONST64(0x0000000104040400), 
+  CONST64(0x0000000000000004), CONST64(0x0000000100000004), CONST64(0x0000000004000004), CONST64(0x0000000104000004), 
+  CONST64(0x0000000000040004), CONST64(0x0000000100040004), CONST64(0x0000000004040004), CONST64(0x0000000104040004), 
+  CONST64(0x0000000000000404), CONST64(0x0000000100000404), CONST64(0x0000000004000404), CONST64(0x0000000104000404), 
+  CONST64(0x0000000000040404), CONST64(0x0000000100040404), CONST64(0x0000000004040404), CONST64(0x0000000104040404), 
+  CONST64(0x0400000000000000), CONST64(0x0400000100000000), CONST64(0x0400000004000000), CONST64(0x0400000104000000), 
+  CONST64(0x0400000000040000), CONST64(0x0400000100040000), CONST64(0x0400000004040000), CONST64(0x0400000104040000), 
+  CONST64(0x0400000000000400), CONST64(0x0400000100000400), CONST64(0x0400000004000400), CONST64(0x0400000104000400), 
+  CONST64(0x0400000000040400), CONST64(0x0400000100040400), CONST64(0x0400000004040400), CONST64(0x0400000104040400), 
+  CONST64(0x0400000000000004), CONST64(0x0400000100000004), CONST64(0x0400000004000004), CONST64(0x0400000104000004), 
+  CONST64(0x0400000000040004), CONST64(0x0400000100040004), CONST64(0x0400000004040004), CONST64(0x0400000104040004), 
+  CONST64(0x0400000000000404), CONST64(0x0400000100000404), CONST64(0x0400000004000404), CONST64(0x0400000104000404), 
+  CONST64(0x0400000000040404), CONST64(0x0400000100040404), CONST64(0x0400000004040404), CONST64(0x0400000104040404), 
+  CONST64(0x0004000000000000), CONST64(0x0004000100000000), CONST64(0x0004000004000000), CONST64(0x0004000104000000), 
+  CONST64(0x0004000000040000), CONST64(0x0004000100040000), CONST64(0x0004000004040000), CONST64(0x0004000104040000), 
+  CONST64(0x0004000000000400), CONST64(0x0004000100000400), CONST64(0x0004000004000400), CONST64(0x0004000104000400), 
+  CONST64(0x0004000000040400), CONST64(0x0004000100040400), CONST64(0x0004000004040400), CONST64(0x0004000104040400), 
+  CONST64(0x0004000000000004), CONST64(0x0004000100000004), CONST64(0x0004000004000004), CONST64(0x0004000104000004), 
+  CONST64(0x0004000000040004), CONST64(0x0004000100040004), CONST64(0x0004000004040004), CONST64(0x0004000104040004), 
+  CONST64(0x0004000000000404), CONST64(0x0004000100000404), CONST64(0x0004000004000404), CONST64(0x0004000104000404), 
+  CONST64(0x0004000000040404), CONST64(0x0004000100040404), CONST64(0x0004000004040404), CONST64(0x0004000104040404), 
+  CONST64(0x0404000000000000), CONST64(0x0404000100000000), CONST64(0x0404000004000000), CONST64(0x0404000104000000), 
+  CONST64(0x0404000000040000), CONST64(0x0404000100040000), CONST64(0x0404000004040000), CONST64(0x0404000104040000), 
+  CONST64(0x0404000000000400), CONST64(0x0404000100000400), CONST64(0x0404000004000400), CONST64(0x0404000104000400), 
+  CONST64(0x0404000000040400), CONST64(0x0404000100040400), CONST64(0x0404000004040400), CONST64(0x0404000104040400), 
+  CONST64(0x0404000000000004), CONST64(0x0404000100000004), CONST64(0x0404000004000004), CONST64(0x0404000104000004), 
+  CONST64(0x0404000000040004), CONST64(0x0404000100040004), CONST64(0x0404000004040004), CONST64(0x0404000104040004), 
+  CONST64(0x0404000000000404), CONST64(0x0404000100000404), CONST64(0x0404000004000404), CONST64(0x0404000104000404), 
+  CONST64(0x0404000000040404), CONST64(0x0404000100040404), CONST64(0x0404000004040404), CONST64(0x0404000104040404), 
+  CONST64(0x0000040000000000), CONST64(0x0000040100000000), CONST64(0x0000040004000000), CONST64(0x0000040104000000), 
+  CONST64(0x0000040000040000), CONST64(0x0000040100040000), CONST64(0x0000040004040000), CONST64(0x0000040104040000), 
+  CONST64(0x0000040000000400), CONST64(0x0000040100000400), CONST64(0x0000040004000400), CONST64(0x0000040104000400), 
+  CONST64(0x0000040000040400), CONST64(0x0000040100040400), CONST64(0x0000040004040400), CONST64(0x0000040104040400), 
+  CONST64(0x0000040000000004), CONST64(0x0000040100000004), CONST64(0x0000040004000004), CONST64(0x0000040104000004), 
+  CONST64(0x0000040000040004), CONST64(0x0000040100040004), CONST64(0x0000040004040004), CONST64(0x0000040104040004), 
+  CONST64(0x0000040000000404), CONST64(0x0000040100000404), CONST64(0x0000040004000404), CONST64(0x0000040104000404), 
+  CONST64(0x0000040000040404), CONST64(0x0000040100040404), CONST64(0x0000040004040404), CONST64(0x0000040104040404), 
+  CONST64(0x0400040000000000), CONST64(0x0400040100000000), CONST64(0x0400040004000000), CONST64(0x0400040104000000), 
+  CONST64(0x0400040000040000), CONST64(0x0400040100040000), CONST64(0x0400040004040000), CONST64(0x0400040104040000), 
+  CONST64(0x0400040000000400), CONST64(0x0400040100000400), CONST64(0x0400040004000400), CONST64(0x0400040104000400), 
+  CONST64(0x0400040000040400), CONST64(0x0400040100040400), CONST64(0x0400040004040400), CONST64(0x0400040104040400), 
+  CONST64(0x0400040000000004), CONST64(0x0400040100000004), CONST64(0x0400040004000004), CONST64(0x0400040104000004), 
+  CONST64(0x0400040000040004), CONST64(0x0400040100040004), CONST64(0x0400040004040004), CONST64(0x0400040104040004), 
+  CONST64(0x0400040000000404), CONST64(0x0400040100000404), CONST64(0x0400040004000404), CONST64(0x0400040104000404), 
+  CONST64(0x0400040000040404), CONST64(0x0400040100040404), CONST64(0x0400040004040404), CONST64(0x0400040104040404), 
+  CONST64(0x0004040000000000), CONST64(0x0004040100000000), CONST64(0x0004040004000000), CONST64(0x0004040104000000), 
+  CONST64(0x0004040000040000), CONST64(0x0004040100040000), CONST64(0x0004040004040000), CONST64(0x0004040104040000), 
+  CONST64(0x0004040000000400), CONST64(0x0004040100000400), CONST64(0x0004040004000400), CONST64(0x0004040104000400), 
+  CONST64(0x0004040000040400), CONST64(0x0004040100040400), CONST64(0x0004040004040400), CONST64(0x0004040104040400), 
+  CONST64(0x0004040000000004), CONST64(0x0004040100000004), CONST64(0x0004040004000004), CONST64(0x0004040104000004), 
+  CONST64(0x0004040000040004), CONST64(0x0004040100040004), CONST64(0x0004040004040004), CONST64(0x0004040104040004), 
+  CONST64(0x0004040000000404), CONST64(0x0004040100000404), CONST64(0x0004040004000404), CONST64(0x0004040104000404), 
+  CONST64(0x0004040000040404), CONST64(0x0004040100040404), CONST64(0x0004040004040404), CONST64(0x0004040104040404), 
+  CONST64(0x0404040000000000), CONST64(0x0404040100000000), CONST64(0x0404040004000000), CONST64(0x0404040104000000), 
+  CONST64(0x0404040000040000), CONST64(0x0404040100040000), CONST64(0x0404040004040000), CONST64(0x0404040104040000), 
+  CONST64(0x0404040000000400), CONST64(0x0404040100000400), CONST64(0x0404040004000400), CONST64(0x0404040104000400), 
+  CONST64(0x0404040000040400), CONST64(0x0404040100040400), CONST64(0x0404040004040400), CONST64(0x0404040104040400), 
+  CONST64(0x0404040000000004), CONST64(0x0404040100000004), CONST64(0x0404040004000004), CONST64(0x0404040104000004), 
+  CONST64(0x0404040000040004), CONST64(0x0404040100040004), CONST64(0x0404040004040004), CONST64(0x0404040104040004), 
+  CONST64(0x0404040000000404), CONST64(0x0404040100000404), CONST64(0x0404040004000404), CONST64(0x0404040104000404), 
+  CONST64(0x0404040000040404), CONST64(0x0404040100040404), CONST64(0x0404040004040404), CONST64(0x0404040104040404)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000010000000), CONST64(0x0000000410000000), 
+  CONST64(0x0000000000100000), CONST64(0x0000000400100000), CONST64(0x0000000010100000), CONST64(0x0000000410100000), 
+  CONST64(0x0000000000001000), CONST64(0x0000000400001000), CONST64(0x0000000010001000), CONST64(0x0000000410001000), 
+  CONST64(0x0000000000101000), CONST64(0x0000000400101000), CONST64(0x0000000010101000), CONST64(0x0000000410101000), 
+  CONST64(0x0000000000000010), CONST64(0x0000000400000010), CONST64(0x0000000010000010), CONST64(0x0000000410000010), 
+  CONST64(0x0000000000100010), CONST64(0x0000000400100010), CONST64(0x0000000010100010), CONST64(0x0000000410100010), 
+  CONST64(0x0000000000001010), CONST64(0x0000000400001010), CONST64(0x0000000010001010), CONST64(0x0000000410001010), 
+  CONST64(0x0000000000101010), CONST64(0x0000000400101010), CONST64(0x0000000010101010), CONST64(0x0000000410101010), 
+  CONST64(0x1000000000000000), CONST64(0x1000000400000000), CONST64(0x1000000010000000), CONST64(0x1000000410000000), 
+  CONST64(0x1000000000100000), CONST64(0x1000000400100000), CONST64(0x1000000010100000), CONST64(0x1000000410100000), 
+  CONST64(0x1000000000001000), CONST64(0x1000000400001000), CONST64(0x1000000010001000), CONST64(0x1000000410001000), 
+  CONST64(0x1000000000101000), CONST64(0x1000000400101000), CONST64(0x1000000010101000), CONST64(0x1000000410101000), 
+  CONST64(0x1000000000000010), CONST64(0x1000000400000010), CONST64(0x1000000010000010), CONST64(0x1000000410000010), 
+  CONST64(0x1000000000100010), CONST64(0x1000000400100010), CONST64(0x1000000010100010), CONST64(0x1000000410100010), 
+  CONST64(0x1000000000001010), CONST64(0x1000000400001010), CONST64(0x1000000010001010), CONST64(0x1000000410001010), 
+  CONST64(0x1000000000101010), CONST64(0x1000000400101010), CONST64(0x1000000010101010), CONST64(0x1000000410101010), 
+  CONST64(0x0010000000000000), CONST64(0x0010000400000000), CONST64(0x0010000010000000), CONST64(0x0010000410000000), 
+  CONST64(0x0010000000100000), CONST64(0x0010000400100000), CONST64(0x0010000010100000), CONST64(0x0010000410100000), 
+  CONST64(0x0010000000001000), CONST64(0x0010000400001000), CONST64(0x0010000010001000), CONST64(0x0010000410001000), 
+  CONST64(0x0010000000101000), CONST64(0x0010000400101000), CONST64(0x0010000010101000), CONST64(0x0010000410101000), 
+  CONST64(0x0010000000000010), CONST64(0x0010000400000010), CONST64(0x0010000010000010), CONST64(0x0010000410000010), 
+  CONST64(0x0010000000100010), CONST64(0x0010000400100010), CONST64(0x0010000010100010), CONST64(0x0010000410100010), 
+  CONST64(0x0010000000001010), CONST64(0x0010000400001010), CONST64(0x0010000010001010), CONST64(0x0010000410001010), 
+  CONST64(0x0010000000101010), CONST64(0x0010000400101010), CONST64(0x0010000010101010), CONST64(0x0010000410101010), 
+  CONST64(0x1010000000000000), CONST64(0x1010000400000000), CONST64(0x1010000010000000), CONST64(0x1010000410000000), 
+  CONST64(0x1010000000100000), CONST64(0x1010000400100000), CONST64(0x1010000010100000), CONST64(0x1010000410100000), 
+  CONST64(0x1010000000001000), CONST64(0x1010000400001000), CONST64(0x1010000010001000), CONST64(0x1010000410001000), 
+  CONST64(0x1010000000101000), CONST64(0x1010000400101000), CONST64(0x1010000010101000), CONST64(0x1010000410101000), 
+  CONST64(0x1010000000000010), CONST64(0x1010000400000010), CONST64(0x1010000010000010), CONST64(0x1010000410000010), 
+  CONST64(0x1010000000100010), CONST64(0x1010000400100010), CONST64(0x1010000010100010), CONST64(0x1010000410100010), 
+  CONST64(0x1010000000001010), CONST64(0x1010000400001010), CONST64(0x1010000010001010), CONST64(0x1010000410001010), 
+  CONST64(0x1010000000101010), CONST64(0x1010000400101010), CONST64(0x1010000010101010), CONST64(0x1010000410101010), 
+  CONST64(0x0000100000000000), CONST64(0x0000100400000000), CONST64(0x0000100010000000), CONST64(0x0000100410000000), 
+  CONST64(0x0000100000100000), CONST64(0x0000100400100000), CONST64(0x0000100010100000), CONST64(0x0000100410100000), 
+  CONST64(0x0000100000001000), CONST64(0x0000100400001000), CONST64(0x0000100010001000), CONST64(0x0000100410001000), 
+  CONST64(0x0000100000101000), CONST64(0x0000100400101000), CONST64(0x0000100010101000), CONST64(0x0000100410101000), 
+  CONST64(0x0000100000000010), CONST64(0x0000100400000010), CONST64(0x0000100010000010), CONST64(0x0000100410000010), 
+  CONST64(0x0000100000100010), CONST64(0x0000100400100010), CONST64(0x0000100010100010), CONST64(0x0000100410100010), 
+  CONST64(0x0000100000001010), CONST64(0x0000100400001010), CONST64(0x0000100010001010), CONST64(0x0000100410001010), 
+  CONST64(0x0000100000101010), CONST64(0x0000100400101010), CONST64(0x0000100010101010), CONST64(0x0000100410101010), 
+  CONST64(0x1000100000000000), CONST64(0x1000100400000000), CONST64(0x1000100010000000), CONST64(0x1000100410000000), 
+  CONST64(0x1000100000100000), CONST64(0x1000100400100000), CONST64(0x1000100010100000), CONST64(0x1000100410100000), 
+  CONST64(0x1000100000001000), CONST64(0x1000100400001000), CONST64(0x1000100010001000), CONST64(0x1000100410001000), 
+  CONST64(0x1000100000101000), CONST64(0x1000100400101000), CONST64(0x1000100010101000), CONST64(0x1000100410101000), 
+  CONST64(0x1000100000000010), CONST64(0x1000100400000010), CONST64(0x1000100010000010), CONST64(0x1000100410000010), 
+  CONST64(0x1000100000100010), CONST64(0x1000100400100010), CONST64(0x1000100010100010), CONST64(0x1000100410100010), 
+  CONST64(0x1000100000001010), CONST64(0x1000100400001010), CONST64(0x1000100010001010), CONST64(0x1000100410001010), 
+  CONST64(0x1000100000101010), CONST64(0x1000100400101010), CONST64(0x1000100010101010), CONST64(0x1000100410101010), 
+  CONST64(0x0010100000000000), CONST64(0x0010100400000000), CONST64(0x0010100010000000), CONST64(0x0010100410000000), 
+  CONST64(0x0010100000100000), CONST64(0x0010100400100000), CONST64(0x0010100010100000), CONST64(0x0010100410100000), 
+  CONST64(0x0010100000001000), CONST64(0x0010100400001000), CONST64(0x0010100010001000), CONST64(0x0010100410001000), 
+  CONST64(0x0010100000101000), CONST64(0x0010100400101000), CONST64(0x0010100010101000), CONST64(0x0010100410101000), 
+  CONST64(0x0010100000000010), CONST64(0x0010100400000010), CONST64(0x0010100010000010), CONST64(0x0010100410000010), 
+  CONST64(0x0010100000100010), CONST64(0x0010100400100010), CONST64(0x0010100010100010), CONST64(0x0010100410100010), 
+  CONST64(0x0010100000001010), CONST64(0x0010100400001010), CONST64(0x0010100010001010), CONST64(0x0010100410001010), 
+  CONST64(0x0010100000101010), CONST64(0x0010100400101010), CONST64(0x0010100010101010), CONST64(0x0010100410101010), 
+  CONST64(0x1010100000000000), CONST64(0x1010100400000000), CONST64(0x1010100010000000), CONST64(0x1010100410000000), 
+  CONST64(0x1010100000100000), CONST64(0x1010100400100000), CONST64(0x1010100010100000), CONST64(0x1010100410100000), 
+  CONST64(0x1010100000001000), CONST64(0x1010100400001000), CONST64(0x1010100010001000), CONST64(0x1010100410001000), 
+  CONST64(0x1010100000101000), CONST64(0x1010100400101000), CONST64(0x1010100010101000), CONST64(0x1010100410101000), 
+  CONST64(0x1010100000000010), CONST64(0x1010100400000010), CONST64(0x1010100010000010), CONST64(0x1010100410000010), 
+  CONST64(0x1010100000100010), CONST64(0x1010100400100010), CONST64(0x1010100010100010), CONST64(0x1010100410100010), 
+  CONST64(0x1010100000001010), CONST64(0x1010100400001010), CONST64(0x1010100010001010), CONST64(0x1010100410001010), 
+  CONST64(0x1010100000101010), CONST64(0x1010100400101010), CONST64(0x1010100010101010), CONST64(0x1010100410101010)
+  }, 
+{ CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000040000000), CONST64(0x0000001040000000), 
+  CONST64(0x0000000000400000), CONST64(0x0000001000400000), CONST64(0x0000000040400000), CONST64(0x0000001040400000), 
+  CONST64(0x0000000000004000), CONST64(0x0000001000004000), CONST64(0x0000000040004000), CONST64(0x0000001040004000), 
+  CONST64(0x0000000000404000), CONST64(0x0000001000404000), CONST64(0x0000000040404000), CONST64(0x0000001040404000), 
+  CONST64(0x0000000000000040), CONST64(0x0000001000000040), CONST64(0x0000000040000040), CONST64(0x0000001040000040), 
+  CONST64(0x0000000000400040), CONST64(0x0000001000400040), CONST64(0x0000000040400040), CONST64(0x0000001040400040), 
+  CONST64(0x0000000000004040), CONST64(0x0000001000004040), CONST64(0x0000000040004040), CONST64(0x0000001040004040), 
+  CONST64(0x0000000000404040), CONST64(0x0000001000404040), CONST64(0x0000000040404040), CONST64(0x0000001040404040), 
+  CONST64(0x4000000000000000), CONST64(0x4000001000000000), CONST64(0x4000000040000000), CONST64(0x4000001040000000), 
+  CONST64(0x4000000000400000), CONST64(0x4000001000400000), CONST64(0x4000000040400000), CONST64(0x4000001040400000), 
+  CONST64(0x4000000000004000), CONST64(0x4000001000004000), CONST64(0x4000000040004000), CONST64(0x4000001040004000), 
+  CONST64(0x4000000000404000), CONST64(0x4000001000404000), CONST64(0x4000000040404000), CONST64(0x4000001040404000), 
+  CONST64(0x4000000000000040), CONST64(0x4000001000000040), CONST64(0x4000000040000040), CONST64(0x4000001040000040), 
+  CONST64(0x4000000000400040), CONST64(0x4000001000400040), CONST64(0x4000000040400040), CONST64(0x4000001040400040), 
+  CONST64(0x4000000000004040), CONST64(0x4000001000004040), CONST64(0x4000000040004040), CONST64(0x4000001040004040), 
+  CONST64(0x4000000000404040), CONST64(0x4000001000404040), CONST64(0x4000000040404040), CONST64(0x4000001040404040), 
+  CONST64(0x0040000000000000), CONST64(0x0040001000000000), CONST64(0x0040000040000000), CONST64(0x0040001040000000), 
+  CONST64(0x0040000000400000), CONST64(0x0040001000400000), CONST64(0x0040000040400000), CONST64(0x0040001040400000), 
+  CONST64(0x0040000000004000), CONST64(0x0040001000004000), CONST64(0x0040000040004000), CONST64(0x0040001040004000), 
+  CONST64(0x0040000000404000), CONST64(0x0040001000404000), CONST64(0x0040000040404000), CONST64(0x0040001040404000), 
+  CONST64(0x0040000000000040), CONST64(0x0040001000000040), CONST64(0x0040000040000040), CONST64(0x0040001040000040), 
+  CONST64(0x0040000000400040), CONST64(0x0040001000400040), CONST64(0x0040000040400040), CONST64(0x0040001040400040), 
+  CONST64(0x0040000000004040), CONST64(0x0040001000004040), CONST64(0x0040000040004040), CONST64(0x0040001040004040), 
+  CONST64(0x0040000000404040), CONST64(0x0040001000404040), CONST64(0x0040000040404040), CONST64(0x0040001040404040), 
+  CONST64(0x4040000000000000), CONST64(0x4040001000000000), CONST64(0x4040000040000000), CONST64(0x4040001040000000), 
+  CONST64(0x4040000000400000), CONST64(0x4040001000400000), CONST64(0x4040000040400000), CONST64(0x4040001040400000), 
+  CONST64(0x4040000000004000), CONST64(0x4040001000004000), CONST64(0x4040000040004000), CONST64(0x4040001040004000), 
+  CONST64(0x4040000000404000), CONST64(0x4040001000404000), CONST64(0x4040000040404000), CONST64(0x4040001040404000), 
+  CONST64(0x4040000000000040), CONST64(0x4040001000000040), CONST64(0x4040000040000040), CONST64(0x4040001040000040), 
+  CONST64(0x4040000000400040), CONST64(0x4040001000400040), CONST64(0x4040000040400040), CONST64(0x4040001040400040), 
+  CONST64(0x4040000000004040), CONST64(0x4040001000004040), CONST64(0x4040000040004040), CONST64(0x4040001040004040), 
+  CONST64(0x4040000000404040), CONST64(0x4040001000404040), CONST64(0x4040000040404040), CONST64(0x4040001040404040), 
+  CONST64(0x0000400000000000), CONST64(0x0000401000000000), CONST64(0x0000400040000000), CONST64(0x0000401040000000), 
+  CONST64(0x0000400000400000), CONST64(0x0000401000400000), CONST64(0x0000400040400000), CONST64(0x0000401040400000), 
+  CONST64(0x0000400000004000), CONST64(0x0000401000004000), CONST64(0x0000400040004000), CONST64(0x0000401040004000), 
+  CONST64(0x0000400000404000), CONST64(0x0000401000404000), CONST64(0x0000400040404000), CONST64(0x0000401040404000), 
+  CONST64(0x0000400000000040), CONST64(0x0000401000000040), CONST64(0x0000400040000040), CONST64(0x0000401040000040), 
+  CONST64(0x0000400000400040), CONST64(0x0000401000400040), CONST64(0x0000400040400040), CONST64(0x0000401040400040), 
+  CONST64(0x0000400000004040), CONST64(0x0000401000004040), CONST64(0x0000400040004040), CONST64(0x0000401040004040), 
+  CONST64(0x0000400000404040), CONST64(0x0000401000404040), CONST64(0x0000400040404040), CONST64(0x0000401040404040), 
+  CONST64(0x4000400000000000), CONST64(0x4000401000000000), CONST64(0x4000400040000000), CONST64(0x4000401040000000), 
+  CONST64(0x4000400000400000), CONST64(0x4000401000400000), CONST64(0x4000400040400000), CONST64(0x4000401040400000), 
+  CONST64(0x4000400000004000), CONST64(0x4000401000004000), CONST64(0x4000400040004000), CONST64(0x4000401040004000), 
+  CONST64(0x4000400000404000), CONST64(0x4000401000404000), CONST64(0x4000400040404000), CONST64(0x4000401040404000), 
+  CONST64(0x4000400000000040), CONST64(0x4000401000000040), CONST64(0x4000400040000040), CONST64(0x4000401040000040), 
+  CONST64(0x4000400000400040), CONST64(0x4000401000400040), CONST64(0x4000400040400040), CONST64(0x4000401040400040), 
+  CONST64(0x4000400000004040), CONST64(0x4000401000004040), CONST64(0x4000400040004040), CONST64(0x4000401040004040), 
+  CONST64(0x4000400000404040), CONST64(0x4000401000404040), CONST64(0x4000400040404040), CONST64(0x4000401040404040), 
+  CONST64(0x0040400000000000), CONST64(0x0040401000000000), CONST64(0x0040400040000000), CONST64(0x0040401040000000), 
+  CONST64(0x0040400000400000), CONST64(0x0040401000400000), CONST64(0x0040400040400000), CONST64(0x0040401040400000), 
+  CONST64(0x0040400000004000), CONST64(0x0040401000004000), CONST64(0x0040400040004000), CONST64(0x0040401040004000), 
+  CONST64(0x0040400000404000), CONST64(0x0040401000404000), CONST64(0x0040400040404000), CONST64(0x0040401040404000), 
+  CONST64(0x0040400000000040), CONST64(0x0040401000000040), CONST64(0x0040400040000040), CONST64(0x0040401040000040), 
+  CONST64(0x0040400000400040), CONST64(0x0040401000400040), CONST64(0x0040400040400040), CONST64(0x0040401040400040), 
+  CONST64(0x0040400000004040), CONST64(0x0040401000004040), CONST64(0x0040400040004040), CONST64(0x0040401040004040), 
+  CONST64(0x0040400000404040), CONST64(0x0040401000404040), CONST64(0x0040400040404040), CONST64(0x0040401040404040), 
+  CONST64(0x4040400000000000), CONST64(0x4040401000000000), CONST64(0x4040400040000000), CONST64(0x4040401040000000), 
+  CONST64(0x4040400000400000), CONST64(0x4040401000400000), CONST64(0x4040400040400000), CONST64(0x4040401040400000), 
+  CONST64(0x4040400000004000), CONST64(0x4040401000004000), CONST64(0x4040400040004000), CONST64(0x4040401040004000), 
+  CONST64(0x4040400000404000), CONST64(0x4040401000404000), CONST64(0x4040400040404000), CONST64(0x4040401040404000), 
+  CONST64(0x4040400000000040), CONST64(0x4040401000000040), CONST64(0x4040400040000040), CONST64(0x4040401040000040), 
+  CONST64(0x4040400000400040), CONST64(0x4040401000400040), CONST64(0x4040400040400040), CONST64(0x4040401040400040), 
+  CONST64(0x4040400000004040), CONST64(0x4040401000004040), CONST64(0x4040400040004040), CONST64(0x4040401040004040), 
+  CONST64(0x4040400000404040), CONST64(0x4040401000404040), CONST64(0x4040400040404040), CONST64(0x4040401040404040)
+  }};
+  
+#endif
+
+
+static void cookey(const ulong32 *raw1, ulong32 *keyout);
+
+#ifdef CLEAN_STACK
+void _deskey(const unsigned char *key, short edf, ulong32 *keyout)
+#else
+void deskey(const unsigned char *key, short edf, ulong32 *keyout)
+#endif
+{
+    ulong32 i, j, l, m, n, kn[32];
+    unsigned char pc1m[56], pcr[56];
+
+    for (j=0; j < 56; j++) {
+        l = (ulong32)pc1[j];
+        m = l & 7;
+        pc1m[j] = (unsigned char)((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0);
+    }
+
+    for (i=0; i < 16; i++) {
+        if (edf == DE1) {
+           m = (15 - i) << 1;
+        } else {
+           m = i << 1;
+        }
+        n = m + 1;
+        kn[m] = kn[n] = 0L;
+        for (j=0; j < 28; j++) {
+            l = j + (ulong32)totrot[i];
+            if (l < 28) {
+               pcr[j] = pc1m[l];
+            } else {
+               pcr[j] = pc1m[l - 28];
+            }
+        }
+        for (/*j = 28*/; j < 56; j++) {
+            l = j + (ulong32)totrot[i];
+            if (l < 56) {
+               pcr[j] = pc1m[l];
+            } else {
+               pcr[j] = pc1m[l - 28];
+            }
+        }
+        for (j=0; j < 24; j++)  {
+            if ((int)pcr[(int)pc2[j]] != 0) {
+               kn[m] |= bigbyte[j];
+            }
+            if ((int)pcr[(int)pc2[j+24]] != 0) {
+               kn[n] |= bigbyte[j];
+            }
+        }
+    }
+
+    cookey(kn, keyout);
+}
+
+#ifdef CLEAN_STACK
+void deskey(const unsigned char *key, short edf, ulong32 *keyout)
+{
+   _deskey(key, edf, keyout);
+   burn_stack(sizeof(int)*5 + sizeof(ulong32)*32 + sizeof(unsigned char)*112);
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _cookey(const ulong32 *raw1, ulong32 *keyout)
+#else
+static void cookey(const ulong32 *raw1, ulong32 *keyout)
+#endif
+{
+    ulong32 *cook;
+    const ulong32 *raw0;
+    ulong32 dough[32];
+    int i;
+
+    cook = dough;
+    for(i=0; i < 16; i++, raw1++)
+    {
+        raw0 = raw1++;
+        *cook    = (*raw0 & 0x00fc0000L) << 6;
+        *cook   |= (*raw0 & 0x00000fc0L) << 10;
+        *cook   |= (*raw1 & 0x00fc0000L) >> 10;
+        *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
+        *cook    = (*raw0 & 0x0003f000L) << 12;
+        *cook   |= (*raw0 & 0x0000003fL) << 16;
+        *cook   |= (*raw1 & 0x0003f000L) >> 4;
+        *cook++ |= (*raw1 & 0x0000003fL);
+    }
+
+    memcpy(keyout, dough, sizeof dough);
+}
+
+#ifdef CLEAN_STACK
+static void cookey(const ulong32 *raw1, ulong32 *keyout)
+{
+   _cookey(raw1, keyout);
+   burn_stack(sizeof(ulong32 *) * 2 + sizeof(ulong32)*32 + sizeof(int));
+}
+#endif
+
+#ifndef CLEAN_STACK
+static void desfunc(ulong32 *block, const ulong32 *keys)
+#else
+static void _desfunc(ulong32 *block, const ulong32 *keys)
+#endif
+{
+    ulong32 work, right, leftt;
+    int round;
+
+    leftt = block[0];
+    right = block[1];
+
+#ifdef SMALL_CODE
+    work = ((leftt >> 4)  ^ right) & 0x0f0f0f0fL;
+    right ^= work;
+    leftt ^= (work << 4);
+
+    work = ((leftt >> 16) ^ right) & 0x0000ffffL;
+    right ^= work;
+    leftt ^= (work << 16);
+
+    work = ((right >> 2)  ^ leftt) & 0x33333333L;
+    leftt ^= work;
+    right ^= (work << 2);
+
+    work = ((right >> 8)  ^ leftt) & 0x00ff00ffL;
+    leftt ^= work;
+    right ^= (work << 8);
+
+    right = ROL(right, 1);
+    work = (leftt ^ right) & 0xaaaaaaaaL;
+    
+    leftt ^= work;
+    right ^= work;
+    leftt = ROL(leftt, 1);
+#else 
+   {
+      ulong64 tmp;
+      tmp = des_ip[0][byte(leftt, 0)] ^
+            des_ip[1][byte(leftt, 1)] ^
+            des_ip[2][byte(leftt, 2)] ^
+            des_ip[3][byte(leftt, 3)] ^
+            des_ip[4][byte(right, 0)] ^
+            des_ip[5][byte(right, 1)] ^
+            des_ip[6][byte(right, 2)] ^
+            des_ip[7][byte(right, 3)];
+      leftt = (ulong32)(tmp >> 32);
+      right = (ulong32)(tmp & 0xFFFFFFFFUL);
+   }
+#endif
+
+    for (round = 0; round < 8; round++) {
+        work  = ROR(right, 4) ^ *keys++;
+        leftt ^= SP7[work        & 0x3fL]
+              ^ SP5[(work >>  8) & 0x3fL]
+              ^ SP3[(work >> 16) & 0x3fL]
+              ^ SP1[(work >> 24) & 0x3fL];
+        work  = right ^ *keys++;
+        leftt ^= SP8[ work        & 0x3fL]
+              ^  SP6[(work >>  8) & 0x3fL]
+              ^  SP4[(work >> 16) & 0x3fL]
+              ^  SP2[(work >> 24) & 0x3fL];
+
+        work = ROR(leftt, 4) ^ *keys++;
+        right ^= SP7[ work        & 0x3fL]
+              ^  SP5[(work >>  8) & 0x3fL]
+              ^  SP3[(work >> 16) & 0x3fL]
+              ^  SP1[(work >> 24) & 0x3fL];
+        work  = leftt ^ *keys++;
+        right ^= SP8[ work        & 0x3fL]
+              ^  SP6[(work >>  8) & 0x3fL]
+              ^  SP4[(work >> 16) & 0x3fL]
+              ^  SP2[(work >> 24) & 0x3fL];
+    }
+
+#ifdef SMALL_CODE    
+    right = ROR(right, 1);
+    work = (leftt ^ right) & 0xaaaaaaaaL;
+    leftt ^= work;
+    right ^= work;
+    leftt = ROR(leftt, 1);
+    work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
+    right ^= work;
+    leftt ^= (work << 8);
+    // --
+    work = ((leftt >> 2) ^ right) & 0x33333333L;
+    right ^= work;
+    leftt ^= (work << 2);
+    work = ((right >> 16) ^ leftt) & 0x0000ffffL;
+    leftt ^= work;
+    right ^= (work << 16);
+    work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
+    leftt ^= work;
+    right ^= (work << 4);
+#else 
+   {
+      ulong64 tmp;
+      tmp = des_fp[0][byte(leftt, 0)] ^
+            des_fp[1][byte(leftt, 1)] ^
+            des_fp[2][byte(leftt, 2)] ^
+            des_fp[3][byte(leftt, 3)] ^
+            des_fp[4][byte(right, 0)] ^
+            des_fp[5][byte(right, 1)] ^
+            des_fp[6][byte(right, 2)] ^
+            des_fp[7][byte(right, 3)];
+      leftt = (ulong32)(tmp >> 32);
+      right = (ulong32)(tmp & 0xFFFFFFFFUL);
+   }
+#endif
+    
+    block[0] = right;
+    block[1] = leftt;
+}
+
+#ifdef CLEAN_STACK
+static void desfunc(ulong32 *block, const ulong32 *keys)
+{
+   _desfunc(block, keys);
+   burn_stack(sizeof(ulong32) * 4 + sizeof(int));
+}
+#endif
+
+int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+    _ARGCHK(key != NULL);
+    _ARGCHK(skey != NULL);
+
+    if (num_rounds != 0 && num_rounds != 16) {
+        return CRYPT_INVALID_ROUNDS;
+    }
+
+    if (keylen != 8) {
+        return CRYPT_INVALID_KEYSIZE;
+    }
+
+    deskey(key, EN0, skey->des.ek);
+    deskey(key, DE1, skey->des.dk);
+
+    return CRYPT_OK;
+}
+
+int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+    _ARGCHK(key != NULL);
+    _ARGCHK(skey != NULL);
+
+    if( num_rounds != 0 && num_rounds != 16) {
+        return CRYPT_INVALID_ROUNDS;
+    }
+
+    if (keylen != 24) {
+        return CRYPT_INVALID_KEYSIZE;
+    }
+
+    deskey(key,    EN0, skey->des3.ek[0]);
+    deskey(key+8,  DE1, skey->des3.ek[1]);
+    deskey(key+16, EN0, skey->des3.ek[2]);
+
+    deskey(key,    DE1, skey->des3.dk[2]);
+    deskey(key+8,  EN0, skey->des3.dk[1]);
+    deskey(key+16, DE1, skey->des3.dk[0]);
+
+    return CRYPT_OK;
+}
+
+void des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+{
+    ulong32 work[2];
+    _ARGCHK(pt != NULL);
+    _ARGCHK(ct != NULL);
+    _ARGCHK(key != NULL);
+    LOAD32H(work[0], pt+0);
+    LOAD32H(work[1], pt+4);
+    desfunc(work, key->des.ek);
+    STORE32H(work[0],ct+0);
+    STORE32H(work[1],ct+4);
+}
+
+void des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+{
+    ulong32 work[2];
+    _ARGCHK(pt != NULL);
+    _ARGCHK(ct != NULL);
+    _ARGCHK(key != NULL);
+    LOAD32H(work[0], ct+0);
+    LOAD32H(work[1], ct+4);
+    desfunc(work, key->des.dk);
+    STORE32H(work[0],pt+0);
+    STORE32H(work[1],pt+4);
+}
+
+void des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+{
+    ulong32 work[2];
+    
+    _ARGCHK(pt != NULL);
+    _ARGCHK(ct != NULL);
+    _ARGCHK(key != NULL);
+    LOAD32H(work[0], pt+0);
+    LOAD32H(work[1], pt+4);
+    desfunc(work, key->des3.ek[0]);
+    desfunc(work, key->des3.ek[1]);
+    desfunc(work, key->des3.ek[2]);
+    STORE32H(work[0],ct+0);
+    STORE32H(work[1],ct+4);
+}
+
+void des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+{
+    ulong32 work[2];
+    _ARGCHK(pt != NULL);
+    _ARGCHK(ct != NULL);
+    _ARGCHK(key != NULL);
+    LOAD32H(work[0], ct+0);
+    LOAD32H(work[1], ct+4);
+    desfunc(work, key->des3.dk[0]);
+    desfunc(work, key->des3.dk[1]);
+    desfunc(work, key->des3.dk[2]);
+    STORE32H(work[0],pt+0);
+    STORE32H(work[1],pt+4);
+}
+
+int des_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+    int err;
+    static const struct des_test_case {
+        int num, mode; // mode 1 = encrypt
+        unsigned char key[8], txt[8], out[8];
+    } cases[] = {
+        { 1, 1,     { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A },
+                    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                    { 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 } },
+        { 2, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 },
+                    { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+        { 3, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 },
+                    { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+        { 4, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA },
+                    { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+        { 5, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F },
+                    { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+        { 6, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 },
+                    { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+        { 7, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF },
+                    { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+        { 8, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F },
+                    { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+        { 9, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 }, 
+                    { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+        {10, 1,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A },
+                    { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+
+        { 1, 0,     { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A },
+                    { 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 },
+                    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+        { 2, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                    { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 } },
+        { 3, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                    { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 } },
+        { 4, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                    { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA } },
+        { 5, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                    { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F } },
+        { 6, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                    { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 } },
+        { 7, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                    { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF } },
+        { 8, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                    { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F } },
+        { 9, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                    { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 } }, 
+        {10, 0,     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+                    { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+                    { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A } }
+
+        /*** more test cases you could add if you are not convinced (the above test cases aren't really too good):
+
+                key              plaintext        ciphertext
+                0000000000000000 0000000000000000 8CA64DE9C1B123A7
+                FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 7359B2163E4EDC58
+                3000000000000000 1000000000000001 958E6E627A05557B
+                1111111111111111 1111111111111111 F40379AB9E0EC533
+                0123456789ABCDEF 1111111111111111 17668DFC7292532D
+                1111111111111111 0123456789ABCDEF 8A5AE1F81AB8F2DD
+                0000000000000000 0000000000000000 8CA64DE9C1B123A7
+                FEDCBA9876543210 0123456789ABCDEF ED39D950FA74BCC4
+                7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B
+                0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271
+                07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A
+                3849674C2602319E 51454B582DDF440A 7178876E01F19B2A
+                04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095
+                0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B
+                0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09
+                43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A
+                07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F
+                04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088
+                37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77
+                1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A
+                584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56
+                025816164629B007 480D39006EE762F2 A1F9915541020B56
+                49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556
+                4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC
+                49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A
+                018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41
+                1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793
+                0101010101010101 0123456789ABCDEF 617B3A0CE8F07100
+                1F1F1F1F0E0E0E0E 0123456789ABCDEF DB958605F8C8C606
+                E0FEE0FEF1FEF1FE 0123456789ABCDEF EDBFD1C66C29CCC7
+                0000000000000000 FFFFFFFFFFFFFFFF 355550B2150E2451
+                FFFFFFFFFFFFFFFF 0000000000000000 CAAAAF4DEAF1DBAE
+                0123456789ABCDEF 0000000000000000 D5D44FF720683D0D
+                FEDCBA9876543210 FFFFFFFFFFFFFFFF 2A2BB008DF97C2F2
+
+            http://www.ecs.soton.ac.uk/~prw99r/ez438/vectors.txt
+        ***/
+    };
+    int i, y;
+    unsigned char tmp[8];
+    symmetric_key des;
+
+    for(i=0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++)
+    {
+        if ((err = des_setup(cases[i].key, 8, 0, &des)) != CRYPT_OK) {
+           return err;
+        }
+        if (cases[i].mode != 0) { 
+           des_ecb_encrypt(cases[i].txt, tmp, &des);
+        } else {
+           des_ecb_decrypt(cases[i].txt, tmp, &des);
+        }
+
+        if (memcmp(cases[i].out, tmp, sizeof(tmp)) != 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[y] = 0;
+      for (y = 0; y < 1000; y++) des_ecb_encrypt(tmp, tmp, &des);
+      for (y = 0; y < 1000; y++) des_ecb_decrypt(tmp, tmp, &des);
+      for (y = 0; y < 8; y++) if (tmp[y] != 0) return CRYPT_FAIL_TESTVECTOR;
+}
+
+    return CRYPT_OK;
+  #endif
+}
+
+int des3_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+   unsigned char key[24], pt[8], ct[8], tmp[8];
+   symmetric_key skey;
+   int x, err;
+
+   if ((err = des_test()) != CRYPT_OK) {
+      return err;
+   }
+
+   for (x = 0; x < 8; x++) {
+       pt[x] = x;
+   }
+   
+   for (x = 0; x < 24; x++) {
+       key[x] = x;
+   }
+
+   if ((err = des3_setup(key, 24, 0, &skey)) != CRYPT_OK) {
+      return err;
+   }
+   
+   des3_ecb_encrypt(pt, ct, &skey);
+   des3_ecb_decrypt(ct, tmp, &skey);
+   
+   if (memcmp(pt, tmp, 8) != 0) {
+      return CRYPT_FAIL_TESTVECTOR;
+   }
+   
+   return CRYPT_OK;
+ #endif
+}
+
+int des_keysize(int *desired_keysize)
+{
+    _ARGCHK(desired_keysize != NULL);
+    if(*desired_keysize < 8) {
+        return CRYPT_INVALID_KEYSIZE;
+    }
+    *desired_keysize = 8;
+    return CRYPT_OK;
+}
+
+int des3_keysize(int *desired_keysize)
+{
+    _ARGCHK(desired_keysize != NULL);
+    if(*desired_keysize < 24) {
+        return CRYPT_INVALID_KEYSIZE;
+    }
+    *desired_keysize = 24;
+    return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dh.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,452 @@
+/* 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 MDH
+
+/* This holds the key settings.  ***MUST*** be organized by size from smallest to largest. */
+static const struct {
+    int size;
+    char *name, *base, *prime;
+} sets[] = {
+#ifdef DH768
+{
+   96,
+   "DH-768",
+   "4",
+   "F///////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "//////m3wvV"
+},
+#endif
+#ifdef DH1024
+{
+   128,
+   "DH-1024",
+   "4",
+   "F///////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////m3C47"
+},
+#endif
+#ifdef DH1280
+{
+   160,
+   "DH-1280",
+   "4",
+   "F///////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "//////////////////////////////m4kSN"
+},
+#endif
+#ifdef DH1536
+{
+   192,
+   "DH-1536",
+   "4",
+   "F///////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////m5uqd"
+},
+#endif
+#ifdef DH1792
+{
+   224,
+   "DH-1792",
+   "4",
+   "F///////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "//////////////////////////////////////////////////////mT/sd"
+},
+#endif
+#ifdef DH2048
+{
+   256,
+   "DH-2048",
+   "4",
+   "3///////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "/////////////////////////////////////////m8MPh"
+},
+#endif
+#ifdef DH2560
+{
+   320,
+   "DH-2560",
+   "4",
+   "3///////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "/////mKFpF"
+},
+#endif
+#ifdef DH3072
+{
+   384,
+   "DH-3072",
+   "4",
+   "3///////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "/////////////////////////////m32nN"
+},
+#endif
+#ifdef DH4096
+{
+   512,
+   "DH-4096",
+   "4",
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "////////////////////////////////////////////////////////////"
+   "/////////////////////m8pOF"
+},
+#endif
+{
+   0,
+   NULL,
+   NULL,
+   NULL
+}
+};
+
+static int is_valid_idx(int n)
+{
+   int x;
+
+   for (x = 0; sets[x].size; x++);
+   if ((n < 0) || (n >= x)) {
+      return 0;
+   }
+   return 1;
+}
+
+int dh_test(void)
+{
+    mp_int p, g, tmp;
+    int x, err, primality;
+
+    if ((err = mp_init_multi(&p, &g, &tmp, NULL)) != MP_OKAY)                 { goto error; }
+
+    for (x = 0; sets[x].size != 0; x++) {
+#if 0
+        printf("dh_test():testing size %d-bits\n", sets[x].size * 8);
+#endif
+        if ((err = mp_read_radix(&g,(char *)sets[x].base, 64)) != MP_OKAY)    { goto error; }
+        if ((err = mp_read_radix(&p,(char *)sets[x].prime, 64)) != MP_OKAY)   { goto error; }
+
+        /* ensure p is prime */
+        if ((err = is_prime(&p, &primality)) != CRYPT_OK)                     { goto done; }
+        if (primality == 0) {
+           err = CRYPT_FAIL_TESTVECTOR;
+           goto done;
+        }
+
+        if ((err = mp_sub_d(&p, 1, &tmp)) != MP_OKAY)                         { goto error; }
+        if ((err = mp_div_2(&tmp, &tmp)) != MP_OKAY)                          { goto error; }
+
+        /* ensure (p-1)/2 is prime */
+        if ((err = is_prime(&tmp, &primality)) != CRYPT_OK)                   { goto done; }
+        if (primality == 0) {
+           err = CRYPT_FAIL_TESTVECTOR;
+           goto done;
+        }
+
+        /* now see if g^((p-1)/2) mod p is in fact 1 */
+        if ((err = mp_exptmod(&g, &tmp, &p, &tmp)) != MP_OKAY)                { goto error; }
+        if (mp_cmp_d(&tmp, 1)) {
+           err = CRYPT_FAIL_TESTVECTOR;
+           goto done;
+        }
+    }
+    err = CRYPT_OK;
+    goto done;
+error:
+    err = mpi_to_ltc_error(err);
+done:
+    mp_clear_multi(&tmp, &g, &p, NULL);
+    return err;
+}
+
+void dh_sizes(int *low, int *high)
+{
+   int x;
+   _ARGCHK(low != NULL);
+   _ARGCHK(high != NULL);
+   *low  = INT_MAX;
+   *high = 0;
+   for (x = 0; sets[x].size != 0; x++) {
+       if (*low > sets[x].size)  *low  = sets[x].size;
+       if (*high < sets[x].size) *high = sets[x].size;
+   }
+}
+
+int dh_get_size(dh_key *key)
+{
+    _ARGCHK(key != NULL);
+    if (is_valid_idx(key->idx) == 1) {
+        return sets[key->idx].size;
+    } else {
+        return INT_MAX; /* large value that would cause dh_make_key() to fail */
+    }
+}
+
+int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key)
+{
+   unsigned char buf[512];
+   unsigned long x;
+   mp_int p, g;
+   int err;
+
+   _ARGCHK(key  != NULL);
+
+   /* good prng? */
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* find key size */
+   for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++);
+#ifdef FAST_PK
+   keysize = MIN(sets[x].size, 32);
+#else
+   keysize = sets[x].size;
+#endif
+
+   if (sets[x].size == 0) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+   key->idx = x;
+
+   /* make up random string */
+   if (prng_descriptor[wprng].read(buf, keysize, prng) != (unsigned long)keysize) {
+      return CRYPT_ERROR_READPRNG;
+   }
+
+   /* init parameters */
+   if ((err = mp_init_multi(&g, &p, &key->x, &key->y, NULL)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+   if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY)      { goto error; }
+   if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY)     { goto error; }
+
+   /* load the x value */
+   if ((err = mp_read_unsigned_bin(&key->x, buf, keysize)) != MP_OKAY)     { goto error; }
+   if ((err = mp_exptmod(&g, &key->x, &p, &key->y)) != MP_OKAY)            { goto error; }
+   key->type = PK_PRIVATE;
+
+   if ((err = mp_shrink(&key->x)) != MP_OKAY)                              { goto error; }
+   if ((err = mp_shrink(&key->y)) != MP_OKAY)                              { goto error; }
+
+   /* free up ram */
+   err = CRYPT_OK;
+   goto done;
+error:
+   err = mpi_to_ltc_error(err);
+   mp_clear_multi(&key->x, &key->y, NULL);
+done:
+   mp_clear_multi(&p, &g, NULL);
+   zeromem(buf, sizeof(buf));
+   return err;
+}
+
+void dh_free(dh_key *key)
+{
+   _ARGCHK(key != NULL);
+   mp_clear_multi(&key->x, &key->y, NULL);
+}
+
+int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key)
+{
+   unsigned long y, z;
+   int err;
+
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+
+   /* can we store the static header?  */
+   if (*outlen < (PACKET_SIZE + 2)) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   
+   if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   /* header */
+   y = PACKET_SIZE;
+
+   /* header */
+   out[y++] = type;
+   out[y++] = (unsigned char)(sets[key->idx].size / 8);
+
+   /* export y */
+   OUTPUT_BIGNUM(&key->y, out, y, z);
+
+   if (type == PK_PRIVATE) {
+      /* export x */
+      OUTPUT_BIGNUM(&key->x, out, y, z);
+   }
+
+   /* store header */
+   packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_KEY);
+
+   /* store len */
+   *outlen = y;
+   return CRYPT_OK;
+}
+
+int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key)
+{
+   unsigned long x, y, s;
+   int err;
+
+   _ARGCHK(in  != NULL);
+   _ARGCHK(key != NULL);
+
+   /* make sure valid length */
+   if ((2+PACKET_SIZE) > inlen) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* check type byte */
+   if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_KEY)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* init */
+   if ((err = mp_init_multi(&key->x, &key->y, NULL)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+
+   /* advance past packet header */
+   y = PACKET_SIZE;
+
+   /* key type, e.g. private, public */
+   key->type = (int)in[y++];
+
+   /* key size in bytes */
+   s  = (unsigned long)in[y++] * 8;
+
+   for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++);
+   if (sets[x].size == 0) {
+      err = CRYPT_INVALID_KEYSIZE;
+      goto error;
+   }
+   key->idx = (int)x;
+
+   /* type check both values */
+   if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE))  {
+      err = CRYPT_PK_TYPE_MISMATCH;
+      goto error;
+   }
+
+   /* is the key idx valid? */
+   if (is_valid_idx(key->idx) != 1) {
+      err = CRYPT_PK_TYPE_MISMATCH;
+      goto error;
+   }
+
+   /* load public value g^x mod p*/
+   INPUT_BIGNUM(&key->y, in, x, y, inlen);
+
+   if (key->type == PK_PRIVATE) {
+      INPUT_BIGNUM(&key->x, in, x, y, inlen);
+   }
+
+   /* eliminate private key if public */
+   if (key->type == PK_PUBLIC) {
+      mp_clear(&key->x);
+   }
+
+   return CRYPT_OK;
+error:
+   mp_clear_multi(&key->y, &key->x, NULL);
+   return err;
+}
+
+int dh_shared_secret(dh_key *private_key, dh_key *public_key,
+                     unsigned char *out, unsigned long *outlen)
+{
+   mp_int tmp, p;
+   unsigned long x;
+   int err;
+
+   _ARGCHK(private_key != NULL);
+   _ARGCHK(public_key  != NULL);
+   _ARGCHK(out         != NULL);
+   _ARGCHK(outlen      != NULL);
+
+   /* types valid? */
+   if (private_key->type != PK_PRIVATE) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   /* same idx? */
+   if (private_key->idx != public_key->idx) {
+      return CRYPT_PK_TYPE_MISMATCH;
+   }
+
+   /* compute y^x mod p */
+   if ((err = mp_init_multi(&tmp, &p, NULL)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+
+   if ((err = mp_read_radix(&p, (char *)sets[private_key->idx].prime, 64)) != MP_OKAY)     { goto error; }
+   if ((err = mp_exptmod(&public_key->y, &private_key->x, &p, &tmp)) != MP_OKAY)           { goto error; }
+
+   /* enough space for output? */
+   x = (unsigned long)mp_unsigned_bin_size(&tmp);
+   if (*outlen < x) {
+      err = CRYPT_BUFFER_OVERFLOW;
+      goto done;
+   }
+   if ((err = mp_to_unsigned_bin(&tmp, out)) != MP_OKAY)                                   { goto error; }
+   *outlen = x;
+   err = CRYPT_OK;
+   goto done;
+error:
+   err = mpi_to_ltc_error(err);
+done:
+   mp_clear_multi(&p, &tmp, NULL);
+   return err;
+}
+
+#include "dh_sys.c"
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dh_sys.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,399 @@
+/* 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
+ */
+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)
+{
+    unsigned char pub_expt[768], dh_shared[768], skey[MAXBLOCKSIZE];
+    dh_key pubkey;
+    unsigned long x, y, z, hashsize, pubkeysize;
+    int err;
+
+    _ARGCHK(inkey != NULL);
+    _ARGCHK(out   != NULL);
+    _ARGCHK(len   != NULL);
+    _ARGCHK(key   != NULL);
+
+    /* check that wprng/hash are not invalid */
+    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+       return err;
+    }
+
+    if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+       return err;
+    }
+
+    if (keylen > hash_descriptor[hash].hashsize)  {
+        return CRYPT_INVALID_HASH;
+    }
+
+    /* make a random key and export the public copy */
+    if ((err = dh_make_key(prng, wprng, dh_get_size(key), &pubkey)) != CRYPT_OK) {
+       return err;
+    }
+
+    pubkeysize = sizeof(pub_expt);
+    if ((err = dh_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
+       dh_free(&pubkey);
+       return err;
+    }
+
+    /* now check if the out buffer is big enough */
+    if (*len < (1 + 4 + 4 + PACKET_SIZE + pubkeysize + keylen)) {
+       dh_free(&pubkey);
+       return CRYPT_BUFFER_OVERFLOW;
+    }
+
+    /* make random key */
+    hashsize  = hash_descriptor[hash].hashsize;
+
+    x = (unsigned long)sizeof(dh_shared);
+    if ((err = dh_shared_secret(&pubkey, key, dh_shared, &x)) != CRYPT_OK) {
+       dh_free(&pubkey);
+       return err;
+    }
+    dh_free(&pubkey);
+
+    z = sizeof(skey);
+    if ((err = hash_memory(hash, dh_shared, x, skey, &z)) != CRYPT_OK) {
+       return err;
+    }
+
+    /* store header */
+    packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENC_KEY);
+
+    /* output header */
+    y = PACKET_SIZE;
+
+    /* size of hash name and the name itself */
+    out[y++] = hash_descriptor[hash].ID;
+
+    /* length of DH pubkey and the key itself */
+    STORE32L(pubkeysize, out+y);
+    y += 4;
+    for (x = 0; x < pubkeysize; x++, y++) {
+        out[y] = pub_expt[x];
+    }
+
+    /* Store the encrypted key */
+    STORE32L(keylen, out+y);
+    y += 4;
+
+    for (x = 0; x < keylen; x++, y++) {
+      out[y] = skey[x] ^ inkey[x];
+    }
+    *len = y;
+
+#ifdef CLEAN_STACK
+    /* clean up */
+    zeromem(pub_expt, sizeof(pub_expt));
+    zeromem(dh_shared, sizeof(dh_shared));
+    zeromem(skey, sizeof(skey));
+#endif
+
+    return CRYPT_OK;
+}
+
+int dh_decrypt_key(const unsigned char *in, unsigned long inlen,
+                         unsigned char *outkey, unsigned long *keylen, 
+                         dh_key *key)
+{
+   unsigned char shared_secret[768], skey[MAXBLOCKSIZE];
+   unsigned long x, y, z,hashsize, keysize;
+   int  hash, err;
+   dh_key pubkey;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(outkey != NULL);
+   _ARGCHK(keylen != NULL);
+   _ARGCHK(key    != NULL);
+
+   /* right key type? */
+   if (key->type != PK_PRIVATE) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   /* check if initial header should fit */
+   if (inlen < PACKET_SIZE+1+4+4) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= PACKET_SIZE+1+4+4;
+   }
+
+   /* is header correct? */
+   if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_ENC_KEY)) != CRYPT_OK)  {
+      return err;
+   }
+
+   /* now lets get the hash name */
+   y = PACKET_SIZE;
+   hash = find_hash_id(in[y++]);
+   if (hash == -1) {
+      return CRYPT_INVALID_HASH;
+   }
+
+   /* common values */
+   hashsize  = hash_descriptor[hash].hashsize;
+
+   /* get public key */
+   LOAD32L(x, in+y);
+   
+   /* now check if the imported key will fit */
+   if (inlen < x) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= x;
+   }
+   
+   y += 4;
+   if ((err = dh_import(in+y, x, &pubkey)) != CRYPT_OK) {
+      return err;
+   }
+   y += x;
+
+   /* make shared key */
+   x = (unsigned long)sizeof(shared_secret);
+   if ((err = dh_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
+      dh_free(&pubkey);
+      return err;
+   }
+   dh_free(&pubkey);
+
+   z = sizeof(skey);
+   if ((err = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* load in the encrypted key */
+   LOAD32L(keysize, in+y);
+   
+   /* will the outkey fit as part of the input */
+   if (inlen < keysize) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= keysize;
+   }
+   
+   if (keysize > *keylen) {
+       err = CRYPT_BUFFER_OVERFLOW;
+       goto done;
+   }
+   y += 4;
+
+   *keylen = keysize;
+
+   for (x = 0; x < keysize; x++, y++) {
+      outkey[x] = skey[x] ^ in[y];
+   }
+
+   err = CRYPT_OK;
+done:
+#ifdef CLEAN_STACK
+   zeromem(shared_secret, sizeof(shared_secret));
+   zeromem(skey, sizeof(skey));
+#endif
+   return err;
+}
+
+/* perform an ElGamal Signature of a hash 
+ *
+ * The math works as follows.  x is the private key, M is the message to sign
+ 
+ 1.  pick a random k
+ 2.  compute a = g^k mod p
+ 3.  compute b = (M - xa)/k mod p
+ 4.  Send (a,b)
+ 
+ Now to verify with y=g^x mod p, a and b
+ 
+ 1.  compute y^a * a^b = g^(xa) * g^(k*(M-xa)/k)
+                       = g^(xa + (M - xa))
+                       = g^M [all mod p]
+                       
+ 2.  Compare against g^M mod p [based on input hash].
+ 3.  If result of #2 == result of #1 then signature valid 
+*/
+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)
+{
+   mp_int a, b, k, m, g, p, p1, tmp;
+   unsigned char buf[520];
+   unsigned long x, y;
+   int err;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+
+   /* check parameters */
+   if (key->type != PK_PRIVATE) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* is the IDX valid ?  */
+   if (is_valid_idx(key->idx) != 1) {
+      return CRYPT_PK_INVALID_TYPE;
+   }
+
+   /* make up a random value k,
+    * since the order of the group is prime
+    * we need not check if gcd(k, r) is 1 
+    */
+   if (prng_descriptor[wprng].read(buf, sets[key->idx].size, prng) != 
+       (unsigned long)(sets[key->idx].size)) {
+      return CRYPT_ERROR_READPRNG;
+   }
+
+   /* init bignums */
+   if ((err = mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL)) != MP_OKAY) { 
+      return mpi_to_ltc_error(err);
+   }
+
+   /* load k and m */
+   if ((err = mp_read_unsigned_bin(&m, (unsigned char *)in, inlen)) != MP_OKAY)        { goto error; }
+#ifdef FAST_PK   
+   if ((err = mp_read_unsigned_bin(&k, buf, MIN(32,sets[key->idx].size))) != MP_OKAY)  { goto error; }
+#else   
+   if ((err = mp_read_unsigned_bin(&k, buf, sets[key->idx].size)) != MP_OKAY)          { goto error; }
+#endif  
+
+   /* load g, p and p1 */
+   if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY)               { goto error; }
+   if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY)              { goto error; }
+   if ((err = mp_sub_d(&p, 1, &p1)) != MP_OKAY)                                     { goto error; }
+   if ((err = mp_div_2(&p1, &p1)) != MP_OKAY)                                       { goto error; } /* p1 = (p-1)/2 */
+
+   /* now get a = g^k mod p */
+   if ((err = mp_exptmod(&g, &k, &p, &a)) != MP_OKAY)                               { goto error; }
+
+   /* now find M = xa + kb mod p1 or just b = (M - xa)/k mod p1 */
+   if ((err = mp_invmod(&k, &p1, &k)) != MP_OKAY)                                   { goto error; } /* k = 1/k mod p1 */
+   if ((err = mp_mulmod(&a, &key->x, &p1, &tmp)) != MP_OKAY)                        { goto error; } /* tmp = xa */
+   if ((err = mp_submod(&m, &tmp, &p1, &tmp)) != MP_OKAY)                           { goto error; } /* tmp = M - xa */
+   if ((err = mp_mulmod(&k, &tmp, &p1, &b)) != MP_OKAY)                             { goto error; } /* b = (M - xa)/k */
+   
+   /* check for overflow */
+   if ((unsigned long)(PACKET_SIZE + 4 + 4 + mp_unsigned_bin_size(&a) + mp_unsigned_bin_size(&b)) > *outlen) {
+      err = CRYPT_BUFFER_OVERFLOW;
+      goto done;
+   }
+   
+   /* store header  */
+   y = PACKET_SIZE;
+
+   /* now store them both (a,b) */
+   x = (unsigned long)mp_unsigned_bin_size(&a);
+   STORE32L(x, out+y);  y += 4;
+   if ((err = mp_to_unsigned_bin(&a, out+y)) != MP_OKAY)                            { goto error; }
+   y += x;
+
+   x = (unsigned long)mp_unsigned_bin_size(&b);
+   STORE32L(x, out+y);  y += 4;
+   if ((err = mp_to_unsigned_bin(&b, out+y)) != MP_OKAY)                            { goto error; }
+   y += x;
+
+   /* check if size too big */
+   if (*outlen < y) {
+      err = CRYPT_BUFFER_OVERFLOW;
+      goto done;
+   }
+
+   /* store header */
+   packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_SIGNED);
+   *outlen = y;
+
+   err = CRYPT_OK;
+   goto done;
+error:
+   err = mpi_to_ltc_error(err);
+done:
+   mp_clear_multi(&tmp, &p1, &g, &p, &m, &k, &b, &a, NULL);
+   return err;
+}
+
+
+/* verify the signature in sig of the given hash */
+int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
+                   const unsigned char *hash, unsigned long hashlen, 
+                         int *stat, dh_key *key)
+{
+   mp_int a, b, p, g, m, tmp;
+   unsigned long x, y;
+   int err;
+
+   _ARGCHK(sig  != NULL);
+   _ARGCHK(hash != NULL);
+   _ARGCHK(stat != NULL);
+   _ARGCHK(key  != NULL);
+
+   /* default to invalid */
+   *stat = 0;
+
+   /* check initial input length */
+   if (siglen < PACKET_SIZE+4+4) {
+      return CRYPT_INVALID_PACKET;
+   } 
+
+   /* header ok? */
+   if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_DH, PACKET_SUB_SIGNED)) != CRYPT_OK) {
+      return err;
+   }
+   
+   /* get hash out of packet */
+   y = PACKET_SIZE;
+
+   /* init all bignums */
+   if ((err = mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL)) != MP_OKAY) { 
+      return mpi_to_ltc_error(err);
+   }
+
+   /* load a and b */
+   INPUT_BIGNUM(&a, sig, x, y, siglen);
+   INPUT_BIGNUM(&b, sig, x, y, siglen);
+
+   /* load p and g */
+   if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY)              { goto error1; }
+   if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY)               { goto error1; }
+
+   /* load m */
+   if ((err = mp_read_unsigned_bin(&m, (unsigned char *)hash, hashlen)) != MP_OKAY) { goto error1; }
+
+   /* find g^m mod p */
+   if ((err = mp_exptmod(&g, &m, &p, &m)) != MP_OKAY)                { goto error1; } /* m = g^m mod p */
+
+   /* find y^a * a^b */
+   if ((err = mp_exptmod(&key->y, &a, &p, &tmp)) != MP_OKAY)         { goto error1; } /* tmp = y^a mod p */
+   if ((err = mp_exptmod(&a, &b, &p, &a)) != MP_OKAY)                { goto error1; } /* a = a^b mod p */
+   if ((err = mp_mulmod(&a, &tmp, &p, &a)) != MP_OKAY)               { goto error1; } /* a = y^a * a^b mod p */
+
+   /* y^a * a^b == g^m ??? */
+   if (mp_cmp(&a, &m) == 0) {
+      *stat = 1;
+   }
+
+   /* clean up */
+   err = CRYPT_OK;
+   goto done;
+error1:
+   err = mpi_to_ltc_error(err);
+error:
+done:
+   mp_clear_multi(&tmp, &m, &g, &p, &b, &a, NULL);
+   return err;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dsa_export.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,62 @@
+/* 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 MDSA
+
+int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key)
+{
+   unsigned long y, z;
+   int err;
+
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+
+   /* can we store the static header?  */
+   if (*outlen < (PACKET_SIZE + 1 + 2)) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   
+   if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
+      return CRYPT_PK_TYPE_MISMATCH;
+   }
+
+   if (type != PK_PUBLIC && type != PK_PRIVATE) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* store header */
+   packet_store_header(out, PACKET_SECT_DSA, PACKET_SUB_KEY);
+   y = PACKET_SIZE;
+
+   /* store g, p, q, qord */
+   out[y++] = type;
+   out[y++] = (key->qord>>8)&255;
+   out[y++] = key->qord & 255;
+
+   OUTPUT_BIGNUM(&key->g,out,y,z);
+   OUTPUT_BIGNUM(&key->p,out,y,z);
+   OUTPUT_BIGNUM(&key->q,out,y,z);
+
+   /* public exponent */
+   OUTPUT_BIGNUM(&key->y,out,y,z);
+   
+   if (type == PK_PRIVATE) {
+      OUTPUT_BIGNUM(&key->x,out,y,z);
+   }
+
+   *outlen = y;
+   return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dsa_free.c	Mon May 31 18:25:41 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"
+
+#ifdef MDSA
+
+void dsa_free(dsa_key *key)
+{
+   _ARGCHK(key != NULL);
+   mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dsa_import.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,59 @@
+/* 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 MDSA
+
+int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
+{
+   unsigned long x, y;
+   int err;
+
+   _ARGCHK(in  != NULL);
+   _ARGCHK(key != NULL);
+
+   /* check length */
+   if ((1+2+PACKET_SIZE) > inlen) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* check type */
+   if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DSA, PACKET_SUB_KEY)) != CRYPT_OK) {
+      return err;
+   }
+   y = PACKET_SIZE;
+
+   /* init key */
+   if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL) != MP_OKAY) {
+      return CRYPT_MEM;
+   }
+
+   /* read type/qord */
+   key->type = in[y++];
+   key->qord = ((unsigned)in[y]<<8)|((unsigned)in[y+1]);
+   y += 2;
+
+   /* input publics */
+   INPUT_BIGNUM(&key->g,in,x,y, inlen);
+   INPUT_BIGNUM(&key->p,in,x,y, inlen);
+   INPUT_BIGNUM(&key->q,in,x,y, inlen);
+   INPUT_BIGNUM(&key->y,in,x,y, inlen);
+   if (key->type == PK_PRIVATE) {
+      INPUT_BIGNUM(&key->x,in,x,y, inlen);
+   }
+
+   return CRYPT_OK;
+error: 
+   mp_clear_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL);
+   return err;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dsa_make_key.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,117 @@
+/* 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 MDSA
+
+int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key)
+{
+   mp_int tmp, tmp2;
+   int err, res;
+   unsigned char buf[512];
+
+   _ARGCHK(key  != NULL);
+
+   /* check prng */
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* check size */
+   if (group_size >= 1024 || group_size <= 15 || 
+       group_size >= modulus_size || (modulus_size - group_size) >= (int)sizeof(buf)) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* init mp_ints  */
+   if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+
+   /* make our prime q */
+   if ((err = rand_prime(&key->q, group_size*8, prng, wprng)) != CRYPT_OK)             { goto error2; }
+
+   /* double q  */
+   if ((err = mp_mul_2(&key->q, &tmp)) != MP_OKAY)                                   { goto error; }
+
+   /* now make a random string and multply it against q */
+   if (prng_descriptor[wprng].read(buf+1, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) {
+      err = CRYPT_ERROR_READPRNG;
+      goto error2;
+   }
+
+   /* force magnitude */
+   buf[0] = 1;
+
+   /* force even */
+   buf[modulus_size - group_size] &= ~1;
+
+   if ((err = mp_read_unsigned_bin(&tmp2, buf, modulus_size - group_size+1)) != MP_OKAY) { goto error; }
+   if ((err = mp_mul(&key->q, &tmp2, &key->p)) != MP_OKAY)                             { goto error; }
+   if ((err = mp_add_d(&key->p, 1, &key->p)) != MP_OKAY)                               { goto error; }
+   
+   /* now loop until p is prime */
+   for (;;) {
+       if ((err = is_prime(&key->p, &res)) != CRYPT_OK)                                { goto error2; }
+       if (res == MP_YES) break;
+
+       /* add 2q to p and 2 to tmp2 */
+       if ((err = mp_add(&tmp, &key->p, &key->p)) != MP_OKAY)                          { goto error; }
+       if ((err = mp_add_d(&tmp2, 2, &tmp2)) != MP_OKAY)                               { goto error; }
+   }
+
+   /* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */
+   mp_set(&key->g, 1);
+
+   do {
+      if ((err = mp_add_d(&key->g, 1, &key->g)) != MP_OKAY)                            { goto error; }
+      if ((err = mp_exptmod(&key->g, &tmp2, &key->p, &tmp)) != MP_OKAY)                { goto error; }
+   } while (mp_cmp_d(&tmp, 1) == MP_EQ);
+
+   /* at this point tmp generates a group of order q mod p */
+   mp_exch(&tmp, &key->g);
+
+   /* so now we have our DH structure, generator g, order q, modulus p 
+      Now we need a random exponent [mod q] and it's power g^x mod p 
+    */
+   do {
+      if (prng_descriptor[wprng].read(buf, group_size, prng) != (unsigned long)group_size) {
+         err = CRYPT_ERROR_READPRNG;
+         goto error2;
+      }
+      if ((err = mp_read_unsigned_bin(&key->x, buf, group_size)) != MP_OKAY)           { goto error; }
+   } while (mp_cmp_d(&key->x, 1) != MP_GT);
+   if ((err = mp_exptmod(&key->g, &key->x, &key->p, &key->y)) != MP_OKAY)              { goto error; }
+   
+   key->type = PK_PRIVATE;
+   key->qord = group_size;
+
+   /* shrink the ram required */
+   if ((err = mp_shrink(&key->g)) != MP_OKAY)                                          { goto error; }
+   if ((err = mp_shrink(&key->p)) != MP_OKAY)                                          { goto error; }
+   if ((err = mp_shrink(&key->q)) != MP_OKAY)                                          { goto error; }
+   if ((err = mp_shrink(&key->x)) != MP_OKAY)                                          { goto error; }
+   if ((err = mp_shrink(&key->y)) != MP_OKAY)                                          { goto error; }
+
+   err = CRYPT_OK;
+
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+
+   goto done;
+error : err = mpi_to_ltc_error(err);
+error2: mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
+done  : mp_clear_multi(&tmp, &tmp2, NULL);
+   return err;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dsa_sign_hash.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,125 @@
+/* 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 MDSA
+
+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)
+{
+   mp_int k, kinv, tmp, r, s;
+   unsigned char buf[512];
+   int err, y;
+   unsigned long len;
+
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err;
+   }
+   if (key->type != PK_PRIVATE) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   /* check group order size  */
+   if (key->qord >= (int)sizeof(buf)) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* Init our temps */
+   if ((err = mp_init_multi(&k, &kinv, &r, &s, &tmp, NULL)) != MP_OKAY)               { goto error; }
+
+retry:
+
+   do {
+      /* gen random k */
+      if (prng_descriptor[wprng].read(buf, key->qord, prng) != (unsigned long)key->qord) {
+         err = CRYPT_ERROR_READPRNG;
+         goto done;
+      }
+
+      /* read k */
+      if ((err = mp_read_unsigned_bin(&k, buf, key->qord)) != MP_OKAY)                { goto error; }
+
+      /* k > 1 ? */
+      if (mp_cmp_d(&k, 1) != MP_GT)                                                   { goto retry; }
+
+      /* test gcd */
+      if ((err = mp_gcd(&k, &key->q, &tmp)) != MP_OKAY)                               { goto error; }
+   } while (mp_cmp_d(&tmp, 1) != MP_EQ);
+
+   /* now find 1/k mod q */
+   if ((err = mp_invmod(&k, &key->q, &kinv)) != MP_OKAY)                              { goto error; }
+
+   /* now find r = g^k mod p mod q */
+   if ((err = mp_exptmod(&key->g, &k, &key->p, &r)) != MP_OKAY)                       { goto error; }
+   if ((err = mp_mod(&r, &key->q, &r)) != MP_OKAY)                                    { goto error; }
+
+   if (mp_iszero(&r) == MP_YES)                                                       { goto retry; }
+
+   /* now find s = (in + xr)/k mod q */
+   if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, inlen)) != MP_OKAY)     { goto error; }
+   if ((err = mp_mul(&key->x, &r, &s)) != MP_OKAY)                                    { goto error; }
+   if ((err = mp_add(&s, &tmp, &s)) != MP_OKAY)                                       { goto error; }
+   if ((err = mp_mulmod(&s, &kinv, &key->q, &s)) != MP_OKAY)                          { goto error; }
+
+   if (mp_iszero(&s) == MP_YES)                                                       { goto retry; }
+
+   /* now store em both */
+   
+   /* first check that we have enough room */
+   if (*outlen < (unsigned long)(PACKET_SIZE + 4 + mp_unsigned_bin_size(&s) + mp_unsigned_bin_size(&r))) {
+      err = CRYPT_BUFFER_OVERFLOW;
+      goto done;
+   }
+
+   /* packet header */
+   packet_store_header(out, PACKET_SECT_DSA, PACKET_SUB_SIGNED);
+   y = PACKET_SIZE;
+
+   /* store length of r */
+   len = mp_unsigned_bin_size(&r);
+   out[y++] = (len>>8)&255;
+   out[y++] = len&255;
+   
+   /* store r */
+   if ((err = mp_to_unsigned_bin(&r, out+y)) != MP_OKAY)                              { goto error; }
+   y += len;
+
+   /* store length of s */
+   len = mp_unsigned_bin_size(&s);
+   out[y++] = (len>>8)&255;
+   out[y++] = len&255;
+   
+   /* store s */
+   if ((err = mp_to_unsigned_bin(&s, out+y)) != MP_OKAY)                              { goto error; }
+   y += len;
+
+   /* reset size */
+   *outlen = y;
+
+   err = CRYPT_OK;
+   goto done;
+
+error : err = mpi_to_ltc_error(err);
+done  : mp_clear_multi(&k, &kinv, &r, &s, &tmp, NULL);
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+   return err;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dsa_verify_hash.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,97 @@
+/* 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 MDSA
+
+int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+                    const unsigned char *hash, unsigned long inlen, 
+                    int *stat, dsa_key *key)
+{
+   mp_int r, s, w, v, u1, u2;
+   unsigned long x, y;
+   int err;
+
+   _ARGCHK(sig  != NULL);
+   _ARGCHK(hash != NULL);
+   _ARGCHK(stat != NULL);
+   _ARGCHK(key  != NULL);
+
+   /* default to invalid signature */
+   *stat = 0;
+
+   if (siglen < PACKET_SIZE+2+2) {
+      return CRYPT_INVALID_PACKET;
+   } 
+
+   /* is the message format correct? */
+   if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_DSA, PACKET_SUB_SIGNED)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* skip over header */
+   y = PACKET_SIZE;
+
+   /* init our variables */
+   if ((err = mp_init_multi(&r, &s, &w, &v, &u1, &u2, NULL)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+
+   /* read in r followed by s */
+   x = ((unsigned)sig[y]<<8)|((unsigned)sig[y+1]);
+   y += 2;
+   if (y + x > siglen) { 
+      err = CRYPT_INVALID_PACKET;
+      goto done;
+   }
+   if ((err = mp_read_unsigned_bin(&r, (unsigned char *)sig+y, x)) != MP_OKAY)             { goto error; }
+   y += x;
+
+   /* load s */
+   x = ((unsigned)sig[y]<<8)|((unsigned)sig[y+1]);
+   y += 2;
+   if (y + x > siglen) { 
+      err = CRYPT_INVALID_PACKET;
+      goto done;
+   }
+   if ((err = mp_read_unsigned_bin(&s, (unsigned char *)sig+y, x)) != MP_OKAY)             { goto error; }
+
+   /* w = 1/s mod q */
+   if ((err = mp_invmod(&s, &key->q, &w)) != MP_OKAY)                                      { goto error; }
+
+   /* u1 = m * w mod q */
+   if ((err = mp_read_unsigned_bin(&u1, (unsigned char *)hash, inlen)) != MP_OKAY)         { goto error; }
+   if ((err = mp_mulmod(&u1, &w, &key->q, &u1)) != MP_OKAY)                                { goto error; }
+
+   /* u2 = r*w mod q */
+   if ((err = mp_mulmod(&r, &w, &key->q, &u2)) != MP_OKAY)                                 { goto error; } 
+
+   /* v = g^u1 * y^u2 mod p mod q */
+   if ((err = mp_exptmod(&key->g, &u1, &key->p, &u1)) != MP_OKAY)                          { goto error; }
+   if ((err = mp_exptmod(&key->y, &u2, &key->p, &u2)) != MP_OKAY)                          { goto error; }
+   if ((err = mp_mulmod(&u1, &u2, &key->p, &v)) != MP_OKAY)                                { goto error; }
+   if ((err = mp_mod(&v, &key->q, &v)) != MP_OKAY)                                         { goto error; }
+
+   /* if r = v then we're set */
+   if (mp_cmp(&r, &v) == MP_EQ) {
+      *stat = 1;
+   }
+
+   err = CRYPT_OK;
+   goto done;
+
+error : err = mpi_to_ltc_error(err);
+done  : mp_clear_multi(&r, &s, &w, &v, &u1, &u2, NULL);
+   return err;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dsa_verify_key.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,86 @@
+/* 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 MDSA
+
+int dsa_verify_key(dsa_key *key, int *stat)
+{
+   mp_int tmp, tmp2;
+   int res, err;
+
+   _ARGCHK(key  != NULL);
+   _ARGCHK(stat != NULL);
+
+   *stat = 0;
+
+   /* first make sure key->q and key->p are prime */
+   if ((err = is_prime(&key->q, &res)) != CRYPT_OK) {
+      return err;
+   }
+   if (res == 0) {
+      return CRYPT_OK;
+   }
+
+
+   if ((err = is_prime(&key->p, &res)) != CRYPT_OK) {
+      return err;
+   }
+   if (res == 0) {
+      return CRYPT_OK;
+   }
+
+   /* now make sure that g is not -1, 0 or 1 and <p */
+   if (mp_cmp_d(&key->g, 0) == MP_EQ || mp_cmp_d(&key->g, 1) == MP_EQ) {
+      return CRYPT_OK;
+   }
+   if ((err = mp_init_multi(&tmp, &tmp2, NULL)) != MP_OKAY)               { goto error; }
+   if ((err = mp_sub_d(&key->p, 1, &tmp)) != MP_OKAY)                     { goto error; }
+   if (mp_cmp(&tmp, &key->g) == MP_EQ || mp_cmp(&key->g, &key->p) != MP_LT) {
+      err = CRYPT_OK;
+      goto done;
+   }
+
+   /* 1 < y < p-1 */
+   if (!(mp_cmp_d(&key->y, 1) == MP_GT && mp_cmp(&key->y, &tmp) == MP_LT)) {
+      err = CRYPT_OK;
+      goto done;
+   }
+
+   /* now we have to make sure that g^q = 1, and that p-1/q gives 0 remainder */
+   if ((err = mp_div(&tmp, &key->q, &tmp, &tmp2)) != MP_OKAY)             { goto error; }
+   if (mp_iszero(&tmp2) != MP_YES) {
+      err = CRYPT_OK;
+      goto done;
+   }
+
+   if ((err = mp_exptmod(&key->g, &key->q, &key->p, &tmp)) != MP_OKAY)    { goto error; }
+   if (mp_cmp_d(&tmp, 1) != MP_EQ) {
+      err = CRYPT_OK;
+      goto done;
+   }
+
+   /* now we have to make sure that y^q = 1, this makes sure y \in g^x mod p */
+   if ((err = mp_exptmod(&key->y, &key->q, &key->p, &tmp)) != MP_OKAY)       { goto error; }
+   if (mp_cmp_d(&tmp, 1) != MP_EQ) {
+      err = CRYPT_OK;
+      goto done;
+   }
+
+   /* at this point we are out of tests ;-( */
+   err   = CRYPT_OK;
+   *stat = 1;
+   goto done;
+error: err = mpi_to_ltc_error(err);
+done : mp_clear_multi(&tmp, &tmp2, NULL);
+   return err;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eax_addheader.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,25 @@
+/* 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
+ */
+
+/* EAX Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef EAX_MODE
+
+/* add header (metadata) to the stream */
+int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length)
+{
+   _ARGCHK(eax    != NULL);
+   _ARGCHK(header != NULL);
+   return omac_process(&eax->headeromac, header, length);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eax_decrypt.c	Mon May 31 18:25:41 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
+ */
+
+/* EAX Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef EAX_MODE
+
+int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length)
+{
+   int err;
+   
+   _ARGCHK(eax != NULL);
+   _ARGCHK(pt  != NULL);
+   _ARGCHK(ct  != NULL);
+
+   /* omac ciphertext */
+   if ((err = omac_process(&eax->ctomac, ct, length)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* decrypt  */
+   return ctr_decrypt(ct, pt, length, &eax->ctr);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eax_decrypt_verify_memory.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,60 @@
+/* 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
+ */
+
+/* EAX Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef EAX_MODE
+
+int eax_decrypt_verify_memory(int cipher,
+    const unsigned char *key,    unsigned long keylen,
+    const unsigned char *nonce,  unsigned long noncelen,
+    const unsigned char *header, unsigned long headerlen,
+    const unsigned char *ct,     unsigned long ctlen,
+          unsigned char *pt,
+          unsigned char *tag,    unsigned long taglen,
+          int           *res)
+{
+   int err;
+   eax_state eax;
+   unsigned char buf[MAXBLOCKSIZE];
+   unsigned long buflen;
+
+   _ARGCHK(res != NULL);
+
+   /* default to zero */
+   *res = 0;
+
+   if ((err = eax_init(&eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) {
+      return err;
+   }
+
+   if ((err = eax_decrypt(&eax, ct, pt, ctlen)) != CRYPT_OK) {
+      return err;
+   }
+ 
+   buflen = MIN(sizeof(buf), taglen);
+   if ((err = eax_done(&eax, buf, &buflen)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* compare tags */
+   if (buflen >= taglen && memcmp(buf, tag, taglen) == 0) {
+      *res = 1;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eax_done.c	Mon May 31 18:25:41 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
+ */
+
+/* EAX Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef EAX_MODE
+
+int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen)
+{
+   int           err;
+   unsigned char headermac[MAXBLOCKSIZE], ctmac[MAXBLOCKSIZE];
+   unsigned long x, len;
+
+   _ARGCHK(eax    != NULL);
+   _ARGCHK(tag    != NULL);
+   _ARGCHK(taglen != NULL);
+
+   /* finish ctomac */
+   len = sizeof(ctmac);
+   if ((err = omac_done(&eax->ctomac, ctmac, &len)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* finish headeromac */
+
+   /* note we specifically don't reset len so the two lens are minimal */
+
+   if ((err = omac_done(&eax->headeromac, headermac, &len)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* compute N xor H xor C */
+   for (x = 0; x < len && x < *taglen; x++) {
+       tag[x] = eax->N[x] ^ headermac[x] ^ ctmac[x];
+   }
+   *taglen = x;
+
+#ifdef CLEAN_STACK
+   zeromem(ctmac, sizeof(ctmac));
+   zeromem(headermac, sizeof(headermac));
+   zeromem(eax, sizeof(*eax));
+#endif
+
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eax_encrypt.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,35 @@
+/* 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
+ */
+
+/* EAX Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef EAX_MODE
+
+int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length)
+{
+   int err;
+   
+   _ARGCHK(eax != NULL);
+   _ARGCHK(pt  != NULL);
+   _ARGCHK(ct  != NULL);
+
+   /* encrypt */
+   if ((err = ctr_encrypt(pt, ct, length, &eax->ctr)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* omac ciphertext */
+   return omac_process(&eax->ctomac, ct, length);
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eax_encrypt_authenticate_memory.c	Mon May 31 18:25:41 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
+ */
+
+/* EAX Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef EAX_MODE
+
+int eax_encrypt_authenticate_memory(int cipher,
+    const unsigned char *key,    unsigned long keylen,
+    const unsigned char *nonce,  unsigned long noncelen,
+    const unsigned char *header, unsigned long headerlen,
+    const unsigned char *pt,     unsigned long ptlen,
+          unsigned char *ct,
+          unsigned char *tag,    unsigned long *taglen)
+{
+   int err;
+   eax_state eax;
+
+   if ((err = eax_init(&eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) {
+      return err;
+   }
+
+   if ((err = eax_encrypt(&eax, pt, ct, ptlen)) != CRYPT_OK) {
+      return err;
+   }
+ 
+   if ((err = eax_done(&eax, tag, taglen)) != CRYPT_OK) {
+      return err;
+   }
+
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eax_init.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,106 @@
+/* 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
+ */
+
+/* EAX Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef EAX_MODE
+
+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)
+{
+   unsigned char buf[MAXBLOCKSIZE];
+   int           err, blklen;
+   omac_state    omac;
+   unsigned long len;
+
+
+   _ARGCHK(eax   != NULL);
+   _ARGCHK(key   != NULL);
+   _ARGCHK(nonce != NULL);
+   if (headerlen > 0) {
+      _ARGCHK(header != NULL);
+   }
+
+   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+      return err;
+   }
+   blklen = cipher_descriptor[cipher].block_length;
+
+   /* N = OMAC_0K(nonce) */
+   zeromem(buf, sizeof(buf));
+   if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* omac the [0]_n */
+   if ((err = omac_process(&omac, buf, blklen)) != CRYPT_OK) {
+      return err;
+   }
+   /* omac the nonce */
+   if ((err = omac_process(&omac, nonce, noncelen)) != CRYPT_OK) {
+      return err;
+   }
+   /* store result */
+   len = sizeof(eax->N);
+   if ((err = omac_done(&omac, eax->N, &len)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* H = OMAC_1K(header) */
+   zeromem(buf, sizeof(buf));
+   buf[blklen - 1] = 1;
+
+   if ((err = omac_init(&eax->headeromac, cipher, key, keylen)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* omac the [1]_n */
+   if ((err = omac_process(&eax->headeromac, buf, blklen)) != CRYPT_OK) {
+      return err;
+   }
+   /* omac the header */
+   if (headerlen != 0) {
+      if ((err = omac_process(&eax->headeromac, header, headerlen)) != CRYPT_OK) {
+         return err;
+      }
+   }
+
+   /* note we don't finish the headeromac, this allows us to add more header later */
+
+   /* setup the CTR mode */
+   if ((err = ctr_start(cipher, eax->N, key, keylen, 0, &eax->ctr)) != CRYPT_OK) {
+      return err;
+   }
+   /* use big-endian counter */
+   eax->ctr.mode = 1;
+
+   /* setup the OMAC for the ciphertext */
+   if ((err = omac_init(&eax->ctomac, cipher, key, keylen)) != CRYPT_OK) { 
+      return err;
+   }
+
+   /* omac [2]_n */
+   zeromem(buf, sizeof(buf));
+   buf[blklen-1] = 2;
+   if ((err = omac_process(&eax->ctomac, buf, blklen)) != CRYPT_OK) {
+      return err;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+   zeromem(&omac, sizeof(omac));
+#endif
+   return CRYPT_OK;
+}
+
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eax_test.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,271 @@
+/* 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
+ */
+
+/* EAX Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef EAX_MODE
+
+int eax_test(void)
+{
+#ifndef LTC_TEST
+   return CRYPT_NOP;
+#else
+   static const struct {
+       int               keylen, 
+                       noncelen, 
+                      headerlen, 
+                         msglen;
+
+       unsigned char        key[MAXBLOCKSIZE], 
+                          nonce[MAXBLOCKSIZE], 
+                         header[MAXBLOCKSIZE], 
+                      plaintext[MAXBLOCKSIZE],
+                     ciphertext[MAXBLOCKSIZE], 
+                            tag[MAXBLOCKSIZE];
+   } tests[] = {
+
+/* NULL message */
+{
+   16, 0, 0, 0,
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* nonce */
+   { 0 },
+   /* header */
+   { 0 },
+   /* plaintext */
+   { 0 },
+   /* ciphertext */
+   { 0 },
+   /* tag */
+   { 0x9a, 0xd0, 0x7e, 0x7d, 0xbf, 0xf3, 0x01, 0xf5,
+     0x05, 0xde, 0x59, 0x6b, 0x96, 0x15, 0xdf, 0xff }
+},
+
+/* test with nonce */
+{
+   16, 16, 0, 0,
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* nonce */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* header */
+   { 0 },
+   /* plaintext */
+   { 0 },
+   /* ciphertext */
+   { 0 },
+   /* tag */
+   { 0x1c, 0xe1, 0x0d, 0x3e, 0xff, 0xd4, 0xca, 0xdb,
+     0xe2, 0xe4, 0x4b, 0x58, 0xd6, 0x0a, 0xb9, 0xec }
+},
+
+/* test with header [no nonce]  */
+{
+   16, 0, 16, 0,
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* nonce */
+   { 0 },
+   /* header */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* plaintext */
+   { 0 },
+   /* ciphertext */
+   { 0 },
+   /* tag */
+   { 0x3a, 0x69, 0x8f, 0x7a, 0x27, 0x0e, 0x51, 0xb0,
+     0xf6, 0x5b, 0x3d, 0x3e, 0x47, 0x19, 0x3c, 0xff }
+},
+
+/* test with header + nonce + plaintext */
+{
+   16, 16, 16, 32,
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* nonce */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },  
+   /* header */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* plaintext */
+   { 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 },
+   /* ciphertext */
+   { 0x29, 0xd8, 0x78, 0xd1, 0xa3, 0xbe, 0x85, 0x7b,
+     0x6f, 0xb8, 0xc8, 0xea, 0x59, 0x50, 0xa7, 0x78,
+     0x33, 0x1f, 0xbf, 0x2c, 0xcf, 0x33, 0x98, 0x6f,
+     0x35, 0xe8, 0xcf, 0x12, 0x1d, 0xcb, 0x30, 0xbc },
+   /* tag */
+   { 0x4f, 0xbe, 0x03, 0x38, 0xbe, 0x1c, 0x8c, 0x7e,
+     0x1d, 0x7a, 0xe7, 0xe4, 0x5b, 0x92, 0xc5, 0x87 }
+},
+
+/* test with header + nonce + plaintext [not even sizes!] */
+{
+   16, 15, 14, 29,
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* nonce */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e },  
+   /* header */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d },
+   /* plaintext */
+   { 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 },
+   /* ciphertext */
+   { 0xdd, 0x25, 0xc7, 0x54, 0xc5, 0xb1, 0x7c, 0x59,
+     0x28, 0xb6, 0x9b, 0x73, 0x15, 0x5f, 0x7b, 0xb8,
+     0x88, 0x8f, 0xaf, 0x37, 0x09, 0x1a, 0xd9, 0x2c,
+     0x8a, 0x24, 0xdb, 0x86, 0x8b },
+   /* tag */
+   { 0x0d, 0x1a, 0x14, 0xe5, 0x22, 0x24, 0xff, 0xd2,
+     0x3a, 0x05, 0xfa, 0x02, 0xcd, 0xef, 0x52, 0xda }
+},
+
+/* Vectors from Brian Gladman */
+
+{
+   16, 16, 8, 0,
+   /* key */
+   { 0x23, 0x39, 0x52, 0xde, 0xe4, 0xd5, 0xed, 0x5f,
+     0x9b, 0x9c, 0x6d, 0x6f, 0xf8, 0x0f, 0xf4, 0x78 },
+   /* nonce */
+   { 0x62, 0xec, 0x67, 0xf9, 0xc3, 0xa4, 0xa4, 0x07,
+     0xfc, 0xb2, 0xa8, 0xc4, 0x90, 0x31, 0xa8, 0xb3 },
+   /* header */
+   { 0x6b, 0xfb, 0x91, 0x4f, 0xd0, 0x7e, 0xae, 0x6b },
+   /* PT */
+   { 0x00 },
+   /* CT */
+   { 0x00 },
+   /* tag */
+   { 0xe0, 0x37, 0x83, 0x0e, 0x83, 0x89, 0xf2, 0x7b,
+     0x02, 0x5a, 0x2d, 0x65, 0x27, 0xe7, 0x9d, 0x01 }
+},
+
+{
+   16, 16, 8, 2,
+   /* key */ 
+   { 0x91, 0x94, 0x5d, 0x3f, 0x4d, 0xcb, 0xee, 0x0b,
+     0xf4, 0x5e, 0xf5, 0x22, 0x55, 0xf0, 0x95, 0xa4 },
+   /* nonce */
+   { 0xbe, 0xca, 0xf0, 0x43, 0xb0, 0xa2, 0x3d, 0x84,
+     0x31, 0x94, 0xba, 0x97, 0x2c, 0x66, 0xde, 0xbd },
+   /* header */
+   { 0xfa, 0x3b, 0xfd, 0x48, 0x06, 0xeb, 0x53, 0xfa },
+   /* PT */
+   { 0xf7, 0xfb },
+   /* CT */
+   { 0x19, 0xdd },
+   /* tag */
+   { 0x5c, 0x4c, 0x93, 0x31, 0x04, 0x9d, 0x0b, 0xda,
+     0xb0, 0x27, 0x74, 0x08, 0xf6, 0x79, 0x67, 0xe5 }
+},
+
+{
+   16, 16, 8, 5,
+   /* key */
+   { 0x01, 0xf7, 0x4a, 0xd6, 0x40, 0x77, 0xf2, 0xe7,
+     0x04, 0xc0, 0xf6, 0x0a, 0xda, 0x3d, 0xd5, 0x23 },
+   /* nonce */
+   { 0x70, 0xc3, 0xdb, 0x4f, 0x0d, 0x26, 0x36, 0x84,
+     0x00, 0xa1, 0x0e, 0xd0, 0x5d, 0x2b, 0xff, 0x5e },
+   /* header */
+   { 0x23, 0x4a, 0x34, 0x63, 0xc1, 0x26, 0x4a, 0xc6 },
+   /* PT */
+   { 0x1a, 0x47, 0xcb, 0x49, 0x33 },
+   /* CT */
+   { 0xd8, 0x51, 0xd5, 0xba, 0xe0 },
+   /* Tag */
+   { 0x3a, 0x59, 0xf2, 0x38, 0xa2, 0x3e, 0x39, 0x19,
+     0x9d, 0xc9, 0x26, 0x66, 0x26, 0xc4, 0x0f, 0x80 }
+}   
+
+};
+   int err, x, idx, res;
+   unsigned long len;
+   unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE];
+
+    /* AES can be under rijndael or aes... try to find it */ 
+    if ((idx = find_cipher("aes")) == -1) {
+       if ((idx = find_cipher("rijndael")) == -1) {
+          return CRYPT_NOP;
+       }
+    }
+
+    for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+        len = sizeof(outtag);
+        if ((err = eax_encrypt_authenticate_memory(idx, tests[x].key, tests[x].keylen,
+            tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen,
+            tests[x].plaintext, tests[x].msglen, outct, outtag, &len)) != CRYPT_OK) {
+           return err;
+        }
+        if (memcmp(outct, tests[x].ciphertext, tests[x].msglen) || memcmp(outtag, tests[x].tag, len)) {
+#if 0
+           unsigned long y;
+           printf("\n\nFailure: \nCT:\n");
+           for (y = 0; y < (unsigned long)tests[x].msglen; ) {
+               printf("0x%02x", outct[y]);
+               if (y < (unsigned long)(tests[x].msglen-1)) printf(", ");
+               if (!(++y % 8)) printf("\n");
+           }
+           printf("\nTAG:\n");
+           for (y = 0; y < len; ) {
+               printf("0x%02x", outtag[y]);
+               if (y < len-1) printf(", ");
+               if (!(++y % 8)) printf("\n");
+           }
+#endif
+           return CRYPT_FAIL_TESTVECTOR;
+        }
+
+        /* test decrypt */
+        if ((err = eax_decrypt_verify_memory(idx, tests[x].key, tests[x].keylen,
+             tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen,
+             outct, tests[x].msglen, outct, outtag, len, &res)) != CRYPT_OK) {
+            return err;
+        }
+        if ((res != 1) || memcmp(outct, tests[x].plaintext, tests[x].msglen)) {
+#if 0
+           unsigned long y;
+           printf("\n\nFailure (res == %d): \nPT:\n", res);
+           for (y = 0; y < (unsigned long)tests[x].msglen; ) {
+               printf("0x%02x", outct[y]);
+               if (y < (unsigned long)(tests[x].msglen-1)) printf(", ");
+               if (!(++y % 8)) printf("\n");
+           }
+           printf("\n\n");
+#endif
+           return CRYPT_FAIL_TESTVECTOR;
+        }
+
+     }
+     return CRYPT_OK;
+#endif /* LTC_TEST */
+}
+
+#endif /* EAX_MODE */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ecb_decrypt.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,31 @@
+/* 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 ECB
+
+int ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ECB *ecb)
+{
+   int err;
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(ecb != NULL);
+
+   if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
+       return err;
+   }
+   cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key);
+   return CRYPT_OK;
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ecb_encrypt.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,29 @@
+/* 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 ECB
+
+int ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_ECB *ecb)
+{
+   int err;
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(ecb != NULL);
+
+   if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
+       return err;
+   }
+   cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key);
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ecb_start.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,29 @@
+/* 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 ECB
+
+int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb)
+{
+   int err;
+   _ARGCHK(key != NULL);
+   _ARGCHK(ecb != NULL);
+
+   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+      return err;
+   }
+   ecb->cipher = cipher;
+   ecb->blocklen = cipher_descriptor[cipher].block_length;
+   return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ecb->key);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ecc.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,937 @@
+/* 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
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+
+#include "mycrypt.h"
+
+#ifdef MECC
+
+/* This holds the key settings.  ***MUST*** be organized by size from smallest to largest. */
+static const struct {
+   int size;
+   char *name, *prime, *B, *order, *Gx, *Gy;
+} sets[] = {
+#ifdef ECC160
+{
+   20,
+   "ECC-160",
+   /* prime */
+   "G00000000000000000000000007",
+   /* B */
+   "1oUV2vOaSlWbxr6",
+   /* order */
+   "G0000000000004sCQUtDxaqDUN5",
+   /* Gx */
+   "jpqOf1BHus6Yd/pyhyVpP",
+   /* Gy */
+   "D/wykuuIFfr+vPyx7kQEPu8MixO",
+},
+#endif
+#ifdef ECC192
+{
+    24,
+   "ECC-192",
+   /* prime */
+   "/////////////////////l//////////",
+
+   /* B */
+   "P2456UMSWESFf+chSYGmIVwutkp1Hhcn",
+
+   /* order */
+   "////////////////cTxuDXHhoR6qqYWn",
+
+   /* Gx */
+   "68se3h0maFPylo3hGw680FJ/2ls2/n0I",
+
+   /* Gy */
+   "1nahbV/8sdXZ417jQoJDrNFvTw4UUKWH"
+},
+#endif
+#ifdef ECC224
+{
+   28,
+   "ECC-224",
+
+   /* prime */
+   "400000000000000000000000000000000000BV",
+
+   /* B */
+   "21HkWGL2CxJIp",
+
+   /* order */
+   "4000000000000000000Kxnixk9t8MLzMiV264/",
+
+   /* Gx */
+   "jpqOf1BHus6Yd/pyhyVpP",
+
+   /* Gy */
+   "3FCtyo2yHA5SFjkCGbYxbOvNeChwS+j6wSIwck",
+},
+#endif
+#ifdef ECC256
+{
+   32,
+   "ECC-256",
+   /* Prime */
+   "F////y000010000000000000000////////////////",
+
+   /* B */
+   "5h6DTYgEfFdi+kzLNQOXhnb7GQmp5EmzZlEF3udqc1B",
+
+   /* Order */
+   "F////y00000//////////+yvlgjfnUUXFEvoiByOoLH",
+
+   /* Gx */
+   "6iNqVBXB497+BpcvMEaGF9t0ts1BUipeFIXEKNOcCAM",
+
+   /* Gy */
+   "4/ZGkB+6d+RZkVhIdmFdXOhpZDNQp5UpiksG6Wtlr7r"
+},
+#endif
+#ifdef ECC384
+{
+   48,
+   "ECC-384",
+   /* prime */
+   "//////////////////////////////////////////x/////00000000003/"
+   "////",
+
+   /* B */
+   "ip4lf+8+v+IOZWLhu/Wj6HWTd6x+WK4I0nG8Zr0JXrh6LZcDYYxHdIg5oEtJ"
+   "x2hl",
+
+   /* Order */
+   "////////////////////////////////nsDDWVGtBTzO6WsoIB2dUkpi6MhC"
+   "nIbp",
+
+   /* Gx and Gy */
+   "geVA8hwB1JUEiSSUyo2jT6uTEsABfvkOMVT1u89KAZXL0l9TlrKfR3fKNZXo"
+   "TWgt",
+
+   "DXVUIfOcB6zTdfY/afBSAVZq7RqecXHywTen4xNmkC0AOB7E7Nw1dNf37NoG"
+   "wWvV"
+},
+#endif
+#ifdef ECC521
+{
+   65,
+   "ECC-521",
+   /* prime */
+   "V///////////////////////////////////////////////////////////"
+   "///////////////////////////",
+
+   /* B */
+   "56LFhbXZXoQ7vAQ8Q2sXK3kejfoMvcp5VEuj8cHZl49uLOPEL7iVfDx5bB0l"
+   "JknlmSrSz+8FImqyUz57zHhK3y0",
+
+   /* Order */
+   "V//////////////////////////////////////////+b66XuE/BvPhVym1I"
+   "FS9fT0xjScuYPn7hhjljnwHE6G9",
+
+   /* Gx and Gy */
+   "CQ5ZWQt10JfpPu+osOZbRH2d6I1EGK/jI7uAAzWQqqzkg5BNdVlvrae/Xt19"
+   "wB/gDupIBF1XMf2c/b+VZ72vRrc",
+
+   "HWvAMfucZl015oANxGiVHlPcFL4ILURH6WNhxqN9pvcB9VkSfbUz2P0nL2v0"
+   "J+j1s4rF726edB2G8Y+b7QVqMPG",
+},
+#endif
+{
+   0,
+   NULL, NULL, NULL, NULL, NULL, NULL
+}
+};
+
+#if 0
+
+/* you plug in a prime and B value and it finds a pseudo-random base point */
+void ecc_find_base(void)
+{
+   static char *prime = "26959946667150639794667015087019630673637144422540572481103610249951";
+   static char *order = "26959946667150639794667015087019637467111563745054605861463538557247";
+   static char *b     = "9538957348957353489587";
+   mp_int pp, p, r, B, tmp1, tmp2, tx, ty, x, y;
+   char buf[4096];
+   int i;
+
+   mp_init_multi(&tx, &ty, &x, &y, &p, &pp, &r, &B, &tmp1, &tmp2, NULL);
+   mp_read_radix(&p, prime, 10);
+   mp_read_radix(&r, order, 10);
+   mp_read_radix(&B, b, 10);
+
+   /* get (p+1)/4 */
+   mp_add_d(&p, 1, &pp);
+   mp_div_2(&pp, &pp);
+   mp_div_2(&pp, &pp);
+
+   buf[0] = 0;
+   do {
+      printf("."); fflush(stdout);
+      /* make a random value of x */
+      for (i = 0; i < 16; i++) buf[i+1] = rand() & 255;
+      mp_read_raw(&x, buf, 17);
+      mp_copy(&x, &tx);
+
+      /* now compute x^3 - 3x + b */
+      mp_expt_d(&x, 3, &tmp1);
+      mp_mul_d(&x, 3, &tmp2);
+      mp_sub(&tmp1, &tmp2, &tmp1);
+      mp_add(&tmp1, &B, &tmp1);
+      mp_mod(&tmp1, &p, &tmp1);
+
+      /* now compute sqrt via x^((p+1)/4) */
+      mp_exptmod(&tmp1, &pp, &p, &tmp2);
+      mp_copy(&tmp2, &ty);
+
+      /* now square it */
+      mp_sqrmod(&tmp2, &p, &tmp2);
+
+      /* tmp2 should equal tmp1 */
+   } while (mp_cmp(&tmp1, &tmp2));
+
+   /* now output values in way that libtomcrypt wants */
+   mp_todecimal(&p, buf);
+   printf("\n\np==%s\n", buf);
+   mp_tohex(&B, buf);
+   printf("b==%s\n", buf);
+   mp_todecimal(&r, buf);
+   printf("r==%s\n", buf);
+   mp_tohex(&tx, buf);
+   printf("Gx==%s\n", buf);
+   mp_tohex(&ty, buf);
+   printf("Gy==%s\n", buf);
+
+   mp_clear_multi(&tx, &ty, &x, &y, &p, &pp, &r, &B, &tmp1, &tmp2, NULL);
+}
+ 
+#endif
+
+
+
+
+static int is_valid_idx(int n)
+{
+   int x;
+
+   for (x = 0; sets[x].size != 0; x++);
+   if ((n < 0) || (n >= x)) {
+      return 0;
+   }
+   return 1;
+}
+
+static ecc_point *new_point(void)
+{
+   ecc_point *p;
+   p = XMALLOC(sizeof(ecc_point));
+   if (p == NULL) {
+      return NULL;
+   }
+   if (mp_init_multi(&p->x, &p->y, NULL) != MP_OKAY) {
+      XFREE(p);
+      return NULL;
+   }
+   return p;
+}
+
+static void del_point(ecc_point *p)
+{
+   /* prevents free'ing null arguments */
+   if (p != NULL) {
+      mp_clear_multi(&p->x, &p->y, NULL);
+      XFREE(p);
+   }
+}
+
+/* double a point R = 2P, R can be P*/
+static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_int *mu)
+{
+   mp_int s, tmp, tmpx;
+   int err;
+
+   if ((err = mp_init_multi(&s, &tmp, &tmpx, NULL)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+
+   /* s = (3Xp^2 + a) / (2Yp) */
+   if ((err = mp_mul_2(&P->y, &tmp)) != MP_OKAY)                   { goto error; } /* tmp = 2*y */
+   if ((err = mp_invmod(&tmp, modulus, &tmp)) != MP_OKAY)          { goto error; } /* tmp = 1/tmp mod modulus */
+   if ((err = mp_sqr(&P->x, &s)) != MP_OKAY)                       { goto error; } /* s = x^2  */
+   if ((err = mp_reduce(&s, modulus, mu)) != MP_OKAY)              { goto error; }
+   if ((err = mp_mul_d(&s,(mp_digit)3, &s)) != MP_OKAY)            { goto error; } /* s = 3*(x^2) */
+   if ((err = mp_sub_d(&s,(mp_digit)3, &s)) != MP_OKAY)            { goto error; } /* s = 3*(x^2) - 3 */
+   if (mp_cmp_d(&s, 0) == MP_LT) {                                         /* if s < 0 add modulus */
+      if ((err = mp_add(&s, modulus, &s)) != MP_OKAY)              { goto error; }
+   }
+   if ((err = mp_mul(&s, &tmp, &s)) != MP_OKAY)                    { goto error; } /* s = tmp * s mod modulus */
+   if ((err = mp_reduce(&s, modulus, mu)) != MP_OKAY)              { goto error; }
+
+   /* Xr = s^2 - 2Xp */
+   if ((err = mp_sqr(&s,  &tmpx)) != MP_OKAY)                      { goto error; } /* tmpx = s^2  */
+   if ((err = mp_reduce(&tmpx, modulus, mu)) != MP_OKAY)           { goto error; } /* tmpx = tmpx mod modulus */
+   if ((err = mp_sub(&tmpx, &P->x, &tmpx)) != MP_OKAY)             { goto error; } /* tmpx = tmpx - x */
+   if ((err = mp_submod(&tmpx, &P->x, modulus, &tmpx)) != MP_OKAY) { goto error; } /* tmpx = tmpx - x mod modulus */
+
+   /* Yr = -Yp + s(Xp - Xr)  */
+   if ((err = mp_sub(&P->x, &tmpx, &tmp)) != MP_OKAY)              { goto error; } /* tmp = x - tmpx */
+   if ((err = mp_mul(&tmp, &s, &tmp)) != MP_OKAY)                  { goto error; } /* tmp = tmp * s */
+   if ((err = mp_submod(&tmp, &P->y, modulus, &R->y)) != MP_OKAY)  { goto error; } /* y = tmp - y mod modulus */
+   if ((err = mp_copy(&tmpx, &R->x)) != MP_OKAY)                   { goto error; } /* x = tmpx */
+
+   err = CRYPT_OK;
+   goto done;
+error:
+   err = mpi_to_ltc_error(err);
+done:
+   mp_clear_multi(&tmpx, &tmp, &s, NULL);
+   return err;
+}
+
+/* add two different points over Z/pZ, R = P + Q, note R can equal either P or Q */
+static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus, mp_int *mu)
+{
+   mp_int s, tmp, tmpx;
+   int err;
+
+   if ((err = mp_init(&tmp)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+
+   /* is P==Q or P==-Q? */
+   if (((err = mp_neg(&Q->y, &tmp)) != MP_OKAY) || ((err = mp_mod(&tmp, modulus, &tmp)) != MP_OKAY)) {
+      mp_clear(&tmp);
+      return mpi_to_ltc_error(err);
+   }
+
+   if (mp_cmp(&P->x, &Q->x) == MP_EQ)
+      if (mp_cmp(&P->y, &Q->y) == MP_EQ || mp_cmp(&P->y, &tmp) == MP_EQ) {
+         mp_clear(&tmp);
+         return dbl_point(P, R, modulus, mu);
+      }
+
+   if ((err = mp_init_multi(&tmpx, &s, NULL)) != MP_OKAY) {
+      mp_clear(&tmp);
+      return mpi_to_ltc_error(err);
+   }
+
+   /* get s = (Yp - Yq)/(Xp-Xq) mod p */
+   if ((err = mp_sub(&P->x, &Q->x, &tmp)) != MP_OKAY)                 { goto error; } /* tmp = Px - Qx mod modulus */
+   if (mp_cmp_d(&tmp, 0) == MP_LT) {                                          /* if tmp<0 add modulus */
+      if ((err = mp_add(&tmp, modulus, &tmp)) != MP_OKAY)             { goto error; }
+   }
+   if ((err = mp_invmod(&tmp, modulus, &tmp)) != MP_OKAY)             { goto error; } /* tmp = 1/tmp mod modulus */
+   if ((err = mp_sub(&P->y, &Q->y, &s)) != MP_OKAY)                   { goto error; } /* s = Py - Qy mod modulus */
+   if (mp_cmp_d(&s, 0) == MP_LT) {                                            /* if s<0 add modulus */
+      if ((err = mp_add(&s, modulus, &s)) != MP_OKAY)                 { goto error; }
+   }
+   if ((err = mp_mul(&s, &tmp, &s)) != MP_OKAY)                       { goto error; } /* s = s * tmp mod modulus */
+   if ((err = mp_reduce(&s, modulus, mu)) != MP_OKAY)                 { goto error; }
+
+   /* Xr = s^2 - Xp - Xq */
+   if ((err = mp_sqr(&s, &tmp)) != MP_OKAY)                           { goto error; } /* tmp = s^2 mod modulus */
+   if ((err = mp_reduce(&tmp, modulus, mu)) != MP_OKAY)               { goto error; }
+   if ((err = mp_sub(&tmp, &P->x, &tmp)) != MP_OKAY)                  { goto error; } /* tmp = tmp - Px */
+   if ((err = mp_sub(&tmp, &Q->x, &tmpx)) != MP_OKAY)                 { goto error; } /* tmpx = tmp - Qx */
+
+   /* Yr = -Yp + s(Xp - Xr) */
+   if ((err = mp_sub(&P->x, &tmpx, &tmp)) != MP_OKAY)                 { goto error; } /* tmp = Px - tmpx */
+   if ((err = mp_mul(&tmp, &s, &tmp)) != MP_OKAY)                     { goto error; } /* tmp = tmp * s */
+   if ((err = mp_submod(&tmp, &P->y, modulus, &R->y)) != MP_OKAY)     { goto error; } /* Ry = tmp - Py mod modulus */
+   if ((err = mp_mod(&tmpx, modulus, &R->x)) != MP_OKAY)              { goto error; } /* Rx = tmpx mod modulus */
+
+   err = CRYPT_OK;
+   goto done;
+error:
+   err = mpi_to_ltc_error(err);
+done:
+   mp_clear_multi(&s, &tmpx, &tmp, NULL);
+   return err;
+}
+
+/* size of sliding window, don't change this! */
+#define WINSIZE 4
+
+/* perform R = kG where k == integer and G == ecc_point */
+static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus)
+{
+   ecc_point *tG, *M[8];
+   int i, j, err;
+   mp_int mu;
+   mp_digit buf;
+   int     first, bitbuf, bitcpy, bitcnt, mode, digidx;
+
+  /* init barrett reduction */
+  if ((err = mp_init(&mu)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+  }
+  if ((err = mp_reduce_setup(&mu, modulus)) != MP_OKAY) {
+      mp_clear(&mu);
+      return mpi_to_ltc_error(err);
+  }
+
+  /* alloc ram for window temps */
+  for (i = 0; i < 8; i++) {
+      M[i] = new_point();
+      if (M[i] == NULL) {
+         for (j = 0; j < i; j++) {
+             del_point(M[j]);
+         }
+         mp_clear(&mu);
+         return CRYPT_MEM;
+      }
+  }
+
+   /* make a copy of G incase R==G */
+   tG = new_point();
+   if (tG == NULL)                                                            { err = CRYPT_MEM; goto done; }
+
+   /* tG = G */
+   if ((err = mp_copy(&G->x, &tG->x)) != MP_OKAY)                             { goto error; }
+   if ((err = mp_copy(&G->y, &tG->y)) != MP_OKAY)                             { goto error; }
+   
+   /* calc the M tab, which holds kG for k==8..15 */
+   /* M[0] == 8G */
+   if ((err = dbl_point(G, M[0], modulus, &mu)) != CRYPT_OK)                  { goto done; }
+   if ((err = dbl_point(M[0], M[0], modulus, &mu)) != CRYPT_OK)               { goto done; }
+   if ((err = dbl_point(M[0], M[0], modulus, &mu)) != CRYPT_OK)               { goto done; }
+
+   /* now find (8+k)G for k=1..7 */
+   for (j = 9; j < 16; j++) {
+       if ((err = add_point(M[j-9], G, M[j-8], modulus, &mu)) != CRYPT_OK)    { goto done; }
+   }
+
+   /* setup sliding window */
+   mode   = 0;
+   bitcnt = 1;
+   buf    = 0;
+   digidx = k->used - 1;
+   bitcpy = bitbuf = 0;
+   first  = 1;
+
+   /* perform ops */
+   for (;;) {
+     /* grab next digit as required */
+     if (--bitcnt == 0) {
+       if (digidx == -1) {
+          break;
+       }
+       buf = k->dp[digidx--];
+       bitcnt = (int) DIGIT_BIT;
+     }
+
+     /* grab the next msb from the multiplicand */
+     i = (buf >> (DIGIT_BIT - 1)) & 1;
+     buf <<= 1;
+
+     /* skip leading zero bits */
+     if (mode == 0 && i == 0) {
+        continue;
+     }
+
+     /* if the bit is zero and mode == 1 then we double */
+     if (mode == 1 && i == 0) {
+        if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK)                { goto done; }
+        continue;
+     }
+
+     /* else we add it to the window */
+     bitbuf |= (i << (WINSIZE - ++bitcpy));
+     mode = 2;
+
+     if (bitcpy == WINSIZE) {
+       /* if this is the first window we do a simple copy */
+       if (first == 1) {
+          /* R = kG [k = first window] */
+          if ((err = mp_copy(&M[bitbuf-8]->x, &R->x)) != MP_OKAY)             { goto error; }
+          if ((err = mp_copy(&M[bitbuf-8]->y, &R->y)) != MP_OKAY)             { goto error; }
+          first = 0;
+       } else {
+         /* normal window */
+         /* ok window is filled so double as required and add  */
+         /* double first */
+         for (j = 0; j < WINSIZE; j++) {
+           if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK)             { goto done; }
+         }
+
+         /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
+         if ((err = add_point(R, M[bitbuf-8], R, modulus, &mu)) != CRYPT_OK)  { goto done; }
+       }
+       /* empty window and reset */
+       bitcpy = bitbuf = 0;
+       mode = 1;
+    }
+  }
+
+   /* if bits remain then double/add */
+   if (mode == 2 && bitcpy > 0) {
+     /* double then add */
+     for (j = 0; j < bitcpy; j++) {
+       /* only double if we have had at least one add first */
+       if (first == 0) {
+          if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK)               { goto done; }
+       }
+
+       bitbuf <<= 1;
+       if ((bitbuf & (1 << WINSIZE)) != 0) {
+         if (first == 1){
+            /* first add, so copy */
+            if ((err = mp_copy(&tG->x, &R->x)) != MP_OKAY)                     { goto error; }
+            if ((err = mp_copy(&tG->y, &R->y)) != MP_OKAY)                     { goto error; }
+            first = 0;
+         } else {
+            /* then add */
+            if ((err = add_point(R, tG, R, modulus, &mu)) != CRYPT_OK)         { goto done; }
+         }
+       }
+     }
+   }
+   err = CRYPT_OK;
+   goto done;
+error:
+   err = mpi_to_ltc_error(err);
+done:
+   del_point(tG);
+   for (i = 0; i < 8; i++) {
+       del_point(M[i]);
+   }
+   mp_clear(&mu);
+   return err;
+}
+
+#undef WINSIZE
+
+int ecc_test(void)
+{
+   mp_int     modulus, order;
+   ecc_point  *G, *GG;
+   int i, err, primality;
+
+   if ((err = mp_init_multi(&modulus, &order, NULL)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+
+   G   = new_point();
+   GG  = new_point();
+   if (G == NULL || GG == NULL) {
+      mp_clear_multi(&modulus, &order, NULL);
+      del_point(G);
+      del_point(GG);
+      return CRYPT_MEM;
+   }
+
+   for (i = 0; sets[i].size; i++) {
+       #if 0
+          printf("Testing %d\n", sets[i].size);
+       #endif
+       if ((err = mp_read_radix(&modulus, (char *)sets[i].prime, 64)) != MP_OKAY)   { goto error; }
+       if ((err = mp_read_radix(&order, (char *)sets[i].order, 64)) != MP_OKAY)     { goto error; }
+
+       /* is prime actually prime? */
+       if ((err = is_prime(&modulus, &primality)) != CRYPT_OK)                      { goto done; }
+       if (primality == 0) {
+          err = CRYPT_FAIL_TESTVECTOR;
+          goto done;
+       }
+
+       /* is order prime ? */
+       if ((err = is_prime(&order, &primality)) != CRYPT_OK)                        { goto done; }
+       if (primality == 0) {
+          err = CRYPT_FAIL_TESTVECTOR;
+          goto done;
+       }
+
+       if ((err = mp_read_radix(&G->x, (char *)sets[i].Gx, 64)) != MP_OKAY)         { goto error; }
+       if ((err = mp_read_radix(&G->y, (char *)sets[i].Gy, 64)) != MP_OKAY)         { goto error; }
+
+       /* then we should have G == (order + 1)G */
+       if ((err = mp_add_d(&order, 1, &order)) != MP_OKAY)                          { goto error; }
+       if ((err = ecc_mulmod(&order, G, GG, &modulus)) != CRYPT_OK)                 { goto done; }
+       if (mp_cmp(&G->x, &GG->x) != 0 || mp_cmp(&G->y, &GG->y) != 0) {
+          err = CRYPT_FAIL_TESTVECTOR;
+          goto done;
+       }
+   }
+   err = CRYPT_OK;
+   goto done;
+error:
+   err = mpi_to_ltc_error(err);
+done:
+   del_point(GG);
+   del_point(G);
+   mp_clear_multi(&order, &modulus, NULL);
+   return err;
+}
+
+void ecc_sizes(int *low, int *high)
+{
+ int i;
+ _ARGCHK(low  != NULL);
+ _ARGCHK(high != NULL);
+
+ *low = INT_MAX;
+ *high = 0;
+ for (i = 0; sets[i].size != 0; i++) {
+     if (sets[i].size < *low)  {
+        *low  = sets[i].size;
+     }
+     if (sets[i].size > *high) {
+        *high = sets[i].size;
+     }
+ }
+}
+
+int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
+{
+   int x, err;
+   ecc_point *base;
+   mp_int prime;
+   unsigned char buf[128];
+
+   _ARGCHK(key != NULL);
+
+   /* good prng? */
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* find key size */
+   for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++);
+   keysize = sets[x].size;
+
+   if (sets[x].size == 0) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+   key->idx = x;
+
+   /* make up random string */
+   if (prng_descriptor[wprng].read(buf, (unsigned long)keysize, prng) != (unsigned long)keysize) {
+      return CRYPT_ERROR_READPRNG;
+   }
+
+   /* setup the key variables */
+   if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, &prime, NULL)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+   base = new_point();
+   if (base == NULL) {
+      mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, &prime, NULL);
+      return CRYPT_MEM;
+   }
+
+   /* read in the specs for this key */
+   if ((err = mp_read_radix(&prime, (char *)sets[key->idx].prime, 64)) != MP_OKAY)      { goto error; }
+   if ((err = mp_read_radix(&base->x, (char *)sets[key->idx].Gx, 64)) != MP_OKAY)       { goto error; }
+   if ((err = mp_read_radix(&base->y, (char *)sets[key->idx].Gy, 64)) != MP_OKAY)       { goto error; }
+   if ((err = mp_read_unsigned_bin(&key->k, (unsigned char *)buf, keysize)) != MP_OKAY) { goto error; }
+
+   /* make the public key */
+   if ((err = ecc_mulmod(&key->k, base, &key->pubkey, &prime)) != CRYPT_OK)             { goto done; }
+   key->type = PK_PRIVATE;
+
+   /* shrink key */
+   if ((err = mp_shrink(&key->k)) != MP_OKAY)                                           { goto error; }
+   if ((err = mp_shrink(&key->pubkey.x)) != MP_OKAY)                                    { goto error; }
+   if ((err = mp_shrink(&key->pubkey.y)) != MP_OKAY)                                    { goto error; }
+
+   /* free up ram */
+   err = CRYPT_OK;
+   goto done;
+error:
+   err = mpi_to_ltc_error(err);
+done:
+   del_point(base);
+   mp_clear(&prime);
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+   return err;
+}
+
+void ecc_free(ecc_key *key)
+{
+   _ARGCHK(key != NULL);
+   mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL);
+}
+
+static int compress_y_point(ecc_point *pt, int idx, int *result)
+{
+   mp_int tmp, tmp2, p;
+   int err;
+
+   _ARGCHK(pt     != NULL);
+   _ARGCHK(result != NULL);
+
+   if ((err = mp_init_multi(&tmp, &tmp2, &p, NULL)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+
+   /* get x^3 - 3x + b */
+   if ((err = mp_read_radix(&p, (char *)sets[idx].B, 64)) != MP_OKAY) { goto error; } /* p = B */
+   if ((err = mp_expt_d(&pt->x, 3, &tmp)) != MP_OKAY)                 { goto error; } /* tmp = pX^3  */
+   if ((err = mp_mul_d(&pt->x, 3, &tmp2)) != MP_OKAY)                 { goto error; } /* tmp2 = 3*pX^3 */
+   if ((err = mp_sub(&tmp, &tmp2, &tmp)) != MP_OKAY)                  { goto error; } /* tmp = tmp - tmp2 */
+   if ((err = mp_add(&tmp, &p, &tmp)) != MP_OKAY)                     { goto error; } /* tmp = tmp + p */
+   if ((err = mp_read_radix(&p, (char *)sets[idx].prime, 64)) != MP_OKAY)  { goto error; } /* p = prime */
+   if ((err = mp_mod(&tmp, &p, &tmp)) != MP_OKAY)                     { goto error; } /* tmp = tmp mod p */
+
+   /* now find square root */
+   if ((err = mp_add_d(&p, 1, &tmp2)) != MP_OKAY)                     { goto error; } /* tmp2 = p + 1 */
+   if ((err = mp_div_2d(&tmp2, 2, &tmp2, NULL)) != MP_OKAY)           { goto error; } /* tmp2 = (p+1)/4 */
+   if ((err = mp_exptmod(&tmp, &tmp2, &p, &tmp)) != MP_OKAY)          { goto error; } /* tmp  = (x^3 - 3x + b)^((p+1)/4) mod p */
+
+   /* if tmp equals the y point give a 0, otherwise 1 */
+   if (mp_cmp(&tmp, &pt->y) == 0) {
+      *result = 0;
+   } else {
+      *result = 1;
+   }
+
+   err = CRYPT_OK;
+   goto done;
+error:
+   err = mpi_to_ltc_error(err);
+done:
+   mp_clear_multi(&p, &tmp, &tmp2, NULL);
+   return err;
+}
+
+static int expand_y_point(ecc_point *pt, int idx, int result)
+{
+   mp_int tmp, tmp2, p;
+   int err;
+
+   _ARGCHK(pt != NULL);
+
+   if ((err = mp_init_multi(&tmp, &tmp2, &p, NULL)) != MP_OKAY) {
+      return CRYPT_MEM;
+   }
+
+   /* get x^3 - 3x + b */
+   if ((err = mp_read_radix(&p, (char *)sets[idx].B, 64)) != MP_OKAY) { goto error; } /* p = B */
+   if ((err = mp_expt_d(&pt->x, 3, &tmp)) != MP_OKAY)                 { goto error; } /* tmp = pX^3 */
+   if ((err = mp_mul_d(&pt->x, 3, &tmp2)) != MP_OKAY)                 { goto error; } /* tmp2 = 3*pX^3 */
+   if ((err = mp_sub(&tmp, &tmp2, &tmp)) != MP_OKAY)                  { goto error; } /* tmp = tmp - tmp2 */
+   if ((err = mp_add(&tmp, &p, &tmp)) != MP_OKAY)                     { goto error; } /* tmp = tmp + p */
+   if ((err = mp_read_radix(&p, (char *)sets[idx].prime, 64)) != MP_OKAY)  { goto error; } /* p = prime */
+   if ((err = mp_mod(&tmp, &p, &tmp)) != MP_OKAY)                     { goto error; } /* tmp = tmp mod p */
+
+   /* now find square root */
+   if ((err = mp_add_d(&p, 1, &tmp2)) != MP_OKAY)                     { goto error; } /* tmp2 = p + 1 */
+   if ((err = mp_div_2d(&tmp2, 2, &tmp2, NULL)) != MP_OKAY)           { goto error; } /* tmp2 = (p+1)/4 */
+   if ((err = mp_exptmod(&tmp, &tmp2, &p, &tmp)) != MP_OKAY)          { goto error; } /* tmp  = (x^3 - 3x + b)^((p+1)/4) mod p */
+
+   /* if result==0, then y==tmp, otherwise y==p-tmp */
+   if (result == 0) {
+      if ((err = mp_copy(&tmp, &pt->y) != MP_OKAY))                   { goto error; }
+   } else {
+      if ((err = mp_sub(&p, &tmp, &pt->y) != MP_OKAY))                { goto error; }
+   }
+
+   err = CRYPT_OK;
+   goto done;
+error:
+   err = mpi_to_ltc_error(err);
+done:
+   mp_clear_multi(&p, &tmp, &tmp2, NULL);
+   return err;
+}
+
+int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
+{
+   unsigned long y, z;
+   int cp, err;
+
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+   
+   /* can we store the static header?  */
+   if (*outlen < (PACKET_SIZE + 3)) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* type valid? */
+   if (key->type != PK_PRIVATE && type == PK_PRIVATE) {
+      return CRYPT_PK_TYPE_MISMATCH;
+   }
+
+   /* output type and magic byte */
+   y = PACKET_SIZE;
+   out[y++] = (unsigned char)type;
+   out[y++] = (unsigned char)sets[key->idx].size;
+
+   /* output x coordinate */
+   OUTPUT_BIGNUM(&(key->pubkey.x), out, y, z);
+
+   /* compress y and output it  */
+   if ((err = compress_y_point(&key->pubkey, key->idx, &cp)) != CRYPT_OK) {
+      return err;
+   }
+   out[y++] = (unsigned char)cp;
+
+   if (type == PK_PRIVATE) {
+      OUTPUT_BIGNUM(&key->k, out, y, z);
+   }
+
+   /* store header */
+   packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_KEY);
+   *outlen = y;
+
+   return CRYPT_OK;
+}
+
+int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+   unsigned long x, y, s;
+   int err;
+
+   _ARGCHK(in  != NULL);
+   _ARGCHK(key != NULL);
+
+   /* check length */
+   if ((3+PACKET_SIZE) > inlen) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* check type */
+   if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_KEY)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* init key */
+   if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL) != MP_OKAY) {
+      return CRYPT_MEM;
+   }
+
+   y = PACKET_SIZE;
+   key->type = (int)in[y++];
+   s = (unsigned long)in[y++];
+
+   for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++);
+   if (sets[x].size == 0) {
+      err = CRYPT_INVALID_KEYSIZE;
+      goto error;
+   }
+   key->idx = (int)x;
+
+   /* type check both values */
+   if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE))  {
+      err = CRYPT_INVALID_PACKET;
+      goto error;
+   }
+
+   /* is the key idx valid? */
+   if (is_valid_idx(key->idx) != 1) {
+      err = CRYPT_INVALID_PACKET;
+      goto error;
+   }
+
+   /* load x coordinate */
+   INPUT_BIGNUM(&key->pubkey.x, in, x, y, inlen);
+
+   /* load y */
+   x = (unsigned long)in[y++];
+   if ((err = expand_y_point(&key->pubkey, key->idx, (int)x)) != CRYPT_OK) {
+       goto error;
+   }
+
+   if (key->type == PK_PRIVATE) {
+      /* load private key */
+      INPUT_BIGNUM(&key->k, in, x, y, inlen);
+   }
+
+   /* eliminate private key if public */
+   if (key->type == PK_PUBLIC) {
+      mp_clear(&key->k);
+   }
+
+   return CRYPT_OK;
+error:
+   mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL);
+   return err;
+}
+
+int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
+                      unsigned char *out, unsigned long *outlen)
+{
+   unsigned long x, y;
+   ecc_point *result;
+   mp_int prime;
+   int err;
+
+   _ARGCHK(private_key != NULL);
+   _ARGCHK(public_key  != NULL);
+   _ARGCHK(out         != NULL);
+   _ARGCHK(outlen      != NULL);
+
+   /* type valid? */
+   if (private_key->type != PK_PRIVATE) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   if (private_key->idx != public_key->idx) {
+      return CRYPT_PK_TYPE_MISMATCH;
+   }
+
+   /* make new point */
+   result = new_point();
+   if (result == NULL) {
+      return CRYPT_MEM;
+   }
+
+   if ((err = mp_init(&prime)) != MP_OKAY) {
+      del_point(result);
+      return mpi_to_ltc_error(err);
+   }
+
+   if ((err = mp_read_radix(&prime, (char *)sets[private_key->idx].prime, 64)) != MP_OKAY)   { goto error; }
+   if ((err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime)) != CRYPT_OK) { goto done1; }
+
+   x = (unsigned long)mp_unsigned_bin_size(&result->x);
+   y = (unsigned long)mp_unsigned_bin_size(&result->y);
+
+   if (*outlen < (x+y)) {
+      err = CRYPT_BUFFER_OVERFLOW;
+      goto done1;
+   }
+   *outlen = x+y;
+   if ((err = mp_to_unsigned_bin(&result->x, out))   != MP_OKAY)          { goto error; }
+   if ((err = mp_to_unsigned_bin(&result->y, out+x)) != MP_OKAY)          { goto error; }
+
+   err = CRYPT_OK;
+   goto done1;
+error:
+   err = mpi_to_ltc_error(err);
+done1:
+   mp_clear(&prime);
+   del_point(result);
+   return err;
+}
+
+int ecc_get_size(ecc_key *key)
+{
+   _ARGCHK(key != NULL);
+   if (is_valid_idx(key->idx))
+      return sets[key->idx].size;
+   else
+      return INT_MAX; /* large value known to cause it to fail when passed to ecc_make_key() */
+}
+
+#include "ecc_sys.c"
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ecc_sys.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,432 @@
+/* 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
+ */
+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)
+{
+    unsigned char pub_expt[256], ecc_shared[256], skey[MAXBLOCKSIZE];
+    ecc_key pubkey;
+    unsigned long x, y, z, hashsize, pubkeysize;
+    int err;
+
+    _ARGCHK(inkey != NULL);
+    _ARGCHK(out   != NULL);
+    _ARGCHK(len   != NULL);
+    _ARGCHK(key   != NULL);
+
+    /* check that wprng/cipher/hash are not invalid */
+    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+       return err;
+    }
+
+    if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+       return err;
+    }
+
+    if (keylen > hash_descriptor[hash].hashsize) {
+       return CRYPT_INVALID_HASH;
+    }
+
+    /* make a random key and export the public copy */
+    if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
+       return err;
+    }
+
+    pubkeysize = (unsigned long)sizeof(pub_expt);
+    if ((err = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
+       ecc_free(&pubkey);
+       return err;
+    }
+    
+    /* now check if the out buffer is big enough */
+    if (*len < (9 + PACKET_SIZE + pubkeysize + hash_descriptor[hash].hashsize)) {
+       ecc_free(&pubkey);
+       return CRYPT_BUFFER_OVERFLOW;
+    }
+
+    /* make random key */
+    hashsize  = hash_descriptor[hash].hashsize;
+    x = (unsigned long)sizeof(ecc_shared);
+    if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) {
+       ecc_free(&pubkey);
+       return err;
+    }
+    ecc_free(&pubkey);
+    z = (unsigned long)sizeof(skey);
+    if ((err = hash_memory(hash, ecc_shared, x, skey, &z)) != CRYPT_OK) {
+       return err;
+    }
+    
+    /* store header */
+    packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY);    
+
+    /* output header */
+    y = PACKET_SIZE;
+ 
+    /* size of hash name and the name itself */
+    out[y++] = hash_descriptor[hash].ID;
+
+    /* length of ECC pubkey and the key itself */
+    STORE32L(pubkeysize, out+y);
+    y += 4;
+
+    for (x = 0; x < pubkeysize; x++, y++) {
+        out[y] = pub_expt[x];
+    }
+
+    STORE32L(keylen, out+y);
+    y += 4;
+
+    /* Encrypt/Store the encrypted key */
+    for (x = 0; x < keylen; x++, y++) {
+      out[y] = skey[x] ^ inkey[x];
+    }
+    *len = y;
+
+#ifdef CLEAN_STACK
+    /* clean up */
+    zeromem(pub_expt, sizeof(pub_expt));
+    zeromem(ecc_shared, sizeof(ecc_shared));
+    zeromem(skey, sizeof(skey));
+#endif
+    return CRYPT_OK;
+}
+
+int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
+                          unsigned char *outkey, unsigned long *keylen, 
+                          ecc_key *key)
+{
+   unsigned char shared_secret[256], skey[MAXBLOCKSIZE];
+   unsigned long x, y, z, hashsize, keysize;
+   int hash, err;
+   ecc_key pubkey;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(outkey != NULL);
+   _ARGCHK(keylen != NULL);
+   _ARGCHK(key    != NULL);
+
+   /* right key type? */
+   if (key->type != PK_PRIVATE) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+   
+   /* correct length ? */
+   if (inlen < PACKET_SIZE+1+4+4) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= PACKET_SIZE+1+4+4;
+   }
+
+   /* is header correct? */
+   if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* now lets get the hash name */
+   y = PACKET_SIZE;
+   hash = find_hash_id(in[y++]);
+   if (hash == -1) {
+      return CRYPT_INVALID_HASH;
+   }
+
+   /* common values */
+   hashsize  = hash_descriptor[hash].hashsize;
+
+   /* get public key */
+   LOAD32L(x, in+y);
+   if (inlen < x) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= x;
+   }
+   y += 4;
+   if ((err = ecc_import(in+y, x, &pubkey)) != CRYPT_OK) {
+      return err;
+   }
+   y += x;
+
+   /* make shared key */
+   x = (unsigned long)sizeof(shared_secret);
+   if ((err = ecc_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
+      ecc_free(&pubkey);
+      return err;
+   }
+   ecc_free(&pubkey);
+
+   z = (unsigned long)sizeof(skey);
+   if ((err = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
+      return err;
+   }
+
+   LOAD32L(keysize, in+y);
+   if (inlen < keysize) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= keysize;
+   }
+   y += 4;
+
+   if (*keylen < keysize) {
+       err = CRYPT_BUFFER_OVERFLOW;
+       goto done;
+   }
+
+   /* Decrypt the key */
+   for (x = 0; x < keysize; x++, y++) {
+     outkey[x] = skey[x] ^ in[y];
+   }
+
+   *keylen = keysize;
+
+   err = CRYPT_OK;
+done:
+#ifdef CLEAN_STACK
+   zeromem(shared_secret, sizeof(shared_secret));
+   zeromem(skey, sizeof(skey));
+#endif
+   return err;
+}
+
+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)
+{
+   ecc_key pubkey;
+   mp_int b, p;
+   unsigned char epubkey[256], er[256];
+   unsigned long x, y, pubkeysize, rsize;
+   int  err;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+
+   /* is this a private key? */
+   if (key->type != PK_PRIVATE) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+   
+   /* is the IDX valid ?  */
+   if (is_valid_idx(key->idx) != 1) {
+      return CRYPT_PK_INVALID_TYPE;
+   }
+   
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* make up a key and export the public copy */
+   if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
+      return err;
+   }
+
+   pubkeysize = (unsigned long)sizeof(epubkey);
+   if ((err = ecc_export(epubkey, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
+      ecc_free(&pubkey);
+      return err;
+   }
+
+   /* get the hash and load it as a bignum into 'b' */
+   /* init the bignums */
+   if ((err = mp_init_multi(&b, &p, NULL)) != MP_OKAY) { 
+      ecc_free(&pubkey);
+      return mpi_to_ltc_error(err);
+   }
+   if ((err = mp_read_radix(&p, (char *)sets[key->idx].order, 64)) != MP_OKAY)        { goto error; }
+   if ((err = mp_read_unsigned_bin(&b, (unsigned char *)in, (int)inlen)) != MP_OKAY)  { goto error; }
+
+   /* find b = (m - x)/k */
+   if ((err = mp_invmod(&pubkey.k, &p, &pubkey.k)) != MP_OKAY)            { goto error; } /* k = 1/k */
+   if ((err = mp_submod(&b, &key->k, &p, &b)) != MP_OKAY)                 { goto error; } /* b = m - x */
+   if ((err = mp_mulmod(&b, &pubkey.k, &p, &b)) != MP_OKAY)               { goto error; } /* b = (m - x)/k */
+
+   /* export it */
+   rsize = (unsigned long)mp_unsigned_bin_size(&b);
+   if (rsize > (unsigned long)sizeof(er)) { 
+      err = CRYPT_BUFFER_OVERFLOW;
+      goto error; 
+   }
+   if ((err = mp_to_unsigned_bin(&b, er)) != MP_OKAY)                     { goto error; }
+
+   /* now lets check the outlen before we write */
+   if (*outlen < (12 + rsize + pubkeysize)) {
+      err = CRYPT_BUFFER_OVERFLOW;
+      goto done;
+   }
+
+   /* lets output */
+   y = PACKET_SIZE;
+   
+   /* size of public key */
+   STORE32L(pubkeysize, out+y);
+   y += 4;
+
+   /* copy the public key */
+   for (x = 0; x < pubkeysize; x++, y++) {
+       out[y] = epubkey[x];
+   }
+
+   /* size of 'r' */
+   STORE32L(rsize, out+y);
+   y += 4;
+
+   /* copy r */
+   for (x = 0; x < rsize; x++, y++) {
+       out[y] = er[x];
+   }
+
+   /* store header */
+   packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_SIGNED);
+
+   /* clear memory */
+   *outlen = y;
+   err = CRYPT_OK;
+   goto done;
+error:
+   err = mpi_to_ltc_error(err);
+done:
+   mp_clear_multi(&b, &p, NULL);
+   ecc_free(&pubkey);
+#ifdef CLEAN_STACK
+   zeromem(er, sizeof(er));
+   zeromem(epubkey, sizeof(epubkey));
+#endif
+   return err;   
+}
+
+/* verify that mG = (bA + Y)
+ *
+ * The signatures work by making up a fresh key "a" with a public key "A".  Now we want to sign so the 
+ * public key Y = xG can verify it.
+ *
+ * b = (m - x)/k, A is the public key embedded and Y is the users public key [who signed it]
+ * A = kG therefore bA == ((m-x)/k)kG == (m-x)G
+ *
+ * Adding Y = xG to the bA gives us (m-x)G + xG == mG
+ *
+ * The user given only xG, kG and b cannot determine k or x which means they can't find the private key.
+ * 
+ */
+int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
+                    const unsigned char *hash, unsigned long inlen, 
+                    int *stat, ecc_key *key)
+{
+   ecc_point *mG;
+   ecc_key   pubkey;
+   mp_int b, p, m, mu;
+   unsigned long x, y;
+   int err;
+
+   _ARGCHK(sig  != NULL);
+   _ARGCHK(hash != NULL);
+   _ARGCHK(stat != NULL);
+   _ARGCHK(key  != NULL);
+
+   /* default to invalid signature */
+   *stat = 0;
+
+   if (siglen < PACKET_SIZE+4+4) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= PACKET_SIZE+4+4;
+   }
+
+   /* is the message format correct? */
+   if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_ECC, PACKET_SUB_SIGNED)) != CRYPT_OK) {
+      return err;
+   }     
+
+   /* get hash name */
+   y = PACKET_SIZE;
+
+   /* get size of public key */
+   LOAD32L(x, sig+y);
+   if (siglen < x) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= x;
+   }
+   y += 4;
+
+   /* load the public key */
+   if ((err = ecc_import((unsigned char*)sig+y, x, &pubkey)) != CRYPT_OK) {
+      return err;
+   }
+   y += x;
+
+   /* load size of 'b' */
+   LOAD32L(x, sig+y);
+   if (siglen < x) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= x;
+   }
+   y += 4;
+
+   /* init values */
+   if ((err = mp_init_multi(&b, &m, &p, &mu, NULL)) != MP_OKAY) { 
+      ecc_free(&pubkey);
+      return mpi_to_ltc_error(err);
+   }
+
+   mG = new_point();
+   if (mG == NULL) { 
+      mp_clear_multi(&b, &m, &p, &mu, NULL);
+      ecc_free(&pubkey);
+      return CRYPT_MEM;
+   } 
+
+   /* load b */
+   if ((err = mp_read_unsigned_bin(&b, (unsigned char *)sig+y, (int)x)) != MP_OKAY)        { goto error; }
+   y += x;
+
+   /* get m in binary a bignum */
+   if ((err = mp_read_unsigned_bin(&m, (unsigned char *)hash, (int)inlen)) != MP_OKAY)     { goto error; }
+   
+   /* load prime */
+   if ((err = mp_read_radix(&p, (char *)sets[key->idx].prime, 64)) != MP_OKAY)             { goto error; }
+   
+   /* calculate barrett stuff */
+   mp_set(&mu, 1); 
+   mp_lshd(&mu, 2 * USED(&p));
+   if ((err = mp_div(&mu, &p, &mu, NULL)) != MP_OKAY)                                      { goto error; }
+
+   /* get bA */
+   if ((err = ecc_mulmod(&b, &pubkey.pubkey, &pubkey.pubkey, &p)) != CRYPT_OK)                  { goto done; }
+   
+   /* get bA + Y */
+   if ((err = add_point(&pubkey.pubkey, &key->pubkey, &pubkey.pubkey, &p, &mu)) != CRYPT_OK)    { goto done; }
+
+   /* get mG */
+   if ((err = mp_read_radix(&mG->x, (char *)sets[key->idx].Gx, 64)) != MP_OKAY)                 { goto error; }
+   if ((err = mp_read_radix(&mG->y, (char *)sets[key->idx].Gy, 64)) != MP_OKAY)                 { goto error; }
+   if ((err = ecc_mulmod(&m, mG, mG, &p)) != CRYPT_OK)                                          { goto done; }
+
+   /* compare mG to bA + Y */
+   if (mp_cmp(&mG->x, &pubkey.pubkey.x) == MP_EQ && mp_cmp(&mG->y, &pubkey.pubkey.y) == MP_EQ) {
+      *stat = 1;
+   }
+
+   /* clear up and return */
+   err = CRYPT_OK;
+   goto done;
+error:
+   err = mpi_to_ltc_error(err);
+done:
+   del_point(mG);
+   ecc_free(&pubkey);
+   mp_clear_multi(&p, &m, &b, &mu, NULL);
+   return err;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/ch1-01.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,18 @@
+/* 
+ * Name      : ch1-01.c
+ * Purpose   : Demonstration of a basic libtomcrypt program
+ * Author    : Tom St Denis
+ *
+ * History   : v0.79 Initial release
+ */
+ 
+/* ch1-01-1  */
+/* Include the default headers and libtomcrypt headers */
+#include <mycrypt.h>
+
+int main(void)
+{
+   return 0;
+}
+/* ch1-01-1  */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/ch1-02.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,25 @@
+/* 
+ * Name      : ch1-02.c
+ * Purpose   : Demonstration of error handling
+ * Author    : Tom St Denis
+ *
+ * History   : v0.79 Initial release
+ */
+ 
+/* ch1-01-1 */
+#include <mycrypt.h>
+
+int main(void)
+{
+   int errno;
+   
+   if ((errno = some_func(...)) != CRYPT_OK) {
+      printf("Error: %s\n", error_to_string(errno));
+      return EXIT_FAILURE;
+   }
+   
+   return 0;
+}
+/*ch1-01-1 */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/ch1-03.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,29 @@
+/* 
+ * Name      : ch1-03.c
+ * Purpose   : Demonstration of variable length outputs
+ * Author    : Tom St Denis
+ *
+ * History   : v0.79 Initial release
+ */
+ 
+ /* ch1-01-1 */
+ #include <mycrypt.h>
+ 
+ int main(void)
+ {
+    unsigned long length;
+    unsigned char buffer[512];
+    int errno;
+    
+    length = sizeof(buffer);
+    if ((errno = some_func(..., buffer, &length)) != CRYPT_OK) {
+       printf("Error: %s\n", error_to_string(errno));
+       return EXIT_FAILURE;
+    }
+    printf("Size of output is %lu bytes\n", length);
+    return 0;
+}
+/* ch1-01-1 */
+
+
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/ch2-01.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,35 @@
+/* 
+ * Name      : ch2-01.c
+ * Purpose   : Demonstration of reading the RNG
+ * Author    : Tom St Denis
+ *
+ * History   : v0.81 Initial release
+ */
+ 
+ /* ch2-02-2 */
+ #include <mycrypt.h>
+ 
+ int main(void) 
+ {
+    unsigned char buf[16];
+    unsigned long len;
+    int           ix;
+    
+    /* read the RNG */
+    len = rng_get_bytes(buf, sizeof(buf), NULL);
+    
+    /* verify return */
+    if (len != sizeof(buf)) {
+       printf("Error: Only read %lu bytes.\n", len);
+    } else {
+       printf("Read %lu bytes\n", len);
+       for (ix = 0; ix < sizeof(buf); ix++) {
+           printf("%02x ", buf[ix]);
+       }
+       printf("\n");
+    }
+    
+    return EXIT_SUCCESS;
+}
+/* ch2-02-2 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gf.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,305 @@
+/* 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
+ */
+/* polynomial basis GF(2^w) routines */
+#include "mycrypt.h"
+
+#ifdef GF
+
+#define FORLOOP for (i = 0; i < LSIZE; i++) 
+
+/* c = a + b */
+void gf_add(gf_intp a, gf_intp b, gf_intp c)
+{
+   int i;
+   FORLOOP c[i] = a[i]^b[i];
+}
+
+/* b = a */
+void gf_copy(gf_intp a, gf_intp b)
+{
+   int i;
+   FORLOOP b[i] = a[i];
+}
+
+/* a = 0 */
+void gf_zero(gf_intp a)
+{
+   int i;
+   FORLOOP a[i] = 0;
+}
+
+/* is a zero? */
+int gf_iszero(gf_intp a)
+{
+   int i;
+   FORLOOP if (a[i]) {
+      return 0;
+   }
+   return 1;
+}
+
+/* is a one? */
+int gf_isone(gf_intp a)
+{ 
+   int i;
+   for (i = 1; i < LSIZE; i++) {
+       if (a[i]) {
+          return 0;
+       }
+   }
+   return a[0] == 1;
+}
+
+/* b = a << 1*/
+void gf_shl(gf_intp a, gf_intp b)
+{
+   int i;
+   gf_int tmp;
+
+   gf_copy(a, tmp);
+   for (i = LSIZE-1; i > 0; i--) 
+       b[i] = ((tmp[i]<<1)|((tmp[i-1]&0xFFFFFFFFUL)>>31))&0xFFFFFFFFUL;
+   b[0] = (tmp[0] << 1)&0xFFFFFFFFUL;
+   gf_zero(tmp);
+}
+
+/* b = a >> 1 */
+void gf_shr(gf_intp a, gf_intp b)
+{
+   int i;
+   gf_int tmp;
+
+   gf_copy(a, tmp);
+   for (i = 0; i < LSIZE-1; i++)
+       b[i] = (((tmp[i]&0xFFFFFFFFUL)>>1)|(tmp[i+1]<<31))&0xFFFFFFFFUL;
+   b[LSIZE-1] = (tmp[LSIZE-1]&0xFFFFFFFFUL)>>1;
+   gf_zero(tmp);
+}
+
+/* returns -1 if its zero, otherwise degree of a */
+int gf_deg(gf_intp a)
+{
+   int i, ii;
+   unsigned long t;
+
+   ii = -1;
+   for (i = LSIZE-1; i >= 0; i--)
+       if (a[i]) {
+          for (t = a[i], ii = 0; t; t >>= 1, ++ii);
+          break;
+       }
+   if (i == -1) i = 0;
+   return (i<<5)+ii;
+}
+
+/* c = ab */
+void gf_mul(gf_intp a, gf_intp b, gf_intp c)
+{
+   gf_int ta, tb;
+   int i, n;
+
+   gf_copy(a, ta);
+   gf_copy(b, tb);
+   gf_zero(c);
+   n = gf_deg(ta)+1;
+   for (i = 0; i < n; i++) {
+       if (ta[i>>5]&(1<<(i&31)))
+          gf_add(c, tb, c);
+       gf_shl(tb, tb);
+   }
+   gf_zero(ta);
+   gf_zero(tb);
+}
+
+/* q = a/b, r = a%b */
+void gf_div(gf_intp a, gf_intp b, gf_intp q, gf_intp r)
+{
+   gf_int ta, tb, shifts[LSIZE*32];
+   int i, magb, mag;
+
+   mag  = gf_deg(a);
+   magb = gf_deg(b);
+
+   /* special cases */
+   if (magb > mag) {
+      gf_copy(a, r);
+      gf_zero(q);
+      return;
+   }
+   if (magb == -1) {
+      return;
+   }
+
+   /* copy locally */
+   gf_copy(a, ta);
+   gf_copy(b, tb);
+   gf_zero(q);
+
+   /* make shifted versions of "b" */
+   gf_copy(tb, shifts[0]);
+   for (i = 1; i <= (mag-magb); i++) 
+       gf_shl(shifts[i-1], shifts[i]);
+
+   while (mag >= magb) {
+       i = (mag - magb);
+       q[i>>5] |= (1<<(i&31));
+       gf_add(ta, shifts[i], ta);
+       mag = gf_deg(ta);
+   }
+   gf_copy(ta, r);
+   gf_zero(ta);
+   gf_zero(tb);
+   zeromem(shifts, sizeof(shifts));
+}
+
+/* b = a mod m */
+void gf_mod(gf_intp a, gf_intp m, gf_intp b)
+{
+   gf_int tmp;
+   gf_div(a,m,tmp,b);
+   gf_zero(tmp);
+}
+
+/* c = ab (mod m) */
+void gf_mulmod(gf_intp a, gf_intp b, gf_intp m, gf_intp c)
+{
+   gf_int tmp;
+   gf_mul(a, b, tmp);
+   gf_mod(tmp, m, c);
+   gf_zero(tmp);
+}
+
+/* B = 1/A mod M */
+void gf_invmod(gf_intp A, gf_intp M, gf_intp B)
+{
+  gf_int m, n, p0, p1, p2, r, q, tmp;
+
+  /* put all variables in known setup state */
+  gf_zero(p0);
+  gf_zero(p2);
+  gf_copy(M, m);
+  gf_copy(A, n);
+  p0[0] = 1;
+  gf_div(m, n, p1, r);
+  gf_copy(p1, q);
+
+  /* loop until r == 0 */
+  while (!gf_iszero(r)) {
+     gf_copy(n, m);
+     gf_copy(r, n);
+     gf_div(m, n, q, r);
+     gf_mul(q, p1, tmp);
+     gf_add(tmp, p0, p2);
+     gf_copy(p1, p0);
+     gf_copy(p2, p1);
+  }
+  gf_copy(p0, B);
+  gf_zero(p0);
+}
+
+/* find a square root modulo a prime.  Note the number of 
+ * elements is 2^k - 1, so we must square k-2 times to get the
+ * square root.. 
+ */
+void gf_sqrt(gf_intp a, gf_intp M, gf_intp b)
+{
+   int k;
+   k = gf_deg(M)-2;
+   gf_copy(a, b);
+   while (k--)
+      gf_mulmod(b, b, M, b);
+}
+
+/* c = gcd(A,B) */
+void gf_gcd(gf_intp A, gf_intp B, gf_intp c)
+{
+   gf_int a, b, r;
+   int n;
+
+   gf_add(A, B, r);
+   n = gf_deg(r);
+   if (gf_deg(A) > n) {
+      gf_copy(A, a);
+      gf_copy(B, b);
+   } else {
+      gf_copy(A, b);
+      gf_copy(B, a);
+   }
+
+   do {
+      gf_mod(a, b, r);
+      gf_copy(b, a);
+      gf_copy(r, b);
+   } while (!gf_iszero(r));
+   gf_copy(a, c);
+   gf_zero(a);
+   gf_zero(b);
+}
+
+/* returns non-zero if 'a' is irreducible */
+int gf_is_prime(gf_intp a)
+{
+   gf_int u, tmp;
+   int m, n;
+
+   gf_zero(u);
+   u[0] = 2;			/* u(x) = x */
+   m = gf_deg(a);
+   for (n = 0; n < (m/2); n++) { 
+       gf_mulmod(u, u, a, u);   /* u(x) = u(x)^2 mod a(x) */
+       gf_copy(u, tmp);
+       tmp[0] ^= 2;		/* tmp(x) = u(x) - x */
+       gf_gcd(tmp, a, tmp);     /* tmp(x) = gcd(a(x), u(x) - x) */
+       if (!gf_isone(tmp)) {
+          return 0;
+       }
+   }
+   return 1;
+}  
+
+/* returns bytes required to store a gf_int */
+int gf_size(gf_intp a)
+{
+   int n;
+
+   n = gf_deg(a);
+   if (n == -1) {
+      return 4;
+   }
+   n = n + (32 - (n&31));
+   return n/8;
+}
+
+/* store a gf_int */
+void gf_toraw(gf_intp a, unsigned char *dst)
+{
+   int x, n;
+   n = gf_size(a)/4;
+   for (x = 0; x < n; x++) {
+       STORE32L(a[x], dst);
+       dst += 4;
+   }
+}
+
+/* read a gf_int (len == in bytes) */
+void gf_readraw(gf_intp a, unsigned char *str, int len)
+{
+   int x;
+   gf_zero(a);
+   for (x = 0; x < len/4; x++) {
+       LOAD32L(a[x], str);
+       str += 4;
+   }
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hash_file.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,41 @@
+/* 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_file(int hash, const char *fname, unsigned char *dst, unsigned long *outlen)
+{
+#ifdef NO_FILE
+    return CRYPT_NOP;
+#else
+    FILE *in;
+    int err;
+    _ARGCHK(fname  != NULL);
+    _ARGCHK(dst    != NULL);
+    _ARGCHK(outlen != NULL);
+
+    if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+        return err;
+    }
+
+    in = fopen(fname, "rb");
+    if (in == NULL) { 
+       return CRYPT_FILE_NOTFOUND;
+    }
+
+    err = hash_filehandle(hash, in, dst, outlen);
+    if (fclose(in) != 0) {
+       return CRYPT_ERROR;
+    }
+
+    return err;
+#endif
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hash_filehandle.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,49 @@
+/* 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_filehandle(int hash, FILE *in, unsigned char *dst, unsigned long *outlen)
+{
+#ifdef NO_FILE
+    return CRYPT_NOP;
+#else
+    hash_state md;
+    unsigned char buf[512];
+    size_t x;
+    int err;
+
+    _ARGCHK(dst    != NULL);
+    _ARGCHK(outlen != NULL);
+    _ARGCHK(in     != NULL);
+
+    if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+        return err;
+    }
+
+    if (*outlen < hash_descriptor[hash].hashsize) {
+       return CRYPT_BUFFER_OVERFLOW;
+    }
+    *outlen = hash_descriptor[hash].hashsize;
+
+    hash_descriptor[hash].init(&md);
+    do {
+        x = fread(buf, 1, sizeof(buf), in);
+        hash_descriptor[hash].process(&md, buf, x);
+    } while (x == sizeof(buf));
+    hash_descriptor[hash].done(&md, dst);
+
+#ifdef CLEAN_STACK
+    zeromem(buf, sizeof(buf));
+#endif
+    return CRYPT_OK;
+#endif
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hash_memory.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,35 @@
+/* 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_memory(int hash, const unsigned char *data, unsigned long len, unsigned char *dst, unsigned long *outlen)
+{
+    hash_state md;
+    int err;
+
+    _ARGCHK(data   != NULL);
+    _ARGCHK(dst    != NULL);
+    _ARGCHK(outlen != NULL);
+
+    if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+        return err;
+    }
+
+    if (*outlen < hash_descriptor[hash].hashsize) {
+       return CRYPT_BUFFER_OVERFLOW;
+    }
+    *outlen = hash_descriptor[hash].hashsize;
+
+    hash_descriptor[hash].init(&md);
+    hash_descriptor[hash].process(&md, data, len);
+    hash_descriptor[hash].done(&md, dst);
+    return CRYPT_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hmac_done.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,84 @@
+/* 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
+ */
+/* Submited by Dobes Vandermeer  ([email protected]) */
+
+#include "mycrypt.h"
+
+/*
+    (1) append zeros to the end of K to create a B byte string
+        (e.g., if K is of length 20 bytes and B=64, then K will be
+         appended with 44 zero bytes 0x00)
+    (2) XOR (bitwise exclusive-OR) the B byte string computed in step
+        (1) with ipad (ipad = the byte 0x36 repeated B times)
+    (3) append the stream of data 'text' to the B byte string resulting
+        from step (2)
+    (4) apply H to the stream generated in step (3)
+    (5) XOR (bitwise exclusive-OR) the B byte string computed in
+        step (1) with opad (opad = the byte 0x5C repeated B times.)
+    (6) append the H result from step (4) to the B byte string
+        resulting from step (5)
+    (7) apply H to the stream generated in step (6) and output
+        the result
+*/
+
+#ifdef HMAC
+
+#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
+
+int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen)
+{
+    unsigned char buf[MAXBLOCKSIZE];
+    unsigned char isha[MAXBLOCKSIZE];
+    unsigned long hashsize, i;
+    int hash, err;
+
+    _ARGCHK(hmac != NULL);
+    _ARGCHK(hashOut != NULL);
+
+    hash = hmac->hash;
+    if((err = hash_is_valid(hash)) != CRYPT_OK) {
+        return err;
+    }
+
+    /* get the hash message digest size */
+    hashsize = hash_descriptor[hash].hashsize;
+
+    // Get the hash of the first HMAC vector plus the data
+    if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) {
+       return err;
+    }
+
+    // Create the second HMAC vector vector for step (3)
+    for(i=0; i < HMAC_BLOCKSIZE; i++) {
+        buf[i] = hmac->key[i] ^ 0x5C;
+    }
+
+    // Now calculate the "outer" hash for step (5), (6), and (7)
+    hash_descriptor[hash].init(&hmac->md);
+    hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE);
+    hash_descriptor[hash].process(&hmac->md, isha, hashsize);
+    hash_descriptor[hash].done(&hmac->md, buf);
+
+    // copy to output 
+    for (i = 0; i < hashsize && i < *outlen; i++) {
+        hashOut[i] = buf[i];
+    }
+    *outlen = i;
+
+#ifdef CLEAN_STACK
+    zeromem(isha, sizeof(buf));
+    zeromem(buf,  sizeof(isha));
+    zeromem(hmac, sizeof(*hmac));
+#endif
+    return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hmac_file.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,96 @@
+/* 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
+ */
+/* Submited by Dobes Vandermeer  ([email protected]) */
+
+#include "mycrypt.h"
+
+/*
+    (1) append zeros to the end of K to create a B byte string
+        (e.g., if K is of length 20 bytes and B=64, then K will be
+         appended with 44 zero bytes 0x00)
+    (2) XOR (bitwise exclusive-OR) the B byte string computed in step
+        (1) with ipad (ipad = the byte 0x36 repeated B times)
+    (3) append the stream of data 'text' to the B byte string resulting
+        from step (2)
+    (4) apply H to the stream generated in step (3)
+    (5) XOR (bitwise exclusive-OR) the B byte string computed in
+        step (1) with opad (opad = the byte 0x5C repeated B times.)
+    (6) append the H result from step (4) to the B byte string
+        resulting from step (5)
+    (7) apply H to the stream generated in step (6) and output
+        the result
+*/
+
+#ifdef HMAC
+
+#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
+
+/* hmac_file added by Tom St Denis */
+int hmac_file(int hash, const char *fname, 
+              const unsigned char *key, unsigned long keylen, 
+                    unsigned char *dst, unsigned long *dstlen)
+{
+#ifdef NO_FILE
+    return CRYPT_NOP;
+#else
+   hmac_state hmac;
+   FILE *in;
+   unsigned char buf[512];
+   size_t x;
+   int err;
+
+   _ARGCHK(fname  != NULL);
+   _ARGCHK(key    != NULL);
+   _ARGCHK(dst    != NULL);
+   _ARGCHK(dstlen != NULL);
+   
+   if((err = hash_is_valid(hash)) != CRYPT_OK) {
+       return err;
+   }
+
+   if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) {
+       return err;
+   }
+
+   in = fopen(fname, "rb");
+   if (in == NULL) {
+      return CRYPT_FILE_NOTFOUND;
+   }
+
+   /* process the file contents */
+   do {
+      x = fread(buf, 1, sizeof(buf), in);
+      if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) {
+         /* we don't trap this error since we're already returning an error! */
+         fclose(in);
+         return err;
+      }
+   } while (x == sizeof(buf));
+
+   if (fclose(in) != 0) {
+      return CRYPT_ERROR;
+   }
+
+   /* get final hmac */
+   if ((err = hmac_done(&hmac, dst, dstlen)) != CRYPT_OK) {
+      return err;
+   }
+
+#ifdef CLEAN_STACK
+   /* clear memory */
+   zeromem(buf, sizeof(buf));
+#endif   
+   return CRYPT_OK;
+#endif
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hmac_init.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,87 @@
+/* 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
+ */
+/* Submited by Dobes Vandermeer  ([email protected]) */
+
+#include "mycrypt.h"
+
+/*
+    (1) append zeros to the end of K to create a B byte string
+        (e.g., if K is of length 20 bytes and B=64, then K will be
+         appended with 44 zero bytes 0x00)
+    (2) XOR (bitwise exclusive-OR) the B byte string computed in step
+        (1) with ipad (ipad = the byte 0x36 repeated B times)
+    (3) append the stream of data 'text' to the B byte string resulting
+        from step (2)
+    (4) apply H to the stream generated in step (3)
+    (5) XOR (bitwise exclusive-OR) the B byte string computed in
+        step (1) with opad (opad = the byte 0x5C repeated B times.)
+    (6) append the H result from step (4) to the B byte string
+        resulting from step (5)
+    (7) apply H to the stream generated in step (6) and output
+        the result
+*/
+
+#ifdef HMAC
+
+#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
+
+int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen)
+{
+    unsigned char buf[MAXBLOCKSIZE];
+    unsigned long hashsize;
+    unsigned long i, z;
+    int err;
+
+    _ARGCHK(hmac != NULL);
+    _ARGCHK(key != NULL);
+
+    if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+        return err;
+    }
+
+    /* valid key length? */
+    if (keylen == 0) {
+        return CRYPT_INVALID_KEYSIZE;
+    }
+
+    hmac->hash = hash;
+
+    // (1) make sure we have a large enough key
+    hashsize = hash_descriptor[hash].hashsize;
+    if(keylen > HMAC_BLOCKSIZE) {
+        z = (unsigned long)sizeof(hmac->key);
+        if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) {
+           return err;
+        }
+        if(hashsize < HMAC_BLOCKSIZE) {
+            zeromem((hmac->key) + hashsize, (size_t)(HMAC_BLOCKSIZE - hashsize));
+        }
+        keylen = hashsize;
+    } else {
+        memcpy(hmac->key, key, (size_t)keylen);
+        if(keylen < HMAC_BLOCKSIZE) {
+            zeromem((hmac->key) + keylen, (size_t)(HMAC_BLOCKSIZE - keylen));
+        }
+    }
+
+    // Create the initial vector for step (3)
+    for(i=0; i < HMAC_BLOCKSIZE;   i++) {
+       buf[i] = hmac->key[i] ^ 0x36;
+    }
+
+    // Pre-pend that to the hash data
+    hash_descriptor[hash].init(&hmac->md);
+    hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE);
+
+    return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hmac_memory.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,67 @@
+/* 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
+ */
+/* Submited by Dobes Vandermeer  ([email protected]) */
+
+#include "mycrypt.h"
+
+/*
+    (1) append zeros to the end of K to create a B byte string
+        (e.g., if K is of length 20 bytes and B=64, then K will be
+         appended with 44 zero bytes 0x00)
+    (2) XOR (bitwise exclusive-OR) the B byte string computed in step
+        (1) with ipad (ipad = the byte 0x36 repeated B times)
+    (3) append the stream of data 'text' to the B byte string resulting
+        from step (2)
+    (4) apply H to the stream generated in step (3)
+    (5) XOR (bitwise exclusive-OR) the B byte string computed in
+        step (1) with opad (opad = the byte 0x5C repeated B times.)
+    (6) append the H result from step (4) to the B byte string
+        resulting from step (5)
+    (7) apply H to the stream generated in step (6) and output
+        the result
+*/
+
+#ifdef HMAC
+
+#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
+
+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)
+{
+    hmac_state hmac;
+    int err;
+
+    _ARGCHK(key    != NULL);
+    _ARGCHK(data   != NULL);
+    _ARGCHK(dst    != NULL); 
+    _ARGCHK(dstlen != NULL);
+    
+    if((err = hash_is_valid(hash)) != CRYPT_OK) {
+        return err;
+    }
+
+    if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) {
+        return err;
+    }
+
+    if ((err = hmac_process(&hmac, data, len)) != CRYPT_OK) {
+       return err;
+    }
+
+    if ((err = hmac_done(&hmac, dst, dstlen)) != CRYPT_OK) {
+       return err;
+    }
+    return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hmac_process.c	Mon May 31 18:25:41 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
+ */
+/* Submited by Dobes Vandermeer  ([email protected]) */
+
+#include "mycrypt.h"
+
+/*
+    (1) append zeros to the end of K to create a B byte string
+        (e.g., if K is of length 20 bytes and B=64, then K will be
+         appended with 44 zero bytes 0x00)
+    (2) XOR (bitwise exclusive-OR) the B byte string computed in step
+        (1) with ipad (ipad = the byte 0x36 repeated B times)
+    (3) append the stream of data 'text' to the B byte string resulting
+        from step (2)
+    (4) apply H to the stream generated in step (3)
+    (5) XOR (bitwise exclusive-OR) the B byte string computed in
+        step (1) with opad (opad = the byte 0x5C repeated B times.)
+    (6) append the H result from step (4) to the B byte string
+        resulting from step (5)
+    (7) apply H to the stream generated in step (6) and output
+        the result
+*/
+
+#ifdef HMAC
+
+#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
+
+int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len)
+{
+    int err;
+    _ARGCHK(hmac != NULL);
+    _ARGCHK(buf != NULL);
+    if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) {
+        return err;
+    }
+    return hash_descriptor[hmac->hash].process(&hmac->md, buf, len);
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hmac_test.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,325 @@
+/* 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
+ */
+/* Submited by Dobes Vandermeer  ([email protected]) */
+
+#include "mycrypt.h"
+
+/*
+    (1) append zeros to the end of K to create a B byte string
+        (e.g., if K is of length 20 bytes and B=64, then K will be
+         appended with 44 zero bytes 0x00)
+    (2) XOR (bitwise exclusive-OR) the B byte string computed in step
+        (1) with ipad (ipad = the byte 0x36 repeated B times)
+    (3) append the stream of data 'text' to the B byte string resulting
+        from step (2)
+    (4) apply H to the stream generated in step (3)
+    (5) XOR (bitwise exclusive-OR) the B byte string computed in
+        step (1) with opad (opad = the byte 0x5C repeated B times.)
+    (6) append the H result from step (4) to the B byte string
+        resulting from step (5)
+    (7) apply H to the stream generated in step (6) and output
+        the result
+*/
+
+#ifdef HMAC
+
+#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
+
+/*
+
+    TEST CASES SOURCE:
+
+Network Working Group                                          P. Cheng
+Request for Comments: 2202                                          IBM
+Category: Informational                                        R. Glenn
+                                                                   NIST
+                                                         September 1997
+
+                 Test Cases for HMAC-MD5 and HMAC-SHA-1
+*/
+
+
+int hmac_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+    unsigned char digest[MAXBLOCKSIZE];
+    int i;
+
+    static const struct hmac_test_case {
+        int num;
+        char *algo;
+        unsigned char key[128];
+        unsigned long keylen;
+        unsigned char data[128];
+        unsigned long datalen;
+        unsigned char digest[MAXBLOCKSIZE];
+    } cases[] = {
+        /*
+        3. Test Cases for HMAC-SHA-1
+
+        test_case =     1
+        key =           0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+        key_len =       20
+        data =          "Hi Ther     20
+        digest =        0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04
+        digest-96 =     0x4c1a03424b55e07fe7f27be1
+        */
+        { 5, "sha1",
+            {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+             0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+             0x0c, 0x0c, 0x0c, 0x0c}, 20,
+            "Test With Truncation", 20,
+            {0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2,
+             0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04} },
+
+        /*
+        test_case =     6
+        key =           0xaa repeated 80 times
+        key_len =       80
+        data =          "Test Using Larger Than Block-Size Key - Hash Key First"
+        data_len =      54
+        digest =        0xaa4ae5e15272d00e95705637ce8a3b55ed402112
+        */
+        { 6, "sha1",
+            {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80,
+            "Test Using Larger Than Block-Size Key - Hash Key First", 54,
+            {0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e,
+             0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 
+             0xed, 0x40, 0x21, 0x12} },
+
+        /*
+        test_case =     7
+        key =           0xaa repeated 80 times
+        key_len =       80
+        data =          "Test Using Larger Than Block-Size Key and Larger
+                        Than One Block-Size Data"
+        data_len =      73
+        digest =        0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91
+        */
+        { 7, "sha1",
+            {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80,
+            "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73,
+            {0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d,
+             0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91} },
+
+        /*
+        2. Test Cases for HMAC-MD5
+
+        test_case =     1
+        key =           0x0b 0b 0b 0b 
+                          0b 0b 0b 0b
+                          0b 0b 0b 0b
+                          0b 0b 0b 0b
+        key_len =       16
+        data =          "Hi There"
+        data_len =      8
+        digest =        0x92 94 72 7a 
+                          36 38 bb 1c 
+                          13 f4 8e f8 
+                          15 8b fc 9d
+        */
+        { 1, "md5",
+            {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 
+             0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 16,
+            "Hi There", 8,
+            {0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, 
+             0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d}  },
+        /*
+        test_case =     2
+        key =           "Jefe"
+        key_len =       4
+        data =          "what do ya want for nothing?"
+        data_len =      28
+        digest =        0x750c783e6ab0b503eaa86e310a5db738
+        */
+        { 2, "md5",
+            "Jefe", 4,
+            "what do ya want for nothing?", 28,
+            {0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, 
+             0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38} },
+
+        /*
+        test_case =     3
+        key =           0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+        key_len         16
+        data =          0xdd repeated 50 times
+        data_len =      50
+        digest =        0x56be34521d144c88dbb8c733f0e8b3f6
+        */
+        { 3, "md5",
+            {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 16,
+            {0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+             0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+             0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+             0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+             0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd}, 50,
+            {0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
+             0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6} },
+        /*
+
+        test_case =     4
+        key = 0x0102030405060708090a0b0c0d0e0f10111213141516171819
+        key_len         25
+        data =          0xcd repeated 50 times
+        data_len =      50
+        digest =        0x697eaf0aca3a3aea3a75164746ffaa79
+        */
+        { 4, "md5",
+            {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}, 25,
+            {0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+             0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+             0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+             0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+             0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd}, 50,
+            {0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, 
+             0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79} },
+
+
+        /*
+ 
+        test_case =     5
+        key =           0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+        key_len =       16
+        data =          "Test With Truncation"
+        data_len =      20
+        digest =        0x56461ef2342edc00f9bab995690efd4c
+        digest-96       0x56461ef2342edc00f9bab995
+        */
+        { 5, "md5",
+            {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+             0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 16,
+            "Test With Truncation", 20,
+            {0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, 
+             0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c} },
+
+        /*
+
+        test_case =     6
+        key =           0xaa repeated 80 times
+        key_len =       80
+        data =          "Test Using Larger Than Block-Size Key - Hash 
+Key First"
+        data_len =      54
+        digest =        0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd
+        */
+        { 6, "md5",
+            {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80,
+            "Test Using Larger Than Block-Size Key - Hash Key First", 54,
+            {0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, 
+             0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd} },
+
+        /*
+
+        test_case =     7
+        key =           0xaa repeated 80 times
+        key_len =       80
+        data =          "Test Using Larger Than Block-Size Key and Larger
+                        Than One Block-Size Data"
+        data_len =      73
+        digest =        0x6f630fad67cda0ee1fb1f562db3aa53e
+        */
+        { 7, "md5",
+            {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+             0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80,
+            "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73,
+            {0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee,
+             0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e} }
+    };
+
+    unsigned long outlen;
+    int err;
+    int tested=0,failed=0;
+    for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) {
+        int hash = find_hash(cases[i].algo);
+        if (hash == -1) continue;
+        ++tested;
+        outlen = sizeof(digest);
+        if((err = hmac_memory(hash, cases[i].key, cases[i].keylen, cases[i].data, cases[i].datalen, digest, &outlen)) != CRYPT_OK) {
+#if 0
+            printf("HMAC-%s test #%d\n", cases[i].algo, cases[i].num);
+#endif
+            return err;
+        }
+
+        if(memcmp(digest, cases[i].digest, (size_t)hash_descriptor[hash].hashsize) != 0)  {
+#if 0
+            unsigned int j;
+            printf("\nHMAC-%s test #%d:\n", cases[i].algo, cases[i].num);
+            printf(  "Result:  0x");
+            for(j=0; j < hash_descriptor[hash].hashsize; j++) {
+                printf("%2x ", digest[j]);
+            }
+            printf("\nCorrect: 0x");
+            for(j=0; j < hash_descriptor[hash].hashsize; j++) {
+               printf("%2x ", cases[i].digest[j]);
+            }
+            printf("\n");
+#endif
+            failed++;
+            //return CRYPT_ERROR;
+        } else {
+            /* printf("HMAC-%s test #%d: Passed\n", cases[i].algo, cases[i].num); */
+        }
+    }
+
+    if (failed != 0) {
+        return CRYPT_FAIL_TESTVECTOR;
+    } else if (tested == 0) {
+        return CRYPT_NOP;
+    } else {
+        return CRYPT_OK;
+    }
+ #endif
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/is_prime.c	Mon May 31 18:25:41 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 protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+#ifdef MPI
+
+/* figures out if a number is prime (MR test) */
+int is_prime(mp_int *N, int *result)
+{
+   int err;
+   _ARGCHK(N != NULL);
+   _ARGCHK(result != NULL);
+   if ((err = mp_prime_is_prime(N, mp_prime_rabin_miller_trials(mp_count_bits(N)), result)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/keyring.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,862 @@
+/* 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
+ */
+/* Provides keyring functionality for libtomcrypt, Tom St Denis */
+#include <mycrypt.h>
+
+#ifdef KR
+
+static const unsigned char key_magic[4]  = { 0x12, 0x34, 0x56, 0x78 };
+static const unsigned char file_magic[4] = { 0x9A, 0xBC, 0xDE, 0xF0 };
+static const unsigned char sign_magic[4] = { 0x87, 0x56, 0x43, 0x21 };
+static const unsigned char enc_magic[4]  = { 0x0F, 0xED, 0xCB, 0xA9 };
+
+static const unsigned long crc_table[256] = {
+  0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+  0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+  0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+  0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+  0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+  0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+  0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+  0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+  0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+  0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+  0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+  0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+  0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+  0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+  0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+  0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+  0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+  0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+  0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+  0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+  0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+  0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+  0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+  0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+  0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+  0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+  0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+  0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+  0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+  0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+  0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+  0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+  0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+  0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+  0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+  0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+  0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+  0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+  0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+  0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+  0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+  0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+  0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+  0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+  0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+  0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+  0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+  0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+  0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+  0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+  0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+  0x2d02ef8dUL
+};
+
+#define DO1(buf) crc = crc_table[(crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
+#define DO2(buf)  DO1(buf); DO1(buf);
+#define DO4(buf)  DO2(buf); DO2(buf);
+#define DO8(buf)  DO4(buf); DO4(buf);
+
+static unsigned long crc32 (unsigned long crc, const unsigned char *buf, unsigned long len)
+{
+  //_ARGCHK(buf != NULL  && len == 0);
+  crc = crc ^ 0xffffffffL;
+  while (len >= 8) {
+      DO8 (buf);
+      len -= 8;
+  }
+  
+  if (len > 0) {
+    do {
+	   DO1 (buf);
+    } while (--len > 0);
+  }    
+  return crc ^ 0xffffffffUL;
+}
+
+int kr_init(pk_key **pk)
+{
+   _ARGCHK(pk != NULL);
+
+   *pk = XCALLOC(1, sizeof(pk_key));
+   if (*pk == NULL) {
+      return CRYPT_MEM;
+   }
+   (*pk)->system = NON_KEY;
+   return CRYPT_OK;
+}
+
+unsigned long kr_crc(const unsigned char *name, const unsigned char *email, const unsigned char *description)
+{
+   unsigned long crc;
+   _ARGCHK(name != NULL);
+   _ARGCHK(email != NULL);
+   _ARGCHK(description != NULL);
+   crc = crc32(0UL, NULL, 0UL);
+   crc = crc32(crc, name,  (unsigned long)MIN(MAXLEN, strlen((char *)name)));
+   crc = crc32(crc, email, (unsigned long)MIN(MAXLEN, strlen((char *)email)));
+   return crc32(crc, description, (unsigned long)MIN(MAXLEN, strlen((char *)description)));
+}
+
+pk_key *kr_find(pk_key *pk, unsigned long ID)
+{
+   _ARGCHK(pk != NULL);
+
+   while (pk != NULL) {
+        if (pk->system != NON_KEY && pk->ID == ID) {
+           return pk;
+        }
+        pk = pk->next;
+   }
+   return NULL;
+}
+
+pk_key *kr_find_name(pk_key *pk, const char *name)
+{
+   _ARGCHK(pk != NULL);
+   _ARGCHK(name != NULL);
+
+   while (pk != NULL) {
+        if (pk->system != NON_KEY && strncmp((char *)pk->name, (char *)name, sizeof(pk->name)-1) == 0) {
+           return pk;
+        }
+        pk = pk->next;
+   }
+   return NULL;
+}
+ 
+
+int kr_add(pk_key *pk, int key_type, int sys, const unsigned char *name, 
+           const unsigned char *email, const unsigned char *description, const _pk_key *key)
+{
+   _ARGCHK(pk != NULL);
+   _ARGCHK(name != NULL);
+   _ARGCHK(email != NULL);
+   _ARGCHK(description != NULL);
+   _ARGCHK(key != NULL);
+
+   /* check parameters */
+   if (key_type != PK_PRIVATE && key_type != PK_PRIVATE_OPTIMIZED && key_type != PK_PUBLIC) {
+      return CRYPT_PK_INVALID_TYPE;
+   }
+ 
+   if (sys != RSA_KEY && sys != DH_KEY && sys != ECC_KEY) {
+      return CRYPT_PK_INVALID_SYSTEM;
+   }
+
+   /* see if its a dupe  */
+   if (kr_find(pk, kr_crc(name, email, description)) != NULL) {
+      return CRYPT_PK_DUP;
+   }
+   
+   /* find spot in key ring */
+   while (pk->system != NON_KEY) {
+         if (pk->next == NULL) {
+            return CRYPT_ERROR;
+         }
+         pk = pk->next;
+   }
+
+   /* now we have a spot make a next spot */
+   pk->next = XCALLOC(1, sizeof(pk_key));
+   if (pk->next == NULL) {
+      return CRYPT_MEM;
+   }
+   pk->next->system = NON_KEY;
+
+   /* now add this new data to this ring spot */
+   pk->key_type = key_type;
+   pk->system   = sys;
+   strncpy((char *)pk->name, (char *)name, sizeof(pk->name)-1);
+   strncpy((char *)pk->email, (char *)email, sizeof(pk->email)-1);
+   strncpy((char *)pk->description, (char *)description, sizeof(pk->description)-1);
+   pk->ID       = kr_crc(pk->name, pk->email, pk->description);
+
+   /* clear the memory area */
+   zeromem(&(pk->key), sizeof(pk->key));
+
+   /* copy the key */
+   switch (sys) {
+         case RSA_KEY:
+              memcpy(&(pk->key.rsa), &(key->rsa), sizeof(key->rsa));
+              break;
+         case DH_KEY:
+              memcpy(&(pk->key.dh), &(key->dh), sizeof(key->dh));
+              break;
+         case ECC_KEY:
+              memcpy(&(pk->key.ecc), &(key->ecc), sizeof(key->ecc));
+              break;
+   }
+   return CRYPT_OK;
+}
+
+int kr_del(pk_key **_pk, unsigned long ID)
+{
+   pk_key *ppk, *pk;
+
+   _ARGCHK(_pk != NULL);
+
+   pk  = *_pk;
+   ppk = NULL;
+   while (pk->system != NON_KEY && pk->ID != ID) {
+        ppk = pk;
+        pk  = pk->next;
+        if (pk == NULL) {
+           return CRYPT_PK_NOT_FOUND;
+        }
+   }
+
+   switch (pk->system) {
+        case RSA_KEY:
+            rsa_free(&(pk->key.rsa));
+            break;
+        case DH_KEY:
+            dh_free(&(pk->key.dh));
+            break;
+        case ECC_KEY:
+            ecc_free(&(pk->key.ecc));
+            break;
+   }
+
+   if (ppk == NULL) {       /* the first element matches the ID */
+      ppk = pk->next;       /* get the 2nd element */
+      XFREE(pk);             /* free the first */
+      *_pk = ppk;           /* make the first element the second */
+   } else {                 /* (not) first element matches the ID */
+      ppk->next = pk->next; /* make the previous'es next point to the current next */
+      XFREE(pk);             /* free the element */
+   }
+   return CRYPT_OK;
+}
+
+int kr_clear(pk_key **pk)
+{
+   int err;
+   _ARGCHK(pk != NULL);
+
+   while ((*pk)->system != NON_KEY) {
+       if ((err = kr_del(pk, (*pk)->ID)) != CRYPT_OK) { 
+          return err;
+       }
+   }       
+   XFREE(*pk);
+   *pk = NULL;
+   return CRYPT_OK;
+}
+
+static unsigned long _write(unsigned char *buf, unsigned long len, FILE *f, symmetric_CTR *ctr)
+{
+#ifdef NO_FILE
+   return 0;
+#else
+   _ARGCHK(buf != NULL);
+   _ARGCHK(f   != NULL);
+   if (ctr != NULL) {
+      if (ctr_encrypt(buf, buf, len, ctr) != CRYPT_OK) {
+         return 0;
+      }
+   }
+   return (unsigned long)fwrite(buf, 1, (size_t)len, f);
+#endif
+}
+
+static unsigned long _read(unsigned char *buf, unsigned long len, FILE *f, symmetric_CTR *ctr)
+{
+#ifdef NO_FILE
+    return 0;
+#else
+   unsigned long y;
+   _ARGCHK(buf != NULL);
+   _ARGCHK(f   != NULL);
+   y = (unsigned long)fread(buf, 1, (size_t)len, f);
+   if (ctr != NULL) {
+      if (ctr_decrypt(buf, buf, y, ctr) != CRYPT_OK) {
+         return 0;
+      }
+   }
+   return y;
+#endif
+}
+
+int kr_export(pk_key *pk, unsigned long ID, int key_type, unsigned char *out, unsigned long *outlen)
+{
+   unsigned char buf[8192], *obuf;
+   pk_key *ppk;
+   unsigned long len;
+   int err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(out != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* find the desired key */
+   ppk = kr_find(pk, ID);
+   if (ppk == NULL) {
+      return CRYPT_PK_NOT_FOUND;
+   }
+
+   if (ppk->key_type == PK_PUBLIC && key_type != PK_PUBLIC) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   /* this makes PK_PRIVATE an alias for PK_PRIVATE_OPTIMIZED type */
+   if (ppk->key_type == PK_PRIVATE_OPTIMIZED && key_type == PK_PRIVATE) {
+      key_type = PK_PRIVATE_OPTIMIZED;
+   }
+
+   /* now copy the header and various other details */
+   memcpy(buf, key_magic, 4);                              /* magic info */
+   buf[4] = key_type;                                      /* key type */
+   buf[5] = ppk->system;                                   /* system */
+   STORE32L(ppk->ID, buf+6);                               /* key ID */
+   memcpy(buf+10, ppk->name, MAXLEN);                      /* the name */
+   memcpy(buf+10+MAXLEN, ppk->email, MAXLEN);              /* the email */
+   memcpy(buf+10+MAXLEN+MAXLEN, ppk->description, MAXLEN); /* the description */
+   
+   /* export key */
+   len = sizeof(buf) - (6 + 4 + MAXLEN*3);
+   obuf = buf+6+4+MAXLEN*3;
+   switch (ppk->system) {
+       case RSA_KEY:
+           if ((err = rsa_export(obuf, &len, key_type, &(ppk->key.rsa))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+       case DH_KEY:
+           if ((err = dh_export(obuf, &len, key_type, &(ppk->key.dh))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+       case ECC_KEY:
+           if ((err = ecc_export(obuf, &len, key_type, &(ppk->key.ecc))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+   }
+
+   /* get the entire length of the packet */
+   len += 6 + 4 + 3*MAXLEN;
+
+   if (*outlen < len) {
+      #ifdef CLEAN_STACK
+          zeromem(buf, sizeof(buf));
+      #endif
+      return CRYPT_BUFFER_OVERFLOW;
+   } else {
+      *outlen = len;
+      memcpy(out, buf, len);
+      #ifdef CLEAN_STACK
+          zeromem(buf, sizeof(buf));
+      #endif
+      return CRYPT_OK;
+   }
+}
+
+int kr_import(pk_key *pk, const unsigned char *in, unsigned long inlen)
+{
+   _pk_key key;
+   int sys, key_type, err;
+   unsigned long ID;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(in != NULL);
+
+   if (inlen < 10) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   if (memcmp(in, key_magic, 4) != 0) {
+      return CRYPT_INVALID_PACKET;
+   }
+   key_type = in[4];                                 /* get type */
+   sys      = in[5];                                 /* get system */
+   LOAD32L(ID,in+6);                                 /* the ID */
+
+   if (ID != kr_crc(in+10, in+10+MAXLEN, in+10+MAXLEN+MAXLEN)) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   zeromem(&key, sizeof(key));
+   
+   /* size of remaining packet */
+   inlen -= 10 + 3*MAXLEN;
+   
+   switch (sys) {
+        case RSA_KEY:
+            if ((err = rsa_import(in+10+3*MAXLEN, inlen, &(key.rsa))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+        case DH_KEY:
+            if ((err = dh_import(in+10+3*MAXLEN, inlen, &(key.dh))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+        case ECC_KEY:
+            if ((err = ecc_import(in+10+3*MAXLEN, inlen, &(key.ecc))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+   }
+   return kr_add(pk, key_type, sys, 
+                 in+10,                           /* the name */
+                 in+10+MAXLEN,                    /* email address */
+                 in+10+MAXLEN+MAXLEN,             /* description */
+                 &key);
+}
+
+
+int kr_load(pk_key **pk, FILE *in, symmetric_CTR *ctr)
+{
+   unsigned char buf[8192], blen[4];
+   unsigned long len;
+   int res, err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(in != NULL);
+
+   /* init keyring */
+   if ((err = kr_init(pk)) != CRYPT_OK) { 
+      return err; 
+   }
+
+   /* read in magic bytes */
+   if (_read(buf, 6, in, ctr) != 6)           { goto done2; }
+
+   if (memcmp(buf, file_magic, 4) != 0) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   len = (unsigned long)buf[4] | ((unsigned long)buf[5] << 8);
+   if (len > CRYPT) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* while there are lengths to read... */
+   while (_read(blen, 4, in, ctr) == 4) {
+      /* get length */
+      LOAD32L(len, blen);
+
+      if (len > (unsigned long)sizeof(buf)) {
+         return CRYPT_INVALID_PACKET;
+      }
+
+      if (_read(buf, len, in, ctr) != len)           { goto done2; }
+      if ((err = kr_import(*pk, buf, len)) != CRYPT_OK) { 
+         return err; 
+      }
+   }
+
+   res = CRYPT_OK;
+   goto done;
+done2:
+   res = CRYPT_ERROR;
+done:
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+   return res;
+}
+
+int kr_save(pk_key *pk, FILE *out, symmetric_CTR *ctr)
+{
+   unsigned char buf[8192], blen[4];
+   unsigned long len;
+   int res, err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(out != NULL);
+
+   /* write out magic bytes */
+   memcpy(buf, file_magic, 4);
+   buf[4] = (unsigned char)(CRYPT&255);
+   buf[5] = (unsigned char)((CRYPT>>8)&255);
+   if (_write(buf, 6, out, ctr) != 6)           { goto done2; }
+
+   while (pk->system != NON_KEY) {
+         len = sizeof(buf);
+         if ((err = kr_export(pk, pk->ID, pk->key_type, buf, &len)) != CRYPT_OK) { 
+            return err;
+         }
+          
+         STORE32L(len, blen);
+         if (_write(blen, 4, out, ctr) != 4)    { goto done2; }
+         if (_write(buf, len, out, ctr) != len) { goto done2; }
+
+         pk = pk->next;
+   }
+         
+   res = CRYPT_OK;
+   goto done;
+done2:
+   res = CRYPT_ERROR;
+done:
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+   return res;
+}
+
+int kr_make_key(pk_key *pk, prng_state *prng, int wprng, 
+                int sys, int keysize, const unsigned char *name,
+                const unsigned char *email, const unsigned char *description)
+{
+   _pk_key key;
+   int key_type, err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(name != NULL);
+   _ARGCHK(email != NULL);
+   _ARGCHK(description != NULL);
+
+   /* valid PRNG? */
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* make the key first */
+   zeromem(&key, sizeof(key));
+   switch (sys) {
+      case RSA_KEY: 
+          if ((err = rsa_make_key(prng, wprng, keysize, 65537, &(key.rsa))) != CRYPT_OK) {
+             return err;
+          }
+          key_type = key.rsa.type;
+          break;
+      case DH_KEY: 
+          if ((err = dh_make_key(prng, wprng, keysize, &(key.dh))) != CRYPT_OK) {
+             return err;
+          }
+          key_type = key.dh.type;
+          break;
+      case ECC_KEY: 
+          if ((err = ecc_make_key(prng, wprng, keysize, &(key.ecc))) != CRYPT_OK) {
+             return err;
+          }
+          key_type = key.ecc.type;
+          break;
+      default:
+          return CRYPT_PK_INVALID_SYSTEM;
+   }
+
+   /* now add the key */
+   if ((err = kr_add(pk, key_type, sys, name, email, description, &key)) != CRYPT_OK) {
+      return err;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(&key, sizeof(key));
+#endif
+   return CRYPT_OK;
+}
+
+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)
+{
+   unsigned char buf[8192];
+   unsigned long len;
+   pk_key *kr;
+   int err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(in != NULL);
+   _ARGCHK(out != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* find the key */
+   kr = kr_find(pk, ID);
+   if (kr == NULL) {
+      return CRYPT_PK_NOT_FOUND;
+   }
+
+   /* store the header */
+   memcpy(buf, enc_magic, 4);
+
+   /* now store the ID */
+   STORE32L(kr->ID,buf+4);
+
+   /* now encrypt it */
+   len = sizeof(buf)-12;
+   switch (kr->system) {
+        case RSA_KEY:
+            if ((err = rsa_encrypt_key(in, inlen, buf+12, &len, prng, wprng, &(kr->key.rsa))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+        case DH_KEY:
+            if ((err = dh_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.dh))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+        case ECC_KEY:
+            if ((err = ecc_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.ecc))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+    }
+    STORE32L(len,buf+8);
+    len += 12;
+
+    if (len > *outlen) {
+       #ifdef CLEAN_STACK
+           zeromem(buf, sizeof(buf));
+       #endif
+       return CRYPT_BUFFER_OVERFLOW;
+    } else {
+       memcpy(out, buf, len);
+       #ifdef CLEAN_STACK
+           zeromem(buf, sizeof(buf));
+       #endif
+       *outlen = len;
+       return CRYPT_OK;
+    }
+}
+
+int kr_decrypt_key(pk_key *pk, const unsigned char *in,
+                   unsigned char *out, unsigned long *outlen)
+{
+   unsigned char buf[8192];
+   unsigned long pklen, len, ID;
+   pk_key *kr;
+   int err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(in != NULL);
+   _ARGCHK(out != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* check magic header */
+   if (memcmp(in, enc_magic, 4)) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* now try to find key */
+   LOAD32L(ID,in+4);
+   kr = kr_find(pk, ID);
+   if (kr == NULL) {
+      return CRYPT_PK_NOT_FOUND;
+   }
+
+   /* is it public? */
+   if (kr->key_type == PK_PUBLIC) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   /* now try and decrypt it */
+   LOAD32L(pklen,in+8);
+   len = sizeof(buf);
+   switch (kr->system) {
+       case RSA_KEY:
+           if ((err = rsa_decrypt_key(in+12, pklen, buf, &len, &(kr->key.rsa))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+       case DH_KEY:
+           if ((err = dh_decrypt_key(in+12, pklen, buf, &len, &(kr->key.dh))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+       case ECC_KEY:
+           if ((err = ecc_decrypt_key(in+12, pklen, buf, &len, &(kr->key.ecc))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+   }
+
+    if (len > *outlen) {
+       #ifdef CLEAN_STACK
+           zeromem(buf, sizeof(buf));
+       #endif
+       return CRYPT_BUFFER_OVERFLOW;
+    } else {
+       memcpy(out, buf, len);
+       #ifdef CLEAN_STACK
+           zeromem(buf, sizeof(buf));
+       #endif
+       *outlen = len;
+       return CRYPT_OK;
+    }
+}
+
+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)
+{
+   unsigned char buf[8192];
+   unsigned long len;
+   pk_key *kr;
+   int err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(in != NULL);
+   _ARGCHK(out != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* find the key */
+   kr = kr_find(pk, ID);
+   if (kr == NULL) {
+      return CRYPT_PK_NOT_FOUND;
+   }
+
+   /* is it public? */
+   if (kr->key_type == PK_PUBLIC) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   /* store the header */
+   memcpy(buf, sign_magic, 4);
+
+   /* now store the ID */
+   STORE32L(kr->ID,buf+4);
+
+   /* now sign it */
+   len = sizeof(buf)-16;
+   switch (kr->system) {
+        case RSA_KEY:
+            if ((err = rsa_sign_hash(in, inlen, buf+16, &len, &(kr->key.rsa))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+        case DH_KEY:
+            if ((err = dh_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.dh))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+        case ECC_KEY:
+            if ((err = ecc_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.ecc))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+    }
+    STORE32L(inlen,buf+8);
+    STORE32L(len,buf+12);
+    len += 16;
+
+    if (len > *outlen) {
+       #ifdef CLEAN_STACK
+           zeromem(buf, sizeof(buf));
+       #endif
+       return CRYPT_BUFFER_OVERFLOW;
+    } else {
+       memcpy(out, buf, len);
+       #ifdef CLEAN_STACK
+           zeromem(buf, sizeof(buf));
+       #endif
+       *outlen = len;
+       return CRYPT_OK;
+    }
+}
+
+int kr_verify_hash(pk_key *pk, const unsigned char *in, const unsigned char *hash, 
+                   unsigned long hashlen, int *stat)
+{
+   unsigned long inlen, pklen, ID;
+   pk_key *kr;
+   int err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(in != NULL);
+   _ARGCHK(hash != NULL);
+   _ARGCHK(stat != NULL);
+
+   /* default to not match */
+   *stat = 0;
+
+   /* check magic header */
+   if (memcmp(in, sign_magic, 4)) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* now try to find key */
+   LOAD32L(ID,in+4);
+   kr = kr_find(pk, ID);
+   if (kr == NULL) {
+      return CRYPT_PK_NOT_FOUND;
+   }
+
+   /* now try and verify it */
+   LOAD32L(inlen,in+8);         /* this is the length of the original inlen */
+   LOAD32L(pklen,in+12);        /* size of the PK packet */
+   if (inlen != hashlen) {      /* size doesn't match means the signature is invalid */
+      return CRYPT_OK;
+   }
+
+   switch (kr->system) {
+       case RSA_KEY:
+           if ((err = rsa_verify_hash(in+16, pklen, hash, stat, &(kr->key.rsa))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+       case DH_KEY:
+           if ((err = dh_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.dh))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+       case ECC_KEY:
+           if ((err = ecc_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.ecc))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+   }
+   return CRYPT_OK;
+}
+
+int kr_fingerprint(pk_key *pk, unsigned long ID, int hash,
+                   unsigned char *out, unsigned long *outlen)
+{
+   unsigned char buf[8192];
+   unsigned long len;
+   int err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(out != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* valid hash? */
+   if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+      return err;
+   }
+
+   len = (unsigned long)sizeof(buf);
+   if ((err = kr_export(pk, ID, PK_PUBLIC, buf, &len)) != CRYPT_OK) {
+      return err;
+   }
+   
+   /* now hash it */
+   if ((err = hash_memory(hash, buf, len, out, outlen)) != CRYPT_OK) {
+      return err;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+   return CRYPT_OK;
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/makefile	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,253 @@
+# MAKEFILE for linux GCC
+#
+# Tom St Denis
+# Modified by Clay Culver
+#
+# NOTE: This should later be replaced by autoconf/automake scripts, but for
+# the time being this is actually pretty clean. The only ugly part is
+# handling CFLAGS so that the x86 specific optimizations don't break
+# a build. This is easy to remedy though, for those that have problems.
+
+# The version
+VERSION=0.95
+
+#ch1-01-1
+# Compiler and Linker Names
+#CC=gcc
+#LD=ld
+
+# Archiver [makes .a files]
+#AR=ar
+#ARFLAGS=r
+#ch1-01-1
+
+#ch1-01-3
+# Compilation flags. Note the += does not write over the user's CFLAGS!
+CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wshadow 
+# -Werror
+
+# optimize for SPEED
+#CFLAGS += -O3 -funroll-loops
+
+#add -fomit-frame-pointer.  v3.2 is buggy for certain platforms!
+#CFLAGS += -fomit-frame-pointer
+
+# optimize for SIZE
+CFLAGS += -Os
+
+# compile for DEBUGING
+#CFLAGS += -g3
+#ch1-01-3
+
+#These flags control how the library gets built.
+
+#Output filenames for various targets.
+LIBNAME=libtomcrypt.a
+TEST=test
+HASH=hashsum
+CRYPT=encrypt
+SMALL=small
+PROF=x86_prof
+TV=tv_gen
+
+#LIBPATH-The directory for libtomcrypt to be installed to.
+#INCPATH-The directory to install the header files for libtomcrypt.
+#DATAPATH-The directory to install the pdf docs.
+DESTDIR=
+LIBPATH=/usr/lib
+INCPATH=/usr/include
+DATAPATH=/usr/share/doc/libtomcrypt/pdf
+
+#List of objects to compile.
+
+#Leave MPI built-in or force developer to link against libtommath?
+MPIOBJECT=mpi.o
+
+OBJECTS=keyring.o gf.o strings.o base64.o \
+\
+crypt.o                    crypt_find_cipher.o      crypt_find_hash_any.o      \
+crypt_hash_is_valid.o      crypt_register_hash.o    crypt_unregister_prng.o    \
+crypt_argchk.o             crypt_find_cipher_any.o  crypt_find_hash_id.o       \
+crypt_prng_descriptor.o    crypt_register_prng.o    crypt_cipher_descriptor.o  \
+crypt_find_cipher_id.o     crypt_find_prng.o        crypt_prng_is_valid.o      \
+crypt_unregister_cipher.o  crypt_cipher_is_valid.o  crypt_find_hash.o          \
+crypt_hash_descriptor.o    crypt_register_cipher.o  crypt_unregister_hash.o    \
+\
+sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
+\
+rand_prime.o is_prime.o \
+\
+ecc.o  dh.o \
+\
+rsa.o rsa_exptmod.o  rsa_free.o  rsa_make_key.o \
+\
+dsa_export.o  dsa_free.o  dsa_import.o  dsa_make_key.o  dsa_sign_hash.o  dsa_verify_hash.o  dsa_verify_key.o \
+\
+xtea.o aes.o des.o safer_tab.o safer.o saferp.o rc2.o \
+rc6.o rc5.o cast5.o noekeon.o blowfish.o twofish.o skipjack.o \
+\
+md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \
+rmd128.o rmd160.o \
+\
+packet_store_header.o  packet_valid_header.o \
+\
+eax_addheader.o  eax_decrypt.o  eax_decrypt_verify_memory.o  eax_done.o  eax_encrypt.o  \
+eax_encrypt_authenticate_memory.o  eax_init.o  eax_test.o \
+\
+ocb_decrypt.o  ocb_decrypt_verify_memory.o  ocb_done_decrypt.o  ocb_done_encrypt.o  \
+ocb_encrypt.o  ocb_encrypt_authenticate_memory.o  ocb_init.o  ocb_ntz.o  \
+ocb_shift_xor.o  ocb_test.o s_ocb_done.o \
+\
+omac_done.o  omac_file.o  omac_init.o  omac_memory.o  omac_process.o  omac_test.o \
+\
+pmac_done.o  pmac_file.o  pmac_init.o  pmac_memory.o  pmac_ntz.o  pmac_process.o  \
+pmac_shift_xor.o  pmac_test.o \
+\
+cbc_start.o cbc_encrypt.o cbc_decrypt.o \
+cfb_start.o cfb_encrypt.o cfb_decrypt.o \
+ofb_start.o ofb_encrypt.o ofb_decrypt.o \
+ctr_start.o ctr_encrypt.o ctr_decrypt.o \
+ecb_start.o ecb_encrypt.o ecb_decrypt.o \
+\
+hash_file.o  hash_filehandle.o  hash_memory.o \
+\
+hmac_done.o  hmac_file.o  hmac_init.o  hmac_memory.o  hmac_process.o  hmac_test.o \
+\
+pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o  \
+pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \
+\
+pkcs_5_1.o pkcs_5_2.o \
+\
+burn_stack.o zeromem.o \
+$(MPIOBJECT)
+
+TESTOBJECTS=demos/test.o
+HASHOBJECTS=demos/hashsum.o
+CRYPTOBJECTS=demos/encrypt.o
+SMALLOBJECTS=demos/small.o
+PROFS=demos/x86_prof.o
+TVS=demos/tv_gen.o
+
+#Files left over from making the crypt.pdf.
+LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind
+
+#Compressed filenames
+COMPRESSED=crypt.tar.bz2 crypt.zip crypt.tar.gz
+
+#Header files used by libtomcrypt.
+HEADERS=tommath.h mycrypt_cfg.h mycrypt_gf.h mycrypt_kr.h \
+mycrypt_misc.h  mycrypt_prng.h mycrypt_cipher.h  mycrypt_hash.h \
+mycrypt_macros.h  mycrypt_pk.h mycrypt.h mycrypt_argchk.h \
+mycrypt_custom.h mycrypt_pkcs.h
+
+#The default rule for make builds the libtomcrypt library.
+default:library mycrypt.h mycrypt_cfg.h
+
+#These are the rules to make certain object files.
+rsa.o: rsa.c rsa_sys.c
+ecc.o: ecc.c ecc_sys.c
+dh.o: dh.c dh_sys.c
+aes.o: aes.c aes_tab.c
+twofish.o: twofish.c twofish_tab.c
+sha512.o: sha512.c sha384.c
+sha256.o: sha256.c sha224.c
+
+#This rule makes the libtomcrypt library.
+library: $(LIBNAME)
+
+$(LIBNAME): $(OBJECTS)
+	$(AR) $(ARFLAGS) $@ $(OBJECTS) 
+
+#This rule makes the test program included with libtomcrypt
+test: library $(TESTOBJECTS)
+	$(CC) $(TESTOBJECTS) $(LIBNAME) -o $(TEST) $(WARN)
+
+#This rule makes the hash program included with libtomcrypt
+hashsum: library $(HASHOBJECTS)
+	$(CC) $(HASHOBJECTS) $(LIBNAME) -o $(HASH) $(WARN)
+
+#makes the crypt program
+crypt: library $(CRYPTOBJECTS)
+	$(CC) $(CRYPTOBJECTS) $(LIBNAME) -o $(CRYPT) $(WARN)
+
+#makes the small program
+small: library $(SMALLOBJECTS)
+	$(CC) $(SMALLOBJECTS) $(LIBNAME) -o $(SMALL) $(WARN)
+	
+x86_prof: library $(PROFS)
+	$(CC) $(PROFS) $(LIBNAME) -o $(PROF)
+
+tv_gen: library $(TVS)
+	$(CC) $(TVS) $(LIBNAME) -o $(TV)
+
+
+#make a profiled library (takes a while!!!)
+#
+# This will build the library with profile generation
+# then run the test demo and rebuild the library.
+# 
+# So far I've seen improvements in the MP math
+#
+# This works with GCC v3.3.x [tested with 3.3.3]
+profiled: $(TESTOBJECTS)
+	make CFLAGS="$(CFLAGS) -fprofile-arcs"
+	$(CC) $(TESTOBJECTS) $(LIBNAME) -o $(TEST)
+	./test
+	rm -f *.a *.o test demos/test.o
+	make CFLAGS="$(CFLAGS) -fbranch-probabilities"
+
+
+#Profiling in GCC 3.4.x is a little diff.  
+#
+#Tested with GCC v3.4.0
+profiled34: $(TESTOBJECTS)
+	make CFLAGS="$(CFLAGS) -fprofile-generate"
+	$(CC) $(TESTOBJECTS) $(LIBNAME) -lgcov -o $(TEST)
+	./test
+	rm -f *.a *.o test demos/test.o
+	make CFLAGS="$(CFLAGS) -fprofile-use"
+
+
+#This rule installs the library and the header files. This must be run
+#as root in order to have a high enough permission to write to the correct
+#directories and to set the owner and group to root.
+install: library docs
+	install -d -g root -o root $(DESTDIR)$(LIBPATH)
+	install -d -g root -o root $(DESTDIR)$(INCPATH)
+	install -d -g root -o root $(DESTDIR)$(DATAPATH)
+	install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH)
+	install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
+	install -g root -o root crypt.pdf $(DESTDIR)$(DATAPATH)
+
+#This rule cleans the source tree of all compiled code, not including the pdf
+#documentation.
+clean:
+	rm -f $(OBJECTS) $(TESTOBJECTS) $(HASHOBJECTS) $(CRYPTOBJECTS) $(SMALLOBJECTS) $(LEFTOVERS) $(LIBNAME)
+	rm -f $(TEST) $(HASH) $(COMPRESSED) $(PROFS) $(PROF) $(TVS) $(TV)
+	rm -f *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt *.il *.da demos/*.il demos/*.da *.dyn *.dpi \
+         *.gcda *.gcno demos/*.gcno demos/*.gcda *~
+
+#This builds the crypt.pdf file. Note that the rm -f *.pdf has been removed
+#from the clean command! This is because most people would like to keep the
+#nice pre-compiled crypt.pdf that comes with libtomcrypt! We only need to
+#delete it if we are rebuilding it.
+docs: crypt.tex
+	rm -f crypt.pdf $(LEFTOVERS)
+	latex crypt > /dev/null
+	makeindex crypt > /dev/null
+	latex crypt > /dev/null
+	latex crypt > /dev/null
+	dvipdf crypt
+	rm -f $(LEFTOVERS)
+       
+#beta
+beta: clean
+	cd .. ; rm -rf crypt* libtomcrypt-$(VERSION)-beta ; mkdir libtomcrypt-$(VERSION)-beta ; \
+	cp -R ./libtomcrypt/* ./libtomcrypt-$(VERSION)-beta/ ; tar -c libtomcrypt-$(VERSION)-beta/* > crypt-$(VERSION)-beta.tar ; \
+	bzip2 -9vv crypt-$(VERSION)-beta.tar ; zip -9 -r crypt-$(VERSION)-beta.zip libtomcrypt-$(VERSION)-beta/*
+
+#zipup the project (take that!)
+zipup: clean docs
+	cd .. ; rm -rf crypt* libtomcrypt-$(VERSION) ; mkdir libtomcrypt-$(VERSION) ; \
+	cp -R ./libtomcrypt/* ./libtomcrypt-$(VERSION)/ ; tar -c libtomcrypt-$(VERSION)/* > crypt-$(VERSION).tar ; \
+	bzip2 -9vv crypt-$(VERSION).tar ; zip -9 -r crypt-$(VERSION).zip libtomcrypt-$(VERSION)/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/makefile.cygwin_dll	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,84 @@
+
+
+default: ltc_dll
+
+
+# Compilation flags. Note the += does not write over the user's CFLAGS!
+CFLAGS += -I./ -Wall -Wsign-compare -W -Wno-unused -Wshadow -mno-cygwin -DWIN32
+
+# optimize for SPEED
+#CFLAGS += -O3 -funroll-loops
+
+#add -fomit-frame-pointer.  v3.2 is buggy for certain platforms!
+#CFLAGS += -fomit-frame-pointer
+
+# optimize for SIZE
+CFLAGS += -Os
+
+#Leave MPI built-in or force developer to link against libtommath?
+MPIOBJECT=mpi.o
+
+OBJECTS=keyring.o gf.o strings.o base64.o \
+\
+crypt.o                    crypt_find_cipher.o      crypt_find_hash_any.o      \
+crypt_hash_is_valid.o      crypt_register_hash.o    crypt_unregister_prng.o    \
+crypt_argchk.o             crypt_find_cipher_any.o  crypt_find_hash_id.o       \
+crypt_prng_descriptor.o    crypt_register_prng.o    crypt_cipher_descriptor.o  \
+crypt_find_cipher_id.o     crypt_find_prng.o        crypt_prng_is_valid.o      \
+crypt_unregister_cipher.o  crypt_cipher_is_valid.o  crypt_find_hash.o          \
+crypt_hash_descriptor.o    crypt_register_cipher.o  crypt_unregister_hash.o    \
+\
+sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
+\
+rand_prime.o is_prime.o \
+\
+ecc.o  dh.o \
+\
+rsa.o rsa_exptmod.o  rsa_free.o  rsa_make_key.o \
+\
+dsa_export.o  dsa_free.o  dsa_import.o  dsa_make_key.o  dsa_sign_hash.o  dsa_verify_hash.o  dsa_verify_key.o \
+\
+xtea.o aes.o des.o safer_tab.o safer.o saferp.o rc2.o \
+rc6.o rc5.o cast5.o noekeon.o blowfish.o twofish.o skipjack.o \
+\
+md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \
+rmd128.o rmd160.o \
+\
+packet_store_header.o  packet_valid_header.o \
+\
+eax_addheader.o  eax_decrypt.o  eax_decrypt_verify_memory.o  eax_done.o  eax_encrypt.o  \
+eax_encrypt_authenticate_memory.o  eax_init.o  eax_test.o \
+\
+ocb_decrypt.o  ocb_decrypt_verify_memory.o  ocb_done_decrypt.o  ocb_done_encrypt.o  \
+ocb_encrypt.o  ocb_encrypt_authenticate_memory.o  ocb_init.o  ocb_ntz.o  \
+ocb_shift_xor.o  ocb_test.o s_ocb_done.o \
+\
+omac_done.o  omac_file.o  omac_init.o  omac_memory.o  omac_process.o  omac_test.o \
+\
+pmac_done.o  pmac_file.o  pmac_init.o  pmac_memory.o  pmac_ntz.o  pmac_process.o  \
+pmac_shift_xor.o  pmac_test.o \
+\
+cbc_start.o cbc_encrypt.o cbc_decrypt.o \
+cfb_start.o cfb_encrypt.o cfb_decrypt.o \
+ofb_start.o ofb_encrypt.o ofb_decrypt.o \
+ctr_start.o ctr_encrypt.o ctr_decrypt.o \
+ecb_start.o ecb_encrypt.o ecb_decrypt.o \
+\
+hash_file.o  hash_filehandle.o  hash_memory.o \
+\
+hmac_done.o  hmac_file.o  hmac_init.o  hmac_memory.o  hmac_process.o  hmac_test.o \
+\
+pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o  \
+pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \
+\
+pkcs_5_1.o pkcs_5_2.o \
+\
+burn_stack.o zeromem.o \
+$(MPIOBJECT)
+
+ltc_dll: $(OBJECTS) $(MPIOBJECT)
+	gcc -mno-cygwin -mdll -o libtomcrypt.dll -Wl,--out-implib=libtomcrypt.dll.a -Wl,--export-all-symbols *.o -ladvapi32
+	ranlib libtomcrypt.dll.a
+
+test: ltc_dll
+	gcc $(CFLAGS) demos/test.c libtomcrypt.dll.a -Wl,--enable-auto-import -o test -s
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/makefile.icc	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,213 @@
+# MAKEFILE for linux ICC (Intel C compiler)
+#
+# Tested with ICC v8....
+#
+# Be aware that ICC isn't quite as stable as GCC and several optimization switches
+# seem to break the code (that GCC and MSVC compile just fine).  In particular
+# "-ip" and "-x*" seem to break the code (ROL/ROR macro problems).  As the makefile 
+# is shipped the code will build and execute properly.
+#
+# Also note that ICC often makes code that is slower than GCC.  This is probably due to 
+# a mix of not being able to use "-ip" and just having fewer optimization algos than GCC.
+#
+# Tom St Denis
+
+#ch1-01-1
+# Compiler and Linker Names
+CC=icc
+#LD=ld
+
+# Archiver [makes .a files]
+#AR=ar
+#ARFLAGS=r
+
+# Compilation flags. Note the += does not write over the user's CFLAGS!
+CFLAGS += -c -I./ -DINTEL_CC
+
+# optimize for SPEED
+#
+# -mcpu= can be pentium, pentiumpro (covers PII through PIII) or pentium4
+# -ax?   specifies make code specifically for ? but compatible with IA-32
+# -x?    specifies compile solely for ? [not specifically IA-32 compatible]
+#
+# where ? is 
+#   K - PIII
+#   W - first P4 [Williamette]
+#   N - P4 Northwood
+#   P - P4 Prescott
+#   B - Blend of P4 and PM [mobile]
+#
+# Default to just generic max opts
+CFLAGS += -O3 -xN -ip
+
+# want to see stuff?
+#CFLAGS += -opt_report
+
+#These flags control how the library gets built.
+
+#Output filenames for various targets.
+LIBNAME=libtomcrypt.a
+TEST=test
+HASH=hashsum
+CRYPT=encrypt
+SMALL=small
+PROF=x86_prof
+TV=tv_gen
+
+#LIBPATH-The directory for libtomcrypt to be installed to.
+#INCPATH-The directory to install the header files for libtomcrypt.
+#DATAPATH-The directory to install the pdf docs.
+DESTDIR=
+LIBPATH=/usr/lib
+INCPATH=/usr/include
+DATAPATH=/usr/share/doc/libtomcrypt/pdf
+
+#List of objects to compile.
+
+#Leave MPI built-in or force developer to link against libtommath?
+MPIOBJECT=mpi.o
+
+OBJECTS=keyring.o gf.o strings.o base64.o \
+\
+crypt.o                    crypt_find_cipher.o      crypt_find_hash_any.o      \
+crypt_hash_is_valid.o      crypt_register_hash.o    crypt_unregister_prng.o    \
+crypt_argchk.o             crypt_find_cipher_any.o  crypt_find_hash_id.o       \
+crypt_prng_descriptor.o    crypt_register_prng.o    crypt_cipher_descriptor.o  \
+crypt_find_cipher_id.o     crypt_find_prng.o        crypt_prng_is_valid.o      \
+crypt_unregister_cipher.o  crypt_cipher_is_valid.o  crypt_find_hash.o          \
+crypt_hash_descriptor.o    crypt_register_cipher.o  crypt_unregister_hash.o    \
+\
+sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
+\
+rand_prime.o is_prime.o \
+\
+ecc.o  dh.o \
+\
+rsa.o rsa_exptmod.o  rsa_free.o  rsa_make_key.o \
+\
+dsa_export.o  dsa_free.o  dsa_import.o  dsa_make_key.o  dsa_sign_hash.o  dsa_verify_hash.o  dsa_verify_key.o \
+\
+xtea.o aes.o des.o safer_tab.o safer.o saferp.o rc2.o \
+rc6.o rc5.o cast5.o noekeon.o blowfish.o twofish.o skipjack.o \
+\
+md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \
+rmd128.o rmd160.o \
+\
+packet_store_header.o  packet_valid_header.o \
+\
+eax_addheader.o  eax_decrypt.o  eax_decrypt_verify_memory.o  eax_done.o  eax_encrypt.o  \
+eax_encrypt_authenticate_memory.o  eax_init.o  eax_test.o \
+\
+ocb_decrypt.o  ocb_decrypt_verify_memory.o  ocb_done_decrypt.o  ocb_done_encrypt.o  \
+ocb_encrypt.o  ocb_encrypt_authenticate_memory.o  ocb_init.o  ocb_ntz.o  \
+ocb_shift_xor.o  ocb_test.o s_ocb_done.o \
+\
+omac_done.o  omac_file.o  omac_init.o  omac_memory.o  omac_process.o  omac_test.o \
+\
+pmac_done.o  pmac_file.o  pmac_init.o  pmac_memory.o  pmac_ntz.o  pmac_process.o  \
+pmac_shift_xor.o  pmac_test.o \
+\
+cbc_start.o cbc_encrypt.o cbc_decrypt.o \
+cfb_start.o cfb_encrypt.o cfb_decrypt.o \
+ofb_start.o ofb_encrypt.o ofb_decrypt.o \
+ctr_start.o ctr_encrypt.o ctr_decrypt.o \
+ecb_start.o ecb_encrypt.o ecb_decrypt.o \
+\
+hash_file.o  hash_filehandle.o  hash_memory.o \
+\
+hmac_done.o  hmac_file.o  hmac_init.o  hmac_memory.o  hmac_process.o  hmac_test.o \
+\
+pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o  \
+pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \
+\
+pkcs_5_1.o pkcs_5_2.o \
+\
+burn_stack.o zeromem.o \
+$(MPIOBJECT)
+
+TESTOBJECTS=demos/test.o
+HASHOBJECTS=demos/hashsum.o
+CRYPTOBJECTS=demos/encrypt.o
+SMALLOBJECTS=demos/small.o
+PROFS=demos/x86_prof.o
+TVS=demos/tv_gen.o
+
+#Files left over from making the crypt.pdf.
+LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind
+
+#Compressed filenames
+COMPRESSED=crypt.tar.bz2 crypt.zip crypt.tar.gz
+
+#Header files used by libtomcrypt.
+HEADERS=tommath.h mycrypt_cfg.h mycrypt_gf.h mycrypt_kr.h \
+mycrypt_misc.h  mycrypt_prng.h mycrypt_cipher.h  mycrypt_hash.h \
+mycrypt_macros.h  mycrypt_pk.h mycrypt.h mycrypt_argchk.h mycrypt_custom.h
+
+#The default rule for make builds the libtomcrypt library.
+default:library mycrypt.h mycrypt_cfg.h
+
+#These are the rules to make certain object files.
+rsa.o: rsa.c rsa_sys.c
+ecc.o: ecc.c ecc_sys.c
+dh.o: dh.c dh_sys.c
+aes.o: aes.c aes_tab.c
+twofish.o: twofish.c twofish_tab.c
+sha512.o: sha512.c sha384.c
+sha256.o: sha256.c sha224.c
+
+#This rule makes the libtomcrypt library.
+library: $(LIBNAME)
+
+$(LIBNAME): $(OBJECTS)
+	$(AR) $(ARFLAGS) $@ $(OBJECTS) 
+
+#This rule makes the test program included with libtomcrypt
+test: library $(TESTOBJECTS)
+	$(CC) $(TESTOBJECTS) $(LIBNAME) -o $(TEST) $(WARN)
+
+#This rule makes the hash program included with libtomcrypt
+hashsum: library $(HASHOBJECTS)
+	$(CC) $(HASHOBJECTS) $(LIBNAME) -o $(HASH) $(WARN)
+
+#makes the crypt program
+crypt: library $(CRYPTOBJECTS)
+	$(CC) $(CRYPTOBJECTS) $(LIBNAME) -o $(CRYPT) $(WARN)
+
+#makes the small program
+small: library $(SMALLOBJECTS)
+	$(CC) $(SMALLOBJECTS) $(LIBNAME) -o $(SMALL) $(WARN)
+	
+x86_prof: library $(PROFS)
+	$(CC) $(PROFS) $(LIBNAME) -o $(PROF)
+
+tv_gen: library $(TVS)
+	$(CC) $(TVS) $(LIBNAME) -o $(TV)
+
+
+#make a profiled library (takes a while!!!)
+#
+# This will build the library with profile generation
+# then run the test demo and rebuild the library.
+# 
+# So far I've seen improvements in the MP math
+profiled:
+	make -f makefile.icc CFLAGS="$(CFLAGS) -prof_gen" test
+	./test
+	rm -f *.a *.o test demos/test.o
+	make -f makefile.icc CFLAGS="$(CFLAGS) -prof_use"
+   
+#This rule installs the library and the header files. This must be run
+#as root in order to have a high enough permission to write to the correct
+#directories and to set the owner and group to root.
+install: library
+	install -d -g root -o root $(DESTDIR)$(LIBPATH)
+	install -d -g root -o root $(DESTDIR)$(INCPATH)
+	install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH)
+	install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
+
+#This rule cleans the source tree of all compiled code, not including the pdf
+#documentation.
+clean:
+	rm -f $(OBJECTS) $(TESTOBJECTS) $(HASHOBJECTS) $(CRYPTOBJECTS) $(SMALLOBJECTS) $(LEFTOVERS) $(LIBNAME)
+	rm -f $(TEST) $(HASH) $(COMPRESSED) $(PROFS) $(PROF) $(TVS) $(TV)
+	rm -f *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt *.il *.da demos/*.il demos/*.da *.dyn
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/makefile.msvc	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,86 @@
+#MSVC Makefile [tested with MSVC 6.00 with SP5]
+#
+#Tom St Denis
+CFLAGS = /I. /Ox /DWIN32 /W3
+
+default: library
+
+# leave this blank and link against libtommath if you want better link resolution
+MPIOBJECT=mpi.obj
+
+#List of objects to compile.
+OBJECTS=keyring.obj gf.obj strings.obj base64.obj \
+\
+crypt.obj                    crypt_find_cipher.obj      crypt_find_hash_any.obj      \
+crypt_hash_is_valid.obj      crypt_register_hash.obj    crypt_unregister_prng.obj    \
+crypt_argchk.obj             crypt_find_cipher_any.obj  crypt_find_hash_id.obj       \
+crypt_prng_descriptor.obj    crypt_register_prng.obj    crypt_cipher_descriptor.obj  \
+crypt_find_cipher_id.obj     crypt_find_prng.obj        crypt_prng_is_valid.obj      \
+crypt_unregister_cipher.obj  crypt_cipher_is_valid.obj  crypt_find_hash.obj          \
+crypt_hash_descriptor.obj    crypt_register_cipher.obj  crypt_unregister_hash.obj    \
+\
+sprng.obj yarrow.obj rc4.obj rng_get_bytes.obj  rng_make_prng.obj \
+\
+rand_prime.obj is_prime.obj \
+\
+ecc.obj  dh.obj \
+\
+rsa.obj rsa_exptmod.obj  rsa_free.obj  rsa_make_key.obj \
+\
+dsa_export.obj  dsa_free.obj  dsa_import.obj  dsa_make_key.obj  dsa_sign_hash.obj  dsa_verify_hash.obj  dsa_verify_key.obj \
+\
+xtea.obj aes.obj des.obj safer_tab.obj safer.obj saferp.obj rc2.obj \
+rc6.obj rc5.obj cast5.obj noekeon.obj blowfish.obj twofish.obj skipjack.obj \
+\
+md2.obj md4.obj md5.obj sha1.obj sha256.obj sha512.obj tiger.obj whirl.obj \
+rmd128.obj rmd160.obj \
+\
+packet_store_header.obj  packet_valid_header.obj \
+\
+eax_addheader.obj  eax_decrypt.obj  eax_decrypt_verify_memory.obj  eax_done.obj  eax_encrypt.obj  \
+eax_encrypt_authenticate_memory.obj  eax_init.obj  eax_test.obj \
+\
+ocb_decrypt.obj  ocb_decrypt_verify_memory.obj  ocb_done_decrypt.obj  ocb_done_encrypt.obj  \
+ocb_encrypt.obj  ocb_encrypt_authenticate_memory.obj  ocb_init.obj  ocb_ntz.obj  \
+ocb_shift_xor.obj  ocb_test.obj s_ocb_done.obj \
+\
+omac_done.obj  omac_file.obj  omac_init.obj  omac_memory.obj  omac_process.obj  omac_test.obj \
+\
+pmac_done.obj  pmac_file.obj  pmac_init.obj  pmac_memory.obj  pmac_ntz.obj  pmac_process.obj  \
+pmac_shift_xor.obj  pmac_test.obj \
+\
+cbc_start.obj cbc_encrypt.obj cbc_decrypt.obj \
+cfb_start.obj cfb_encrypt.obj cfb_decrypt.obj \
+ofb_start.obj ofb_encrypt.obj ofb_decrypt.obj \
+ctr_start.obj ctr_encrypt.obj ctr_decrypt.obj \
+ecb_start.obj ecb_encrypt.obj ecb_decrypt.obj \
+\
+hash_file.obj  hash_filehandle.obj  hash_memory.obj \
+\
+hmac_done.obj  hmac_file.obj  hmac_init.obj  hmac_memory.obj  hmac_process.obj  hmac_test.obj \
+\
+pkcs_1_mgf1.obj pkcs_1_oaep_encode.obj pkcs_1_oaep_decode.obj  \
+pkcs_1_pss_encode.obj pkcs_1_pss_decode.obj pkcs_1_i2osp.obj pkcs_1_os2ip.obj \
+\
+pkcs_5_1.obj pkcs_5_2.obj \
+\
+burn_stack.obj zeromem.obj 	\
+$(MPIOBJECT)
+
+library: $(OBJECTS)
+	lib /out:tomcrypt.lib $(OBJECTS)
+	
+test.obj: demos/test.c
+	cl $(CFLAGS) /c demos/test.c
+
+test: library test.obj
+	cl test.obj tomcrypt.lib advapi32.lib	
+	
+x86_prof: demos/x86_prof.c library
+	cl $(CFLAGS) demos/x86_prof.c tomcrypt.lib advapi32.lib 
+
+tv_gen: demos/tv_gen.c library
+	cl $(CFLAGS) demos/tv_gen.c tomcrypt.lib advapi32.lib 
+
+hashsum: demos/hashsum.c library
+	cl $(CFLAGS) demos/hashsum.c tomcrypt.lib advapi32.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/md2.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,214 @@
+/* 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
+ */
+/* MD2 (RFC 1319) hash function implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef MD2
+
+const struct _hash_descriptor md2_desc =
+{
+    "md2",
+    7,
+    16,
+    16,
+    &md2_init,
+    &md2_process,
+    &md2_done,
+    &md2_test
+};
+
+static const unsigned char PI_SUBST[256] = {
+  41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
+  19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
+  76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
+  138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
+  245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
+  148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
+  39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
+  181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
+  150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
+  112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
+  96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
+  85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
+  234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
+  129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
+  8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
+  203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
+  166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
+  31, 26, 219, 153, 141, 51, 159, 17, 131, 20
+};
+
+/* adds 16 bytes to the checksum */
+static void md2_update_chksum(hash_state *md)
+{
+   int j;
+   unsigned char L;
+   L = md->md2.chksum[15];
+   for (j = 0; j < 16; j++) {
+
+/* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the reference source code [and test vectors] say 
+   otherwise.
+*/
+       L = (md->md2.chksum[j] ^= PI_SUBST[(int)(md->md2.buf[j] ^ L)] & 255);
+   }
+}
+
+static void md2_compress(hash_state *md)
+{
+   int j, k;
+   unsigned char t;
+   
+   /* copy block */
+   for (j = 0; j < 16; j++) {
+       md->md2.X[16+j] = md->md2.buf[j];
+       md->md2.X[32+j] = md->md2.X[j] ^ md->md2.X[16+j];
+   }
+
+   t = (unsigned char)0;
+
+   /* do 18 rounds */
+   for (j = 0; j < 18; j++) {
+       for (k = 0; k < 48; k++) {
+           t = (md->md2.X[k] ^= PI_SUBST[(int)(t & 255)]);
+       }
+       t = (t + (unsigned char)j) & 255;
+   }
+}
+
+void md2_init(hash_state *md)
+{
+   _ARGCHK(md != NULL);
+
+   /* MD2 uses a zero'ed state... */
+   zeromem(md->md2.X, sizeof(md->md2.X));
+   zeromem(md->md2.chksum, sizeof(md->md2.chksum));
+   zeromem(md->md2.buf, sizeof(md->md2.buf));
+   md->md2.curlen = 0;
+}
+
+int md2_process(hash_state *md, const unsigned char *buf, unsigned long len)
+{
+    unsigned long n;
+    _ARGCHK(md != NULL);
+    _ARGCHK(buf != NULL);
+    if (md-> md2 .curlen > sizeof(md-> md2 .buf)) {                            
+       return CRYPT_INVALID_ARG;                                                           
+    }                                                                                       
+    while (len > 0) {
+        n = MIN(len, (16 - md->md2.curlen));
+        memcpy(md->md2.buf + md->md2.curlen, buf, (size_t)n);
+        md->md2.curlen += n;
+        buf            += n;
+        len            -= n;
+
+        /* is 16 bytes full? */
+        if (md->md2.curlen == 16) {
+            md2_compress(md);
+            md2_update_chksum(md);
+            md->md2.curlen = 0;
+        }
+    }
+    return CRYPT_OK;
+}
+
+int md2_done(hash_state * md, unsigned char *hash)
+{
+    unsigned long i, k;
+
+    _ARGCHK(md != NULL);
+    _ARGCHK(hash != NULL);
+
+    if (md->md2.curlen >= sizeof(md->md2.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+
+    /* pad the message */
+    k = 16 - md->md2.curlen;
+    for (i = md->md2.curlen; i < 16; i++) {
+        md->md2.buf[i] = (unsigned char)k;
+    }
+
+    /* hash and update */
+    md2_compress(md);
+    md2_update_chksum(md);
+
+    /* hash checksum */
+    memcpy(md->md2.buf, md->md2.chksum, 16);
+    md2_compress(md);
+
+    /* output is lower 16 bytes of X */
+    memcpy(hash, md->md2.X, 16);
+
+#ifdef CLEAN_STACK
+    zeromem(md, sizeof(hash_state));
+#endif
+    return CRYPT_OK;
+}
+
+int md2_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+   static const struct {
+        char *msg;
+        unsigned char md[16];
+   } tests[] = {
+      { "",
+        {0x83,0x50,0xe5,0xa3,0xe2,0x4c,0x15,0x3d,
+         0xf2,0x27,0x5c,0x9f,0x80,0x69,0x27,0x73
+        }
+      },
+      { "a",
+        {0x32,0xec,0x01,0xec,0x4a,0x6d,0xac,0x72,
+         0xc0,0xab,0x96,0xfb,0x34,0xc0,0xb5,0xd1
+        }
+      },
+      { "message digest",
+        {0xab,0x4f,0x49,0x6b,0xfb,0x2a,0x53,0x0b,
+         0x21,0x9f,0xf3,0x30,0x31,0xfe,0x06,0xb0
+        }
+      },
+      { "abcdefghijklmnopqrstuvwxyz",
+        {0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab,
+         0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b
+        }
+      },
+      { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+        {0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39,
+         0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd
+        }
+      },
+      { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+        {0xd5,0x97,0x6f,0x79,0xd8,0x3d,0x3a,0x0d,
+         0xc9,0x80,0x6c,0x3c,0x66,0xf3,0xef,0xd8
+        }
+      }
+   };
+   int i;
+   hash_state md;
+   unsigned char buf[16];
+
+   for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+       md2_init(&md);
+       md2_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
+       md2_done(&md, buf);
+       if (memcmp(buf, tests[i].md, 16) != 0) {
+          return CRYPT_FAIL_TESTVECTOR;
+       }
+   }
+   return CRYPT_OK;        
+  #endif
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/md4.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,266 @@
+/* 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
+ */
+/* Submitted by Dobes Vandermeer  ([email protected]) */
+#include "mycrypt.h"
+
+#ifdef MD4
+
+const struct _hash_descriptor md4_desc =
+{
+    "md4",
+    6,
+    16,
+    64,
+    &md4_init,
+    &md4_process,
+    &md4_done,
+    &md4_test
+};
+
+#define S11 3
+#define S12 7
+#define S13 11
+#define S14 19
+#define S21 3
+#define S22 5
+#define S23 9
+#define S24 13
+#define S31 3
+#define S32 9
+#define S33 11
+#define S34 15
+
+/* F, G and H are basic MD4 functions. */
+#define F(x, y, z) (z ^ (x & (y ^ z)))
+#define G(x, y, z) ((x & y) | (z & (x | y)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits. */
+#define ROTATE_LEFT(x, n) ROL(x, n)
+
+/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ 
+/* Rotation is separate from addition to prevent recomputation */ 
+
+#define FF(a, b, c, d, x, s) { \
+    (a) += F ((b), (c), (d)) + (x); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+  }
+#define GG(a, b, c, d, x, s) { \
+    (a) += G ((b), (c), (d)) + (x) + 0x5a827999UL; \
+    (a) = ROTATE_LEFT ((a), (s)); \
+  }
+#define HH(a, b, c, d, x, s) { \
+    (a) += H ((b), (c), (d)) + (x) + 0x6ed9eba1UL; \
+    (a) = ROTATE_LEFT ((a), (s)); \
+  }
+
+#ifdef CLEAN_STACK
+static void _md4_compress(hash_state *md, unsigned char *buf)
+#else
+static void md4_compress(hash_state *md, unsigned char *buf)
+#endif
+{
+    ulong32 x[16], a, b, c, d;
+    int i;
+
+    /* copy state */
+    a = md->md4.state[0];
+    b = md->md4.state[1];
+    c = md->md4.state[2];
+    d = md->md4.state[3];
+
+    /* copy the state into 512-bits into W[0..15] */
+    for (i = 0; i < 16; i++) {
+        LOAD32L(x[i], buf + (4*i));
+    }
+ 
+    /* Round 1 */ 
+    FF (a, b, c, d, x[ 0], S11); /* 1 */ 
+    FF (d, a, b, c, x[ 1], S12); /* 2 */ 
+    FF (c, d, a, b, x[ 2], S13); /* 3 */ 
+    FF (b, c, d, a, x[ 3], S14); /* 4 */ 
+    FF (a, b, c, d, x[ 4], S11); /* 5 */ 
+    FF (d, a, b, c, x[ 5], S12); /* 6 */ 
+    FF (c, d, a, b, x[ 6], S13); /* 7 */ 
+    FF (b, c, d, a, x[ 7], S14); /* 8 */ 
+    FF (a, b, c, d, x[ 8], S11); /* 9 */ 
+    FF (d, a, b, c, x[ 9], S12); /* 10 */
+    FF (c, d, a, b, x[10], S13); /* 11 */ 
+    FF (b, c, d, a, x[11], S14); /* 12 */
+    FF (a, b, c, d, x[12], S11); /* 13 */
+    FF (d, a, b, c, x[13], S12); /* 14 */ 
+    FF (c, d, a, b, x[14], S13); /* 15 */ 
+    FF (b, c, d, a, x[15], S14); /* 16 */ 
+    
+    /* Round 2 */ 
+    GG (a, b, c, d, x[ 0], S21); /* 17 */ 
+    GG (d, a, b, c, x[ 4], S22); /* 18 */ 
+    GG (c, d, a, b, x[ 8], S23); /* 19 */ 
+    GG (b, c, d, a, x[12], S24); /* 20 */ 
+    GG (a, b, c, d, x[ 1], S21); /* 21 */ 
+    GG (d, a, b, c, x[ 5], S22); /* 22 */ 
+    GG (c, d, a, b, x[ 9], S23); /* 23 */ 
+    GG (b, c, d, a, x[13], S24); /* 24 */ 
+    GG (a, b, c, d, x[ 2], S21); /* 25 */ 
+    GG (d, a, b, c, x[ 6], S22); /* 26 */ 
+    GG (c, d, a, b, x[10], S23); /* 27 */ 
+    GG (b, c, d, a, x[14], S24); /* 28 */ 
+    GG (a, b, c, d, x[ 3], S21); /* 29 */ 
+    GG (d, a, b, c, x[ 7], S22); /* 30 */ 
+    GG (c, d, a, b, x[11], S23); /* 31 */ 
+    GG (b, c, d, a, x[15], S24); /* 32 */ 
+    
+    /* Round 3 */
+    HH (a, b, c, d, x[ 0], S31); /* 33 */ 
+    HH (d, a, b, c, x[ 8], S32); /* 34 */ 
+    HH (c, d, a, b, x[ 4], S33); /* 35 */ 
+    HH (b, c, d, a, x[12], S34); /* 36 */ 
+    HH (a, b, c, d, x[ 2], S31); /* 37 */ 
+    HH (d, a, b, c, x[10], S32); /* 38 */ 
+    HH (c, d, a, b, x[ 6], S33); /* 39 */ 
+    HH (b, c, d, a, x[14], S34); /* 40 */ 
+    HH (a, b, c, d, x[ 1], S31); /* 41 */ 
+    HH (d, a, b, c, x[ 9], S32); /* 42 */ 
+    HH (c, d, a, b, x[ 5], S33); /* 43 */ 
+    HH (b, c, d, a, x[13], S34); /* 44 */ 
+    HH (a, b, c, d, x[ 3], S31); /* 45 */ 
+    HH (d, a, b, c, x[11], S32); /* 46 */ 
+    HH (c, d, a, b, x[ 7], S33); /* 47 */ 
+    HH (b, c, d, a, x[15], S34); /* 48 */ 
+    
+
+    /* Update our state */
+    md->md4.state[0] = md->md4.state[0] + a;
+    md->md4.state[1] = md->md4.state[1] + b;
+    md->md4.state[2] = md->md4.state[2] + c;
+    md->md4.state[3] = md->md4.state[3] + d;
+}
+
+#ifdef CLEAN_STACK
+static void md4_compress(hash_state *md, unsigned char *buf)
+{
+   _md4_compress(md, buf);
+   burn_stack(sizeof(ulong32) * 20 + sizeof(int));
+}
+#endif
+
+void md4_init(hash_state * md)
+{
+   _ARGCHK(md != NULL);
+   md->md4.state[0] = 0x67452301UL;
+   md->md4.state[1] = 0xefcdab89UL;
+   md->md4.state[2] = 0x98badcfeUL;
+   md->md4.state[3] = 0x10325476UL;
+   md->md4.length  = 0;
+   md->md4.curlen  = 0;
+}
+
+HASH_PROCESS(md4_process, md4_compress, md4, 64)
+
+int md4_done(hash_state * md, unsigned char *hash)
+{
+    int i;
+
+    _ARGCHK(md != NULL);
+    _ARGCHK(hash != NULL);
+
+    if (md->md4.curlen >= sizeof(md->md4.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+    /* increase the length of the message */
+    md->md4.length += md->md4.curlen * 8;
+
+    /* append the '1' bit */
+    md->md4.buf[md->md4.curlen++] = (unsigned char)0x80;
+
+    /* if the length is currently above 56 bytes we append zeros
+     * then compress.  Then we can fall back to padding zeros and length
+     * encoding like normal.
+     */
+    if (md->md4.curlen > 56) {
+        while (md->md4.curlen < 64) {
+            md->md4.buf[md->md4.curlen++] = (unsigned char)0;
+        }
+        md4_compress(md, md->md4.buf);
+        md->md4.curlen = 0;
+    }
+
+    /* pad upto 56 bytes of zeroes */
+    while (md->md4.curlen < 56) {
+        md->md4.buf[md->md4.curlen++] = (unsigned char)0;
+    }
+
+    /* store length */
+    STORE64L(md->md4.length, md->md4.buf+56);
+    md4_compress(md, md->md4.buf);
+
+    /* copy output */
+    for (i = 0; i < 4; i++) {
+        STORE32L(md->md4.state[i], hash+(4*i));
+    }
+#ifdef CLEAN_STACK
+    zeromem(md, sizeof(hash_state));
+#endif 
+    return CRYPT_OK;
+}
+
+int md4_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+    static const struct md4_test_case {
+        char *input;
+        unsigned char digest[16];
+    } cases[] = {
+        { "", 
+          {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
+           0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0} },
+        { "a",
+          {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
+           0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24} },
+        { "abc",
+          {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, 
+           0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d} },
+        { "message digest", 
+          {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, 
+           0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b} },
+        { "abcdefghijklmnopqrstuvwxyz", 
+          {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, 
+           0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9} },
+        { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 
+          {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, 
+           0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4} },
+        { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 
+          {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, 
+           0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36} },
+    };
+    int i;
+    hash_state md;
+    unsigned char digest[16];
+
+    for(i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) {
+        md4_init(&md);
+        md4_process(&md, (unsigned char *)cases[i].input, (unsigned long)strlen(cases[i].input));
+        md4_done(&md, digest);
+        if (memcmp(digest, cases[i].digest, 16) != 0) {
+           return CRYPT_FAIL_TESTVECTOR;
+        }
+
+    }
+    return CRYPT_OK;
+  #endif
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/md5.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,258 @@
+/* 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
+ */
+
+/* MD5 hash function by Tom St Denis */
+
+#include "mycrypt.h"
+
+#ifdef MD5
+
+const struct _hash_descriptor md5_desc =
+{
+    "md5",
+    3,
+    16,
+    64,
+    &md5_init,
+    &md5_process,
+    &md5_done,
+    &md5_test
+};
+
+#define F(x,y,z)  (z ^ (x & (y ^ z)))
+#define G(x,y,z)  (y ^ (z & (y ^ x)))
+#define H(x,y,z)  (x^y^z)
+#define I(x,y,z)  (y^(x|(~z)))
+
+#define FF(a,b,c,d,M,s,t) \
+    a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b;
+
+#define GG(a,b,c,d,M,s,t) \
+    a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b;
+
+#define HH(a,b,c,d,M,s,t) \
+    a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b;
+
+#define II(a,b,c,d,M,s,t) \
+    a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b;
+
+#ifdef CLEAN_STACK
+static void _md5_compress(hash_state *md, unsigned char *buf)
+#else
+static void md5_compress(hash_state *md, unsigned char *buf)
+#endif
+{
+    ulong32 i, W[16], a, b, c, d;
+
+    /* copy the state into 512-bits into W[0..15] */
+    for (i = 0; i < 16; i++) {
+        LOAD32L(W[i], buf + (4*i));
+    }
+ 
+    /* copy state */
+    a = md->md5.state[0];
+    b = md->md5.state[1];
+    c = md->md5.state[2];
+    d = md->md5.state[3];
+
+    FF(a,b,c,d,W[0],7,0xd76aa478UL)
+    FF(d,a,b,c,W[1],12,0xe8c7b756UL)
+    FF(c,d,a,b,W[2],17,0x242070dbUL)
+    FF(b,c,d,a,W[3],22,0xc1bdceeeUL)
+    FF(a,b,c,d,W[4],7,0xf57c0fafUL)
+    FF(d,a,b,c,W[5],12,0x4787c62aUL)
+    FF(c,d,a,b,W[6],17,0xa8304613UL)
+    FF(b,c,d,a,W[7],22,0xfd469501UL)
+    FF(a,b,c,d,W[8],7,0x698098d8UL)
+    FF(d,a,b,c,W[9],12,0x8b44f7afUL)
+    FF(c,d,a,b,W[10],17,0xffff5bb1UL)
+    FF(b,c,d,a,W[11],22,0x895cd7beUL)
+    FF(a,b,c,d,W[12],7,0x6b901122UL)
+    FF(d,a,b,c,W[13],12,0xfd987193UL)
+    FF(c,d,a,b,W[14],17,0xa679438eUL)
+    FF(b,c,d,a,W[15],22,0x49b40821UL)
+    GG(a,b,c,d,W[1],5,0xf61e2562UL)
+    GG(d,a,b,c,W[6],9,0xc040b340UL)
+    GG(c,d,a,b,W[11],14,0x265e5a51UL)
+    GG(b,c,d,a,W[0],20,0xe9b6c7aaUL)
+    GG(a,b,c,d,W[5],5,0xd62f105dUL)
+    GG(d,a,b,c,W[10],9,0x02441453UL)
+    GG(c,d,a,b,W[15],14,0xd8a1e681UL)
+    GG(b,c,d,a,W[4],20,0xe7d3fbc8UL)
+    GG(a,b,c,d,W[9],5,0x21e1cde6UL)
+    GG(d,a,b,c,W[14],9,0xc33707d6UL)
+    GG(c,d,a,b,W[3],14,0xf4d50d87UL)
+    GG(b,c,d,a,W[8],20,0x455a14edUL)
+    GG(a,b,c,d,W[13],5,0xa9e3e905UL)
+    GG(d,a,b,c,W[2],9,0xfcefa3f8UL)
+    GG(c,d,a,b,W[7],14,0x676f02d9UL)
+    GG(b,c,d,a,W[12],20,0x8d2a4c8aUL)
+    HH(a,b,c,d,W[5],4,0xfffa3942UL)
+    HH(d,a,b,c,W[8],11,0x8771f681UL)
+    HH(c,d,a,b,W[11],16,0x6d9d6122UL)
+    HH(b,c,d,a,W[14],23,0xfde5380cUL)
+    HH(a,b,c,d,W[1],4,0xa4beea44UL)
+    HH(d,a,b,c,W[4],11,0x4bdecfa9UL)
+    HH(c,d,a,b,W[7],16,0xf6bb4b60UL)
+    HH(b,c,d,a,W[10],23,0xbebfbc70UL)
+    HH(a,b,c,d,W[13],4,0x289b7ec6UL)
+    HH(d,a,b,c,W[0],11,0xeaa127faUL)
+    HH(c,d,a,b,W[3],16,0xd4ef3085UL)
+    HH(b,c,d,a,W[6],23,0x04881d05UL)
+    HH(a,b,c,d,W[9],4,0xd9d4d039UL)
+    HH(d,a,b,c,W[12],11,0xe6db99e5UL)
+    HH(c,d,a,b,W[15],16,0x1fa27cf8UL)
+    HH(b,c,d,a,W[2],23,0xc4ac5665UL)
+    II(a,b,c,d,W[0],6,0xf4292244UL)
+    II(d,a,b,c,W[7],10,0x432aff97UL)
+    II(c,d,a,b,W[14],15,0xab9423a7UL)
+    II(b,c,d,a,W[5],21,0xfc93a039UL)
+    II(a,b,c,d,W[12],6,0x655b59c3UL)
+    II(d,a,b,c,W[3],10,0x8f0ccc92UL)
+    II(c,d,a,b,W[10],15,0xffeff47dUL)
+    II(b,c,d,a,W[1],21,0x85845dd1UL)
+    II(a,b,c,d,W[8],6,0x6fa87e4fUL)
+    II(d,a,b,c,W[15],10,0xfe2ce6e0UL)
+    II(c,d,a,b,W[6],15,0xa3014314UL)
+    II(b,c,d,a,W[13],21,0x4e0811a1UL)
+    II(a,b,c,d,W[4],6,0xf7537e82UL)
+    II(d,a,b,c,W[11],10,0xbd3af235UL)
+    II(c,d,a,b,W[2],15,0x2ad7d2bbUL)
+    II(b,c,d,a,W[9],21,0xeb86d391UL)
+
+    md->md5.state[0] = md->md5.state[0] + a;
+    md->md5.state[1] = md->md5.state[1] + b;
+    md->md5.state[2] = md->md5.state[2] + c;
+    md->md5.state[3] = md->md5.state[3] + d;
+}
+
+#ifdef CLEAN_STACK
+static void md5_compress(hash_state *md, unsigned char *buf)
+{
+   _md5_compress(md, buf);
+   burn_stack(sizeof(ulong32) * 21);
+}
+#endif
+
+void md5_init(hash_state * md)
+{
+   _ARGCHK(md != NULL);
+   md->md5.state[0] = 0x67452301UL;
+   md->md5.state[1] = 0xefcdab89UL;
+   md->md5.state[2] = 0x98badcfeUL;
+   md->md5.state[3] = 0x10325476UL;
+   md->md5.curlen = 0;
+   md->md5.length = 0;
+}
+
+HASH_PROCESS(md5_process, md5_compress, md5, 64)
+
+int md5_done(hash_state * md, unsigned char *hash)
+{
+    int i;
+
+    _ARGCHK(md != NULL);
+    _ARGCHK(hash != NULL);
+
+    if (md->md5.curlen >= sizeof(md->md5.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+
+    /* increase the length of the message */
+    md->md5.length += md->md5.curlen * 8;
+
+    /* append the '1' bit */
+    md->md5.buf[md->md5.curlen++] = (unsigned char)0x80;
+
+    /* if the length is currently above 56 bytes we append zeros
+     * then compress.  Then we can fall back to padding zeros and length
+     * encoding like normal.
+     */
+    if (md->md5.curlen > 56) {
+        while (md->md5.curlen < 64) {
+            md->md5.buf[md->md5.curlen++] = (unsigned char)0;
+        }
+        md5_compress(md, md->md5.buf);
+        md->md5.curlen = 0;
+    }
+
+    /* pad upto 56 bytes of zeroes */
+    while (md->md5.curlen < 56) {
+        md->md5.buf[md->md5.curlen++] = (unsigned char)0;
+    }
+
+    /* store length */
+    STORE64L(md->md5.length, md->md5.buf+56);
+    md5_compress(md, md->md5.buf);
+
+    /* copy output */
+    for (i = 0; i < 4; i++) {
+        STORE32L(md->md5.state[i], hash+(4*i));
+    }
+#ifdef CLEAN_STACK
+    zeromem(md, sizeof(hash_state));
+#endif
+    return CRYPT_OK;
+}
+
+int  md5_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+  static const struct {
+      char *msg;
+      unsigned char hash[16];
+  } tests[] = {
+    { "",
+      { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 
+        0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
+    { "a",
+      {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 
+       0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },
+    { "abc",
+      { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 
+        0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },
+    { "message digest", 
+      { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 
+        0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, 
+    { "abcdefghijklmnopqrstuvwxyz",
+      { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 
+        0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },
+    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+      { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 
+        0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },
+    { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+      { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 
+        0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, 
+    { NULL, { 0 } }
+  };
+
+  int i;
+  unsigned char tmp[16];
+  hash_state md;
+
+  for (i = 0; tests[i].msg != NULL; i++) {
+      md5_init(&md);
+      md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
+      md5_done(&md, tmp);
+      if (memcmp(tmp, tests[i].hash, 16) != 0) {
+         return CRYPT_FAIL_TESTVECTOR;
+      }
+  }
+  return CRYPT_OK;
+ #endif
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpi.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,8414 @@
+/* Start: bn_error.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+static const struct {
+     int code;
+     char *msg;
+} msgs[] = {
+     { MP_OKAY, "Successful" },
+     { MP_MEM,  "Out of heap" },
+     { MP_VAL,  "Value out of range" }
+};
+
+/* return a char * string for a given code */
+char *mp_error_to_string(int code)
+{
+   int x;
+
+   /* scan the lookup table for the given message */
+   for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) {
+       if (msgs[x].code == code) {
+          return msgs[x].msg;
+       }
+   }
+
+   /* generic reply for invalid code */
+   return "Invalid error code";
+}
+
+
+/* End: bn_error.c */
+
+/* Start: bn_fast_mp_invmod.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* computes the modular inverse via binary extended euclidean algorithm, 
+ * that is c = 1/a mod b 
+ *
+ * Based on mp_invmod except this is optimized for the case where b is 
+ * odd as per HAC Note 14.64 on pp. 610
+ */
+int
+fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x, y, u, v, B, D;
+  int     res, neg;
+
+  /* 2. [modified] b must be odd   */
+  if (mp_iseven (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* init all our temps */
+  if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
+     return res;
+  }
+
+  /* x == modulus, y == value to invert */
+  if ((res = mp_copy (b, &x)) != MP_OKAY) {
+    goto __ERR;
+  }
+
+  /* we need y = |a| */
+  if ((res = mp_abs (a, &y)) != MP_OKAY) {
+    goto __ERR;
+  }
+
+  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+    goto __ERR;
+  }
+  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+    goto __ERR;
+  }
+  mp_set (&D, 1);
+
+top:
+  /* 4.  while u is even do */
+  while (mp_iseven (&u) == 1) {
+    /* 4.1 u = u/2 */
+    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+      goto __ERR;
+    }
+    /* 4.2 if B is odd then */
+    if (mp_isodd (&B) == 1) {
+      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+        goto __ERR;
+      }
+    }
+    /* B = B/2 */
+    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+      goto __ERR;
+    }
+  }
+
+  /* 5.  while v is even do */
+  while (mp_iseven (&v) == 1) {
+    /* 5.1 v = v/2 */
+    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+      goto __ERR;
+    }
+    /* 5.2 if D is odd then */
+    if (mp_isodd (&D) == 1) {
+      /* D = (D-x)/2 */
+      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+        goto __ERR;
+      }
+    }
+    /* D = D/2 */
+    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+      goto __ERR;
+    }
+  }
+
+  /* 6.  if u >= v then */
+  if (mp_cmp (&u, &v) != MP_LT) {
+    /* u = u - v, B = B - D */
+    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+      goto __ERR;
+    }
+
+    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+      goto __ERR;
+    }
+  } else {
+    /* v - v - u, D = D - B */
+    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+      goto __ERR;
+    }
+
+    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+      goto __ERR;
+    }
+  }
+
+  /* if not zero goto step 4 */
+  if (mp_iszero (&u) == 0) {
+    goto top;
+  }
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (mp_cmp_d (&v, 1) != MP_EQ) {
+    res = MP_VAL;
+    goto __ERR;
+  }
+
+  /* b is now the inverse */
+  neg = a->sign;
+  while (D.sign == MP_NEG) {
+    if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
+      goto __ERR;
+    }
+  }
+  mp_exch (&D, c);
+  c->sign = neg;
+  res = MP_OKAY;
+
+__ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
+  return res;
+}
+
+/* End: bn_fast_mp_invmod.c */
+
+/* Start: bn_fast_mp_montgomery_reduce.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of mp_montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+int
+fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+  int     ix, res, olduse;
+  mp_word W[MP_WARRAY];
+
+  /* get old used count */
+  olduse = x->used;
+
+  /* grow a as required */
+  if (x->alloc < n->used + 1) {
+    if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* first we have to get the digits of the input into
+   * an array of double precision words W[...]
+   */
+  {
+    register mp_word *_W;
+    register mp_digit *tmpx;
+
+    /* alias for the W[] array */
+    _W   = W;
+
+    /* alias for the digits of  x*/
+    tmpx = x->dp;
+
+    /* copy the digits of a into W[0..a->used-1] */
+    for (ix = 0; ix < x->used; ix++) {
+      *_W++ = *tmpx++;
+    }
+
+    /* zero the high words of W[a->used..m->used*2] */
+    for (; ix < n->used * 2 + 1; ix++) {
+      *_W++ = 0;
+    }
+  }
+
+  /* now we proceed to zero successive digits
+   * from the least significant upwards
+   */
+  for (ix = 0; ix < n->used; ix++) {
+    /* mu = ai * m' mod b
+     *
+     * We avoid a double precision multiplication (which isn't required)
+     * by casting the value down to a mp_digit.  Note this requires
+     * that W[ix-1] have  the carry cleared (see after the inner loop)
+     */
+    register mp_digit mu;
+    mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
+
+    /* a = a + mu * m * b**i
+     *
+     * This is computed in place and on the fly.  The multiplication
+     * by b**i is handled by offseting which columns the results
+     * are added to.
+     *
+     * Note the comba method normally doesn't handle carries in the
+     * inner loop In this case we fix the carry from the previous
+     * column since the Montgomery reduction requires digits of the
+     * result (so far) [see above] to work.  This is
+     * handled by fixing up one carry after the inner loop.  The
+     * carry fixups are done in order so after these loops the
+     * first m->used words of W[] have the carries fixed
+     */
+    {
+      register int iy;
+      register mp_digit *tmpn;
+      register mp_word *_W;
+
+      /* alias for the digits of the modulus */
+      tmpn = n->dp;
+
+      /* Alias for the columns set by an offset of ix */
+      _W = W + ix;
+
+      /* inner loop */
+      for (iy = 0; iy < n->used; iy++) {
+          *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
+      }
+    }
+
+    /* now fix carry for next digit, W[ix+1] */
+    W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
+  }
+
+  /* now we have to propagate the carries and
+   * shift the words downward [all those least
+   * significant digits we zeroed].
+   */
+  {
+    register mp_digit *tmpx;
+    register mp_word *_W, *_W1;
+
+    /* nox fix rest of carries */
+
+    /* alias for current word */
+    _W1 = W + ix;
+
+    /* alias for next word, where the carry goes */
+    _W = W + ++ix;
+
+    for (; ix <= n->used * 2 + 1; ix++) {
+      *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
+    }
+
+    /* copy out, A = A/b**n
+     *
+     * The result is A/b**n but instead of converting from an
+     * array of mp_word to mp_digit than calling mp_rshd
+     * we just copy them in the right order
+     */
+
+    /* alias for destination word */
+    tmpx = x->dp;
+
+    /* alias for shifted double precision result */
+    _W = W + n->used;
+
+    for (ix = 0; ix < n->used + 1; ix++) {
+      *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
+    }
+
+    /* zero oldused digits, if the input a was larger than
+     * m->used+1 we'll have to clear the digits
+     */
+    for (; ix < olduse; ix++) {
+      *tmpx++ = 0;
+    }
+  }
+
+  /* set the max used and clamp */
+  x->used = n->used + 1;
+  mp_clamp (x);
+
+  /* if A >= m then A = A - m */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    return s_mp_sub (x, n, x);
+  }
+  return MP_OKAY;
+}
+
+/* End: bn_fast_mp_montgomery_reduce.c */
+
+/* Start: bn_fast_s_mp_mul_digs.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* Fast (comba) multiplier
+ *
+ * This is the fast column-array [comba] multiplier.  It is 
+ * designed to compute the columns of the product first 
+ * then handle the carries afterwards.  This has the effect 
+ * of making the nested loops that compute the columns very
+ * simple and schedulable on super-scalar processors.
+ *
+ * This has been modified to produce a variable number of 
+ * digits of output so if say only a half-product is required 
+ * you don't have to compute the upper half (a feature 
+ * required for fast Barrett reduction).
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ *
+ */
+int
+fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  int     olduse, res, pa, ix;
+  mp_word W[MP_WARRAY];
+
+  /* grow the destination as required */
+  if (c->alloc < digs) {
+    if ((res = mp_grow (c, digs)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* clear temp buf (the columns) */
+  memset (W, 0, sizeof (mp_word) * digs);
+
+  /* calculate the columns */
+  pa = a->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* this multiplier has been modified to allow you to 
+     * control how many digits of output are produced.  
+     * So at most we want to make upto "digs" digits of output.
+     *
+     * this adds products to distinct columns (at ix+iy) of W
+     * note that each step through the loop is not dependent on
+     * the previous which means the compiler can easily unroll
+     * the loop without scheduling problems
+     */
+    {
+      register mp_digit tmpx, *tmpy;
+      register mp_word *_W;
+      register int iy, pb;
+
+      /* alias for the the word on the left e.g. A[ix] * A[iy] */
+      tmpx = a->dp[ix];
+
+      /* alias for the right side */
+      tmpy = b->dp;
+
+      /* alias for the columns, each step through the loop adds a new
+         term to each column
+       */
+      _W = W + ix;
+
+      /* the number of digits is limited by their placement.  E.g.
+         we avoid multiplying digits that will end up above the # of
+         digits of precision requested
+       */
+      pb = MIN (b->used, digs - ix);
+
+      for (iy = 0; iy < pb; iy++) {
+        *_W++ += ((mp_word)tmpx) * ((mp_word)*tmpy++);
+      }
+    }
+
+  }
+
+  /* setup dest */
+  olduse = c->used;
+  c->used = digs;
+
+  {
+    register mp_digit *tmpc;
+
+    /* At this point W[] contains the sums of each column.  To get the
+     * correct result we must take the extra bits from each column and
+     * carry them down
+     *
+     * Note that while this adds extra code to the multiplier it 
+     * saves time since the carry propagation is removed from the 
+     * above nested loop.This has the effect of reducing the work 
+     * from N*(N+N*c)==N**2 + c*N**2 to N**2 + N*c where c is the 
+     * cost of the shifting.  On very small numbers this is slower 
+     * but on most cryptographic size numbers it is faster.
+     *
+     * In this particular implementation we feed the carries from
+     * behind which means when the loop terminates we still have one
+     * last digit to copy
+     */
+    tmpc = c->dp;
+    for (ix = 1; ix < digs; ix++) {
+      /* forward the carry from the previous temp */
+      W[ix] += (W[ix - 1] >> ((mp_word) DIGIT_BIT));
+
+      /* now extract the previous digit [below the carry] */
+      *tmpc++ = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK));
+    }
+    /* fetch the last digit */
+    *tmpc++ = (mp_digit) (W[digs - 1] & ((mp_word) MP_MASK));
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpc++ = 0;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+/* End: bn_fast_s_mp_mul_digs.c */
+
+/* Start: bn_fast_s_mp_mul_high_digs.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+ #include <tommath.h>
+
+/* this is a modified version of fast_s_mp_mul_digs that only produces
+ * output digits *above* digs.  See the comments for fast_s_mp_mul_digs
+ * to see how it works.
+ *
+ * This is used in the Barrett reduction since for one of the multiplications
+ * only the higher digits were needed.  This essentially halves the work.
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ */
+int
+fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  int     oldused, newused, res, pa, pb, ix;
+  mp_word W[MP_WARRAY];
+
+  /* calculate size of product and allocate more space if required */
+  newused = a->used + b->used + 1;
+  if (c->alloc < newused) {
+    if ((res = mp_grow (c, newused)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* like the other comba method we compute the columns first */
+  pa = a->used;
+  pb = b->used;
+  memset (W + digs, 0, (pa + pb + 1 - digs) * sizeof (mp_word));
+  for (ix = 0; ix < pa; ix++) {
+    {
+      register mp_digit tmpx, *tmpy;
+      register int iy;
+      register mp_word *_W;
+
+      /* work todo, that is we only calculate digits that are at "digs" or above  */
+      iy = digs - ix;
+
+      /* copy of word on the left of A[ix] * B[iy] */
+      tmpx = a->dp[ix];
+
+      /* alias for right side */
+      tmpy = b->dp + iy;
+     
+      /* alias for the columns of output.  Offset to be equal to or above the 
+       * smallest digit place requested 
+       */
+      _W = W + digs;     
+      
+      /* skip cases below zero where ix > digs */
+      if (iy < 0) {
+         iy    = abs(iy);
+         tmpy += iy;
+         _W   += iy;
+         iy    = 0;
+      }
+
+      /* compute column products for digits above the minimum */
+      for (; iy < pb; iy++) {
+         *_W++ += ((mp_word) tmpx) * ((mp_word)*tmpy++);
+      }
+    }
+  }
+
+  /* setup dest */
+  oldused = c->used;
+  c->used = newused;
+
+  /* now convert the array W downto what we need
+   *
+   * See comments in bn_fast_s_mp_mul_digs.c
+   */
+  for (ix = digs + 1; ix < newused; ix++) {
+    W[ix] += (W[ix - 1] >> ((mp_word) DIGIT_BIT));
+    c->dp[ix - 1] = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK));
+  }
+  c->dp[newused - 1] = (mp_digit) (W[newused - 1] & ((mp_word) MP_MASK));
+
+  for (; ix < oldused; ix++) {
+    c->dp[ix] = 0;
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+/* End: bn_fast_s_mp_mul_high_digs.c */
+
+/* Start: bn_fast_s_mp_sqr.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* fast squaring
+ *
+ * This is the comba method where the columns of the product
+ * are computed first then the carries are computed.  This
+ * has the effect of making a very simple inner loop that
+ * is executed the most
+ *
+ * W2 represents the outer products and W the inner.
+ *
+ * A further optimizations is made because the inner
+ * products are of the form "A * B * 2".  The *2 part does
+ * not need to be computed until the end which is good
+ * because 64-bit shifts are slow!
+ *
+ * Based on Algorithm 14.16 on pp.597 of HAC.
+ *
+ */
+int fast_s_mp_sqr (mp_int * a, mp_int * b)
+{
+  int     olduse, newused, res, ix, pa;
+  mp_word W2[MP_WARRAY], W[MP_WARRAY];
+
+  /* calculate size of product and allocate as required */
+  pa = a->used;
+  newused = pa + pa + 1;
+  if (b->alloc < newused) {
+    if ((res = mp_grow (b, newused)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* zero temp buffer (columns)
+   * Note that there are two buffers.  Since squaring requires
+   * a outer and inner product and the inner product requires
+   * computing a product and doubling it (a relatively expensive
+   * op to perform n**2 times if you don't have to) the inner and
+   * outer products are computed in different buffers.  This way
+   * the inner product can be doubled using n doublings instead of
+   * n**2
+   */
+  memset (W,  0, newused * sizeof (mp_word));
+  memset (W2, 0, newused * sizeof (mp_word));
+
+  /* This computes the inner product.  To simplify the inner N**2 loop
+   * the multiplication by two is done afterwards in the N loop.
+   */
+  for (ix = 0; ix < pa; ix++) {
+    /* compute the outer product
+     *
+     * Note that every outer product is computed
+     * for a particular column only once which means that
+     * there is no need todo a double precision addition
+     * into the W2[] array.
+     */
+    W2[ix + ix] = ((mp_word)a->dp[ix]) * ((mp_word)a->dp[ix]);
+
+    {
+      register mp_digit tmpx, *tmpy;
+      register mp_word *_W;
+      register int iy;
+
+      /* copy of left side */
+      tmpx = a->dp[ix];
+
+      /* alias for right side */
+      tmpy = a->dp + (ix + 1);
+
+      /* the column to store the result in */
+      _W = W + (ix + ix + 1);
+
+      /* inner products */
+      for (iy = ix + 1; iy < pa; iy++) {
+          *_W++ += ((mp_word)tmpx) * ((mp_word)*tmpy++);
+      }
+    }
+  }
+
+  /* setup dest */
+  olduse  = b->used;
+  b->used = newused;
+
+  /* now compute digits
+   *
+   * We have to double the inner product sums, add in the
+   * outer product sums, propagate carries and convert
+   * to single precision.
+   */
+  {
+    register mp_digit *tmpb;
+
+    /* double first value, since the inner products are
+     * half of what they should be
+     */
+    W[0] += W[0] + W2[0];
+
+    tmpb = b->dp;
+    for (ix = 1; ix < newused; ix++) {
+      /* double/add next digit */
+      W[ix] += W[ix] + W2[ix];
+
+      /* propagate carry forwards [from the previous digit] */
+      W[ix] = W[ix] + (W[ix - 1] >> ((mp_word) DIGIT_BIT));
+
+      /* store the current digit now that the carry isn't
+       * needed
+       */
+      *tmpb++ = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK));
+    }
+    /* set the last value.  Note even if the carry is zero
+     * this is required since the next step will not zero
+     * it if b originally had a value at b->dp[2*a.used]
+     */
+    *tmpb++ = (mp_digit) (W[(newused) - 1] & ((mp_word) MP_MASK));
+
+    /* clear high digits of b if there were any originally */
+    for (; ix < olduse; ix++) {
+      *tmpb++ = 0;
+    }
+  }
+
+  mp_clamp (b);
+  return MP_OKAY;
+}
+
+/* End: bn_fast_s_mp_sqr.c */
+
+/* Start: bn_mp_2expt.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* computes a = 2**b 
+ *
+ * Simple algorithm which zeroes the int, grows it then just sets one bit
+ * as required.
+ */
+int
+mp_2expt (mp_int * a, int b)
+{
+  int     res;
+
+  /* zero a as per default */
+  mp_zero (a);
+
+  /* grow a to accomodate the single bit */
+  if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* set the used count of where the bit will go */
+  a->used = b / DIGIT_BIT + 1;
+
+  /* put the single bit in its place */
+  a->dp[b / DIGIT_BIT] = 1 << (b % DIGIT_BIT);
+
+  return MP_OKAY;
+}
+
+/* End: bn_mp_2expt.c */
+
+/* Start: bn_mp_abs.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* b = |a| 
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+int
+mp_abs (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  /* copy a to b */
+  if (a != b) {
+     if ((res = mp_copy (a, b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* force the sign of b to positive */
+  b->sign = MP_ZPOS;
+
+  return MP_OKAY;
+}
+
+/* End: bn_mp_abs.c */
+
+/* Start: bn_mp_add.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* high level addition (handles signs) */
+int mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  /* get sign of both inputs */
+  sa = a->sign;
+  sb = b->sign;
+
+  /* handle two cases, not four */
+  if (sa == sb) {
+    /* both positive or both negative */
+    /* add their magnitudes, copy the sign */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* one positive, the other negative */
+    /* subtract the one with the greater magnitude from */
+    /* the one of the lesser magnitude.  The result gets */
+    /* the sign of the one with the greater magnitude. */
+    if (mp_cmp_mag (a, b) == MP_LT) {
+      c->sign = sb;
+      res = s_mp_sub (b, a, c);
+    } else {
+      c->sign = sa;
+      res = s_mp_sub (a, b, c);
+    }
+  }
+  return res;
+}
+
+
+/* End: bn_mp_add.c */
+
+/* Start: bn_mp_add_d.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* single digit addition */
+int
+mp_add_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  int     res, ix, oldused;
+  mp_digit *tmpa, *tmpc, mu;
+
+  /* grow c as required */
+  if (c->alloc < a->used + 1) {
+     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* if a is negative and |a| >= b, call c = |a| - b */
+  if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
+     /* temporarily fix sign of a */
+     a->sign = MP_ZPOS;
+
+     /* c = |a| - b */
+     res = mp_sub_d(a, b, c);
+
+     /* fix sign  */
+     a->sign = c->sign = MP_NEG;
+
+     return res;
+  }
+
+  /* old number of used digits in c */
+  oldused = c->used;
+
+  /* sign always positive */
+  c->sign = MP_ZPOS;
+
+  /* source alias */
+  tmpa    = a->dp;
+
+  /* destination alias */
+  tmpc    = c->dp;
+
+  /* if a is positive */
+  if (a->sign == MP_ZPOS) {
+     /* add digit, after this we're propagating
+      * the carry.
+      */
+     *tmpc   = *tmpa++ + b;
+     mu      = *tmpc >> DIGIT_BIT;
+     *tmpc++ &= MP_MASK;
+
+     /* now handle rest of the digits */
+     for (ix = 1; ix < a->used; ix++) {
+        *tmpc   = *tmpa++ + mu;
+        mu      = *tmpc >> DIGIT_BIT;
+        *tmpc++ &= MP_MASK;
+     }
+     /* set final carry */
+     ix++;
+     *tmpc++  = mu;
+
+     /* setup size */
+     c->used = a->used + 1;
+  } else {
+     /* a was negative and |a| < b */
+     c->used  = 1;
+
+     /* the result is a single digit */
+     if (a->used == 1) {
+        *tmpc++  =  b - a->dp[0];
+     } else {
+        *tmpc++  =  b;
+     }
+
+     /* setup count so the clearing of oldused
+      * can fall through correctly
+      */
+     ix       = 1;
+  }
+
+  /* now zero to oldused */
+  while (ix++ < oldused) {
+     *tmpc++ = 0;
+  }
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+
+
+/* End: bn_mp_add_d.c */
+
+/* Start: bn_mp_addmod.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* d = a + b (mod c) */
+int
+mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_add (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+
+/* End: bn_mp_addmod.c */
+
+/* Start: bn_mp_and.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* AND two ints together */
+int
+mp_and (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, ix, px;
+  mp_int  t, *x;
+
+  if (a->used > b->used) {
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+      return res;
+    }
+    px = b->used;
+    x = b;
+  } else {
+    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+      return res;
+    }
+    px = a->used;
+    x = a;
+  }
+
+  for (ix = 0; ix < px; ix++) {
+    t.dp[ix] &= x->dp[ix];
+  }
+
+  /* zero digits above the last from the smallest mp_int */
+  for (; ix < t.used; ix++) {
+    t.dp[ix] = 0;
+  }
+
+  mp_clamp (&t);
+  mp_exch (c, &t);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+/* End: bn_mp_and.c */
+
+/* Start: bn_mp_clamp.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* trim unused digits 
+ *
+ * This is used to ensure that leading zero digits are
+ * trimed and the leading "used" digit will be non-zero
+ * Typically very fast.  Also fixes the sign if there
+ * are no more leading digits
+ */
+void
+mp_clamp (mp_int * a)
+{
+  /* decrease used while the most significant digit is
+   * zero.
+   */
+  while (a->used > 0 && a->dp[a->used - 1] == 0) {
+    --(a->used);
+  }
+
+  /* reset the sign flag if used == 0 */
+  if (a->used == 0) {
+    a->sign = MP_ZPOS;
+  }
+}
+
+/* End: bn_mp_clamp.c */
+
+/* Start: bn_mp_clear.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* clear one (frees)  */
+void
+mp_clear (mp_int * a)
+{
+  /* only do anything if a hasn't been freed previously */
+  if (a->dp != NULL) {
+    /* first zero the digits */
+    memset (a->dp, 0, sizeof (mp_digit) * a->used);
+
+    /* free ram */
+    XFREE(a->dp);
+
+    /* reset members to make debugging easier */
+    a->dp    = NULL;
+    a->alloc = a->used = 0;
+    a->sign  = MP_ZPOS;
+  }
+}
+
+/* End: bn_mp_clear.c */
+
+/* Start: bn_mp_clear_multi.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+#include <stdarg.h>
+
+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);
+}
+
+/* End: bn_mp_clear_multi.c */
+
+/* Start: bn_mp_cmp.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* compare two ints (signed)*/
+int
+mp_cmp (mp_int * a, mp_int * b)
+{
+  /* compare based on sign */
+  if (a->sign != b->sign) {
+     if (a->sign == MP_NEG) {
+        return MP_LT;
+     } else {
+        return MP_GT;
+     }
+  }
+  
+  /* compare digits */
+  if (a->sign == MP_NEG) {
+     /* if negative compare opposite direction */
+     return mp_cmp_mag(b, a);
+  } else {
+     return mp_cmp_mag(a, b);
+  }
+}
+
+/* End: bn_mp_cmp.c */
+
+/* Start: bn_mp_cmp_d.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* compare a digit */
+int mp_cmp_d(mp_int * a, mp_digit b)
+{
+  /* compare based on sign */
+  if (a->sign == MP_NEG) {
+    return MP_LT;
+  }
+
+  /* compare based on magnitude */
+  if (a->used > 1) {
+    return MP_GT;
+  }
+
+  /* compare the only digit of a to b */
+  if (a->dp[0] > b) {
+    return MP_GT;
+  } else if (a->dp[0] < b) {
+    return MP_LT;
+  } else {
+    return MP_EQ;
+  }
+}
+
+/* End: bn_mp_cmp_d.c */
+
+/* Start: bn_mp_cmp_mag.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* compare maginitude of two ints (unsigned) */
+int mp_cmp_mag (mp_int * a, mp_int * b)
+{
+  int     n;
+  mp_digit *tmpa, *tmpb;
+
+  /* compare based on # of non-zero digits */
+  if (a->used > b->used) {
+    return MP_GT;
+  }
+  
+  if (a->used < b->used) {
+    return MP_LT;
+  }
+
+  /* alias for a */
+  tmpa = a->dp + (a->used - 1);
+
+  /* alias for b */
+  tmpb = b->dp + (a->used - 1);
+
+  /* compare based on digits  */
+  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
+    if (*tmpa > *tmpb) {
+      return MP_GT;
+    }
+
+    if (*tmpa < *tmpb) {
+      return MP_LT;
+    }
+  }
+  return MP_EQ;
+}
+
+/* End: bn_mp_cmp_mag.c */
+
+/* Start: bn_mp_cnt_lsb.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+static const int lnz[16] = { 
+   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a)
+{
+   int x;
+   mp_digit q, qq;
+
+   /* easy out */
+   if (mp_iszero(a) == 1) {
+      return 0;
+   }
+
+   /* scan lower digits until non-zero */
+   for (x = 0; x < a->used && a->dp[x] == 0; x++);
+   q = a->dp[x];
+   x *= DIGIT_BIT;
+
+   /* now scan this digit until a 1 is found */
+   if ((q & 1) == 0) {
+      do {
+         qq  = q & 15;
+         x  += lnz[qq];
+         q >>= 4;
+      } while (qq == 0);
+   }
+   return x;
+}
+
+
+/* End: bn_mp_cnt_lsb.c */
+
+/* Start: bn_mp_copy.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* copy, b = a */
+int
+mp_copy (mp_int * a, mp_int * b)
+{
+  int     res, n;
+
+  /* if dst == src do nothing */
+  if (a == b) {
+    return MP_OKAY;
+  }
+
+  /* grow dest */
+  if (b->alloc < a->used) {
+     if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero b and copy the parameters over */
+  {
+    register mp_digit *tmpa, *tmpb;
+
+    /* pointer aliases */
+
+    /* source */
+    tmpa = a->dp;
+
+    /* destination */
+    tmpb = b->dp;
+
+    /* copy all the digits */
+    for (n = 0; n < a->used; n++) {
+      *tmpb++ = *tmpa++;
+    }
+
+    /* clear high digits */
+    for (; n < b->used; n++) {
+      *tmpb++ = 0;
+    }
+  }
+
+  /* copy used count and sign */
+  b->used = a->used;
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+
+/* End: bn_mp_copy.c */
+
+/* Start: bn_mp_count_bits.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* returns the number of bits in an int */
+int
+mp_count_bits (mp_int * a)
+{
+  int     r;
+  mp_digit q;
+
+  /* shortcut */
+  if (a->used == 0) {
+    return 0;
+  }
+
+  /* get number of digits and add that */
+  r = (a->used - 1) * DIGIT_BIT;
+  
+  /* take the last digit and count the bits in it */
+  q = a->dp[a->used - 1];
+  while (q > ((mp_digit) 0)) {
+    ++r;
+    q >>= ((mp_digit) 1);
+  }
+  return r;
+}
+
+/* End: bn_mp_count_bits.c */
+
+/* Start: bn_mp_div.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* integer signed division. 
+ * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
+ * HAC pp.598 Algorithm 14.20
+ *
+ * Note that the description in HAC is horribly 
+ * incomplete.  For example, it doesn't consider 
+ * the case where digits are removed from 'x' in 
+ * the inner loop.  It also doesn't consider the 
+ * case that y has fewer than three digits, etc..
+ *
+ * The overall algorithm is as described as 
+ * 14.20 from HAC but fixed to treat these cases.
+*/
+int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  mp_int  q, x, y, t1, t2;
+  int     res, n, t, i, norm, neg;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+
+  if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
+    return res;
+  }
+  q.used = a->used + 2;
+
+  if ((res = mp_init (&t1)) != MP_OKAY) {
+    goto __Q;
+  }
+
+  if ((res = mp_init (&t2)) != MP_OKAY) {
+    goto __T1;
+  }
+
+  if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
+    goto __T2;
+  }
+
+  if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
+    goto __X;
+  }
+
+  /* fix the sign */
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+  x.sign = y.sign = MP_ZPOS;
+
+  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
+  norm = mp_count_bits(&y) % DIGIT_BIT;
+  if (norm < (int)(DIGIT_BIT-1)) {
+     norm = (DIGIT_BIT-1) - norm;
+     if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
+       goto __Y;
+     }
+     if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
+       goto __Y;
+     }
+  } else {
+     norm = 0;
+  }
+
+  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+  n = x.used - 1;
+  t = y.used - 1;
+
+  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
+  if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
+    goto __Y;
+  }
+
+  while (mp_cmp (&x, &y) != MP_LT) {
+    ++(q.dp[n - t]);
+    if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
+      goto __Y;
+    }
+  }
+
+  /* reset y by shifting it back down */
+  mp_rshd (&y, n - t);
+
+  /* step 3. for i from n down to (t + 1) */
+  for (i = n; i >= (t + 1); i--) {
+    if (i > x.used) {
+      continue;
+    }
+
+    /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 
+     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
+    if (x.dp[i] == y.dp[t]) {
+      q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
+    } else {
+      mp_word tmp;
+      tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
+      tmp |= ((mp_word) x.dp[i - 1]);
+      tmp /= ((mp_word) y.dp[t]);
+      if (tmp > (mp_word) MP_MASK)
+        tmp = MP_MASK;
+      q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
+    }
+
+    /* while (q{i-t-1} * (yt * b + y{t-1})) > 
+             xi * b**2 + xi-1 * b + xi-2 
+     
+       do q{i-t-1} -= 1; 
+    */
+    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
+    do {
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
+
+      /* find left hand */
+      mp_zero (&t1);
+      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
+      t1.dp[1] = y.dp[t];
+      t1.used = 2;
+      if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+        goto __Y;
+      }
+
+      /* find right hand */
+      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
+      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
+      t2.dp[2] = x.dp[i];
+      t2.used = 3;
+    } while (mp_cmp_mag(&t1, &t2) == MP_GT);
+
+    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
+    if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+      goto __Y;
+    }
+
+    if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+      goto __Y;
+    }
+
+    if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
+      goto __Y;
+    }
+
+    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
+    if (x.sign == MP_NEG) {
+      if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
+        goto __Y;
+      }
+      if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+        goto __Y;
+      }
+      if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
+        goto __Y;
+      }
+
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
+    }
+  }
+
+  /* now q is the quotient and x is the remainder 
+   * [which we have to normalize] 
+   */
+  
+  /* get sign before writing to c */
+  x.sign = a->sign;
+
+  if (c != NULL) {
+    mp_clamp (&q);
+    mp_exch (&q, c);
+    c->sign = neg;
+  }
+
+  if (d != NULL) {
+    mp_div_2d (&x, norm, &x, NULL);
+    mp_exch (&x, d);
+  }
+
+  res = MP_OKAY;
+
+__Y:mp_clear (&y);
+__X:mp_clear (&x);
+__T2:mp_clear (&t2);
+__T1:mp_clear (&t1);
+__Q:mp_clear (&q);
+  return res;
+}
+
+/* End: bn_mp_div.c */
+
+/* Start: bn_mp_div_2.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* b = a/2 */
+int mp_div_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* copy */
+  if (b->alloc < a->used) {
+    if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* source alias */
+    tmpa = a->dp + b->used - 1;
+
+    /* dest alias */
+    tmpb = b->dp + b->used - 1;
+
+    /* carry */
+    r = 0;
+    for (x = b->used - 1; x >= 0; x--) {
+      /* get the carry for the next iteration */
+      rr = *tmpa & 1;
+
+      /* shift the current digit, add in carry and store */
+      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+      /* forward carry to next iteration */
+      r = rr;
+    }
+
+    /* zero excess digits */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  mp_clamp (b);
+  return MP_OKAY;
+}
+
+/* End: bn_mp_div_2.c */
+
+/* Start: bn_mp_div_2d.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
+int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
+{
+  mp_digit D, r, rr;
+  int     x, res;
+  mp_int  t;
+
+
+  /* if the shift count is <= 0 then we do no work */
+  if (b <= 0) {
+    res = mp_copy (a, c);
+    if (d != NULL) {
+      mp_zero (d);
+    }
+    return res;
+  }
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  /* get the remainder */
+  if (d != NULL) {
+    if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    mp_rshd (c, b / DIGIT_BIT);
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  D = (mp_digit) (b % DIGIT_BIT);
+  if (D != 0) {
+    register mp_digit *tmpc, mask, shift;
+
+    /* mask */
+    mask = (((mp_digit)1) << D) - 1;
+
+    /* shift for lsb */
+    shift = DIGIT_BIT - D;
+
+    /* alias */
+    tmpc = c->dp + (c->used - 1);
+
+    /* carry */
+    r = 0;
+    for (x = c->used - 1; x >= 0; x--) {
+      /* get the lower  bits of this word in a temp */
+      rr = *tmpc & mask;
+
+      /* shift the current word and mix in the carry bits from the previous word */
+      *tmpc = (*tmpc >> D) | (r << shift);
+      --tmpc;
+
+      /* set the carry to the carry bits of the current word found above */
+      r = rr;
+    }
+  }
+  mp_clamp (c);
+  if (d != NULL) {
+    mp_exch (&t, d);
+  }
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+/* End: bn_mp_div_2d.c */
+
+/* Start: bn_mp_div_3.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* divide by three (based on routine from MPI and the GMP manual) */
+int
+mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
+{
+  mp_int   q;
+  mp_word  w, t;
+  mp_digit b;
+  int      res, ix;
+  
+  /* b = 2**DIGIT_BIT / 3 */
+  b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);
+
+  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+     return res;
+  }
+  
+  q.used = a->used;
+  q.sign = a->sign;
+  w = 0;
+  for (ix = a->used - 1; ix >= 0; ix--) {
+     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+     if (w >= 3) {
+        /* multiply w by [1/3] */
+        t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
+
+        /* now subtract 3 * [w/3] from w, to get the remainder */
+        w -= t+t+t;
+
+        /* fixup the remainder as required since
+         * the optimization is not exact.
+         */
+        while (w >= 3) {
+           t += 1;
+           w -= 3;
+        }
+      } else {
+        t = 0;
+      }
+      q.dp[ix] = (mp_digit)t;
+  }
+
+  /* [optional] store the remainder */
+  if (d != NULL) {
+     *d = (mp_digit)w;
+  }
+
+  /* [optional] store the quotient */
+  if (c != NULL) {
+     mp_clamp(&q);
+     mp_exch(&q, c);
+  }
+  mp_clear(&q);
+  
+  return res;
+}
+
+
+/* End: bn_mp_div_3.c */
+
+/* Start: bn_mp_div_d.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+static int s_is_power_of_two(mp_digit b, int *p)
+{
+   int x;
+
+   for (x = 1; x < DIGIT_BIT; x++) {
+      if (b == (((mp_digit)1)<<x)) {
+         *p = x;
+         return 1;
+      }
+   }
+   return 0;
+}
+
+/* single digit division (based on routine from MPI) */
+int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
+{
+  mp_int  q;
+  mp_word w;
+  mp_digit t;
+  int     res, ix;
+
+  /* cannot divide by zero */
+  if (b == 0) {
+     return MP_VAL;
+  }
+
+  /* quick outs */
+  if (b == 1 || mp_iszero(a) == 1) {
+     if (d != NULL) {
+        *d = 0;
+     }
+     if (c != NULL) {
+        return mp_copy(a, c);
+     }
+     return MP_OKAY;
+  }
+
+  /* power of two ? */
+  if (s_is_power_of_two(b, &ix) == 1) {
+     if (d != NULL) {
+        *d = a->dp[0] & ((1<<ix) - 1);
+     }
+     if (c != NULL) {
+        return mp_div_2d(a, ix, c, NULL);
+     }
+     return MP_OKAY;
+  }
+
+  /* three? */
+  if (b == 3) {
+     return mp_div_3(a, c, d);
+  }
+
+  /* no easy answer [c'est la vie].  Just division */
+  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+     return res;
+  }
+  
+  q.used = a->used;
+  q.sign = a->sign;
+  w = 0;
+  for (ix = a->used - 1; ix >= 0; ix--) {
+     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+     
+     if (w >= b) {
+        t = (mp_digit)(w / b);
+        w -= ((mp_word)t) * ((mp_word)b);
+      } else {
+        t = 0;
+      }
+      q.dp[ix] = (mp_digit)t;
+  }
+  
+  if (d != NULL) {
+     *d = (mp_digit)w;
+  }
+  
+  if (c != NULL) {
+     mp_clamp(&q);
+     mp_exch(&q, c);
+  }
+  mp_clear(&q);
+  
+  return res;
+}
+
+
+/* End: bn_mp_div_d.c */
+
+/* Start: bn_mp_dr_is_modulus.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* determines if a number is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a)
+{
+   int ix;
+
+   /* must be at least two digits */
+   if (a->used < 2) {
+      return 0;
+   }
+
+   /* must be of the form b**k - a [a <= b] so all
+    * but the first digit must be equal to -1 (mod b).
+    */
+   for (ix = 1; ix < a->used; ix++) {
+       if (a->dp[ix] != MP_MASK) {
+          return 0;
+       }
+   }
+   return 1;
+}
+
+
+/* End: bn_mp_dr_is_modulus.c */
+
+/* Start: bn_mp_dr_reduce.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
+ *
+ * Based on algorithm from the paper
+ *
+ * "Generating Efficient Primes for Discrete Log Cryptosystems"
+ *                 Chae Hoon Lim, Pil Loong Lee,
+ *          POSTECH Information Research Laboratories
+ *
+ * The modulus must be of a special format [see manual]
+ *
+ * Has been modified to use algorithm 7.10 from the LTM book instead
+ *
+ * Input x must be in the range 0 <= x <= (n-1)**2
+ */
+int
+mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
+{
+  int      err, i, m;
+  mp_word  r;
+  mp_digit mu, *tmpx1, *tmpx2;
+
+  /* m = digits in modulus */
+  m = n->used;
+
+  /* ensure that "x" has at least 2m digits */
+  if (x->alloc < m + m) {
+    if ((err = mp_grow (x, m + m)) != MP_OKAY) {
+      return err;
+    }
+  }
+
+/* top of loop, this is where the code resumes if
+ * another reduction pass is required.
+ */
+top:
+  /* aliases for digits */
+  /* alias for lower half of x */
+  tmpx1 = x->dp;
+
+  /* alias for upper half of x, or x/B**m */
+  tmpx2 = x->dp + m;
+
+  /* set carry to zero */
+  mu = 0;
+
+  /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
+  for (i = 0; i < m; i++) {
+      r         = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
+      *tmpx1++  = (mp_digit)(r & MP_MASK);
+      mu        = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
+  }
+
+  /* set final carry */
+  *tmpx1++ = mu;
+
+  /* zero words above m */
+  for (i = m + 1; i < x->used; i++) {
+      *tmpx1++ = 0;
+  }
+
+  /* clamp, sub and return */
+  mp_clamp (x);
+
+  /* if x >= n then subtract and reduce again
+   * Each successive "recursion" makes the input smaller and smaller.
+   */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    s_mp_sub(x, n, x);
+    goto top;
+  }
+  return MP_OKAY;
+}
+
+/* End: bn_mp_dr_reduce.c */
+
+/* Start: bn_mp_dr_setup.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* determines the setup value */
+void mp_dr_setup(mp_int *a, mp_digit *d)
+{
+   /* the casts are required if DIGIT_BIT is one less than
+    * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
+    */
+   *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - 
+        ((mp_word)a->dp[0]));
+}
+
+
+/* End: bn_mp_dr_setup.c */
+
+/* Start: bn_mp_exch.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* swap the elements of two integers, for cases where you can't simply swap the 
+ * mp_int pointers around
+ */
+void
+mp_exch (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+
+  t  = *a;
+  *a = *b;
+  *b = t;
+}
+
+/* End: bn_mp_exch.c */
+
+/* Start: bn_mp_expt_d.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* calculate c = a**b  using a square-multiply algorithm */
+int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  int     res, x;
+  mp_int  g;
+
+  if ((res = mp_init_copy (&g, a)) != MP_OKAY) {
+    return res;
+  }
+
+  /* set initial result */
+  mp_set (c, 1);
+
+  for (x = 0; x < (int) DIGIT_BIT; x++) {
+    /* square */
+    if ((res = mp_sqr (c, c)) != MP_OKAY) {
+      mp_clear (&g);
+      return res;
+    }
+
+    /* if the bit is set multiply */
+    if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) {
+      if ((res = mp_mul (c, &g, c)) != MP_OKAY) {
+         mp_clear (&g);
+         return res;
+      }
+    }
+
+    /* shift to next bit */
+    b <<= 1;
+  }
+
+  mp_clear (&g);
+  return MP_OKAY;
+}
+
+/* End: bn_mp_expt_d.c */
+
+/* Start: bn_mp_exptmod.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+
+/* this is a shell function that calls either the normal or Montgomery
+ * exptmod functions.  Originally the call to the montgomery code was
+ * embedded in the normal function but that wasted alot of stack space
+ * for nothing (since 99% of the time the Montgomery code would be called)
+ */
+int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+{
+  int dr;
+
+  /* modulus P must be positive */
+  if (P->sign == MP_NEG) {
+     return MP_VAL;
+  }
+
+  /* if exponent X is negative we have to recurse */
+  if (X->sign == MP_NEG) {
+     mp_int tmpG, tmpX;
+     int err;
+
+     /* first compute 1/G mod P */
+     if ((err = mp_init(&tmpG)) != MP_OKAY) {
+        return err;
+     }
+     if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+
+     /* now get |X| */
+     if ((err = mp_init(&tmpX)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+     if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
+        mp_clear_multi(&tmpG, &tmpX, NULL);
+        return err;
+     }
+
+     /* and now compute (1/G)**|X| instead of G**X [X < 0] */
+     err = mp_exptmod(&tmpG, &tmpX, P, Y);
+     mp_clear_multi(&tmpG, &tmpX, NULL);
+     return err;
+  }
+
+  /* is it a DR modulus? */
+  dr = mp_dr_is_modulus(P);
+
+  /* if not, is it a uDR modulus? */
+  if (dr == 0) {
+     dr = mp_reduce_is_2k(P) << 1;
+  }
+    
+  /* if the modulus is odd or dr != 0 use the fast method */
+  if (mp_isodd (P) == 1 || dr !=  0) {
+    return mp_exptmod_fast (G, X, P, Y, dr);
+  } else {
+    /* otherwise use the generic Barrett reduction technique */
+    return s_mp_exptmod (G, X, P, Y);
+  }
+}
+
+
+/* End: bn_mp_exptmod.c */
+
+/* Start: bn_mp_exptmod_fast.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+
+#ifdef MP_LOW_MEM
+   #define TAB_SIZE 32
+#else
+   #define TAB_SIZE 256
+#endif
+
+int
+mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res;
+  mp_digit buf, mp;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+  /* use a pointer to the reduction algorithm.  This allows us to use
+   * one of many reduction algorithms without modding the guts of
+   * the code with if statements everywhere.
+   */
+  int     (*redux)(mp_int*,mp_int*,mp_digit);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+  if (winsize > 5) {
+     winsize = 5;
+  }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err;
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* determine and setup reduction code */
+  if (redmode == 0) {
+     /* now setup montgomery  */
+     if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
+        goto __M;
+     }
+
+     /* automatically pick the comba one if available (saves quite a few calls/ifs) */
+     if (((P->used * 2 + 1) < MP_WARRAY) &&
+          P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+        redux = fast_mp_montgomery_reduce;
+     } else {
+        /* use slower baseline Montgomery method */
+        redux = mp_montgomery_reduce;
+     }
+  } else if (redmode == 1) {
+     /* setup DR reduction for moduli of the form B**k - b */
+     mp_dr_setup(P, &mp);
+     redux = mp_dr_reduce;
+  } else {
+     /* setup DR reduction for moduli of the form 2**k - b */
+     if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
+        goto __M;
+     }
+     redux = mp_reduce_2k;
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto __M;
+  }
+
+  /* create M table
+   *
+   * The M table contains powers of the input base, e.g. M[x] = G^x mod P
+   *
+   * The first half of the table is not computed though accept for M[0] and M[1]
+   */
+
+  if (redmode == 0) {
+     /* now we need R mod m */
+     if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
+       goto __RES;
+     }
+
+     /* now set M[1] to G * R mod m */
+     if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
+       goto __RES;
+     }
+  } else {
+     mp_set(&res, 1);
+     if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
+        goto __RES;
+     }
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto __RES;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto __RES;
+    }
+    if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
+      goto __RES;
+    }
+  }
+
+  /* create upper table */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto __RES;
+    }
+    if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
+      goto __RES;
+    }
+  }
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits so break */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int)DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto __RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto __RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto __RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto __RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto __RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto __RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto __RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto __RES;
+      }
+
+      /* get next bit of the window */
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto __RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto __RES;
+        }
+      }
+    }
+  }
+
+  if (redmode == 0) {
+     /* fixup result if Montgomery reduction is used
+      * recall that any value in a Montgomery system is
+      * actually multiplied by R mod n.  So we have
+      * to reduce one more time to cancel out the factor
+      * of R.
+      */
+     if ((err = mp_montgomery_reduce (&res, P, mp)) != MP_OKAY) {
+       goto __RES;
+     }
+  }
+
+  /* swap res with Y */
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+__RES:mp_clear (&res);
+__M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+
+/* End: bn_mp_exptmod_fast.c */
+
+/* Start: bn_mp_exteuclid.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* Extended euclidean algorithm of (a, b) produces 
+   a*u1 + b*u2 = u3
+ */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
+{
+   mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
+   int err;
+
+   if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
+      return err;
+   }
+
+   /* initialize, (u1,u2,u3) = (1,0,a) */
+   mp_set(&u1, 1);
+   if ((err = mp_copy(a, &u3)) != MP_OKAY)                                        { goto _ERR; }
+
+   /* initialize, (v1,v2,v3) = (0,1,b) */
+   mp_set(&v2, 1);
+   if ((err = mp_copy(b, &v3)) != MP_OKAY)                                        { goto _ERR; }
+
+   /* loop while v3 != 0 */
+   while (mp_iszero(&v3) == MP_NO) {
+       /* q = u3/v3 */
+       if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY)                         { goto _ERR; }
+
+       /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
+       if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
+       if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY)                             { goto _ERR; }
+       if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
+       if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY)                             { goto _ERR; }
+       if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
+       if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY)                             { goto _ERR; }
+
+       /* (u1,u2,u3) = (v1,v2,v3) */
+       if ((err = mp_copy(&v1, &u1)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&v2, &u2)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&v3, &u3)) != MP_OKAY)                                  { goto _ERR; }
+
+       /* (v1,v2,v3) = (t1,t2,t3) */
+       if ((err = mp_copy(&t1, &v1)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&t2, &v2)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; }
+   }
+
+   /* copy result out */
+   if (U1 != NULL) { mp_exch(U1, &u1); }
+   if (U2 != NULL) { mp_exch(U2, &u2); }
+   if (U3 != NULL) { mp_exch(U3, &u3); }
+
+   err = MP_OKAY;
+_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
+   return err;
+}
+
+/* End: bn_mp_exteuclid.c */
+
+/* Start: bn_mp_fread.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* read a bigint from a file stream in ASCII */
+int mp_fread(mp_int *a, int radix, FILE *stream)
+{
+   int err, ch, neg, y;
+   
+   /* clear a */
+   mp_zero(a);
+   
+   /* if first digit is - then set negative */
+   ch = fgetc(stream);
+   if (ch == '-') {
+      neg = MP_NEG;
+      ch = fgetc(stream);
+   } else {
+      neg = MP_ZPOS;
+   }
+   
+   for (;;) {
+      /* find y in the radix map */
+      for (y = 0; y < radix; y++) {
+          if (mp_s_rmap[y] == ch) {
+             break;
+          }
+      }
+      if (y == radix) {
+         break;
+      }
+      
+      /* shift up and add */
+      if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {
+         return err;
+      }
+      if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
+         return err;
+      }
+      
+      ch = fgetc(stream);
+   }
+   if (mp_cmp_d(a, 0) != MP_EQ) {
+      a->sign = neg;
+   }
+   
+   return MP_OKAY;
+}
+
+
+/* End: bn_mp_fread.c */
+
+/* Start: bn_mp_fwrite.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+int mp_fwrite(mp_int *a, int radix, FILE *stream)
+{
+   char *buf;
+   int err, len, x;
+   
+   if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
+      return err;
+   }
+
+   buf = OPT_CAST(char) XMALLOC (len);
+   if (buf == NULL) {
+      return MP_MEM;
+   }
+   
+   if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
+      XFREE (buf);
+      return err;
+   }
+   
+   for (x = 0; x < len; x++) {
+       if (fputc(buf[x], stream) == EOF) {
+          XFREE (buf);
+          return MP_VAL;
+       }
+   }
+   
+   XFREE (buf);
+   return MP_OKAY;
+}
+
+
+/* End: bn_mp_fwrite.c */
+
+/* Start: bn_mp_gcd.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* Greatest Common Divisor using the binary method */
+int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  u, v;
+  int     k, u_lsb, v_lsb, res;
+
+  /* either zero than gcd is the largest */
+  if (mp_iszero (a) == 1 && mp_iszero (b) == 0) {
+    return mp_abs (b, c);
+  }
+  if (mp_iszero (a) == 0 && mp_iszero (b) == 1) {
+    return mp_abs (a, c);
+  }
+
+  /* optimized.  At this point if a == 0 then
+   * b must equal zero too
+   */
+  if (mp_iszero (a) == 1) {
+    mp_zero(c);
+    return MP_OKAY;
+  }
+
+  /* get copies of a and b we can modify */
+  if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
+    goto __U;
+  }
+
+  /* must be positive for the remainder of the algorithm */
+  u.sign = v.sign = MP_ZPOS;
+
+  /* B1.  Find the common power of two for u and v */
+  u_lsb = mp_cnt_lsb(&u);
+  v_lsb = mp_cnt_lsb(&v);
+  k     = MIN(u_lsb, v_lsb);
+
+  if (k > 0) {
+     /* divide the power of two out */
+     if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
+        goto __V;
+     }
+
+     if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
+        goto __V;
+     }
+  }
+
+  /* divide any remaining factors of two out */
+  if (u_lsb != k) {
+     if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
+        goto __V;
+     }
+  }
+
+  if (v_lsb != k) {
+     if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
+        goto __V;
+     }
+  }
+
+  while (mp_iszero(&v) == 0) {
+     /* make sure v is the largest */
+     if (mp_cmp_mag(&u, &v) == MP_GT) {
+        /* swap u and v to make sure v is >= u */
+        mp_exch(&u, &v);
+     }
+     
+     /* subtract smallest from largest */
+     if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
+        goto __V;
+     }
+     
+     /* Divide out all factors of two */
+     if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
+        goto __V;
+     } 
+  } 
+
+  /* multiply by 2**k which we divided out at the beginning */
+  if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
+     goto __V;
+  }
+  c->sign = MP_ZPOS;
+  res = MP_OKAY;
+__V:mp_clear (&u);
+__U:mp_clear (&v);
+  return res;
+}
+
+/* End: bn_mp_gcd.c */
+
+/* Start: bn_mp_get_int.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* get the lower 32-bits of an mp_int */
+unsigned long mp_get_int(mp_int * a) 
+{
+  int i;
+  unsigned long res;
+
+  if (a->used == 0) {
+     return 0;
+  }
+
+  /* get number of digits of the lsb we have to read */
+  i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1;
+
+  /* get most significant digit of result */
+  res = DIGIT(a,i);
+   
+  while (--i >= 0) {
+    res = (res << DIGIT_BIT) | DIGIT(a,i);
+  }
+
+  /* force result to 32-bits always so it is consistent on non 32-bit platforms */
+  return res & 0xFFFFFFFFUL;
+}
+
+/* End: bn_mp_get_int.c */
+
+/* Start: bn_mp_grow.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* grow as required */
+int mp_grow (mp_int * a, int size)
+{
+  int     i;
+  mp_digit *tmp;
+
+  /* if the alloc size is smaller alloc more ram */
+  if (a->alloc < size) {
+    /* ensure there are always at least MP_PREC digits extra on top */
+    size += (MP_PREC * 2) - (size % MP_PREC);
+
+    /* reallocate the array a->dp
+     *
+     * We store the return in a temporary variable
+     * in case the operation failed we don't want
+     * to overwrite the dp member of a.
+     */
+    tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
+    if (tmp == NULL) {
+      /* reallocation failed but "a" is still valid [can be freed] */
+      return MP_MEM;
+    }
+
+    /* reallocation succeeded so set a->dp */
+    a->dp = tmp;
+
+    /* zero excess digits */
+    i        = a->alloc;
+    a->alloc = size;
+    for (; i < a->alloc; i++) {
+      a->dp[i] = 0;
+    }
+  }
+  return MP_OKAY;
+}
+
+/* End: bn_mp_grow.c */
+
+/* Start: bn_mp_init.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* init a new bigint */
+int mp_init (mp_int * a)
+{
+  /* allocate memory required and clear it */
+  a->dp = OPT_CAST(mp_digit) XCALLOC (sizeof (mp_digit), MP_PREC);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the used to zero, allocated digits to the default precision
+   * and sign to positive */
+  a->used  = 0;
+  a->alloc = MP_PREC;
+  a->sign  = MP_ZPOS;
+
+  return MP_OKAY;
+}
+
+/* End: bn_mp_init.c */
+
+/* Start: bn_mp_init_copy.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* creates "a" then copies b into it */
+int mp_init_copy (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  if ((res = mp_init (a)) != MP_OKAY) {
+    return res;
+  }
+  return mp_copy (b, a);
+}
+
+/* End: bn_mp_init_copy.c */
+
+/* Start: bn_mp_init_multi.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+#include <stdarg.h>
+
+int 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;
+            
+            /* end the current list */
+            va_end(args);
+            
+            /* now start cleaning up */            
+            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. */
+}
+
+
+/* End: bn_mp_init_multi.c */
+
+/* Start: bn_mp_init_set.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b)
+{
+  int err;
+  if ((err = mp_init(a)) != MP_OKAY) {
+     return err;
+  }
+  mp_set(a, b);
+  return err;
+}
+
+/* End: bn_mp_init_set.c */
+
+/* Start: bn_mp_init_set_int.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* initialize and set a digit */
+int mp_init_set_int (mp_int * a, unsigned long b)
+{
+  int err;
+  if ((err = mp_init(a)) != MP_OKAY) {
+     return err;
+  }
+  return mp_set_int(a, b);
+}
+
+/* End: bn_mp_init_set_int.c */
+
+/* Start: bn_mp_init_size.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* init an mp_init for a given size */
+int mp_init_size (mp_int * a, int size)
+{
+  /* pad size so there are always extra digits */
+  size += (MP_PREC * 2) - (size % MP_PREC);	
+  
+  /* alloc mem */
+  a->dp = OPT_CAST(mp_digit) XCALLOC (sizeof (mp_digit), size);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+  a->used  = 0;
+  a->alloc = size;
+  a->sign  = MP_ZPOS;
+
+  return MP_OKAY;
+}
+
+/* End: bn_mp_init_size.c */
+
+/* Start: bn_mp_invmod.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* hac 14.61, pp608 */
+int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x, y, u, v, A, B, C, D;
+  int     res;
+
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if the modulus is odd we can use a faster routine instead */
+  if (mp_isodd (b) == 1) {
+    return fast_mp_invmod (a, b, c);
+  }
+  
+  /* init temps */
+  if ((res = mp_init_multi(&x, &y, &u, &v, 
+                           &A, &B, &C, &D, NULL)) != MP_OKAY) {
+     return res;
+  }
+
+  /* x = a, y = b */
+  if ((res = mp_copy (a, &x)) != MP_OKAY) {
+    goto __ERR;
+  }
+  if ((res = mp_copy (b, &y)) != MP_OKAY) {
+    goto __ERR;
+  }
+
+  /* 2. [modified] if x,y are both even then return an error! */
+  if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
+    res = MP_VAL;
+    goto __ERR;
+  }
+
+  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+    goto __ERR;
+  }
+  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+    goto __ERR;
+  }
+  mp_set (&A, 1);
+  mp_set (&D, 1);
+
+top:
+  /* 4.  while u is even do */
+  while (mp_iseven (&u) == 1) {
+    /* 4.1 u = u/2 */
+    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+      goto __ERR;
+    }
+    /* 4.2 if A or B is odd then */
+    if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
+      /* A = (A+y)/2, B = (B-x)/2 */
+      if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
+         goto __ERR;
+      }
+      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+         goto __ERR;
+      }
+    }
+    /* A = A/2, B = B/2 */
+    if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
+      goto __ERR;
+    }
+    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+      goto __ERR;
+    }
+  }
+
+  /* 5.  while v is even do */
+  while (mp_iseven (&v) == 1) {
+    /* 5.1 v = v/2 */
+    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+      goto __ERR;
+    }
+    /* 5.2 if C or D is odd then */
+    if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
+      /* C = (C+y)/2, D = (D-x)/2 */
+      if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
+         goto __ERR;
+      }
+      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+         goto __ERR;
+      }
+    }
+    /* C = C/2, D = D/2 */
+    if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
+      goto __ERR;
+    }
+    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+      goto __ERR;
+    }
+  }
+
+  /* 6.  if u >= v then */
+  if (mp_cmp (&u, &v) != MP_LT) {
+    /* u = u - v, A = A - C, B = B - D */
+    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+      goto __ERR;
+    }
+
+    if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
+      goto __ERR;
+    }
+
+    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+      goto __ERR;
+    }
+  } else {
+    /* v - v - u, C = C - A, D = D - B */
+    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+      goto __ERR;
+    }
+
+    if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
+      goto __ERR;
+    }
+
+    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+      goto __ERR;
+    }
+  }
+
+  /* if not zero goto step 4 */
+  if (mp_iszero (&u) == 0)
+    goto top;
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (mp_cmp_d (&v, 1) != MP_EQ) {
+    res = MP_VAL;
+    goto __ERR;
+  }
+
+  /* if its too low */
+  while (mp_cmp_d(&C, 0) == MP_LT) {
+      if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
+         goto __ERR;
+      }
+  }
+  
+  /* too big */
+  while (mp_cmp_mag(&C, b) != MP_LT) {
+      if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
+         goto __ERR;
+      }
+  }
+  
+  /* C is now the inverse */
+  mp_exch (&C, c);
+  res = MP_OKAY;
+__ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
+  return res;
+}
+
+/* End: bn_mp_invmod.c */
+
+/* Start: bn_mp_is_square.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* Check if remainders are possible squares - fast exclude non-squares */
+static const char rem_128[128] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
+};
+
+static const char rem_105[105] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
+};
+
+/* Store non-zero to ret if arg is square, and zero if not */
+int mp_is_square(mp_int *arg,int *ret) 
+{
+  int           res;
+  mp_digit      c;
+  mp_int        t;
+  unsigned long r;
+
+  /* Default to Non-square :) */
+  *ret = MP_NO; 
+
+  if (arg->sign == MP_NEG) {
+    return MP_VAL;
+  }
+
+  /* digits used?  (TSD) */
+  if (arg->used == 0) {
+     return MP_OKAY;
+  }
+
+  /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
+  if (rem_128[127 & DIGIT(arg,0)] == 1) {
+     return MP_OKAY;
+  }
+
+  /* Next check mod 105 (3*5*7) */
+  if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) {
+     return res;
+  }
+  if (rem_105[c] == 1) {
+     return MP_OKAY;
+  }
+
+  /* product of primes less than 2^31 */
+  if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) {
+     return res;
+  }
+  if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) {
+     goto ERR;
+  }
+  r = mp_get_int(&t);
+  /* Check for other prime modules, note it's not an ERROR but we must
+   * free "t" so the easiest way is to goto ERR.  We know that res
+   * is already equal to MP_OKAY from the mp_mod call 
+   */ 
+  if ( (1L<<(r%11)) & 0x5C4L )             goto ERR;
+  if ( (1L<<(r%13)) & 0x9E4L )             goto ERR;
+  if ( (1L<<(r%17)) & 0x5CE8L )            goto ERR;
+  if ( (1L<<(r%19)) & 0x4F50CL )           goto ERR;
+  if ( (1L<<(r%23)) & 0x7ACCA0L )          goto ERR;
+  if ( (1L<<(r%29)) & 0xC2EDD0CL )         goto ERR;
+  if ( (1L<<(r%31)) & 0x6DE2B848L )        goto ERR;
+
+  /* Final check - is sqr(sqrt(arg)) == arg ? */
+  if ((res = mp_sqrt(arg,&t)) != MP_OKAY) {
+     goto ERR;
+  }
+  if ((res = mp_sqr(&t,&t)) != MP_OKAY) {
+     goto ERR;
+  }
+
+  *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO;
+ERR:mp_clear(&t);
+  return res;
+}
+
+/* End: bn_mp_is_square.c */
+
+/* Start: bn_mp_jacobi.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* computes the jacobi c = (a | n) (or Legendre if n is prime)
+ * HAC pp. 73 Algorithm 2.149
+ */
+int mp_jacobi (mp_int * a, mp_int * p, int *c)
+{
+  mp_int  a1, p1;
+  int     k, s, r, res;
+  mp_digit residue;
+
+  /* if p <= 0 return MP_VAL */
+  if (mp_cmp_d(p, 0) != MP_GT) {
+     return MP_VAL;
+  }
+
+  /* step 1.  if a == 0, return 0 */
+  if (mp_iszero (a) == 1) {
+    *c = 0;
+    return MP_OKAY;
+  }
+
+  /* step 2.  if a == 1, return 1 */
+  if (mp_cmp_d (a, 1) == MP_EQ) {
+    *c = 1;
+    return MP_OKAY;
+  }
+
+  /* default */
+  s = 0;
+
+  /* step 3.  write a = a1 * 2**k  */
+  if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init (&p1)) != MP_OKAY) {
+    goto __A1;
+  }
+
+  /* divide out larger power of two */
+  k = mp_cnt_lsb(&a1);
+  if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) {
+     goto __P1;
+  }
+
+  /* step 4.  if e is even set s=1 */
+  if ((k & 1) == 0) {
+    s = 1;
+  } else {
+    /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
+    residue = p->dp[0] & 7;
+
+    if (residue == 1 || residue == 7) {
+      s = 1;
+    } else if (residue == 3 || residue == 5) {
+      s = -1;
+    }
+  }
+
+  /* step 5.  if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
+  if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
+    s = -s;
+  }
+
+  /* if a1 == 1 we're done */
+  if (mp_cmp_d (&a1, 1) == MP_EQ) {
+    *c = s;
+  } else {
+    /* n1 = n mod a1 */
+    if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) {
+      goto __P1;
+    }
+    if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) {
+      goto __P1;
+    }
+    *c = s * r;
+  }
+
+  /* done */
+  res = MP_OKAY;
+__P1:mp_clear (&p1);
+__A1:mp_clear (&a1);
+  return res;
+}
+
+/* End: bn_mp_jacobi.c */
+
+/* Start: bn_mp_karatsuba_mul.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* c = |a| * |b| using Karatsuba Multiplication using 
+ * three half size multiplications
+ *
+ * Let B represent the radix [e.g. 2**DIGIT_BIT] and 
+ * let n represent half of the number of digits in 
+ * the min(a,b)
+ *
+ * a = a1 * B**n + a0
+ * b = b1 * B**n + b0
+ *
+ * Then, a * b => 
+   a1b1 * B**2n + ((a1 - a0)(b1 - b0) + a0b0 + a1b1) * B + a0b0
+ *
+ * Note that a1b1 and a0b0 are used twice and only need to be 
+ * computed once.  So in total three half size (half # of 
+ * digit) multiplications are performed, a0b0, a1b1 and 
+ * (a1-b1)(a0-b0)
+ *
+ * Note that a multiplication of half the digits requires
+ * 1/4th the number of single precision multiplications so in 
+ * total after one call 25% of the single precision multiplications 
+ * are saved.  Note also that the call to mp_mul can end up back 
+ * in this function if the a0, a1, b0, or b1 are above the threshold.  
+ * This is known as divide-and-conquer and leads to the famous 
+ * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than 
+ * the standard O(N**2) that the baseline/comba methods use.  
+ * Generally though the overhead of this method doesn't pay off 
+ * until a certain size (N ~ 80) is reached.
+ */
+int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x0, x1, y0, y1, t1, x0y0, x1y1;
+  int     B, err;
+
+  /* default the return code to an error */
+  err = MP_MEM;
+
+  /* min # of digits */
+  B = MIN (a->used, b->used);
+
+  /* now divide in two */
+  B = B >> 1;
+
+  /* init copy all the temps */
+  if (mp_init_size (&x0, B) != MP_OKAY)
+    goto ERR;
+  if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+    goto X0;
+  if (mp_init_size (&y0, B) != MP_OKAY)
+    goto X1;
+  if (mp_init_size (&y1, b->used - B) != MP_OKAY)
+    goto Y0;
+
+  /* init temps */
+  if (mp_init_size (&t1, B * 2) != MP_OKAY)
+    goto Y1;
+  if (mp_init_size (&x0y0, B * 2) != MP_OKAY)
+    goto T1;
+  if (mp_init_size (&x1y1, B * 2) != MP_OKAY)
+    goto X0Y0;
+
+  /* now shift the digits */
+  x0.sign = x1.sign = a->sign;
+  y0.sign = y1.sign = b->sign;
+
+  x0.used = y0.used = B;
+  x1.used = a->used - B;
+  y1.used = b->used - B;
+
+  {
+    register int x;
+    register mp_digit *tmpa, *tmpb, *tmpx, *tmpy;
+
+    /* we copy the digits directly instead of using higher level functions
+     * since we also need to shift the digits
+     */
+    tmpa = a->dp;
+    tmpb = b->dp;
+
+    tmpx = x0.dp;
+    tmpy = y0.dp;
+    for (x = 0; x < B; x++) {
+      *tmpx++ = *tmpa++;
+      *tmpy++ = *tmpb++;
+    }
+
+    tmpx = x1.dp;
+    for (x = B; x < a->used; x++) {
+      *tmpx++ = *tmpa++;
+    }
+
+    tmpy = y1.dp;
+    for (x = B; x < b->used; x++) {
+      *tmpy++ = *tmpb++;
+    }
+  }
+
+  /* only need to clamp the lower words since by definition the 
+   * upper words x1/y1 must have a known number of digits
+   */
+  mp_clamp (&x0);
+  mp_clamp (&y0);
+
+  /* now calc the products x0y0 and x1y1 */
+  /* after this x0 is no longer required, free temp [x0==t2]! */
+  if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY)  
+    goto X1Y1;          /* x0y0 = x0*y0 */
+  if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY)
+    goto X1Y1;          /* x1y1 = x1*y1 */
+
+  /* now calc x1-x0 and y1-y0 */
+  if (mp_sub (&x1, &x0, &t1) != MP_OKAY)
+    goto X1Y1;          /* t1 = x1 - x0 */
+  if (mp_sub (&y1, &y0, &x0) != MP_OKAY)
+    goto X1Y1;          /* t2 = y1 - y0 */
+  if (mp_mul (&t1, &x0, &t1) != MP_OKAY)
+    goto X1Y1;          /* t1 = (x1 - x0) * (y1 - y0) */
+
+  /* add x0y0 */
+  if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY)
+    goto X1Y1;          /* t2 = x0y0 + x1y1 */
+  if (mp_sub (&x0, &t1, &t1) != MP_OKAY)
+    goto X1Y1;          /* t1 = x0y0 + x1y1 - (x1-x0)*(y1-y0) */
+
+  /* shift by B */
+  if (mp_lshd (&t1, B) != MP_OKAY)
+    goto X1Y1;          /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
+  if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
+    goto X1Y1;          /* x1y1 = x1y1 << 2*B */
+
+  if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
+    goto X1Y1;          /* t1 = x0y0 + t1 */
+  if (mp_add (&t1, &x1y1, c) != MP_OKAY)
+    goto X1Y1;          /* t1 = x0y0 + t1 + x1y1 */
+
+  /* Algorithm succeeded set the return code to MP_OKAY */
+  err = MP_OKAY;
+
+X1Y1:mp_clear (&x1y1);
+X0Y0:mp_clear (&x0y0);
+T1:mp_clear (&t1);
+Y1:mp_clear (&y1);
+Y0:mp_clear (&y0);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+  return err;
+}
+
+/* End: bn_mp_karatsuba_mul.c */
+
+/* Start: bn_mp_karatsuba_sqr.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* Karatsuba squaring, computes b = a*a using three 
+ * half size squarings
+ *
+ * See comments of mp_karatsuba_mul for details.  It 
+ * is essentially the same algorithm but merely 
+ * tuned to perform recursive squarings.
+ */
+int mp_karatsuba_sqr (mp_int * a, mp_int * b)
+{
+  mp_int  x0, x1, t1, t2, x0x0, x1x1;
+  int     B, err;
+
+  err = MP_MEM;
+
+  /* min # of digits */
+  B = a->used;
+
+  /* now divide in two */
+  B = B >> 1;
+
+  /* init copy all the temps */
+  if (mp_init_size (&x0, B) != MP_OKAY)
+    goto ERR;
+  if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+    goto X0;
+
+  /* init temps */
+  if (mp_init_size (&t1, a->used * 2) != MP_OKAY)
+    goto X1;
+  if (mp_init_size (&t2, a->used * 2) != MP_OKAY)
+    goto T1;
+  if (mp_init_size (&x0x0, B * 2) != MP_OKAY)
+    goto T2;
+  if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY)
+    goto X0X0;
+
+  {
+    register int x;
+    register mp_digit *dst, *src;
+
+    src = a->dp;
+
+    /* now shift the digits */
+    dst = x0.dp;
+    for (x = 0; x < B; x++) {
+      *dst++ = *src++;
+    }
+
+    dst = x1.dp;
+    for (x = B; x < a->used; x++) {
+      *dst++ = *src++;
+    }
+  }
+
+  x0.used = B;
+  x1.used = a->used - B;
+
+  mp_clamp (&x0);
+
+  /* now calc the products x0*x0 and x1*x1 */
+  if (mp_sqr (&x0, &x0x0) != MP_OKAY)
+    goto X1X1;           /* x0x0 = x0*x0 */
+  if (mp_sqr (&x1, &x1x1) != MP_OKAY)
+    goto X1X1;           /* x1x1 = x1*x1 */
+
+  /* now calc (x1-x0)**2 */
+  if (mp_sub (&x1, &x0, &t1) != MP_OKAY)
+    goto X1X1;           /* t1 = x1 - x0 */
+  if (mp_sqr (&t1, &t1) != MP_OKAY)
+    goto X1X1;           /* t1 = (x1 - x0) * (x1 - x0) */
+
+  /* add x0y0 */
+  if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY)
+    goto X1X1;           /* t2 = x0x0 + x1x1 */
+  if (mp_sub (&t2, &t1, &t1) != MP_OKAY)
+    goto X1X1;           /* t1 = x0x0 + x1x1 - (x1-x0)*(x1-x0) */
+
+  /* shift by B */
+  if (mp_lshd (&t1, B) != MP_OKAY)
+    goto X1X1;           /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
+  if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
+    goto X1X1;           /* x1x1 = x1x1 << 2*B */
+
+  if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
+    goto X1X1;           /* t1 = x0x0 + t1 */
+  if (mp_add (&t1, &x1x1, b) != MP_OKAY)
+    goto X1X1;           /* t1 = x0x0 + t1 + x1x1 */
+
+  err = MP_OKAY;
+
+X1X1:mp_clear (&x1x1);
+X0X0:mp_clear (&x0x0);
+T2:mp_clear (&t2);
+T1:mp_clear (&t1);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+  return err;
+}
+
+/* End: bn_mp_karatsuba_sqr.c */
+
+/* Start: bn_mp_lcm.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* computes least common multiple as |a*b|/(a, b) */
+int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res;
+  mp_int  t1, t2;
+
+
+  if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) {
+    return res;
+  }
+
+  /* t1 = get the GCD of the two inputs */
+  if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
+    goto __T;
+  }
+
+  /* divide the smallest by the GCD */
+  if (mp_cmp_mag(a, b) == MP_LT) {
+     /* store quotient in t2 such that t2 * b is the LCM */
+     if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
+        goto __T;
+     }
+     res = mp_mul(b, &t2, c);
+  } else {
+     /* store quotient in t2 such that t2 * a is the LCM */
+     if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
+        goto __T;
+     }
+     res = mp_mul(a, &t2, c);
+  }
+
+  /* fix the sign to positive */
+  c->sign = MP_ZPOS;
+
+__T:
+  mp_clear_multi (&t1, &t2, NULL);
+  return res;
+}
+
+/* End: bn_mp_lcm.c */
+
+/* Start: bn_mp_lshd.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* shift left a certain amount of digits */
+int mp_lshd (mp_int * a, int b)
+{
+  int     x, res;
+
+  /* if its less than zero return */
+  if (b <= 0) {
+    return MP_OKAY;
+  }
+
+  /* grow to fit the new digits */
+  if (a->alloc < a->used + b) {
+     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  {
+    register mp_digit *top, *bottom;
+
+    /* increment the used by the shift amount then copy upwards */
+    a->used += b;
+
+    /* top */
+    top = a->dp + a->used - 1;
+
+    /* base */
+    bottom = a->dp + a->used - 1 - b;
+
+    /* much like mp_rshd this is implemented using a sliding window
+     * except the window goes the otherway around.  Copying from
+     * the bottom to the top.  see bn_mp_rshd.c for more info.
+     */
+    for (x = a->used - 1; x >= b; x--) {
+      *top-- = *bottom--;
+    }
+
+    /* zero the lower digits */
+    top = a->dp;
+    for (x = 0; x < b; x++) {
+      *top++ = 0;
+    }
+  }
+  return MP_OKAY;
+}
+
+/* End: bn_mp_lshd.c */
+
+/* Start: bn_mp_mod.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* c = a mod b, 0 <= c < b */
+int
+mp_mod (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  t;
+  int     res;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  if (t.sign != b->sign) {
+    res = mp_add (b, &t, c);
+  } else {
+    res = MP_OKAY;
+    mp_exch (&t, c);
+  }
+
+  mp_clear (&t);
+  return res;
+}
+
+/* End: bn_mp_mod.c */
+
+/* Start: bn_mp_mod_2d.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* calc a value mod 2**b */
+int
+mp_mod_2d (mp_int * a, int b, mp_int * c)
+{
+  int     x, res;
+
+  /* if b is <= 0 then zero the int */
+  if (b <= 0) {
+    mp_zero (c);
+    return MP_OKAY;
+  }
+
+  /* if the modulus is larger than the value than return */
+  if (b > (int) (a->used * DIGIT_BIT)) {
+    res = mp_copy (a, c);
+    return res;
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    return res;
+  }
+
+  /* zero digits above the last digit of the modulus */
+  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+    c->dp[x] = 0;
+  }
+  /* clear the digit that is not completely outside/inside the modulus */
+  c->dp[b / DIGIT_BIT] &=
+    (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+/* End: bn_mp_mod_2d.c */
+
+/* Start: bn_mp_mod_d.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+int
+mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
+{
+  return mp_div_d(a, b, NULL, c);
+}
+
+/* End: bn_mp_mod_d.c */
+
+/* Start: bn_mp_montgomery_calc_normalization.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* calculates a = B^n mod b for Montgomery reduction
+ * Where B is the base [e.g. 2^DIGIT_BIT].
+ * B^n mod b is computed by first computing
+ * A = B^(n-1) which doesn't require a reduction but a simple OR.
+ * then C = A * B = B^n is computed by performing upto DIGIT_BIT
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally upto just under
+ * the leading bit of b.  This saves alot of multiple precision shifting.
+ */
+int
+mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+  int     x, bits, res;
+
+  /* how many bits of last digit does b use */
+  bits = mp_count_bits (b) % DIGIT_BIT;
+
+  /* compute A = B^(n-1) * 2^(bits-1) */
+  if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* now compute C = A * B mod b */
+  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+    if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+      return res;
+    }
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+        return res;
+      }
+    }
+  }
+
+  return MP_OKAY;
+}
+
+/* End: bn_mp_montgomery_calc_normalization.c */
+
+/* Start: bn_mp_montgomery_reduce.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction */
+int
+mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+  int     ix, res, digs;
+  mp_digit mu;
+
+  /* can the fast reduction [comba] method be used?
+   *
+   * Note that unlike in mp_mul you're safely allowed *less*
+   * than the available columns [255 per default] since carries
+   * are fixed up in the inner loop.
+   */
+  digs = n->used * 2 + 1;
+  if ((digs < MP_WARRAY) &&
+      n->used <
+      (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_mp_montgomery_reduce (x, n, rho);
+  }
+
+  /* grow the input as required */
+  if (x->alloc < digs) {
+    if ((res = mp_grow (x, digs)) != MP_OKAY) {
+      return res;
+    }
+  }
+  x->used = digs;
+
+  for (ix = 0; ix < n->used; ix++) {
+    /* mu = ai * rho mod b
+     *
+     * The value of rho must be precalculated via
+     * bn_mp_montgomery_setup() such that
+     * it equals -1/n0 mod b this allows the
+     * following inner loop to reduce the
+     * input one digit at a time
+     */
+    mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
+
+    /* a = a + mu * m * b**i */
+    {
+      register int iy;
+      register mp_digit *tmpn, *tmpx, u;
+      register mp_word r;
+
+      /* alias for digits of the modulus */
+      tmpn = n->dp;
+
+      /* alias for the digits of x [the input] */
+      tmpx = x->dp + ix;
+
+      /* set the carry to zero */
+      u = 0;
+
+      /* Multiply and add in place */
+      for (iy = 0; iy < n->used; iy++) {
+        /* compute product and sum */
+        r       = ((mp_word)mu) * ((mp_word)*tmpn++) +
+                  ((mp_word) u) + ((mp_word) * tmpx);
+
+        /* get carry */
+        u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+        /* fix digit */
+        *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
+      }
+      /* At this point the ix'th digit of x should be zero */
+
+
+      /* propagate carries upwards as required*/
+      while (u) {
+        *tmpx   += u;
+        u        = *tmpx >> DIGIT_BIT;
+        *tmpx++ &= MP_MASK;
+      }
+    }
+  }
+
+  /* at this point the n.used'th least
+   * significant digits of x are all zero
+   * which means we can shift x to the
+   * right by n.used digits and the
+   * residue is unchanged.
+   */
+
+  /* x = x/b**n.used */
+  mp_clamp(x);
+  mp_rshd (x, n->used);
+
+  /* if x >= n then x = x - n */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    return s_mp_sub (x, n, x);
+  }
+
+  return MP_OKAY;
+}
+
+/* End: bn_mp_montgomery_reduce.c */
+
+/* Start: bn_mp_montgomery_setup.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* setups the montgomery reduction stuff */
+int
+mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+  mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
+ *                    =>  2*X*A - X*X*A*A = 1
+ *                    =>  2*(1) - (1)     = 1
+ */
+  b = n->dp[0];
+
+  if ((b & 1) == 0) {
+    return MP_VAL;
+  }
+
+  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
+#if !defined(MP_8BIT)
+  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
+#endif
+#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
+  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
+#endif
+#ifdef MP_64BIT
+  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
+#endif
+
+  /* rho = -1/m mod b */
+  *rho = (((mp_digit) 1 << ((mp_digit) DIGIT_BIT)) - x) & MP_MASK;
+
+  return MP_OKAY;
+}
+
+/* End: bn_mp_montgomery_setup.c */
+
+/* Start: bn_mp_mul.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* high level multiplication (handles sign) */
+int mp_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, neg;
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+
+  /* use Toom-Cook? */
+  if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
+    res = mp_toom_mul(a, b, c);
+  /* use Karatsuba? */
+  } else if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
+    res = mp_karatsuba_mul (a, b, c);
+  } else {
+    /* can we use the fast multiplier?
+     *
+     * The fast multiplier can be used if the output will 
+     * have less than MP_WARRAY digits and the number of 
+     * digits won't affect carry propagation
+     */
+    int     digs = a->used + b->used + 1;
+
+    if ((digs < MP_WARRAY) &&
+        MIN(a->used, b->used) <= 
+        (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+      res = fast_s_mp_mul_digs (a, b, c, digs);
+    } else {
+      res = s_mp_mul (a, b, c);
+    }
+  }
+  c->sign = neg;
+  return res;
+}
+
+/* End: bn_mp_mul.c */
+
+/* Start: bn_mp_mul_2.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* b = a*2 */
+int mp_mul_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* grow to accomodate result */
+  if (b->alloc < a->used + 1) {
+    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* alias for source */
+    tmpa = a->dp;
+    
+    /* alias for dest */
+    tmpb = b->dp;
+
+    /* carry */
+    r = 0;
+    for (x = 0; x < a->used; x++) {
+    
+      /* get what will be the *next* carry bit from the 
+       * MSB of the current digit 
+       */
+      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+      
+      /* now shift up this digit, add in the carry [from the previous] */
+      *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+      
+      /* copy the carry that would be from the source 
+       * digit into the next iteration 
+       */
+      r = rr;
+    }
+
+    /* new leading digit? */
+    if (r != 0) {
+      /* add a MSB which is always 1 at this point */
+      *tmpb = 1;
+      ++(b->used);
+    }
+
+    /* now zero any excess digits on the destination 
+     * that we didn't write to 
+     */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+
+/* End: bn_mp_mul_2.c */
+
+/* Start: bn_mp_mul_2d.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* shift left by a certain bit count */
+int mp_mul_2d (mp_int * a, int b, mp_int * c)
+{
+  mp_digit d;
+  int      res;
+
+  /* copy */
+  if (a != c) {
+     if ((res = mp_copy (a, c)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
+     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  d = (mp_digit) (b % DIGIT_BIT);
+  if (d != 0) {
+    register mp_digit *tmpc, shift, mask, r, rr;
+    register int x;
+
+    /* bitmask for carries */
+    mask = (((mp_digit)1) << d) - 1;
+
+    /* shift for msbs */
+    shift = DIGIT_BIT - d;
+
+    /* alias */
+    tmpc = c->dp;
+
+    /* carry */
+    r    = 0;
+    for (x = 0; x < c->used; x++) {
+      /* get the higher bits of the current word */
+      rr = (*tmpc >> shift) & mask;
+
+      /* shift the current word and OR in the carry */
+      *tmpc = ((*tmpc << d) | r) & MP_MASK;
+      ++tmpc;
+
+      /* set the carry to the carry bits of the current word */
+      r = rr;
+    }
+    
+    /* set final carry */
+    if (r != 0) {
+       c->dp[(c->used)++] = r;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+/* End: bn_mp_mul_2d.c */
+
+/* Start: bn_mp_mul_d.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* multiply by a digit */
+int
+mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit u, *tmpa, *tmpc;
+  mp_word  r;
+  int      ix, res, olduse;
+
+  /* make sure c is big enough to hold a*b */
+  if (c->alloc < a->used + 1) {
+    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get the original destinations used count */
+  olduse = c->used;
+
+  /* set the sign */
+  c->sign = a->sign;
+
+  /* alias for a->dp [source] */
+  tmpa = a->dp;
+
+  /* alias for c->dp [dest] */
+  tmpc = c->dp;
+
+  /* zero carry */
+  u = 0;
+
+  /* compute columns */
+  for (ix = 0; ix < a->used; ix++) {
+    /* compute product and carry sum for this term */
+    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+    /* mask off higher bits to get a single digit */
+    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* send carry into next iteration */
+    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+  }
+
+  /* store final carry [if any] */
+  *tmpc++ = u;
+
+  /* now zero digits above the top */
+  while (ix++ < olduse) {
+     *tmpc++ = 0;
+  }
+
+  /* set used count */
+  c->used = a->used + 1;
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+
+/* End: bn_mp_mul_d.c */
+
+/* Start: bn_mp_mulmod.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* d = a * b (mod c) */
+int
+mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+
+/* End: bn_mp_mulmod.c */
+
+/* Start: bn_mp_n_root.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* find the n'th root of an integer 
+ *
+ * Result found such that (c)**b <= a and (c+1)**b > a 
+ *
+ * This algorithm uses Newton's approximation 
+ * x[i+1] = x[i] - f(x[i])/f'(x[i]) 
+ * which will find the root in log(N) time where 
+ * each step involves a fair bit.  This is not meant to 
+ * find huge roots [square and cube, etc].
+ */
+int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_int  t1, t2, t3;
+  int     res, neg;
+
+  /* input must be positive if b is even */
+  if ((b & 1) == 0 && a->sign == MP_NEG) {
+    return MP_VAL;
+  }
+
+  if ((res = mp_init (&t1)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init (&t2)) != MP_OKAY) {
+    goto __T1;
+  }
+
+  if ((res = mp_init (&t3)) != MP_OKAY) {
+    goto __T2;
+  }
+
+  /* if a is negative fudge the sign but keep track */
+  neg     = a->sign;
+  a->sign = MP_ZPOS;
+
+  /* t2 = 2 */
+  mp_set (&t2, 2);
+
+  do {
+    /* t1 = t2 */
+    if ((res = mp_copy (&t2, &t1)) != MP_OKAY) {
+      goto __T3;
+    }
+
+    /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
+    
+    /* t3 = t1**(b-1) */
+    if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) {   
+      goto __T3;
+    }
+
+    /* numerator */
+    /* t2 = t1**b */
+    if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) {    
+      goto __T3;
+    }
+
+    /* t2 = t1**b - a */
+    if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) {  
+      goto __T3;
+    }
+
+    /* denominator */
+    /* t3 = t1**(b-1) * b  */
+    if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) {    
+      goto __T3;
+    }
+
+    /* t3 = (t1**b - a)/(b * t1**(b-1)) */
+    if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) {  
+      goto __T3;
+    }
+
+    if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) {
+      goto __T3;
+    }
+  }  while (mp_cmp (&t1, &t2) != MP_EQ);
+
+  /* result can be off by a few so check */
+  for (;;) {
+    if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) {
+      goto __T3;
+    }
+
+    if (mp_cmp (&t2, a) == MP_GT) {
+      if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) {
+         goto __T3;
+      }
+    } else {
+      break;
+    }
+  }
+
+  /* reset the sign of a first */
+  a->sign = neg;
+
+  /* set the result */
+  mp_exch (&t1, c);
+
+  /* set the sign of the result */
+  c->sign = neg;
+
+  res = MP_OKAY;
+
+__T3:mp_clear (&t3);
+__T2:mp_clear (&t2);
+__T1:mp_clear (&t1);
+  return res;
+}
+
+/* End: bn_mp_n_root.c */
+
+/* Start: bn_mp_neg.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* b = -a */
+int mp_neg (mp_int * a, mp_int * b)
+{
+  int     res;
+  if ((res = mp_copy (a, b)) != MP_OKAY) {
+    return res;
+  }
+  if (mp_iszero(b) != MP_YES) {
+     b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+  }
+  return MP_OKAY;
+}
+
+/* End: bn_mp_neg.c */
+
+/* Start: bn_mp_or.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* OR two ints together */
+int mp_or (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, ix, px;
+  mp_int  t, *x;
+
+  if (a->used > b->used) {
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+      return res;
+    }
+    px = b->used;
+    x = b;
+  } else {
+    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+      return res;
+    }
+    px = a->used;
+    x = a;
+  }
+
+  for (ix = 0; ix < px; ix++) {
+    t.dp[ix] |= x->dp[ix];
+  }
+  mp_clamp (&t);
+  mp_exch (c, &t);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+/* End: bn_mp_or.c */
+
+/* Start: bn_mp_prime_fermat.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* performs one Fermat test.
+ * 
+ * If "a" were prime then b**a == b (mod a) since the order of
+ * the multiplicative sub-group would be phi(a) = a-1.  That means
+ * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
+ *
+ * Sets result to 1 if the congruence holds, or zero otherwise.
+ */
+int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
+{
+  mp_int  t;
+  int     err;
+
+  /* default to composite  */
+  *result = MP_NO;
+
+  /* ensure b > 1 */
+  if (mp_cmp_d(b, 1) != MP_GT) {
+     return MP_VAL;
+  }
+
+  /* init t */
+  if ((err = mp_init (&t)) != MP_OKAY) {
+    return err;
+  }
+
+  /* compute t = b**a mod a */
+  if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) {
+    goto __T;
+  }
+
+  /* is it equal to b? */
+  if (mp_cmp (&t, b) == MP_EQ) {
+    *result = MP_YES;
+  }
+
+  err = MP_OKAY;
+__T:mp_clear (&t);
+  return err;
+}
+
+/* End: bn_mp_prime_fermat.c */
+
+/* Start: bn_mp_prime_is_divisible.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* determines if an integers is divisible by one 
+ * of the first PRIME_SIZE primes or not
+ *
+ * sets result to 0 if not, 1 if yes
+ */
+int mp_prime_is_divisible (mp_int * a, int *result)
+{
+  int     err, ix;
+  mp_digit res;
+
+  /* default to not */
+  *result = MP_NO;
+
+  for (ix = 0; ix < PRIME_SIZE; ix++) {
+    /* what is a mod __prime_tab[ix] */
+    if ((err = mp_mod_d (a, __prime_tab[ix], &res)) != MP_OKAY) {
+      return err;
+    }
+
+    /* is the residue zero? */
+    if (res == 0) {
+      *result = MP_YES;
+      return MP_OKAY;
+    }
+  }
+
+  return MP_OKAY;
+}
+
+/* End: bn_mp_prime_is_divisible.c */
+
+/* Start: bn_mp_prime_is_prime.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* performs a variable number of rounds of Miller-Rabin
+ *
+ * Probability of error after t rounds is no more than
+ * (1/4)^t when 1 <= t <= PRIME_SIZE
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime (mp_int * a, int t, int *result)
+{
+  mp_int  b;
+  int     ix, err, res;
+
+  /* default to no */
+  *result = MP_NO;
+
+  /* valid value of t? */
+  if (t <= 0 || t > PRIME_SIZE) {
+    return MP_VAL;
+  }
+
+  /* is the input equal to one of the primes in the table? */
+  for (ix = 0; ix < PRIME_SIZE; ix++) {
+      if (mp_cmp_d(a, __prime_tab[ix]) == MP_EQ) {
+         *result = 1;
+         return MP_OKAY;
+      }
+  }
+
+  /* first perform trial division */
+  if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
+    return err;
+  }
+
+  /* return if it was trivially divisible */
+  if (res == MP_YES) {
+    return MP_OKAY;
+  }
+
+  /* now perform the miller-rabin rounds */
+  if ((err = mp_init (&b)) != MP_OKAY) {
+    return err;
+  }
+
+  for (ix = 0; ix < t; ix++) {
+    /* set the prime */
+    mp_set (&b, __prime_tab[ix]);
+
+    if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
+      goto __B;
+    }
+
+    if (res == MP_NO) {
+      goto __B;
+    }
+  }
+
+  /* passed the test */
+  *result = MP_YES;
+__B:mp_clear (&b);
+  return err;
+}
+
+/* End: bn_mp_prime_is_prime.c */
+
+/* Start: bn_mp_prime_miller_rabin.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* Miller-Rabin test of "a" to the base of "b" as described in 
+ * HAC pp. 139 Algorithm 4.24
+ *
+ * Sets result to 0 if definitely composite or 1 if probably prime.
+ * Randomly the chance of error is no more than 1/4 and often 
+ * very much lower.
+ */
+int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
+{
+  mp_int  n1, y, r;
+  int     s, j, err;
+
+  /* default */
+  *result = MP_NO;
+
+  /* ensure b > 1 */
+  if (mp_cmp_d(b, 1) != MP_GT) {
+     return MP_VAL;
+  }     
+
+  /* get n1 = a - 1 */
+  if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
+    return err;
+  }
+  if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
+    goto __N1;
+  }
+
+  /* set 2**s * r = n1 */
+  if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
+    goto __N1;
+  }
+
+  /* count the number of least significant bits
+   * which are zero
+   */
+  s = mp_cnt_lsb(&r);
+
+  /* now divide n - 1 by 2**s */
+  if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
+    goto __R;
+  }
+
+  /* compute y = b**r mod a */
+  if ((err = mp_init (&y)) != MP_OKAY) {
+    goto __R;
+  }
+  if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
+    goto __Y;
+  }
+
+  /* if y != 1 and y != n1 do */
+  if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
+    j = 1;
+    /* while j <= s-1 and y != n1 */
+    while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
+      if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
+         goto __Y;
+      }
+
+      /* if y == 1 then composite */
+      if (mp_cmp_d (&y, 1) == MP_EQ) {
+         goto __Y;
+      }
+
+      ++j;
+    }
+
+    /* if y != n1 then composite */
+    if (mp_cmp (&y, &n1) != MP_EQ) {
+      goto __Y;
+    }
+  }
+
+  /* probably prime now */
+  *result = MP_YES;
+__Y:mp_clear (&y);
+__R:mp_clear (&r);
+__N1:mp_clear (&n1);
+  return err;
+}
+
+/* End: bn_mp_prime_miller_rabin.c */
+
+/* Start: bn_mp_prime_next_prime.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
+{
+   int      err, res, x, y;
+   mp_digit res_tab[PRIME_SIZE], step, kstep;
+   mp_int   b;
+
+   /* ensure t is valid */
+   if (t <= 0 || t > PRIME_SIZE) {
+      return MP_VAL;
+   }
+
+   /* force positive */
+   a->sign = MP_ZPOS;
+
+   /* simple algo if a is less than the largest prime in the table */
+   if (mp_cmp_d(a, __prime_tab[PRIME_SIZE-1]) == MP_LT) {
+      /* find which prime it is bigger than */
+      for (x = PRIME_SIZE - 2; x >= 0; x--) {
+          if (mp_cmp_d(a, __prime_tab[x]) != MP_LT) {
+             if (bbs_style == 1) {
+                /* ok we found a prime smaller or
+                 * equal [so the next is larger]
+                 *
+                 * however, the prime must be
+                 * congruent to 3 mod 4
+                 */
+                if ((__prime_tab[x + 1] & 3) != 3) {
+                   /* scan upwards for a prime congruent to 3 mod 4 */
+                   for (y = x + 1; y < PRIME_SIZE; y++) {
+                       if ((__prime_tab[y] & 3) == 3) {
+                          mp_set(a, __prime_tab[y]);
+                          return MP_OKAY;
+                       }
+                   }
+                }
+             } else {
+                mp_set(a, __prime_tab[x + 1]);
+                return MP_OKAY;
+             }
+          }
+      }
+      /* at this point a maybe 1 */
+      if (mp_cmp_d(a, 1) == MP_EQ) {
+         mp_set(a, 2);
+         return MP_OKAY;
+      }
+      /* fall through to the sieve */
+   }
+
+   /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */
+   if (bbs_style == 1) {
+      kstep   = 4;
+   } else {
+      kstep   = 2;
+   }
+
+   /* at this point we will use a combination of a sieve and Miller-Rabin */
+
+   if (bbs_style == 1) {
+      /* if a mod 4 != 3 subtract the correct value to make it so */
+      if ((a->dp[0] & 3) != 3) {
+         if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; };
+      }
+   } else {
+      if (mp_iseven(a) == 1) {
+         /* force odd */
+         if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) {
+            return err;
+         }
+      }
+   }
+
+   /* generate the restable */
+   for (x = 1; x < PRIME_SIZE; x++) {
+      if ((err = mp_mod_d(a, __prime_tab[x], res_tab + x)) != MP_OKAY) {
+         return err;
+      }
+   }
+
+   /* init temp used for Miller-Rabin Testing */
+   if ((err = mp_init(&b)) != MP_OKAY) {
+      return err;
+   }
+
+   for (;;) {
+      /* skip to the next non-trivially divisible candidate */
+      step = 0;
+      do {
+         /* y == 1 if any residue was zero [e.g. cannot be prime] */
+         y     =  0;
+
+         /* increase step to next candidate */
+         step += kstep;
+
+         /* compute the new residue without using division */
+         for (x = 1; x < PRIME_SIZE; x++) {
+             /* add the step to each residue */
+             res_tab[x] += kstep;
+
+             /* subtract the modulus [instead of using division] */
+             if (res_tab[x] >= __prime_tab[x]) {
+                res_tab[x]  -= __prime_tab[x];
+             }
+
+             /* set flag if zero */
+             if (res_tab[x] == 0) {
+                y = 1;
+             }
+         }
+      } while (y == 1 && step < ((((mp_digit)1)<<DIGIT_BIT) - kstep));
+
+      /* add the step */
+      if ((err = mp_add_d(a, step, a)) != MP_OKAY) {
+         goto __ERR;
+      }
+
+      /* if didn't pass sieve and step == MAX then skip test */
+      if (y == 1 && step >= ((((mp_digit)1)<<DIGIT_BIT) - kstep)) {
+         continue;
+      }
+
+      /* is this prime? */
+      for (x = 0; x < t; x++) {
+          mp_set(&b, __prime_tab[t]);
+          if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
+             goto __ERR;
+          }
+          if (res == MP_NO) {
+             break;
+          }
+      }
+
+      if (res == MP_YES) {
+         break;
+      }
+   }
+
+   err = MP_OKAY;
+__ERR:
+   mp_clear(&b);
+   return err;
+}
+
+
+/* End: bn_mp_prime_next_prime.c */
+
+/* Start: bn_mp_prime_random_ex.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ * 
+ *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
+ *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+
+/* This is possibly the mother of all prime generation functions, muahahahahaha! */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat)
+{
+   unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
+   int res, err, bsize, maskOR_msb_offset;
+
+   /* sanity check the input */
+   if (size <= 1 || t <= 0) {
+      return MP_VAL;
+   }
+
+   /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */
+   if (flags & LTM_PRIME_SAFE) {
+      flags |= LTM_PRIME_BBS;
+   }
+
+   /* calc the byte size */
+   bsize = (size>>3)+(size&7?1:0);
+
+   /* we need a buffer of bsize bytes */
+   tmp = OPT_CAST(unsigned char) XMALLOC(bsize);
+   if (tmp == NULL) {
+      return MP_MEM;
+   }
+
+   /* calc the maskAND value for the MSbyte*/
+   maskAND = 0xFF >> (8 - (size & 7));
+
+   /* calc the maskOR_msb */
+   maskOR_msb        = 0;
+   maskOR_msb_offset = (size - 2) >> 3;
+   if (flags & LTM_PRIME_2MSB_ON) {
+      maskOR_msb     |= 1 << ((size - 2) & 7);
+   } else if (flags & LTM_PRIME_2MSB_OFF) {
+      maskAND        &= ~(1 << ((size - 2) & 7));
+   }
+
+   /* get the maskOR_lsb */
+   maskOR_lsb         = 0;
+   if (flags & LTM_PRIME_BBS) {
+      maskOR_lsb     |= 3;
+   }
+
+   do {
+      /* read the bytes */
+      if (cb(tmp, bsize, dat) != bsize) {
+         err = MP_VAL;
+         goto error;
+      }
+ 
+      /* work over the MSbyte */
+      tmp[0]    &= maskAND;
+      tmp[0]    |= 1 << ((size - 1) & 7);
+
+      /* mix in the maskORs */
+      tmp[maskOR_msb_offset]   |= maskOR_msb;
+      tmp[bsize-1]             |= maskOR_lsb;
+
+      /* read it in */
+      if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY)     { goto error; }
+
+      /* is it prime? */
+      if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)           { goto error; }
+
+      if (flags & LTM_PRIME_SAFE) {
+         /* see if (a-1)/2 is prime */
+         if ((err = mp_sub_d(a, 1, a)) != MP_OKAY)                    { goto error; }
+         if ((err = mp_div_2(a, a)) != MP_OKAY)                       { goto error; }
+ 
+         /* is it prime? */
+         if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)        { goto error; }
+      }
+   } while (res == MP_NO);
+
+   if (flags & LTM_PRIME_SAFE) {
+      /* restore a to the original value */
+      if ((err = mp_mul_2(a, a)) != MP_OKAY)                          { goto error; }
+      if ((err = mp_add_d(a, 1, a)) != MP_OKAY)                       { goto error; }
+   }
+
+   err = MP_OKAY;
+error:
+   XFREE(tmp);
+   return err;
+}
+
+
+
+/* End: bn_mp_prime_random_ex.c */
+
+/* Start: bn_mp_radix_size.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* returns size of ASCII reprensentation */
+int mp_radix_size (mp_int * a, int radix, int *size)
+{
+  int     res, digs;
+  mp_int  t;
+  mp_digit d;
+
+  *size = 0;
+
+  /* special case for binary */
+  if (radix == 2) {
+    *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
+    return MP_OKAY;
+  }
+
+  /* make sure the radix is in range */
+  if (radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  /* init a copy of the input */
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  /* digs is the digit count */
+  digs = 0;
+
+  /* if it's negative add one for the sign */
+  if (t.sign == MP_NEG) {
+    ++digs;
+    t.sign = MP_ZPOS;
+  }
+
+  /* fetch out all of the digits */
+  while (mp_iszero (&t) == 0) {
+    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+    ++digs;
+  }
+  mp_clear (&t);
+
+  /* return digs + 1, the 1 is for the NULL byte that would be required. */
+  *size = digs + 1;
+  return MP_OKAY;
+}
+
+
+/* End: bn_mp_radix_size.c */
+
+/* Start: bn_mp_radix_smap.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* chars used in radix conversions */
+const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+
+/* End: bn_mp_radix_smap.c */
+
+/* Start: bn_mp_rand.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* makes a pseudo-random int of a given size */
+int
+mp_rand (mp_int * a, int digits)
+{
+  int     res;
+  mp_digit d;
+
+  mp_zero (a);
+  if (digits <= 0) {
+    return MP_OKAY;
+  }
+
+  /* first place a random non-zero digit */
+  do {
+    d = ((mp_digit) abs (rand ()));
+  } while (d == 0);
+
+  if ((res = mp_add_d (a, d, a)) != MP_OKAY) {
+    return res;
+  }
+
+  while (digits-- > 0) {
+    if ((res = mp_lshd (a, 1)) != MP_OKAY) {
+      return res;
+    }
+
+    if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  return MP_OKAY;
+}
+
+/* End: bn_mp_rand.c */
+
+/* Start: bn_mp_read_radix.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* read a string [ASCII] in a given radix */
+int mp_read_radix (mp_int * a, char *str, int radix)
+{
+  int     y, res, neg;
+  char    ch;
+
+  /* make sure the radix is ok */
+  if (radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  /* if the leading digit is a 
+   * minus set the sign to negative. 
+   */
+  if (*str == '-') {
+    ++str;
+    neg = MP_NEG;
+  } else {
+    neg = MP_ZPOS;
+  }
+
+  /* set the integer to the default of zero */
+  mp_zero (a);
+  
+  /* process each digit of the string */
+  while (*str) {
+    /* if the radix < 36 the conversion is case insensitive
+     * this allows numbers like 1AB and 1ab to represent the same  value
+     * [e.g. in hex]
+     */
+    ch = (char) ((radix < 36) ? toupper (*str) : *str);
+    for (y = 0; y < 64; y++) {
+      if (ch == mp_s_rmap[y]) {
+         break;
+      }
+    }
+
+    /* if the char was found in the map 
+     * and is less than the given radix add it
+     * to the number, otherwise exit the loop. 
+     */
+    if (y < radix) {
+      if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
+         return res;
+      }
+      if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
+         return res;
+      }
+    } else {
+      break;
+    }
+    ++str;
+  }
+  
+  /* set the sign only if a != 0 */
+  if (mp_iszero(a) != 1) {
+     a->sign = neg;
+  }
+  return MP_OKAY;
+}
+
+/* End: bn_mp_read_radix.c */
+
+/* Start: bn_mp_read_signed_bin.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* read signed bin, big endian, first byte is 0==positive or 1==negative */
+int
+mp_read_signed_bin (mp_int * a, unsigned char *b, int c)
+{
+  int     res;
+
+  /* read magnitude */
+  if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* first byte is 0 for positive, non-zero for negative */
+  if (b[0] == 0) {
+     a->sign = MP_ZPOS;
+  } else {
+     a->sign = MP_NEG;
+  }
+
+  return MP_OKAY;
+}
+
+/* End: bn_mp_read_signed_bin.c */
+
+/* Start: bn_mp_read_unsigned_bin.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* reads a unsigned char array, assumes the msb is stored first [big endian] */
+int
+mp_read_unsigned_bin (mp_int * a, unsigned char *b, int c)
+{
+  int     res;
+
+  /* make sure there are at least two digits */
+  if (a->alloc < 2) {
+     if ((res = mp_grow(a, 2)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero the int */
+  mp_zero (a);
+
+  /* read the bytes in */
+  while (c-- > 0) {
+    if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
+      return res;
+    }
+
+#ifndef MP_8BIT
+      a->dp[0] |= *b++;
+      a->used += 1;
+#else
+      a->dp[0] = (*b & MP_MASK);
+      a->dp[1] |= ((*b++ >> 7U) & 1);
+      a->used += 2;
+#endif
+  }
+  mp_clamp (a);
+  return MP_OKAY;
+}
+
+/* End: bn_mp_read_unsigned_bin.c */
+
+/* Start: bn_mp_reduce.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* reduces x mod m, assumes 0 < x < m**2, mu is 
+ * precomputed via mp_reduce_setup.
+ * From HAC pp.604 Algorithm 14.42
+ */
+int
+mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
+{
+  mp_int  q;
+  int     res, um = m->used;
+
+  /* q = x */
+  if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
+    return res;
+  }
+
+  /* q1 = x / b**(k-1)  */
+  mp_rshd (&q, um - 1);         
+
+  /* according to HAC this optimization is ok */
+  if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
+    if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  } else {
+    if ((res = s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  }
+
+  /* q3 = q2 / b**(k+1) */
+  mp_rshd (&q, um + 1);         
+
+  /* x = x mod b**(k+1), quick (no division) */
+  if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* q = q * m mod b**(k+1), quick (no division) */
+  if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* x = x - q */
+  if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* If x < 0, add b**(k+1) to it */
+  if (mp_cmp_d (x, 0) == MP_LT) {
+    mp_set (&q, 1);
+    if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
+      goto CLEANUP;
+    if ((res = mp_add (x, &q, x)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  /* Back off if it's too big */
+  while (mp_cmp (x, m) != MP_LT) {
+    if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  }
+  
+CLEANUP:
+  mp_clear (&q);
+
+  return res;
+}
+
+/* End: bn_mp_reduce.c */
+
+/* Start: bn_mp_reduce_2k.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* reduces a modulo n where n is of the form 2**p - d */
+int
+mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
+{
+   mp_int q;
+   int    p, res;
+   
+   if ((res = mp_init(&q)) != MP_OKAY) {
+      return res;
+   }
+   
+   p = mp_count_bits(n);    
+top:
+   /* q = a/2**p, a = a mod 2**p */
+   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if (d != 1) {
+      /* q = q * d */
+      if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { 
+         goto ERR;
+      }
+   }
+   
+   /* a = a + q */
+   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if (mp_cmp_mag(a, n) != MP_LT) {
+      s_mp_sub(a, n, a);
+      goto top;
+   }
+   
+ERR:
+   mp_clear(&q);
+   return res;
+}
+
+
+/* End: bn_mp_reduce_2k.c */
+
+/* Start: bn_mp_reduce_2k_setup.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* determines the setup value */
+int 
+mp_reduce_2k_setup(mp_int *a, mp_digit *d)
+{
+   int res, p;
+   mp_int tmp;
+   
+   if ((res = mp_init(&tmp)) != MP_OKAY) {
+      return res;
+   }
+   
+   p = mp_count_bits(a);
+   if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
+      mp_clear(&tmp);
+      return res;
+   }
+   
+   if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
+      mp_clear(&tmp);
+      return res;
+   }
+   
+   *d = tmp.dp[0];
+   mp_clear(&tmp);
+   return MP_OKAY;
+}
+
+/* End: bn_mp_reduce_2k_setup.c */
+
+/* Start: bn_mp_reduce_is_2k.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* determines if mp_reduce_2k can be used */
+int mp_reduce_is_2k(mp_int *a)
+{
+   int ix, iy, iz, iw;
+   
+   if (a->used == 0) {
+      return 0;
+   } else if (a->used == 1) {
+      return 1;
+   } else if (a->used > 1) {
+      iy = mp_count_bits(a);
+      iz = 1;
+      iw = 1;
+    
+      /* Test every bit from the second digit up, must be 1 */
+      for (ix = DIGIT_BIT; ix < iy; ix++) {
+          if ((a->dp[iw] & iz) == 0) {
+             return 0;
+          }
+          iz <<= 1;
+          if (iz > (int)MP_MASK) {
+             ++iw;
+             iz = 1;
+          }
+      }
+   }
+   return 1;
+}
+
+
+/* End: bn_mp_reduce_is_2k.c */
+
+/* Start: bn_mp_reduce_setup.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calulates the value required in "a"
+ */
+int
+mp_reduce_setup (mp_int * a, mp_int * b)
+{
+  int     res;
+  
+  if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
+    return res;
+  }
+  return mp_div (a, b, a, NULL);
+}
+
+/* End: bn_mp_reduce_setup.c */
+
+/* Start: bn_mp_rshd.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* shift right a certain amount of digits */
+void mp_rshd (mp_int * a, int b)
+{
+  int     x;
+
+  /* if b <= 0 then ignore it */
+  if (b <= 0) {
+    return;
+  }
+
+  /* if b > used then simply zero it and return */
+  if (a->used <= b) {
+    mp_zero (a);
+    return;
+  }
+
+  {
+    register mp_digit *bottom, *top;
+
+    /* shift the digits down */
+
+    /* bottom */
+    bottom = a->dp;
+
+    /* top [offset into digits] */
+    top = a->dp + b;
+
+    /* this is implemented as a sliding window where 
+     * the window is b-digits long and digits from 
+     * the top of the window are copied to the bottom
+     *
+     * e.g.
+
+     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
+                 /\                   |      ---->
+                  \-------------------/      ---->
+     */
+    for (x = 0; x < (a->used - b); x++) {
+      *bottom++ = *top++;
+    }
+
+    /* zero the top digits */
+    for (; x < a->used; x++) {
+      *bottom++ = 0;
+    }
+  }
+  
+  /* remove excess digits */
+  a->used -= b;
+}
+
+/* End: bn_mp_rshd.c */
+
+/* Start: bn_mp_set.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* set to a digit */
+void mp_set (mp_int * a, mp_digit b)
+{
+  mp_zero (a);
+  a->dp[0] = b & MP_MASK;
+  a->used  = (a->dp[0] != 0) ? 1 : 0;
+}
+
+/* End: bn_mp_set.c */
+
+/* Start: bn_mp_set_int.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* set a 32-bit const */
+int mp_set_int (mp_int * a, unsigned long b)
+{
+  int     x, res;
+
+  mp_zero (a);
+  
+  /* set four bits at a time */
+  for (x = 0; x < 8; x++) {
+    /* shift the number up four bits */
+    if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
+      return res;
+    }
+
+    /* OR in the top four bits of the source */
+    a->dp[0] |= (b >> 28) & 15;
+
+    /* shift the source up to the next four bits */
+    b <<= 4;
+
+    /* ensure that digits are not clamped off */
+    a->used += 1;
+  }
+  mp_clamp (a);
+  return MP_OKAY;
+}
+
+/* End: bn_mp_set_int.c */
+
+/* Start: bn_mp_shrink.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* shrink a bignum */
+int mp_shrink (mp_int * a)
+{
+  mp_digit *tmp;
+  if (a->alloc != a->used && a->used > 0) {
+    if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
+      return MP_MEM;
+    }
+    a->dp    = tmp;
+    a->alloc = a->used;
+  }
+  return MP_OKAY;
+}
+
+/* End: bn_mp_shrink.c */
+
+/* Start: bn_mp_signed_bin_size.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* get the size for an signed equivalent */
+int mp_signed_bin_size (mp_int * a)
+{
+  return 1 + mp_unsigned_bin_size (a);
+}
+
+/* End: bn_mp_signed_bin_size.c */
+
+/* Start: bn_mp_sqr.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* computes b = a*a */
+int
+mp_sqr (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  /* use Toom-Cook? */
+  if (a->used >= TOOM_SQR_CUTOFF) {
+    res = mp_toom_sqr(a, b);
+  /* Karatsuba? */
+  } else if (a->used >= KARATSUBA_SQR_CUTOFF) {
+    res = mp_karatsuba_sqr (a, b);
+  } else {
+    /* can we use the fast comba multiplier? */
+    if ((a->used * 2 + 1) < MP_WARRAY && 
+         a->used < 
+         (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
+      res = fast_s_mp_sqr (a, b);
+    } else {
+      res = s_mp_sqr (a, b);
+    }
+  }
+  b->sign = MP_ZPOS;
+  return res;
+}
+
+/* End: bn_mp_sqr.c */
+
+/* Start: bn_mp_sqrmod.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* c = a * a (mod b) */
+int
+mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_sqr (a, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, b, c);
+  mp_clear (&t);
+  return res;
+}
+
+/* End: bn_mp_sqrmod.c */
+
+/* Start: bn_mp_sqrt.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* this function is less generic than mp_n_root, simpler and faster */
+int mp_sqrt(mp_int *arg, mp_int *ret) 
+{
+  int res;
+  mp_int t1,t2;
+
+  /* must be positive */
+  if (arg->sign == MP_NEG) {
+    return MP_VAL;
+  }
+
+  /* easy out */
+  if (mp_iszero(arg) == MP_YES) {
+    mp_zero(ret);
+    return MP_OKAY;
+  }
+
+  if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init(&t2)) != MP_OKAY) {
+    goto E2;
+  }
+
+  /* First approx. (not very bad for large arg) */
+  mp_rshd (&t1,t1.used/2);
+
+  /* t1 > 0  */ 
+  if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+    goto E1;
+  }
+  if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+    goto E1;
+  }
+  if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+    goto E1;
+  }
+  /* And now t1 > sqrt(arg) */
+  do { 
+    if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+      goto E1;
+    }
+    if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+      goto E1;
+    }
+    if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+      goto E1;
+    }
+    /* t1 >= sqrt(arg) >= t2 at this point */
+  } while (mp_cmp_mag(&t1,&t2) == MP_GT);
+
+  mp_exch(&t1,ret);
+
+E1: mp_clear(&t2);
+E2: mp_clear(&t1);
+  return res;
+}
+
+
+/* End: bn_mp_sqrt.c */
+
+/* Start: bn_mp_sub.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* high level subtraction (handles signs) */
+int
+mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  sa = a->sign;
+  sb = b->sign;
+
+  if (sa != sb) {
+    /* subtract a negative from a positive, OR */
+    /* subtract a positive from a negative. */
+    /* In either case, ADD their magnitudes, */
+    /* and use the sign of the first number. */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* subtract a positive from a positive, OR */
+    /* subtract a negative from a negative. */
+    /* First, take the difference between their */
+    /* magnitudes, then... */
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      /* Copy the sign from the first */
+      c->sign = sa;
+      /* The first has a larger or equal magnitude */
+      res = s_mp_sub (a, b, c);
+    } else {
+      /* The result has the *opposite* sign from */
+      /* the first number. */
+      c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+      /* The second has a larger magnitude */
+      res = s_mp_sub (b, a, c);
+    }
+  }
+  return res;
+}
+
+
+/* End: bn_mp_sub.c */
+
+/* Start: bn_mp_sub_d.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* single digit subtraction */
+int
+mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit *tmpa, *tmpc, mu;
+  int       res, ix, oldused;
+
+  /* grow c as required */
+  if (c->alloc < a->used + 1) {
+     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* if a is negative just do an unsigned
+   * addition [with fudged signs]
+   */
+  if (a->sign == MP_NEG) {
+     a->sign = MP_ZPOS;
+     res     = mp_add_d(a, b, c);
+     a->sign = c->sign = MP_NEG;
+     return res;
+  }
+
+  /* setup regs */
+  oldused = c->used;
+  tmpa    = a->dp;
+  tmpc    = c->dp;
+
+  /* if a <= b simply fix the single digit */
+  if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
+     if (a->used == 1) {
+        *tmpc++ = b - *tmpa;
+     } else {
+        *tmpc++ = b;
+     }
+     ix      = 1;
+
+     /* negative/1digit */
+     c->sign = MP_NEG;
+     c->used = 1;
+  } else {
+     /* positive/size */
+     c->sign = MP_ZPOS;
+     c->used = a->used;
+
+     /* subtract first digit */
+     *tmpc    = *tmpa++ - b;
+     mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+     *tmpc++ &= MP_MASK;
+
+     /* handle rest of the digits */
+     for (ix = 1; ix < a->used; ix++) {
+        *tmpc    = *tmpa++ - mu;
+        mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+        *tmpc++ &= MP_MASK;
+     }
+  }
+
+  /* zero excess digits */
+  while (ix++ < oldused) {
+     *tmpc++ = 0;
+  }
+  mp_clamp(c);
+  return MP_OKAY;
+}
+
+
+/* End: bn_mp_sub_d.c */
+
+/* Start: bn_mp_submod.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* d = a - b (mod c) */
+int
+mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+
+/* End: bn_mp_submod.c */
+
+/* Start: bn_mp_to_signed_bin.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* store in signed [big endian] format */
+int
+mp_to_signed_bin (mp_int * a, unsigned char *b)
+{
+  int     res;
+
+  if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) {
+    return res;
+  }
+  b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
+  return MP_OKAY;
+}
+
+/* End: bn_mp_to_signed_bin.c */
+
+/* Start: bn_mp_to_unsigned_bin.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* store in unsigned [big endian] format */
+int
+mp_to_unsigned_bin (mp_int * a, unsigned char *b)
+{
+  int     x, res;
+  mp_int  t;
+
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  x = 0;
+  while (mp_iszero (&t) == 0) {
+#ifndef MP_8BIT
+      b[x++] = (unsigned char) (t.dp[0] & 255);
+#else
+      b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
+#endif
+    if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+  bn_reverse (b, x);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+/* End: bn_mp_to_unsigned_bin.c */
+
+/* Start: bn_mp_toom_mul.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* multiplication using the Toom-Cook 3-way algorithm */
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
+{
+    mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
+    int res, B;
+        
+    /* init temps */
+    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, 
+                             &a0, &a1, &a2, &b0, &b1, 
+                             &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
+       return res;
+    }
+    
+    /* B */
+    B = MIN(a->used, b->used) / 3;
+    
+    /* a = a2 * B**2 + a1 * B + a0 */
+    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&a1, B);
+    mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+    if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&a2, B*2);
+    
+    /* b = b2 * B**2 + b1 * B + b0 */
+    if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_copy(b, &b1)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&b1, B);
+    mp_mod_2d(&b1, DIGIT_BIT * B, &b1);
+
+    if ((res = mp_copy(b, &b2)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&b2, B*2);
+    
+    /* w0 = a0*b0 */
+    if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    /* w4 = a2 * b2 */
+    if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
+    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
+    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+
+    /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
+    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    /* now solve the matrix 
+    
+       0  0  0  0  1
+       1  2  4  8  16
+       1  1  1  1  1
+       16 8  4  2  1
+       1  0  0  0  0
+       
+       using 12 subtractions, 4 shifts, 
+              2 small divisions and 1 small multiplication 
+     */
+     
+     /* r1 - r4 */
+     if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r0 */
+     if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1/2 */
+     if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3/2 */
+     if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r2 - r0 - r4 */
+     if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - r2 */
+     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r2 */
+     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - 8r0 */
+     if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - 8r4 */
+     if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* 3r2 - r1 - r3 */
+     if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - r2 */
+     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r2 */
+     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1/3 */
+     if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3/3 */
+     if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+        goto ERR;
+     }
+     
+     /* at this point shift W[n] by B*n */
+     if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+        goto ERR;
+     }     
+     
+     if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
+        goto ERR;
+     }     
+     
+ERR:
+     mp_clear_multi(&w0, &w1, &w2, &w3, &w4, 
+                    &a0, &a1, &a2, &b0, &b1, 
+                    &b2, &tmp1, &tmp2, NULL);
+     return res;
+}     
+     
+
+/* End: bn_mp_toom_mul.c */
+
+/* Start: bn_mp_toom_sqr.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* squaring using Toom-Cook 3-way algorithm */
+int
+mp_toom_sqr(mp_int *a, mp_int *b)
+{
+    mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
+    int res, B;
+
+    /* init temps */
+    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
+       return res;
+    }
+
+    /* B */
+    B = a->used / 3;
+
+    /* a = a2 * B**2 + a1 * B + a0 */
+    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&a1, B);
+    mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+    if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&a2, B*2);
+
+    /* w0 = a0*a0 */
+    if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    /* w4 = a2 * a2 */
+    if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    /* w1 = (a2 + 2(a1 + 2a0))**2 */
+    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    /* w3 = (a0 + 2(a1 + 2a2))**2 */
+    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
+       goto ERR;
+    }
+
+
+    /* w2 = (a2 + a1 + a0)**2 */
+    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    /* now solve the matrix
+
+       0  0  0  0  1
+       1  2  4  8  16
+       1  1  1  1  1
+       16 8  4  2  1
+       1  0  0  0  0
+
+       using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
+     */
+
+     /* r1 - r4 */
+     if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r0 */
+     if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1/2 */
+     if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3/2 */
+     if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r2 - r0 - r4 */
+     if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - r2 */
+     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r2 */
+     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - 8r0 */
+     if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - 8r4 */
+     if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* 3r2 - r1 - r3 */
+     if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - r2 */
+     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r2 */
+     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1/3 */
+     if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3/3 */
+     if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+        goto ERR;
+     }
+
+     /* at this point shift W[n] by B*n */
+     if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+        goto ERR;
+     }
+
+     if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
+        goto ERR;
+     }
+
+ERR:
+     mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
+     return res;
+}
+
+
+/* End: bn_mp_toom_sqr.c */
+
+/* Start: bn_mp_toradix.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* stores a bignum as a ASCII string in a given radix (2..64) */
+int mp_toradix (mp_int * a, char *str, int radix)
+{
+  int     res, digs;
+  mp_int  t;
+  mp_digit d;
+  char   *_s = str;
+
+  /* check range of the radix */
+  if (radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  /* quick out if its zero */
+  if (mp_iszero(a) == 1) {
+     *str++ = '0';
+     *str = '\0';
+     return MP_OKAY;
+  }
+
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  /* if it is negative output a - */
+  if (t.sign == MP_NEG) {
+    ++_s;
+    *str++ = '-';
+    t.sign = MP_ZPOS;
+  }
+
+  digs = 0;
+  while (mp_iszero (&t) == 0) {
+    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+    *str++ = mp_s_rmap[d];
+    ++digs;
+  }
+
+  /* reverse the digits of the string.  In this case _s points
+   * to the first digit [exluding the sign] of the number]
+   */
+  bn_reverse ((unsigned char *)_s, digs);
+
+  /* append a NULL so the string is properly terminated */
+  *str = '\0';
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* End: bn_mp_toradix.c */
+
+/* Start: bn_mp_toradix_n.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* stores a bignum as a ASCII string in a given radix (2..64) 
+ *
+ * Stores upto maxlen-1 chars and always a NULL byte 
+ */
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen)
+{
+  int     res, digs;
+  mp_int  t;
+  mp_digit d;
+  char   *_s = str;
+
+  /* check range of the maxlen, radix */
+  if (maxlen < 3 || radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  /* quick out if its zero */
+  if (mp_iszero(a) == 1) {
+     *str++ = '0';
+     *str = '\0';
+     return MP_OKAY;
+  }
+
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  /* if it is negative output a - */
+  if (t.sign == MP_NEG) {
+    /* we have to reverse our digits later... but not the - sign!! */
+    ++_s;
+
+    /* store the flag and mark the number as positive */
+    *str++ = '-';
+    t.sign = MP_ZPOS;
+ 
+    /* subtract a char */
+    --maxlen;
+  }
+
+  digs = 0;
+  while (mp_iszero (&t) == 0) {
+    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+    *str++ = mp_s_rmap[d];
+    ++digs;
+
+    if (--maxlen == 1) {
+       /* no more room */
+       break;
+    }
+  }
+
+  /* reverse the digits of the string.  In this case _s points
+   * to the first digit [exluding the sign] of the number]
+   */
+  bn_reverse ((unsigned char *)_s, digs);
+
+  /* append a NULL so the string is properly terminated */
+  *str = '\0';
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* End: bn_mp_toradix_n.c */
+
+/* Start: bn_mp_unsigned_bin_size.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* get the size for an unsigned equivalent */
+int
+mp_unsigned_bin_size (mp_int * a)
+{
+  int     size = mp_count_bits (a);
+  return (size / 8 + ((size & 7) != 0 ? 1 : 0));
+}
+
+/* End: bn_mp_unsigned_bin_size.c */
+
+/* Start: bn_mp_xor.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* XOR two ints together */
+int
+mp_xor (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, ix, px;
+  mp_int  t, *x;
+
+  if (a->used > b->used) {
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+      return res;
+    }
+    px = b->used;
+    x = b;
+  } else {
+    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+      return res;
+    }
+    px = a->used;
+    x = a;
+  }
+
+  for (ix = 0; ix < px; ix++) {
+    t.dp[ix] ^= x->dp[ix];
+  }
+  mp_clamp (&t);
+  mp_exch (c, &t);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+/* End: bn_mp_xor.c */
+
+/* Start: bn_mp_zero.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* set to zero */
+void
+mp_zero (mp_int * a)
+{
+  a->sign = MP_ZPOS;
+  a->used = 0;
+  memset (a->dp, 0, sizeof (mp_digit) * a->alloc);
+}
+
+/* End: bn_mp_zero.c */
+
+/* Start: bn_prime_sizes_tab.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* this table gives the # of rabin miller trials for a prob of failure lower than 2^-96 */
+static const struct {
+   int k, t;
+} sizes[] = {
+{   128,    28 },
+{   256,    16 },
+{   384,    10 },
+{   512,     7 },
+{   640,     6 },
+{   768,     5 },
+{   896,     4 },
+{  1024,     4 },
+{  1152,     3 },
+{  1280,     3 },
+{  1408,     3 },
+{  1536,     3 },
+{  1664,     3 },
+{  1792,     2 } };
+
+/* returns # of RM trials required for a given bit size */
+int mp_prime_rabin_miller_trials(int size)
+{
+   int x;
+
+   for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
+       if (sizes[x].k == size) {
+          return sizes[x].t;
+       } else if (sizes[x].k > size) {
+          return (x == 0) ? sizes[0].t : sizes[x - 1].t;
+       }
+   }
+   return 1;
+}
+
+
+
+/* End: bn_prime_sizes_tab.c */
+
+/* Start: bn_prime_tab.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+const mp_digit __prime_tab[] = {
+  0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
+  0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
+  0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
+  0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
+#ifndef MP_8BIT
+  0x0083,
+  0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
+  0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
+  0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
+  0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
+
+  0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
+  0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
+  0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
+  0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
+  0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
+  0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
+  0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
+  0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
+
+  0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
+  0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
+  0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
+  0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
+  0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
+  0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
+  0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
+  0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
+
+  0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
+  0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
+  0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
+  0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
+  0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
+  0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
+  0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
+  0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
+#endif
+};
+
+/* End: bn_prime_tab.c */
+
+/* Start: bn_reverse.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* reverse an array, used for radix code */
+void
+bn_reverse (unsigned char *s, int len)
+{
+  int     ix, iy;
+  unsigned char t;
+
+  ix = 0;
+  iy = len - 1;
+  while (ix < iy) {
+    t     = s[ix];
+    s[ix] = s[iy];
+    s[iy] = t;
+    ++ix;
+    --iy;
+  }
+}
+
+/* End: bn_reverse.c */
+
+/* Start: bn_s_mp_add.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+int
+s_mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int *x;
+  int     olduse, res, min, max;
+
+  /* find sizes, we let |a| <= |b| which means we have to sort
+   * them.  "x" will point to the input with the most digits
+   */
+  if (a->used > b->used) {
+    min = b->used;
+    max = a->used;
+    x = a;
+  } else {
+    min = a->used;
+    max = b->used;
+    x = b;
+  }
+
+  /* init result */
+  if (c->alloc < max + 1) {
+    if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get old used digit count and set new one */
+  olduse = c->used;
+  c->used = max + 1;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+
+    /* first input */
+    tmpa = a->dp;
+
+    /* second input */
+    tmpb = b->dp;
+
+    /* destination */
+    tmpc = c->dp;
+
+    /* zero the carry */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
+      *tmpc = *tmpa++ + *tmpb++ + u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+      /* take away carry bit from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, that is in A+B 
+     * if A or B has more digits add those in 
+     */
+    if (min != max) {
+      for (; i < max; i++) {
+        /* T[i] = X[i] + U */
+        *tmpc = x->dp[i] + u;
+
+        /* U = carry bit of T[i] */
+        u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+        /* take away carry bit from T[i] */
+        *tmpc++ &= MP_MASK;
+      }
+    }
+
+    /* add carry */
+    *tmpc++ = u;
+
+    /* clear digits above oldused */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+/* End: bn_s_mp_add.c */
+
+/* Start: bn_s_mp_exptmod.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+#ifdef MP_LOW_MEM
+   #define TAB_SIZE 32
+#else
+   #define TAB_SIZE 256
+#endif
+
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+{
+  mp_int  M[TAB_SIZE], res, mu;
+  mp_digit buf;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+    if (winsize > 5) {
+       winsize = 5;
+    }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err; 
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* create mu, used for Barrett reduction */
+  if ((err = mp_init (&mu)) != MP_OKAY) {
+    goto __M;
+  }
+  if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
+    goto __MU;
+  }
+
+  /* create M table
+   *
+   * The M table contains powers of the base, 
+   * e.g. M[x] = G**x mod P
+   *
+   * The first half of the table is not 
+   * computed though accept for M[0] and M[1]
+   */
+  if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
+    goto __MU;
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring 
+   * M[1] (winsize-1) times 
+   */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto __MU;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    if ((err = mp_sqr (&M[1 << (winsize - 1)], 
+                       &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto __MU;
+    }
+    if ((err = mp_reduce (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
+      goto __MU;
+    }
+  }
+
+  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+   */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto __MU;
+    }
+    if ((err = mp_reduce (&M[x], P, &mu)) != MP_OKAY) {
+      goto __MU;
+    }
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto __MU;
+  }
+  mp_set (&res, 1);
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset the bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int) DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto __RES;
+      }
+      if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
+        goto __RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto __RES;
+        }
+        if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
+          goto __RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto __RES;
+      }
+      if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
+        goto __RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto __RES;
+      }
+      if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
+        goto __RES;
+      }
+
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto __RES;
+        }
+        if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
+          goto __RES;
+        }
+      }
+    }
+  }
+
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+__RES:mp_clear (&res);
+__MU:mp_clear (&mu);
+__M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+
+/* End: bn_s_mp_exptmod.c */
+
+/* Start: bn_s_mp_mul_digs.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* multiplies |a| * |b| and only computes upto digs digits of result
+ * HAC pp. 595, Algorithm 14.12  Modified so you can control how 
+ * many digits of output are created.
+ */
+int
+s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+  if (((digs) < MP_WARRAY) &&
+      MIN (a->used, b->used) < 
+          (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_digs (a, b, c, digs);
+  }
+
+  if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
+    return res;
+  }
+  t.used = digs;
+
+  /* compute the digits of the product directly */
+  pa = a->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* set the carry to zero */
+    u = 0;
+
+    /* limit ourselves to making digs digits of output */
+    pb = MIN (b->used, digs - ix);
+
+    /* setup some aliases */
+    /* copy of the digit from a used within the nested loop */
+    tmpx = a->dp[ix];
+    
+    /* an alias for the destination shifted ix places */
+    tmpt = t.dp + ix;
+    
+    /* an alias for the digits of b */
+    tmpy = b->dp;
+
+    /* compute the columns of the output and propagate the carry */
+    for (iy = 0; iy < pb; iy++) {
+      /* compute the column as a mp_word */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* the new column is the lower part of the result */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get the carry word from the result */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    /* set carry if it is placed below digs */
+    if (ix + iy < digs) {
+      *tmpt = u;
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, c);
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+/* End: bn_s_mp_mul_digs.c */
+
+/* Start: bn_s_mp_mul_high_digs.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* multiplies |a| * |b| and does not compute the lower digs digits
+ * [meant to get the higher part of the product]
+ */
+int
+s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+  if (((a->used + b->used + 1) < MP_WARRAY)
+      && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_high_digs (a, b, c, digs);
+  }
+
+  if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
+    return res;
+  }
+  t.used = a->used + b->used + 1;
+
+  pa = a->used;
+  pb = b->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* clear the carry */
+    u = 0;
+
+    /* left hand side of A[ix] * B[iy] */
+    tmpx = a->dp[ix];
+
+    /* alias to the address of where the digits will be stored */
+    tmpt = &(t.dp[digs]);
+
+    /* alias for where to read the right hand side from */
+    tmpy = b->dp + (digs - ix);
+
+    for (iy = digs - ix; iy < pb; iy++) {
+      /* calculate the double precision result */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* get the lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* carry the carry */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    *tmpt = u;
+  }
+  mp_clamp (&t);
+  mp_exch (&t, c);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+/* End: bn_s_mp_mul_high_digs.c */
+
+/* Start: bn_s_mp_sqr.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
+int
+s_mp_sqr (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+  int     res, ix, iy, pa;
+  mp_word r;
+  mp_digit u, tmpx, *tmpt;
+
+  pa = a->used;
+  if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* default used is maximum possible size */
+  t.used = 2*pa + 1;
+
+  for (ix = 0; ix < pa; ix++) {
+    /* first calculate the digit at 2*ix */
+    /* calculate double precision result */
+    r = ((mp_word) t.dp[2*ix]) +
+        ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
+
+    /* store lower part in result */
+    t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* get the carry */
+    u           = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+    /* left hand side of A[ix] * A[iy] */
+    tmpx        = a->dp[ix];
+
+    /* alias for where to store the results */
+    tmpt        = t.dp + (2*ix + 1);
+    
+    for (iy = ix + 1; iy < pa; iy++) {
+      /* first calculate the product */
+      r       = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
+
+      /* now calculate the double precision result, note we use
+       * addition instead of *2 since it's easier to optimize
+       */
+      r       = ((mp_word) *tmpt) + r + r + ((mp_word) u);
+
+      /* store lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get carry */
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+    /* propagate upwards */
+    while (u != ((mp_digit) 0)) {
+      r       = ((mp_word) *tmpt) + ((mp_word) u);
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, b);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+/* End: bn_s_mp_sqr.c */
+
+/* Start: bn_s_mp_sub.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
+int
+s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     olduse, res, min, max;
+
+  /* find sizes */
+  min = b->used;
+  max = a->used;
+
+  /* init result */
+  if (c->alloc < max) {
+    if ((res = mp_grow (c, max)) != MP_OKAY) {
+      return res;
+    }
+  }
+  olduse = c->used;
+  c->used = max;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+    tmpa = a->dp;
+    tmpb = b->dp;
+    tmpc = c->dp;
+
+    /* set carry to zero */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* T[i] = A[i] - B[i] - U */
+      *tmpc = *tmpa++ - *tmpb++ - u;
+
+      /* U = carry bit of T[i]
+       * Note this saves performing an AND operation since
+       * if a carry does occur it will propagate all the way to the
+       * MSB.  As a result a single shift is enough to get the carry
+       */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, e.g. if A has more digits than B  */
+    for (; i < max; i++) {
+      /* T[i] = A[i] - U */
+      *tmpc = *tmpa++ - u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* clear digits above used (since we may not have grown result above) */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* End: bn_s_mp_sub.c */
+
+/* Start: bncore.c */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#include <tommath.h>
+
+/* Known optimal configurations
+
+ CPU                    /Compiler     /MUL CUTOFF/SQR CUTOFF
+-------------------------------------------------------------
+ Intel P4               /GCC v3.2     /        70/       108
+ AMD Athlon XP          /GCC v3.2     /       109/       127
+
+*/
+
+/* configured for a AMD XP Thoroughbred core with etc/tune.c */
+int     KARATSUBA_MUL_CUTOFF = 70,      /* Min. number of digits before Karatsuba multiplication is used. */
+        KARATSUBA_SQR_CUTOFF = 108,      /* Min. number of digits before Karatsuba squaring is used. */
+        
+        TOOM_MUL_CUTOFF      = 350,      /* no optimal values of these are known yet so set em high */
+        TOOM_SQR_CUTOFF      = 400; 
+
+/* End: bncore.c */
+
+
+/* EOF */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,82 @@
+#ifndef CRYPT_H_
+#define CRYPT_H_
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#include <limits.h>
+
+/* if there is a custom definition header file use it */
+#include <mycrypt_custom.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* version */
+#define CRYPT   0x0095
+#define SCRYPT  "0.95"
+
+/* max size of either a cipher/hash block or symmetric key [largest of the two] */
+#define MAXBLOCKSIZE           128
+
+/* descriptor table size */
+#define TAB_SIZE    32
+
+/* error codes [will be expanded in future releases] */
+enum {
+   CRYPT_OK=0,             /* Result OK */
+   CRYPT_ERROR,            /* Generic Error */
+   CRYPT_NOP,              /* Not a failure but no operation was performed */
+
+   CRYPT_INVALID_KEYSIZE,  /* Invalid key size given */
+   CRYPT_INVALID_ROUNDS,   /* Invalid number of rounds */
+   CRYPT_FAIL_TESTVECTOR,  /* Algorithm failed test vectors */
+
+   CRYPT_BUFFER_OVERFLOW,  /* Not enough space for output */
+   CRYPT_INVALID_PACKET,   /* Invalid input packet given */
+
+   CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
+   CRYPT_ERROR_READPRNG,   /* Could not read enough from PRNG */
+
+   CRYPT_INVALID_CIPHER,   /* Invalid cipher specified */
+   CRYPT_INVALID_HASH,     /* Invalid hash specified */
+   CRYPT_INVALID_PRNG,     /* Invalid PRNG specified */
+
+   CRYPT_MEM,              /* Out of memory */
+
+   CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
+   CRYPT_PK_NOT_PRIVATE,   /* Requires a private PK key */
+
+   CRYPT_INVALID_ARG,      /* Generic invalid argument */
+   CRYPT_FILE_NOTFOUND,    /* File Not Found */
+
+   CRYPT_PK_INVALID_TYPE,  /* Invalid type of PK key */
+   CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */
+   CRYPT_PK_DUP,           /* Duplicate key already in key ring */
+   CRYPT_PK_NOT_FOUND,     /* Key not found in keyring */
+   CRYPT_PK_INVALID_SIZE,  /* Invalid size input for PK parameters */
+
+   CRYPT_INVALID_PRIME_SIZE/* Invalid size of prime requested */
+};
+
+#include <mycrypt_cfg.h>
+#include <mycrypt_macros.h>
+#include <mycrypt_cipher.h>
+#include <mycrypt_hash.h>
+#include <mycrypt_prng.h>
+#include <mycrypt_pk.h>
+#include <mycrypt_gf.h>
+#include <mycrypt_misc.h>
+#include <mycrypt_kr.h>
+#include <mycrypt_argchk.h>
+#include <mycrypt_pkcs.h>
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif /* CRYPT_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt_argchk.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,24 @@
+/* Defines the _ARGCHK macro used within the library */
+
+/* ch1-01-1 */
+/* ARGTYPE is defined in mycrypt_cfg.h */
+#if ARGTYPE == 0
+
+#include <signal.h>
+
+/* this is the default LibTomCrypt macro  */
+extern void crypt_argchk(char *v, char *s, int d);
+#define _ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }
+
+#elif ARGTYPE == 1
+
+/* fatal type of error */
+#define _ARGCHK(x) assert((x))
+
+#elif ARGTYPE == 2
+
+#define _ARGCHK(x) 
+
+#endif
+/* ch1-01-1 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt_cfg.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,78 @@
+/* This is the build config file.
+ *
+ * With this you can setup what to inlcude/exclude automatically during any build.  Just comment
+ * out the line that #define's the word for the thing you want to remove.  phew!
+ */
+
+#ifndef MYCRYPT_CFG_H
+#define MYCRYPT_CFG_H
+
+/* you can change how memory allocation works ... */
+extern void *XMALLOC(size_t n);
+extern void *REALLOC(void *p, size_t n);
+extern void *XCALLOC(size_t n, size_t s);
+extern void XFREE(void *p);
+
+/* change the clock function too */
+extern clock_t XCLOCK(void);
+
+/* ch1-01-1 */
+/* type of argument checking, 0=default, 1=fatal and 2=none */
+#define ARGTYPE  0
+/* ch1-01-1 */
+
+/* Controls endianess and size of registers.  Leave uncommented to get platform neutral [slower] code */
+/* detect x86-32 machines somewhat */
+#if defined(INTEL_CC) || (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__)))
+   #define ENDIAN_LITTLE
+   #define ENDIAN_32BITWORD
+#endif
+
+/* detects MIPS R5900 processors (PS2) */
+#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips))
+   #define ENDIAN_LITTLE
+   #define ENDIAN_64BITWORD
+#endif
+
+/* #define ENDIAN_LITTLE */
+/* #define ENDIAN_BIG */
+
+/* #define ENDIAN_32BITWORD */
+/* #define ENDIAN_64BITWORD */
+
+#if (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD))
+    #error You must specify a word size as well as endianess in mycrypt_cfg.h
+#endif
+
+#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE))
+   #define ENDIAN_NEUTRAL
+#endif
+
+#ifdef YARROW
+   #ifndef CTR
+      #error YARROW requires CTR chaining mode to be defined!
+   #endif
+#endif
+
+/* packet code */
+#if defined(MRSA) || defined(MDH) || defined(MECC)
+    #define PACKET
+
+    /* size of a packet header in bytes */
+    #define PACKET_SIZE            4
+
+    /* Section tags */
+    #define PACKET_SECT_RSA        0
+    #define PACKET_SECT_DH         1
+    #define PACKET_SECT_ECC        2
+    #define PACKET_SECT_DSA        3
+
+    /* Subsection Tags for the first three sections */
+    #define PACKET_SUB_KEY         0
+    #define PACKET_SUB_ENCRYPTED   1
+    #define PACKET_SUB_SIGNED      2
+    #define PACKET_SUB_ENC_KEY     3
+#endif
+
+#endif /* MYCRYPT_CFG_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt_cipher.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,378 @@
+/* ---- SYMMETRIC KEY STUFF -----
+ *
+ * We put each of the ciphers scheduled keys in their own structs then we put all of 
+ * the key formats in one union.  This makes the function prototypes easier to use.
+ */
+#ifdef BLOWFISH
+struct blowfish_key {
+   ulong32 S[4][256];
+   ulong32 K[18];
+};
+#endif
+
+#ifdef RC5
+struct rc5_key {
+   int rounds;
+   ulong32 K[50];
+};
+#endif
+
+#ifdef RC6
+struct rc6_key {
+   ulong32 K[44];
+};
+#endif
+
+#ifdef SAFERP
+struct saferp_key {
+   unsigned char K[33][16];
+   long rounds;
+};
+#endif
+
+#ifdef RIJNDAEL
+struct rijndael_key {
+   ulong32 eK[64], dK[64];
+   int Nr;
+};
+#endif
+
+#ifdef XTEA
+struct xtea_key {
+   unsigned long A[32], B[32];
+};
+#endif
+
+#ifdef TWOFISH
+#ifndef TWOFISH_SMALL
+   struct twofish_key {
+      ulong32 S[4][256], K[40];
+   };
+#else
+   struct twofish_key {
+      ulong32 K[40];
+      unsigned char S[32], start;
+   };
+#endif
+#endif
+
+#ifdef SAFER
+#define SAFER_K64_DEFAULT_NOF_ROUNDS     6
+#define SAFER_K128_DEFAULT_NOF_ROUNDS   10
+#define SAFER_SK64_DEFAULT_NOF_ROUNDS    8
+#define SAFER_SK128_DEFAULT_NOF_ROUNDS  10
+#define SAFER_MAX_NOF_ROUNDS            13
+#define SAFER_BLOCK_LEN                  8
+#define SAFER_KEY_LEN     (1 + SAFER_BLOCK_LEN * (1 + 2 * SAFER_MAX_NOF_ROUNDS))
+typedef unsigned char safer_block_t[SAFER_BLOCK_LEN];
+typedef unsigned char safer_key_t[SAFER_KEY_LEN];
+struct safer_key { safer_key_t key; };
+#endif
+
+#ifdef RC2
+struct rc2_key { unsigned xkey[64]; };
+#endif
+
+#ifdef DES
+struct des_key {
+    ulong32 ek[32], dk[32];
+};
+
+struct des3_key {
+    ulong32 ek[3][32], dk[3][32];
+};
+#endif
+
+#ifdef CAST5
+struct cast5_key {
+    ulong32 K[32], keylen;
+};
+#endif
+
+#ifdef NOEKEON
+struct noekeon_key {
+    ulong32 K[4], dK[4];
+};
+#endif
+
+#ifdef SKIPJACK 
+struct skipjack_key {
+    unsigned char key[10];
+};
+#endif
+
+typedef union Symmetric_key {
+#ifdef DES
+   struct des_key des;
+   struct des3_key des3;
+#endif
+#ifdef RC2
+   struct rc2_key rc2;
+#endif
+#ifdef SAFER
+   struct safer_key safer;
+#endif
+#ifdef TWOFISH
+   struct twofish_key  twofish;
+#endif
+#ifdef BLOWFISH
+   struct blowfish_key blowfish;
+#endif
+#ifdef RC5
+   struct rc5_key      rc5;
+#endif
+#ifdef RC6
+   struct rc6_key      rc6;
+#endif
+#ifdef SAFERP
+   struct saferp_key   saferp;
+#endif
+#ifdef RIJNDAEL
+   struct rijndael_key rijndael;
+#endif
+#ifdef XTEA
+   struct xtea_key     xtea;
+#endif
+#ifdef CAST5
+   struct cast5_key    cast5;
+#endif
+#ifdef NOEKEON
+   struct noekeon_key  noekeon;
+#endif   
+#ifdef SKIPJACK
+   struct skipjack_key skipjack;
+#endif
+} symmetric_key;
+
+/* A block cipher ECB structure */
+typedef struct {
+   int                 cipher, blocklen;
+   symmetric_key       key;
+} symmetric_ECB;
+
+/* A block cipher CFB structure */
+typedef struct {
+   int                 cipher, blocklen, padlen;
+   unsigned char       IV[MAXBLOCKSIZE], pad[MAXBLOCKSIZE];
+   symmetric_key       key;
+} symmetric_CFB;
+
+/* A block cipher OFB structure */
+typedef struct {
+   int                 cipher, blocklen, padlen;
+   unsigned char       IV[MAXBLOCKSIZE];
+   symmetric_key       key;
+} symmetric_OFB;
+
+/* A block cipher CBC structure */
+typedef struct Symmetric_CBC {
+   int                 cipher, blocklen;
+   unsigned char       IV[MAXBLOCKSIZE];
+   symmetric_key       key;
+} symmetric_CBC;
+
+/* A block cipher CTR structure */
+typedef struct Symmetric_CTR {
+   int                 cipher, blocklen, padlen, mode;
+   unsigned char       ctr[MAXBLOCKSIZE], pad[MAXBLOCKSIZE];
+   symmetric_key       key;
+} symmetric_CTR;
+
+/* cipher descriptor table, last entry has "name == NULL" to mark the end of table */
+extern  struct _cipher_descriptor {
+   char *name;
+   unsigned char ID;
+   int  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);
+} cipher_descriptor[];
+
+#ifdef BLOWFISH
+extern int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+extern int blowfish_test(void);
+extern int blowfish_keysize(int *desired_keysize);
+extern const struct _cipher_descriptor blowfish_desc;
+#endif
+
+#ifdef RC5
+extern int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+extern int rc5_test(void);
+extern int rc5_keysize(int *desired_keysize);
+extern const struct _cipher_descriptor rc5_desc;
+#endif
+
+#ifdef RC6
+extern int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+extern int rc6_test(void);
+extern int rc6_keysize(int *desired_keysize);
+extern const struct _cipher_descriptor rc6_desc;
+#endif
+
+#ifdef RC2
+extern int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+extern int rc2_test(void);
+extern int rc2_keysize(int *desired_keysize);
+extern const struct _cipher_descriptor rc2_desc;
+#endif
+
+#ifdef SAFERP
+extern int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+extern int saferp_test(void);
+extern int saferp_keysize(int *desired_keysize);
+extern const struct _cipher_descriptor saferp_desc;
+#endif
+
+#ifdef SAFER
+extern int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+
+extern int safer_k64_test(void);
+extern int safer_sk64_test(void);
+extern int safer_sk128_test(void);
+
+extern int safer_64_keysize(int *desired_keysize);
+extern int safer_128_keysize(int *desired_keysize);
+extern const struct _cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc;
+#endif
+
+#ifdef RIJNDAEL
+
+/* make aes an alias */
+#define aes_setup           rijndael_setup
+#define aes_ecb_encrypt     rijndael_ecb_encrypt
+#define aes_ecb_decrypt     rijndael_ecb_decrypt
+#define aes_test            rijndael_test
+#define aes_keysize         rijndael_keysize
+
+extern int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+extern int rijndael_test(void);
+extern int rijndael_keysize(int *desired_keysize);
+extern const struct _cipher_descriptor rijndael_desc, aes_desc;
+#endif
+
+#ifdef XTEA
+extern int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+extern int xtea_test(void);
+extern int xtea_keysize(int *desired_keysize);
+extern const struct _cipher_descriptor xtea_desc;
+#endif
+
+#ifdef TWOFISH
+extern int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+extern int twofish_test(void);
+extern int twofish_keysize(int *desired_keysize);
+extern const struct _cipher_descriptor twofish_desc;
+#endif
+
+#ifdef DES
+extern int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+extern int des_test(void);
+extern int des_keysize(int *desired_keysize);
+
+extern int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+extern int des3_test(void);
+extern int des3_keysize(int *desired_keysize);
+
+extern const struct _cipher_descriptor des_desc, des3_desc;
+#endif
+
+#ifdef CAST5
+extern int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+extern int cast5_test(void);
+extern int cast5_keysize(int *desired_keysize);
+extern const struct _cipher_descriptor cast5_desc;
+#endif
+
+#ifdef NOEKEON
+extern int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+extern int noekeon_test(void);
+extern int noekeon_keysize(int *desired_keysize);
+extern const struct _cipher_descriptor noekeon_desc;
+#endif
+
+#ifdef SKIPJACK
+extern int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern void skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+extern int skipjack_test(void);
+extern int skipjack_keysize(int *desired_keysize);
+extern const struct _cipher_descriptor skipjack_desc;
+#endif
+
+#ifdef ECB
+extern int ecb_start(int cipher, const unsigned char *key, 
+                     int keylen, int num_rounds, symmetric_ECB *ecb);
+extern int ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_ECB *ecb);
+extern int ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ECB *ecb);
+#endif
+
+#ifdef CFB
+extern int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, 
+                     int keylen, int num_rounds, symmetric_CFB *cfb);
+extern int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb);
+extern int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb);
+#endif
+
+#ifdef OFB
+extern int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, 
+                     int keylen, int num_rounds, symmetric_OFB *ofb);
+extern int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb);
+extern int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb);
+#endif
+
+#ifdef CBC
+extern int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
+                     int keylen, int num_rounds, symmetric_CBC *cbc);
+extern int cbc_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_CBC *cbc);
+extern int cbc_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_CBC *cbc);
+#endif
+
+#ifdef CTR
+extern int ctr_start(int cipher, const unsigned char *IV, const unsigned char *key, 
+                     int keylen, int num_rounds, symmetric_CTR *ctr);
+extern int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr);
+extern int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr);
+#endif
+
+
+    
+extern int find_cipher(const char *name);
+extern int find_cipher_any(const char *name, int blocklen, int keylen);
+extern int find_cipher_id(unsigned char ID);
+
+extern int register_cipher(const struct _cipher_descriptor *cipher);
+extern int unregister_cipher(const struct _cipher_descriptor *cipher);
+
+extern int cipher_is_valid(int idx);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt_custom.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,89 @@
+/* This header is meant to be included before mycrypt.h in projects where
+ * you don't want to throw all the defines in a makefile. 
+ */
+
+#ifndef MYCRYPT_CUSTOM_H_
+#define MYCRYPT_CUSTOM_H_
+
+#ifdef CRYPT
+	#error mycrypt_custom.h should be included before mycrypt.h
+#endif
+
+#define XMALLOC malloc
+#define XREALLOC realloc
+#define XCALLOC calloc
+#define XFREE free
+#define XCLOCK clock
+#define XCLOCKS_PER_SEC CLOCKS_PER_SEC
+#define SMALL_CODE
+#define LTC_TEST
+#define BLOWFISH
+#define RC2
+#define RC5
+#define RC6
+#define SAFERP
+#define RIJNDAEL
+#define XTEA
+#define TWOFISH
+#define TWOFISH_TABLES
+#define DES
+#define CAST5
+#define NOEKEON
+#define SKIPJACK
+#define CFB
+#define OFB
+#define ECB
+#define CBC
+#define CTR
+#define WHIRLPOOL
+#define SHA512
+#define SHA384
+#define SHA256
+#define SHA224
+#define TIGER
+#define SHA1
+#define MD5
+#define MD4
+#define MD2
+#define RIPEMD128
+#define RIPEMD160
+#define HMAC
+#define OMAC
+#define PMAC
+#define EAX_MODE
+#define OCB_MODE
+#define BASE64
+#define YARROW
+#define SPRNG
+#define RC4
+#define DEVRANDOM
+#define TRY_URANDOM_FIRST
+#define MRSA
+#define MDSA
+#define MDH
+#define MECC
+#define DH768
+#define DH1024
+#define DH1280
+#define DH1536
+#define DH1792
+#define DH2048
+#define DH2560
+#define DH3072
+#define DH4096
+#define ECC160
+#define ECC192
+#define ECC224
+#define ECC256
+#define ECC384
+#define ECC521
+#define MPI
+
+#define PKCS_1
+#define PKCS_5
+
+
+#include <mycrypt.h>
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt_gf.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,32 @@
+
+/* ---- GF(2^w) polynomial basis ---- */
+#ifdef GF
+#define   LSIZE    32   /* handle upto 1024-bit GF numbers */
+
+typedef unsigned long gf_int[LSIZE];
+typedef unsigned long *gf_intp;
+
+extern void gf_copy(gf_intp a, gf_intp b);
+extern void gf_zero(gf_intp a);
+extern int gf_iszero(gf_intp a);
+extern int gf_isone(gf_intp a);
+extern int gf_deg(gf_intp a);
+
+extern void gf_shl(gf_intp a, gf_intp b);
+extern void gf_shr(gf_intp a, gf_intp b);
+extern void gf_add(gf_intp a, gf_intp b, gf_intp c);
+extern void gf_mul(gf_intp a, gf_intp b, gf_intp c);
+extern void gf_div(gf_intp a, gf_intp b, gf_intp q, gf_intp r);
+
+extern void gf_mod(gf_intp a, gf_intp m, gf_intp b);
+extern void gf_mulmod(gf_intp a, gf_intp b, gf_intp m, gf_intp c);
+extern void gf_invmod(gf_intp A, gf_intp M, gf_intp B);
+extern void gf_sqrt(gf_intp a, gf_intp M, gf_intp b);
+extern void gf_gcd(gf_intp A, gf_intp B, gf_intp c);
+extern int gf_is_prime(gf_intp a);
+
+extern int gf_size(gf_intp a);
+extern void gf_toraw(gf_intp a, unsigned char *dst);
+extern void gf_readraw(gf_intp a, unsigned char *str, int len);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt_hash.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,447 @@
+/* ---- HASH FUNCTIONS ---- */
+#ifdef SHA512
+struct sha512_state {
+    ulong64  length, state[8];
+    unsigned long curlen;
+    unsigned char buf[128];
+};
+#endif
+
+#ifdef SHA256
+struct sha256_state {
+    ulong64 length;
+    ulong32 state[8], curlen;
+    unsigned char buf[64];
+};
+#endif
+
+#ifdef SHA1
+struct sha1_state {
+    ulong64 length;
+    ulong32 state[5], curlen;
+    unsigned char buf[64];
+};
+#endif
+
+#ifdef MD5
+struct md5_state {
+    ulong64 length;
+    ulong32 state[4], curlen;
+    unsigned char buf[64];
+};
+#endif
+
+#ifdef MD4
+struct md4_state {
+    ulong64 length;
+    ulong32 state[4], curlen;
+    unsigned char buf[64];
+};
+#endif
+
+#ifdef TIGER
+struct tiger_state {
+    ulong64 state[3], length;
+    unsigned long curlen;
+    unsigned char buf[64];
+};
+#endif
+
+#ifdef MD2
+struct md2_state {
+    unsigned char chksum[16], X[48], buf[16];
+    unsigned long curlen;
+};
+#endif
+
+#ifdef RIPEMD128
+struct rmd128_state {
+    ulong64 length;
+    unsigned char buf[64];
+    ulong32 curlen, state[4];
+};
+#endif
+
+#ifdef RIPEMD160
+struct rmd160_state {
+    ulong64 length;
+    unsigned char buf[64];
+    ulong32 curlen, state[5];
+};
+#endif
+
+#ifdef WHIRLPOOL
+struct whirlpool_state {
+    ulong64 length, state[8];
+    unsigned char buf[64];
+    ulong32 curlen;
+};
+#endif
+
+typedef union Hash_state {
+#ifdef WHIRLPOOL
+    struct whirlpool_state whirlpool;
+#endif
+#ifdef SHA512
+    struct sha512_state sha512;
+#endif
+#ifdef SHA256
+    struct sha256_state sha256;
+#endif
+#ifdef SHA1
+    struct sha1_state   sha1;
+#endif
+#ifdef MD5
+    struct md5_state    md5;
+#endif
+#ifdef MD4
+    struct md4_state    md4;
+#endif
+#ifdef MD2
+    struct md2_state    md2;
+#endif
+#ifdef TIGER
+    struct tiger_state  tiger;
+#endif
+#ifdef RIPEMD128
+    struct rmd128_state rmd128;
+#endif
+#ifdef RIPEMD160
+    struct rmd160_state rmd160;
+#endif
+} hash_state;
+
+extern struct _hash_descriptor {
+    char *name;
+    unsigned char ID;
+    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);
+} hash_descriptor[];
+
+
+#ifdef WHIRLPOOL
+extern void whirlpool_init(hash_state * md);
+extern int whirlpool_process(hash_state * md, const unsigned char *buf, unsigned long len);
+extern int whirlpool_done(hash_state * md, unsigned char *hash);
+extern int  whirlpool_test(void);
+extern const struct _hash_descriptor whirlpool_desc;
+#endif
+
+#ifdef SHA512
+extern void sha512_init(hash_state * md);
+extern int sha512_process(hash_state * md, const unsigned char *buf, unsigned long len);
+extern int sha512_done(hash_state * md, unsigned char *hash);
+extern int  sha512_test(void);
+extern const struct _hash_descriptor sha512_desc;
+#endif
+
+#ifdef SHA384
+#ifndef SHA512
+   #error SHA512 is required for SHA384
+#endif
+extern void sha384_init(hash_state * md);
+#define sha384_process sha512_process
+extern int sha384_done(hash_state * md, unsigned char *hash);
+extern int  sha384_test(void);
+extern const struct _hash_descriptor sha384_desc;
+#endif
+
+#ifdef SHA256
+extern void sha256_init(hash_state * md);
+extern int sha256_process(hash_state * md, const unsigned char *buf, unsigned long len);
+extern int sha256_done(hash_state * md, unsigned char *hash);
+extern int  sha256_test(void);
+extern const struct _hash_descriptor sha256_desc;
+
+#ifdef SHA224
+#ifndef SHA256
+   #error SHA256 is required for SHA224
+#endif
+extern void sha224_init(hash_state * md);
+#define sha224_process sha256_process
+extern int sha224_done(hash_state * md, unsigned char *hash);
+extern int  sha224_test(void);
+extern const struct _hash_descriptor sha224_desc;
+#endif
+#endif
+
+#ifdef SHA1
+extern void sha1_init(hash_state * md);
+extern int sha1_process(hash_state * md, const unsigned char *buf, unsigned long len);
+extern int sha1_done(hash_state * md, unsigned char *hash);
+extern int  sha1_test(void);
+extern const struct _hash_descriptor sha1_desc;
+#endif
+
+#ifdef MD5
+extern void md5_init(hash_state * md);
+extern int md5_process(hash_state * md, const unsigned char *buf, unsigned long len);
+extern int md5_done(hash_state * md, unsigned char *hash);
+extern int  md5_test(void);
+extern const struct _hash_descriptor md5_desc;
+#endif
+
+#ifdef MD4
+extern void md4_init(hash_state * md);
+extern int md4_process(hash_state * md, const unsigned char *buf, unsigned long len);
+extern int md4_done(hash_state * md, unsigned char *hash);
+extern int  md4_test(void);
+extern const struct _hash_descriptor md4_desc;
+#endif
+
+#ifdef MD2
+extern void md2_init(hash_state * md);
+extern int md2_process(hash_state * md, const unsigned char *buf, unsigned long len);
+extern int md2_done(hash_state * md, unsigned char *hash);
+extern int  md2_test(void);
+extern const struct _hash_descriptor md2_desc;
+#endif
+
+#ifdef TIGER
+extern void tiger_init(hash_state * md);
+extern int tiger_process(hash_state * md, const unsigned char *buf, unsigned long len);
+extern int tiger_done(hash_state * md, unsigned char *hash);
+extern int  tiger_test(void);
+extern const struct _hash_descriptor tiger_desc;
+#endif
+
+#ifdef RIPEMD128
+extern void rmd128_init(hash_state * md);
+extern int rmd128_process(hash_state * md, const unsigned char *buf, unsigned long len);
+extern int rmd128_done(hash_state * md, unsigned char *hash);
+extern int  rmd128_test(void);
+extern const struct _hash_descriptor rmd128_desc;
+#endif
+
+#ifdef RIPEMD160
+extern void rmd160_init(hash_state * md);
+extern int rmd160_process(hash_state * md, const unsigned char *buf, unsigned long len);
+extern int rmd160_done(hash_state * md, unsigned char *hash);
+extern int  rmd160_test(void);
+extern const struct _hash_descriptor rmd160_desc;
+#endif
+
+
+extern int find_hash(const char *name);
+extern int find_hash_id(unsigned char ID);
+extern int find_hash_any(const char *name, int digestlen);
+extern int register_hash(const struct _hash_descriptor *hash);
+extern int unregister_hash(const struct _hash_descriptor *hash);
+extern int hash_is_valid(int idx);
+
+extern int hash_memory(int hash, const unsigned char *data, unsigned long len, unsigned char *dst, unsigned long *outlen);
+extern int hash_filehandle(int hash, FILE *in, unsigned char *dst, unsigned long *outlen);
+extern int hash_file(int hash, const char *fname, unsigned char *dst, unsigned long *outlen);
+
+/* a simple macro for making hash "process" functions */
+#define HASH_PROCESS(func_name, compress_name, state_var, block_size)                       \
+int func_name (hash_state * md, const unsigned char *buf, unsigned long len)               \
+{                                                                                           \
+    unsigned long n;                                                                        \
+    _ARGCHK(md != NULL);                                                                    \
+    _ARGCHK(buf != NULL);                                                                   \
+    if (md-> state_var .curlen > sizeof(md-> state_var .buf)) {                             \
+       return CRYPT_INVALID_ARG;                                                            \
+    }                                                                                       \
+    while (len > 0) {                                                                       \
+        if (md-> state_var .curlen == 0 && len >= block_size) {                             \
+           compress_name (md, (unsigned char *)buf);                                        \
+           md-> state_var .length += block_size * 8;                                        \
+           buf             += block_size;                                                   \
+           len             -= block_size;                                                   \
+        } else {                                                                            \
+           n = MIN(len, (block_size - md-> state_var .curlen));                             \
+           memcpy(md-> state_var .buf + md-> state_var.curlen, buf, (size_t)n);             \
+           md-> state_var .curlen += n;                                                     \
+           buf             += n;                                                            \
+           len             -= n;                                                            \
+           if (md-> state_var .curlen == block_size) {                                      \
+              compress_name (md, md-> state_var .buf);                                      \
+              md-> state_var .length += 8*block_size;                                       \
+              md-> state_var .curlen = 0;                                                   \
+           }                                                                                \
+       }                                                                                    \
+    }                                                                                       \
+    return CRYPT_OK;                                                                        \
+}
+
+#ifdef HMAC
+typedef struct Hmac_state {
+     hash_state     md;
+     int            hash;
+     hash_state     hashstate;
+     unsigned char  key[MAXBLOCKSIZE];
+} hmac_state;
+
+extern int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen);
+extern int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len);
+extern int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen);
+extern int hmac_test(void);
+extern 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);
+extern int hmac_file(int hash, const char *fname, const unsigned char *key,
+                     unsigned long keylen, 
+                     unsigned char *dst, unsigned long *dstlen);
+#endif
+
+#ifdef OMAC
+
+typedef struct {
+   int             cipher_idx, 
+                   buflen,
+                   blklen;
+   unsigned char   block[MAXBLOCKSIZE],
+                   prev[MAXBLOCKSIZE],
+                   Lu[2][MAXBLOCKSIZE];
+   symmetric_key   key;
+} omac_state;
+
+extern int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen);
+extern int omac_process(omac_state *state, const unsigned char *buf, unsigned long len);
+extern int omac_done(omac_state *state, unsigned char *out, unsigned long *outlen);
+extern 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);
+extern int omac_file(int cipher, const unsigned char *key, unsigned long keylen,
+              const char *filename, unsigned char *out, unsigned long *outlen);
+extern int omac_test(void);
+#endif /* OMAC */
+
+#ifdef PMAC
+
+typedef struct {
+   unsigned char     Ls[32][MAXBLOCKSIZE],    /* L shifted by i bits to the left */
+                     Li[MAXBLOCKSIZE],        /* value of Li [current value, we calc from previous recall] */
+                     Lr[MAXBLOCKSIZE],        /* L * x^-1 */
+                     block[MAXBLOCKSIZE],     /* currently accumulated block */
+                     checksum[MAXBLOCKSIZE];  /* current checksum */
+
+   symmetric_key     key;                     /* scheduled key for cipher */
+   unsigned long     block_index;             /* index # for current block */
+   int               cipher_idx,              /* cipher idx */
+                     block_len,               /* length of block */
+                     buflen;                  /* number of bytes in the buffer */
+} pmac_state;
+
+extern int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen);
+extern int pmac_process(pmac_state *state, const unsigned char *buf, unsigned long len);
+extern int pmac_done(pmac_state *state, unsigned char *out, unsigned long *outlen);
+
+extern 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);
+
+extern int pmac_file(int cipher, const unsigned char *key, unsigned long keylen,
+              const char *filename, unsigned char *out, unsigned long *outlen);
+
+extern int pmac_test(void);
+
+/* internal functions */
+extern int pmac_ntz(unsigned long x);
+extern void pmac_shift_xor(pmac_state *pmac);
+
+#endif /* PMAC */
+
+#ifdef EAX_MODE
+
+#if !(defined(OMAC) && defined(CTR))
+   #error EAX_MODE requires OMAC and CTR
+#endif
+
+typedef struct {
+   unsigned char N[MAXBLOCKSIZE];
+   symmetric_CTR ctr;
+   omac_state    headeromac, ctomac;
+} eax_state;
+
+extern 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);
+
+extern int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length);
+extern int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length);
+extern int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length);
+extern int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen);
+
+extern int eax_encrypt_authenticate_memory(int cipher,
+    const unsigned char *key,    unsigned long keylen,
+    const unsigned char *nonce,  unsigned long noncelen,
+    const unsigned char *header, unsigned long headerlen,
+    const unsigned char *pt,     unsigned long ptlen,
+          unsigned char *ct,
+          unsigned char *tag,    unsigned long *taglen);
+
+extern int eax_decrypt_verify_memory(int cipher,
+    const unsigned char *key,    unsigned long keylen,
+    const unsigned char *nonce,  unsigned long noncelen,
+    const unsigned char *header, unsigned long headerlen,
+    const unsigned char *ct,     unsigned long ctlen,
+          unsigned char *pt,
+          unsigned char *tag,    unsigned long taglen,
+          int           *res);
+
+extern int eax_test(void);
+#endif /* EAX MODE */
+
+#ifdef OCB_MODE
+typedef struct {
+   unsigned char     L[MAXBLOCKSIZE],         /* L value */
+                     Ls[32][MAXBLOCKSIZE],    /* L shifted by i bits to the left */
+                     Li[MAXBLOCKSIZE],        /* value of Li [current value, we calc from previous recall] */
+                     Lr[MAXBLOCKSIZE],        /* L * x^-1 */
+                     R[MAXBLOCKSIZE],         /* R value */
+                     checksum[MAXBLOCKSIZE];  /* current checksum */
+
+   symmetric_key     key;                     /* scheduled key for cipher */
+   unsigned long     block_index;             /* index # for current block */
+   int               cipher,                  /* cipher idx */
+                     block_len;               /* length of block */
+} ocb_state;
+
+extern int ocb_init(ocb_state *ocb, int cipher, 
+             const unsigned char *key, unsigned long keylen, const unsigned char *nonce);
+
+extern int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct);
+extern int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt);
+
+extern int ocb_done_encrypt(ocb_state *ocb, 
+                     const unsigned char *pt,  unsigned long ptlen,
+                           unsigned char *ct, 
+                           unsigned char *tag, unsigned long *taglen);
+
+extern 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);
+
+extern 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);
+
+extern 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);
+
+extern int ocb_test(void);
+
+/* internal functions */
+extern void ocb_shift_xor(ocb_state *ocb, unsigned char *Z);
+extern int ocb_ntz(unsigned long x);
+extern int __ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen,
+                     unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode);
+
+#endif /* OCB_MODE */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt_kr.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,81 @@
+#ifdef KR
+
+#if !defined(MRSA) || !defined(MDH) || !defined(MECC)
+    #error "Keyring code requires all three public key algorithms."
+#endif
+
+#define MAXLEN    256
+
+enum {
+   NON_KEY=0,
+   RSA_KEY,
+   DH_KEY,
+   ECC_KEY
+};
+
+typedef union {
+    rsa_key rsa;
+    dh_key  dh;
+    ecc_key ecc;
+} _pk_key;
+
+typedef struct Pk_key {
+    int     key_type,             /* PUBLIC, PRIVATE, PRIVATE_OPTIMIZED */
+            system;               /* RSA, ECC or DH ?   */
+
+    unsigned 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;
+
+extern int kr_init(pk_key **pk);
+
+extern unsigned long kr_crc(const unsigned char *name, const unsigned char *email, const unsigned char *description);
+
+extern pk_key *kr_find(pk_key *pk, unsigned long ID);
+extern pk_key *kr_find_name(pk_key *pk, const char *name);
+
+extern int kr_add(pk_key *pk, int key_type, int sys, const unsigned char *name, 
+                  const unsigned char *email, const unsigned char *description, const _pk_key *key);
+                  
+extern int kr_del(pk_key **_pk, unsigned long ID);
+extern int kr_clear(pk_key **pk);
+extern int kr_make_key(pk_key *pk, prng_state *prng, int wprng, 
+                       int sys, int keysize, const unsigned char *name,
+                       const unsigned char *email, const unsigned char *description);
+
+extern int kr_export(pk_key *pk, unsigned long ID, int key_type, unsigned char *out, unsigned long *outlen);
+extern int kr_import(pk_key *pk, const unsigned char *in, unsigned long inlen);
+
+extern int kr_load(pk_key **pk, FILE *in, symmetric_CTR *ctr);
+extern int kr_save(pk_key *pk, FILE *out, symmetric_CTR *ctr);
+
+extern 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);
+
+extern int kr_decrypt_key(pk_key *pk, const unsigned char *in,
+                          unsigned char *out, unsigned long *outlen);
+
+extern 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);
+
+extern int kr_verify_hash(pk_key *pk, const unsigned char *in, 
+                          const unsigned char *hash, unsigned long hashlen,
+                          int *stat);
+
+extern int kr_fingerprint(pk_key *pk, unsigned long ID, int hash,
+                          unsigned char *out, unsigned long *outlen);
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt_macros.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,241 @@
+/* fix for MSVC ...evil! */
+#ifdef _MSC_VER
+   #define CONST64(n) n ## ui64
+   typedef unsigned __int64 ulong64;
+#else
+   #define CONST64(n) n ## ULL
+   typedef unsigned long long ulong64;
+#endif
+
+/* this is the "32-bit at least" data type 
+ * Re-define it to suit your platform but it must be at least 32-bits 
+ */
+typedef unsigned long ulong32;
+
+/* ---- HELPER MACROS ---- */
+#ifdef ENDIAN_NEUTRAL
+
+#define STORE32L(x, y)                                                                     \
+     { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);   \
+       (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD32L(x, y)                            \
+     { x = ((unsigned long)((y)[3] & 255)<<24) | \
+           ((unsigned long)((y)[2] & 255)<<16) | \
+           ((unsigned long)((y)[1] & 255)<<8)  | \
+           ((unsigned long)((y)[0] & 255)); }
+
+#define STORE64L(x, y)                                                                     \
+     { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255);   \
+       (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255);   \
+       (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);   \
+       (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD64L(x, y)                                                       \
+     { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
+           (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
+           (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
+           (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
+
+#define STORE32H(x, y)                                                                     \
+     { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255);   \
+       (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
+
+#define LOAD32H(x, y)                            \
+     { x = ((unsigned long)((y)[0] & 255)<<24) | \
+           ((unsigned long)((y)[1] & 255)<<16) | \
+           ((unsigned long)((y)[2] & 255)<<8)  | \
+           ((unsigned long)((y)[3] & 255)); }
+
+#define STORE64H(x, y)                                                                     \
+   { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255);     \
+     (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255);     \
+     (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255);     \
+     (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
+
+#define LOAD64H(x, y)                                                      \
+   { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
+         (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
+         (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
+         (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
+
+#endif /* ENDIAN_NEUTRAL */
+
+#ifdef ENDIAN_LITTLE
+
+#define STORE32H(x, y)                                                                     \
+     { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255);   \
+       (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
+
+#define LOAD32H(x, y)                            \
+     { x = ((unsigned long)((y)[0] & 255)<<24) | \
+           ((unsigned long)((y)[1] & 255)<<16) | \
+           ((unsigned long)((y)[2] & 255)<<8)  | \
+           ((unsigned long)((y)[3] & 255)); }
+
+#define STORE64H(x, y)                                                                     \
+   { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255);     \
+     (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255);     \
+     (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255);     \
+     (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
+
+#define LOAD64H(x, y)                                                      \
+   { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
+         (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
+         (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
+         (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
+
+#ifdef ENDIAN_32BITWORD 
+
+#define STORE32L(x, y)        \
+     { unsigned long __t = (x); memcpy(y, &__t, 4); }
+
+#define LOAD32L(x, y)         \
+     memcpy(&(x), y, 4);
+
+#define STORE64L(x, y)                                                                     \
+     { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255);   \
+       (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255);   \
+       (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);   \
+       (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD64L(x, y)                                                       \
+     { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
+           (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
+           (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
+           (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
+
+#else /* 64-bit words then  */
+
+#define STORE32L(x, y)        \
+     { unsigned long __t = (x); memcpy(y, &__t, 4); }
+
+#define LOAD32L(x, y)         \
+     { memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
+
+#define STORE64L(x, y)        \
+     { ulong64 __t = (x); memcpy(y, &__t, 8); }
+
+#define LOAD64L(x, y)         \
+    { memcpy(&(x), y, 8); }
+
+#endif /* ENDIAN_64BITWORD */
+
+#endif /* ENDIAN_LITTLE */
+
+#ifdef ENDIAN_BIG
+#define STORE32L(x, y)                                                                     \
+     { (y)[z0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255);   \
+       (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
+
+#define LOAD32L(x, y)                            \
+     { x = ((unsigned long)((y)[0] & 255)<<24) | \
+           ((unsigned long)((y)[1] & 255)<<16) | \
+           ((unsigned long)((y)[2] & 255)<<8)  | \
+           ((unsigned long)((y)[3] & 255)); }
+
+#define STORE64L(x, y)                                                                     \
+   { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255);     \
+     (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255);     \
+     (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255);     \
+     (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
+
+#define LOAD64L(x, y)                                                      \
+   { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
+         (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
+         (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
+         (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
+
+#ifdef ENDIAN_32BITWORD 
+
+#define STORE32H(x, y)        \
+     { unsigned long __t = (x); memcpy(y, &__t, 4); }
+
+#define LOAD32H(x, y)         \
+     memcpy(&(x), y, 4);
+
+#define STORE64H(x, y)                                                                     \
+     { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255);   \
+       (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255);   \
+       (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);   \
+       (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD64H(x, y)                                                       \
+     { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
+           (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
+           (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
+           (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
+
+#else /* 64-bit words then  */
+
+#define STORE32H(x, y)        \
+     { unsigned long __t = (x); memcpy(y, &__t, 4); }
+
+#define LOAD32H(x, y)         \
+     { memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
+
+#define STORE64H(x, y)        \
+     { ulong64 __t = (x); memcpy(y, &__t, 8); }
+
+#define LOAD64H(x, y)         \
+    { memcpy(&(x), y, 8); }
+
+#endif /* ENDIAN_64BITWORD */
+#endif /* ENDIAN_BIG */
+
+#define BSWAP(x)  ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL)  | \
+                    ((x>>8)&0x0000FF00UL)  | ((x<<8)&0x00FF0000UL) )
+
+#ifdef _MSC_VER
+
+/* instrinsic rotate */
+#include <stdlib.h>
+#pragma intrinsic(_lrotr,_lrotl)
+#define ROR(x,n) _lrotr(x,n)
+#define ROL(x,n) _lrotl(x,n)
+
+#elif defined(__GNUC__) && defined(__i386__) && !defined(INTEL_CC)
+
+static inline unsigned long ROL(unsigned long word, int i)
+{
+   __asm__("roll %%cl,%0"
+      :"=r" (word)
+      :"0" (word),"c" (i));
+   return word;
+}
+
+static inline unsigned long ROR(unsigned long word, int i)
+{
+   __asm__("rorl %%cl,%0"
+      :"=r" (word)
+      :"0" (word),"c" (i));
+   return word;
+}
+
+#else
+
+/* rotates the hard way */
+#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+
+#endif
+
+#define ROL64(x, y) \
+    ( (((x)<<((ulong64)(y)&63)) | \
+      (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#define ROR64(x, y) \
+    ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
+      ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#undef MAX
+#undef MIN
+#define MAX(x, y) ( ((x)>(y))?(x):(y) )
+#define MIN(x, y) ( ((x)<(y))?(x):(y) )
+
+/* extract a byte portably */
+#ifdef _MSC_VER
+   #define byte(x, n) ((unsigned char)((x) >> (8 * (n))))
+#else
+   #define byte(x, n) (((x) >> (8 * (n))) & 255)
+#endif   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt_misc.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,17 @@
+/* ---- BASE64 Routines ---- */
+#ifdef BASE64
+extern int base64_encode(const unsigned char *in,  unsigned long len, 
+                               unsigned char *out, unsigned long *outlen);
+
+extern int base64_decode(const unsigned char *in,  unsigned long len, 
+                               unsigned char *out, unsigned long *outlen);
+#endif
+
+/* ---- MEM routines ---- */
+extern void zeromem(void *dst, size_t len);
+extern void burn_stack(unsigned long len);
+
+extern const char *error_to_string(int err);
+extern int mpi_to_ltc_error(int err);
+
+extern const char *crypt_build_settings;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt_pk.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,245 @@
+/* ---- NUMBER THEORY ---- */
+#ifdef MPI
+
+#include "tommath.h"
+
+/* in/out macros */
+#define OUTPUT_BIGNUM(num, out, y, z)                                                             \
+{                                                                                                 \
+      if ((y + 4) > *outlen) { return CRYPT_BUFFER_OVERFLOW; }                                    \
+      z = (unsigned long)mp_unsigned_bin_size(num);                                               \
+      STORE32L(z, out+y);                                                                         \
+      y += 4;                                                                                     \
+      if ((y + z) > *outlen) { return CRYPT_BUFFER_OVERFLOW; }                                    \
+      if ((err = mp_to_unsigned_bin(num, out+y)) != MP_OKAY) { return mpi_to_ltc_error(err); }    \
+      y += z;                                                                                     \
+}
+
+
+#define INPUT_BIGNUM(num, in, x, y, inlen)                       \
+{                                                                \
+     /* load value */                                            \
+     if ((y + 4) > inlen) {                                      \
+        err = CRYPT_INVALID_PACKET;                              \
+        goto error;                                              \
+     }                                                           \
+     LOAD32L(x, in+y);                                           \
+     y += 4;                                                     \
+                                                                 \
+     /* sanity check... */                                       \
+     if ((x+y) > inlen) {                                        \
+        err = CRYPT_INVALID_PACKET;                              \
+        goto error;                                              \
+     }                                                           \
+                                                                 \
+     /* load it */                                               \
+     if ((err = mp_read_unsigned_bin(num, (unsigned char *)in+y, (int)x)) != MP_OKAY) {\
+        err = mpi_to_ltc_error(err);                             \
+        goto error;                                              \
+     }                                                           \
+     y += x;                                                     \
+     if ((err = mp_shrink(num)) != MP_OKAY) {                    \
+        err = mpi_to_ltc_error(err);                             \
+        goto error;                                              \
+     }                                                           \
+}
+
+extern int is_prime(mp_int *, int *);
+extern int rand_prime(mp_int *N, long len, prng_state *prng, int wprng);
+
+#else
+   #ifdef MRSA
+      #error RSA requires the big int library 
+   #endif
+   #ifdef MECC
+      #error ECC requires the big int library 
+   #endif
+   #ifdef MDH
+      #error DH requires the big int library 
+   #endif
+   #ifdef MDSA
+      #error DSA requires the big int library 
+   #endif
+#endif /* MPI */
+
+
+/* ---- PUBLIC KEY CRYPTO ---- */
+
+#define PK_PRIVATE            0        /* PK private keys */
+#define PK_PUBLIC             1        /* PK public keys */
+#define PK_PRIVATE_OPTIMIZED  2        /* PK private key [rsa optimized] */
+
+/* ---- PACKET ---- */
+#ifdef PACKET
+
+extern void packet_store_header(unsigned char *dst, int section, int subsection);
+extern int packet_valid_header(unsigned char *src, int section, int subsection);
+
+#endif
+
+
+/* ---- RSA ---- */
+#ifdef MRSA
+
+/* Min and Max RSA key sizes (in bits) */
+#define MIN_RSA_SIZE 1024
+#define MAX_RSA_SIZE 4096
+
+/* Stack required for temps (plus padding) */
+#define RSA_STACK    (8 + (MAX_RSA_SIZE/8))
+
+typedef struct Rsa_key {
+    int type;
+    mp_int e, d, N, qP, pQ, dP, dQ, p, q;
+} rsa_key;
+
+extern int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key);
+
+extern int rsa_exptmod(const unsigned char *in,  unsigned long inlen, 
+                             unsigned char *out, unsigned long *outlen, int which, 
+                             rsa_key *key);
+
+extern int rsa_pad(const unsigned char *in,  unsigned long inlen, 
+                         unsigned char *out, unsigned long *outlen, 
+                         int wprng, prng_state *prng);
+
+extern int rsa_signpad(const unsigned char *in,  unsigned long inlen, 
+                             unsigned char *out, unsigned long *outlen);
+
+extern int rsa_depad(const unsigned char *in,  unsigned long inlen, 
+                           unsigned char *out, unsigned long *outlen);
+
+extern int rsa_signdepad(const unsigned char *in,  unsigned long inlen,
+                               unsigned char *out, unsigned long *outlen);
+
+
+extern void rsa_free(rsa_key *key);
+
+extern 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);
+
+extern int rsa_decrypt_key(const unsigned char *in, unsigned long inlen,
+                                 unsigned char *outkey, unsigned long *keylen, 
+                                 rsa_key *key);
+
+extern int rsa_sign_hash(const unsigned char *in,  unsigned long inlen, 
+                               unsigned char *out, unsigned long *outlen, 
+                               rsa_key *key);
+
+extern int rsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+                           const unsigned char *hash, int *stat, rsa_key *key);
+
+extern int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key);
+extern int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key);
+#endif
+
+/* ---- DH Routines ---- */
+#ifdef MDH 
+
+typedef struct Dh_key {
+    int idx, type;
+    mp_int x, y;
+} dh_key;
+
+extern int dh_test(void);
+extern void dh_sizes(int *low, int *high);
+extern int dh_get_size(dh_key *key);
+
+extern int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key);
+extern void dh_free(dh_key *key);
+
+extern int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key);
+extern int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key);
+
+extern int dh_shared_secret(dh_key *private_key, dh_key *public_key,
+                            unsigned char *out, unsigned long *outlen);
+
+extern 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);
+
+extern int dh_decrypt_key(const unsigned char *in,  unsigned long inlen, 
+                                unsigned char *outkey, unsigned long *keylen, 
+                                dh_key *key);
+
+extern 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);
+
+extern int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
+                          const unsigned char *hash, unsigned long hashlen, 
+                                int *stat, dh_key *key);
+
+
+#endif
+
+/* ---- ECC Routines ---- */
+#ifdef MECC
+typedef struct {
+    mp_int x, y;
+} ecc_point;
+
+typedef struct {
+    int type, idx;
+    ecc_point pubkey;
+    mp_int k;
+} ecc_key;
+
+extern int ecc_test(void);
+extern void ecc_sizes(int *low, int *high);
+extern int ecc_get_size(ecc_key *key);
+
+extern int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);
+extern void ecc_free(ecc_key *key);
+
+extern int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
+extern int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
+
+extern int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, 
+                             unsigned char *out, unsigned long *outlen);
+
+extern 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);
+
+extern int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
+                                 unsigned char *outkey, unsigned long *keylen, 
+                                 ecc_key *key);
+
+extern 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);
+
+extern int ecc_verify_hash(const unsigned char *sig,  unsigned long siglen,
+                           const unsigned char *hash, unsigned long hashlen, 
+                                 int *stat, ecc_key *key);
+#endif
+
+#ifdef MDSA
+
+typedef struct {
+   int type, qord;
+   mp_int g, q, p, x, y;
+} dsa_key;
+
+extern int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key);
+extern void dsa_free(dsa_key *key);
+
+extern 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);
+
+extern int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+                           const unsigned char *hash, unsigned long inlen, 
+                           int *stat, dsa_key *key);
+
+extern int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);
+
+extern int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key);
+
+extern int dsa_verify_key(dsa_key *key, int *stat);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt_pkcs.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,53 @@
+/* PKCS Header Info */
+
+/* ===> PKCS #1 -- RSA Cryptography <=== */
+#ifdef PKCS_1
+
+int pkcs_1_mgf1(const unsigned char *seed, unsigned long seedlen,
+                      int            hash_idx,
+                      unsigned char *mask, unsigned long masklen);
+
+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);
+
+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);
+
+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);
+
+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);
+
+int pkcs_1_i2osp(mp_int *n, unsigned long modulus_len, unsigned char *out);
+int pkcs_1_os2ip(mp_int *n, unsigned char *in, unsigned long inlen);
+
+
+#endif /* PKCS_1 */
+
+/* ===> PKCS #5 -- Password Based Cryptography <=== */
+#ifdef PKCS_5
+
+/* Algorithm #1 (old) */
+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);
+
+/* Algorithm #2 (new) */
+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);
+
+#endif  /* PKCS_5 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt_prng.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,66 @@
+/* ---- PRNG Stuff ---- */
+struct yarrow_prng {
+    int                   cipher, hash;
+    unsigned char         pool[MAXBLOCKSIZE];
+    symmetric_CTR         ctr;
+};
+
+struct rc4_prng {
+    int x, y;
+    unsigned char buf[256];
+};
+
+typedef union Prng_state {
+    struct yarrow_prng    yarrow;
+    struct rc4_prng       rc4;
+} prng_state;
+
+extern 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 *);
+} prng_descriptor[];
+
+#ifdef YARROW
+extern int yarrow_start(prng_state *prng);
+extern int yarrow_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
+extern int yarrow_ready(prng_state *prng);
+extern unsigned long yarrow_read(unsigned char *buf, unsigned long len, prng_state *prng);
+extern const struct _prng_descriptor yarrow_desc;
+#endif
+
+#ifdef RC4
+extern int rc4_start(prng_state *prng);
+extern int rc4_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
+extern int rc4_ready(prng_state *prng);
+extern unsigned long rc4_read(unsigned char *buf, unsigned long len, prng_state *prng);
+extern const struct _prng_descriptor rc4_desc;
+#endif
+
+#ifdef SPRNG
+extern int sprng_start(prng_state *prng);
+extern int sprng_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
+extern int sprng_ready(prng_state *prng);
+extern unsigned long sprng_read(unsigned char *buf, unsigned long len, prng_state *prng);
+extern const struct _prng_descriptor sprng_desc;
+#endif
+
+extern int find_prng(const char *name);
+extern int register_prng(const struct _prng_descriptor *prng);
+extern int unregister_prng(const struct _prng_descriptor *prng);
+extern int prng_is_valid(int idx);
+
+
+/* Slow RNG you **might** be able to use to seed a PRNG with.  Be careful as this
+ * might not work on all platforms as planned
+ */
+/* ch2-02-1 */ 
+extern unsigned long rng_get_bytes(unsigned char *buf, 
+                                   unsigned long len, 
+                                   void (*callback)(void));
+/* ch2-02-1 */
+
+extern int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/noekeon.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,270 @@
+/* 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 the Noekeon block cipher by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef NOEKEON
+
+const struct _cipher_descriptor noekeon_desc =
+{
+    "noekeon",
+    16,
+    16, 16, 16, 16,
+    &noekeon_setup,
+    &noekeon_ecb_encrypt,
+    &noekeon_ecb_decrypt,
+    &noekeon_test,
+    &noekeon_keysize
+};
+
+static const ulong32 RC[] = {
+   0x00000080UL, 0x0000001bUL, 0x00000036UL, 0x0000006cUL,
+   0x000000d8UL, 0x000000abUL, 0x0000004dUL, 0x0000009aUL,
+   0x0000002fUL, 0x0000005eUL, 0x000000bcUL, 0x00000063UL,
+   0x000000c6UL, 0x00000097UL, 0x00000035UL, 0x0000006aUL,
+   0x000000d4UL 
+};
+
+
+#define kTHETA(a, b, c, d)                                 \
+    temp = a^c; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \
+    b ^= temp; d ^= temp;                                  \
+    temp = b^d; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \
+    a ^= temp; c ^= temp;
+
+#define THETA(k, a, b, c, d)                               \
+    temp = a^c; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \
+    b ^= temp ^ k[1]; d ^= temp ^ k[3];                    \
+    temp = b^d; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \
+    a ^= temp ^ k[0]; c ^= temp ^ k[2];
+    
+#define GAMMA(a, b, c, d)     \
+    b ^= ~(d|c);              \
+    a ^= c&b;                 \
+    temp = d; d = a; a = temp;\
+    c ^= a ^ b ^ d;           \
+    b ^= ~(d|c);              \
+    a ^= c&b;
+    
+#define PI1(a, b, c, d) \
+    a = ROL(a, 1); c = ROL(c, 5); d = ROL(d, 2);
+    
+#define PI2(a, b, c, d) \
+    a = ROR(a, 1); c = ROR(c, 5); d = ROR(d, 2);
+    
+int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+   ulong32 temp;
+   
+   _ARGCHK(key != NULL);
+   _ARGCHK(skey != NULL);
+   
+   if (keylen != 16) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+   
+   if (num_rounds != 16 && num_rounds != 0) {
+      return CRYPT_INVALID_ROUNDS;
+   }
+   
+   LOAD32H(skey->noekeon.K[0],&key[0]);
+   LOAD32H(skey->noekeon.K[1],&key[4]);
+   LOAD32H(skey->noekeon.K[2],&key[8]);
+   LOAD32H(skey->noekeon.K[3],&key[12]);
+   
+   LOAD32H(skey->noekeon.dK[0],&key[0]);
+   LOAD32H(skey->noekeon.dK[1],&key[4]);
+   LOAD32H(skey->noekeon.dK[2],&key[8]);
+   LOAD32H(skey->noekeon.dK[3],&key[12]);
+
+   kTHETA(skey->noekeon.dK[0], skey->noekeon.dK[1], skey->noekeon.dK[2], skey->noekeon.dK[3]);
+
+   return CRYPT_OK;
+}
+
+#ifdef CLEAN_STACK
+static void _noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#else
+void noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#endif
+{
+   ulong32 a,b,c,d,temp;
+#ifdef SMALL_CODE
+   int r;
+#endif
+
+   _ARGCHK(key != NULL);
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   
+   LOAD32H(a,&pt[0]); LOAD32H(b,&pt[4]);
+   LOAD32H(c,&pt[8]); LOAD32H(d,&pt[12]);
+   
+#define ROUND(i) \
+       a ^= RC[i]; \
+       THETA(key->noekeon.K, a,b,c,d); \
+       PI1(a,b,c,d); \
+       GAMMA(a,b,c,d); \
+       PI2(a,b,c,d);
+
+#ifdef SMALL_CODE
+   for (r = 0; r < 16; ++r) {
+       ROUND(r);
+   }
+#else 
+   ROUND( 0); ROUND( 1); ROUND( 2); ROUND( 3);
+   ROUND( 4); ROUND( 5); ROUND( 6); ROUND( 7);
+   ROUND( 8); ROUND( 9); ROUND(10); ROUND(11);
+   ROUND(12); ROUND(13); ROUND(14); ROUND(15);
+#endif
+
+#undef ROUND
+
+   a ^= RC[16];
+   THETA(key->noekeon.K, a, b, c, d);
+   
+   STORE32H(a,&ct[0]); STORE32H(b,&ct[4]);
+   STORE32H(c,&ct[8]); STORE32H(d,&ct[12]);
+}
+
+#ifdef CLEAN_STACK
+void noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+{
+   _noekeon_ecb_encrypt(pt, ct, key);
+   burn_stack(sizeof(ulong32) * 5 + sizeof(int));
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#else
+void noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#endif
+{
+   ulong32 a,b,c,d, temp;
+#ifdef SMALL_CODE
+   int r;
+#endif
+
+   _ARGCHK(key != NULL);
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   
+   LOAD32H(a,&ct[0]); LOAD32H(b,&ct[4]);
+   LOAD32H(c,&ct[8]); LOAD32H(d,&ct[12]);
+   
+
+#define ROUND(i) \
+       THETA(key->noekeon.dK, a,b,c,d); \
+       a ^= RC[i]; \
+       PI1(a,b,c,d); \
+       GAMMA(a,b,c,d); \
+       PI2(a,b,c,d); 
+
+#ifdef SMALL_CODE
+   for (r = 16; r > 0; --r) {
+       ROUND(r);
+   }
+#else
+   ROUND(16); ROUND(15); ROUND(14); ROUND(13);
+   ROUND(12); ROUND(11); ROUND(10); ROUND( 9);
+   ROUND( 8); ROUND( 7); ROUND( 6); ROUND( 5);
+   ROUND( 4); ROUND( 3); ROUND( 2); ROUND( 1);
+#endif
+   
+#undef ROUND
+
+   THETA(key->noekeon.dK, a,b,c,d);
+   a ^= RC[0];
+   STORE32H(a,&pt[0]); STORE32H(b, &pt[4]);
+   STORE32H(c,&pt[8]); STORE32H(d, &pt[12]);
+}
+
+#ifdef CLEAN_STACK
+void noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+{
+   _noekeon_ecb_decrypt(ct, pt, key);
+   burn_stack(sizeof(ulong32) * 5 + sizeof(int));
+}
+#endif
+
+int noekeon_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else
+ static const struct {
+     int keylen;
+     unsigned char key[16], pt[16], ct[16];
+ } tests[] = {
+   {
+      16,
+      { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+      { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+      { 0x18, 0xa6, 0xec, 0xe5, 0x28, 0xaa, 0x79, 0x73,
+        0x28, 0xb2, 0xc0, 0x91, 0xa0, 0x2f, 0x54, 0xc5}
+   }
+ };
+ symmetric_key key;
+ unsigned char tmp[2][16];
+ int err, i, y;
+ 
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+    zeromem(&key, sizeof(key));
+    if ((err = noekeon_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { 
+       return err;
+    }
+  
+    noekeon_ecb_encrypt(tests[i].pt, tmp[0], &key);
+    noekeon_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++) noekeon_ecb_encrypt(tmp[0], tmp[0], &key);
+      for (y = 0; y < 1000; y++) noekeon_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 noekeon_keysize(int *desired_keysize)
+{
+   _ARGCHK(desired_keysize != NULL);
+   if (*desired_keysize < 16) {
+      return CRYPT_INVALID_KEYSIZE;
+   } else {
+      *desired_keysize = 16;
+      return CRYPT_OK;
+   }
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/base64_tv.txt	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,35 @@
+Base64 vectors.  These are the base64 encodings of the strings 00,01,02...NN-1
+
+ 0: 
+ 1: AA==
+ 2: AAE=
+ 3: AAEC
+ 4: AAECAw==
+ 5: AAECAwQ=
+ 6: AAECAwQF
+ 7: AAECAwQFBg==
+ 8: AAECAwQFBgc=
+ 9: AAECAwQFBgcI
+10: AAECAwQFBgcICQ==
+11: AAECAwQFBgcICQo=
+12: AAECAwQFBgcICQoL
+13: AAECAwQFBgcICQoLDA==
+14: AAECAwQFBgcICQoLDA0=
+15: AAECAwQFBgcICQoLDA0O
+16: AAECAwQFBgcICQoLDA0ODw==
+17: AAECAwQFBgcICQoLDA0ODxA=
+18: AAECAwQFBgcICQoLDA0ODxAR
+19: AAECAwQFBgcICQoLDA0ODxAREg==
+20: AAECAwQFBgcICQoLDA0ODxAREhM=
+21: AAECAwQFBgcICQoLDA0ODxAREhMU
+22: AAECAwQFBgcICQoLDA0ODxAREhMUFQ==
+23: AAECAwQFBgcICQoLDA0ODxAREhMUFRY=
+24: AAECAwQFBgcICQoLDA0ODxAREhMUFRYX
+25: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGA==
+26: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBk=
+27: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBka
+28: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGw==
+29: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxw=
+30: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwd
+31: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHg==
+32: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/cipher_tv.txt	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,1539 @@
+Cipher Test Vectors
+
+These are test encryptions with key of nn bytes '00 01 02 03 .. (nn-1)' and original PT of the same style.
+The output of step N is used as the key and plaintext for step N+1 (key bytes repeated as required to fill the key)
+
+Cipher: aes
+Key Size: 16 bytes
+ 0: 0A940BB5416EF045F1C39458C653EA5A
+ 1: 2B20AF92A928562CF645B1B824F2E6D9
+ 2: FC29C3356937ECC3159D8D6EF5E883A1
+ 3: 4C07B5A2EF31A3229C87AB2E4DE88602
+ 4: 93AFA1147E793FFCC3D852695A62D008
+ 5: D4BCC317DC9AFE0E6C7AD1E76F79DBE9
+ 6: FEDB3371F3C65162AFCCDC6D18C79A65
+ 7: 4AF2A76F93F07C14161C16B5C176E439
+ 8: 00A1A596AF7CF44FD12981FA12CB1515
+ 9: 8013D7006AB38AEBD40D0DC10328751C
+10: 81A077F3A262FA4D00D98EE4D1BEC390
+11: 0CCBC99A3135F26D2BE824D633C0366F
+12: CDBB5568610AD428706408B64DB66E50
+13: CE94461EB0D57C8DB6AEB2BC8E8CE1D2
+14: 06F14868F4298979462595C0FBF33F5A
+15: FE22A7097513246074B7C8DFD57D32B2
+16: 0F2D936610F6D9E32C0E624568BB8E6F
+17: F32BCD92B563D475E98322E5850AC277
+18: 6E6FCB72930D81469F9E05B20FD406C0
+19: 42FF674CBA6C19C4AD84D42816173099
+20: 41C12474A49B6B2B5E7D38E03A4DD4E0
+21: F9E234E3CE3FCED184C775B6140AD733
+22: 7EB5CC6B183D8B3EB4FBA4717CD8838A
+23: CB6C5D78F9721E5BF8E980F0EDCAD4AF
+24: B3F20EF6C26FD9301576D82DA6D50809
+25: F9375037377D86599FB4F241166C43E9
+26: 98BAF9AB7402479C2DA356F5DAE35D5F
+27: 58D1A8E0DC3BC53FD995BB0F60F25FE7
+28: 0A75C0D22D2627C97BA2A7344B9B8C74
+29: 88C299B2F8C9EDAF86A301BBF534BDA7
+30: 755E3A17420281F2C619588A6B521FF9
+31: 0E540DD25C0C147461146E11F832A63D
+32: DC5B58691C6BA5B243036A41301BD7D1
+33: E9299A7336C2D8A51D6C7E2BD1B8F054
+34: 78CA6F682FC649DB289DD62D28D3A22D
+35: 98D96EDA081DE416083650B22BD3869D
+36: E747DE96D122CE1EF6F89BDE0FAE75FF
+37: E48DDF2EDDEB54C861A1E42F5B649EEE
+38: C650C2CF1E903B7F9C8536A2446CA762
+39: CF0BCDCE0F1FE7EB40016C1231FB2962
+40: 37B1C8BE3812147E0D5D115A797663EF
+41: 45DD8184581049C4B28FBC0809690C5D
+42: 11B0D889F96E677EEC2E934E9F7F5398
+43: CEC30BC1128A96CD506E406B5ADFAE19
+44: DE67D5439BF83D5338D53F362FCF79B6
+45: 724FBB2D95CBEABC568AA44941D9B6E5
+46: C63F480DA3C73B2A661F1FBC3E4D1F89
+47: 225CD18789D18FF09C982EF38AEF0AAF
+48: B493DEC7E3D11911DEF8788102453670
+49: 23E0B12A67DF025CB77CBDF9E295FCAF
+
+Key Size: 24 bytes
+ 0: 0060BFFE46834BB8DA5CF9A61FF220AE
+ 1: 597FA00D03EDDC81C2575B4DD6B6AEFD
+ 2: 4881E4EF69005DCB9110BA327CAC8460
+ 3: FC4A968AF65FCFF45E4698455918673D
+ 4: 3079D7B27A3DA5C0805A61CC37109EE0
+ 5: 9B3F2C7C35806276E2C53826EC1B3C84
+ 6: FCDFCB1FD9FCF1B63E1AB6737FC154E8
+ 7: 4A8012AFD410D29CE2CEE0FD195EF9DA
+ 8: 9F4201C4174C71A3AEF8FD6822197D67
+ 9: DE3E5E98DA60E895389A1C17E3D50DA1
+10: 20C9064A076C01D1BC121A5A2A1F913C
+11: BA41A36CD24B515545B8B464B244E5BE
+12: 2CC1DE9DBCAC45269C6DBBC9203095F4
+13: 2ED2499CFEB30203E6305B3E1C329C4D
+14: FD709FC0AB48B204C95B74AD189C8832
+15: 7ED298B472C53A4CB7A3BAE588805E86
+16: CB0C6FE2BA76901F9EDE752634DCC31D
+17: 6C5CA6EFCF7101881507AB8770ACF1DE
+18: DEC3C5209E98BBFAA469C5FE6C02A674
+19: CFAC040C1198C8264679CACEAA7E9DE7
+20: EF990992EBA8ECA7E5F95E3B9D69D3A4
+21: 8FC1B640EB55A96D08D83D1184B77769
+22: E1F3DFB9D055BCB2D6CED6DCB8361BFB
+23: 6621F47057706F2A079819DBC0197B9C
+24: 882611AC68778CBD6A46FB5DD4611A37
+25: F35E1367A283CC641FBCE26512A8F2F1
+26: 5A4A71F69056CFBAB67DDA777F5CD945
+27: C446F2BFAD060A9E9E17F71B05ADABD0
+28: 1F0E50F71A67FAA7D169A7A1017FFD65
+29: A6A38588848915509451A2354D2AAC8E
+30: 4C887574F2C5DB00ED4FBAF814A70302
+31: 1B642944162A049CCA9FD0284D7AB4C3
+32: 431BD9293C5BFD12F948C255C838880B
+33: 32CD23A30039AE2FB80B804B905362B1
+34: EBB30E07E7517580A645CD1B5F664182
+35: 292F2BB28BB172620B05C7621BA347D6
+36: 46C06E1223F392D57B98EFCF4C832C18
+37: 451DFBAD2AA92080204F85432236A42C
+38: 768D6206D2B3DD1B9C26FAA5977A6477
+39: 3705F9CEBFE8F91ECE07F84578C05494
+40: 085EB0DCF360F5403FF1E7402A0F7A03
+41: 2A0D56F2E7C7FCE3095F511BDE4AD9A2
+42: A8AB2F3643A61AF164F99FEFAE2CE1B4
+43: E73FD4B1FAE0E5E6A6A31CCC2AF96386
+44: 578E84FD1AA16FF350374E4FD5FDD529
+45: EEAE301DD57084801DB01F8B9C4036CE
+46: 1C44A93B404298327857F71962E0604C
+47: B5F64CD5835C85A68DC23E26D4B8FF80
+48: 6C6F97850A87088AF195D0500B3F5D78
+49: 0BAB3A60A25CD1A750C2C443AA01C57A
+
+Key Size: 32 bytes
+ 0: 5A6E045708FB7196F02E553D02C3A692
+ 1: 5F7229D6AACF0DAFE3B518C0D4ADBAB4
+ 2: 96477F47C0A6F482AC4036D2C60FAAD8
+ 3: 7F791D54914F12E9F0D92F4416EFBEC0
+ 4: 87DDB19415BEDC42BD361FE380553C5A
+ 5: 8EDB2A09DC8731DB76D9F67A03AC4D9E
+ 6: 269A7C08C28D5E4D9355DDBA161F862E
+ 7: 042A3397BA5029C443DD76755008DB2A
+ 8: 469C82A94BC5F7B2DF57F0CE1716EE74
+ 9: 5A84A93077FA19146078310035F4B7E4
+10: 28CAF1C0D811F86CFD3C5EFC30DF79F9
+11: 05B575D06C2D593B708F7C695CE97571
+12: B7E8CACF0A0BD7F2F5DA0B09CC8B8AEC
+13: 0ADDE90F66F1BCF38CEC63EFBF9DBD46
+14: 9BF99E7F5B8F176DD686AF017D5196E2
+15: ABC189EE80D4A4588B3D54DDACCD9778
+16: A57405378580B1E8A8D877791300374C
+17: D1EF03F72FAB3DB68022FC60A2CEC13D
+18: 3D2406231BA17FF7CC973C5E203872DF
+19: C3E07233BD101502953D6186001838E4
+20: DC281C0CE02A83098C80D6C9463F3449
+21: A923023D2390B2230FCE9217776AAAFC
+22: 92E28E69009959FB84046C5ED1B64D1A
+23: CEF8F684EC64A31C651280CDC942DFC2
+24: 5A954684B22691F9CFC60442A654EF61
+25: 56A38A0D93188BAA50DFAF2CB799A76C
+26: 54503340C5DE26679AA5F35215DE85EA
+27: E74BFAF64946DFD699583FF9C47A1EAF
+28: 01F234F9868B085E9B1A2EC84738E2DB
+29: BBCA3DAEAB24EF25BC7B623F4D9FD680
+30: 3956C880F7F7D94ABC259D3D86157F27
+31: 4672C2149054C839C537BDA1F5BBF8F4
+32: CF1E9ACBEB391062593BD88C7948F64D
+33: CA5B4E867AE9D8BA2D4416C908EB99F1
+34: 36666180C768636CF1708CC5C85A6875
+35: 53E396D2755218675494C7AA515A2310
+36: C2B7D31A59A602A65E155F80353DB83D
+37: 0EBCE19FF6FC03E327A2602F858D835E
+38: E47CC2A5E6C7FEF185806E2CFB304D91
+39: D61F15FF75E0F523FA3872132A09AF42
+40: DCC25495052980986AE30756BA0417DA
+41: 451BF5B7C1F1AED9F3D5E18A391EA4DA
+42: 1B6B105C580083D23F3A8EACE41B7984
+43: 8C2F86CD6C86B67C9EBDCAFC5720E4F8
+44: 41360BDB3E4C6836BE0D15B659CEC5AA
+45: F972104AD851BAE0AD963817A3F03F58
+46: 396095F7C102B5A238110DD3D6D4ADFF
+47: F58391AEB9A5D8BB32A3055B37556E81
+48: A23789B146CE89C876F3C331901261D8
+49: 2684AF345C4B13FA154E93A3E2CD2A90
+
+
+Cipher: blowfish
+Key Size: 8 bytes
+ 0: 84BF44A1442B8217
+ 1: 3981205BDD22C01E
+ 2: 0ACC5CCBA118CD07
+ 3: DF76980D5E089145
+ 4: A8503E8D849C599D
+ 5: 5E56574687038F5F
+ 6: D63296B036996F50
+ 7: FD2FD7A0669A9E7A
+ 8: BC6583720A962585
+ 9: 4B38C2856256103E
+10: 48A4FA354DB3A8A6
+11: EF97C32734BE2A10
+12: A7467E9C729F8123
+13: 04D2507F9C4B5854
+14: 57F76A4D406B22D1
+15: ED0A3B26D842C8F2
+16: 047CB457E9730CD1
+17: 9F13BB1A97BF5E2F
+18: 628CA4F77161C95A
+19: 37C7D8EF718DFD50
+20: 2C9A9C655B839B1E
+21: AB222D66579DBE0D
+22: 57950CDEAD6FAE88
+23: 67AAB3669431E403
+24: 6B35C87144F6B748
+25: 94C2E8A1DBC963C2
+26: ECD68F56EED1F78E
+27: 2E7BE0B866B1D3C7
+28: 6671DCDCB3D8EED4
+29: 8ACBE7A2F77FBB35
+30: 0BF0AC4EAE284F93
+31: 29928AE5DC8A57C6
+32: 84E48C27E21264DF
+33: 4EF0E943E4F48ED3
+34: DA155BEFBFFD2638
+35: 611EC83E0931FFBE
+36: 3BDDEC15BC543A92
+37: D7B9564BBAEE19FC
+38: DE44907E9F0A1F11
+39: C8638C0594D13614
+40: 9E67F1B15418BF14
+41: EDF531A083F72852
+42: 7E5F8F9A72890BB3
+43: 2A0B060E3EDDE9C3
+44: 9B4B0F6FE6511106
+45: 328658F222C7FCE4
+46: F6F1B50B4F9F9C93
+47: A620519E69952F5E
+48: 24DA24DFE96AD818
+49: 226C43435FBDA34A
+
+Key Size: 32 bytes
+ 0: 46CDCC4D4D14BA2E
+ 1: C079641BD6584E5A
+ 2: 38828DF8B4C4920C
+ 3: B4ABCF6B78A721F3
+ 4: 8E7E2914CBBA708C
+ 5: C0EBE7002C888495
+ 6: C60F404DE7CF9B78
+ 7: B29E843E1771EF26
+ 8: 983033386CA6A09B
+ 9: 76F1F89AFDCF7130
+10: BED4E2114F4376FA
+11: 879A2B9D19AFAB87
+12: 366201BC87532AE5
+13: 6F409580FA907A64
+14: F7A202F00A38863E
+15: 98B0A9C79FFC27B1
+16: 1CB68D9BBF8A1A8A
+17: C21A2C54E5471D23
+18: 76A81C3DFC149934
+19: C7A0627412FC323A
+20: A034684D7058E7A6
+21: AC87722F27029BC2
+22: 36A6C2AF10245E3E
+23: 1F85B90D11217EBE
+24: 9C2A0C383A4AB7D5
+25: 11D5C689039CA179
+26: B0B38C7077E1450B
+27: C59C7DCCC3B8A1BB
+28: 9BC539F29208AC24
+29: 8546F17C77C60C05
+30: B189C3E92AF53844
+31: 3C7689163B8D2776
+32: 6AFEB9A0671156A8
+33: 05514E39F2990008
+34: C941E31A2A1F42BF
+35: 87C3777C74A730A0
+36: 2861667755C8B727
+37: AF75A0312433B151
+38: F76939331E9C9792
+39: 819FF8C81FC7C8DC
+40: 31E7B07EB03D170D
+41: 696E5EC1A741170E
+42: 6C5BF0E0BA48FEC3
+43: 6D751BCCDC475797
+44: BB5A91D0CA7E60F4
+45: 7F7EC0531C88B14C
+46: 9F302392529B70E8
+47: CAC9A1A88F09AC1D
+48: 39D56A652E02D5B0
+49: 13641D42BC126517
+
+Key Size: 56 bytes
+ 0: 373C66BBA50EB9CC
+ 1: A4E8C602AE3A2CEB
+ 2: A59F08BA78502F32
+ 3: D0D4968015F4E4FF
+ 4: 0D3C2F291E6C2EE0
+ 5: 3F99F5DADAD5FD2C
+ 6: 5BA41EC1A506396D
+ 7: 0BDE3B5B50591D35
+ 8: 5C4A6AEFA69A115D
+ 9: ADABFE96D6D159E8
+10: F97F0B9C88ACD5C0
+11: 8882A163F0F02BB2
+12: F00556C9F5A56A32
+13: 257615BEC96CC228
+14: D58DAEC547DD8B89
+15: E677F4953EC44097
+16: 20156D066DC37000
+17: 6F18E01C6FDF947E
+18: C8DFF24F12621237
+19: 032F91C5119AE308
+20: 394194AD8BC1E5CF
+21: 6F24E937F3925581
+22: 086A4510D95759F3
+23: 073204BADF0EE942
+24: 5BC8B8E402D90F43
+25: A10B7E9D01DD3809
+26: 22C0B183AFFDA506
+27: 216306AE6DDBAF3F
+28: E275E1F52430A1FD
+29: C3BDB49D588D31BB
+30: B860818C5923B688
+31: BE1BC7A444B0E141
+32: E4C4B67900DBC8DB
+33: 36D7B7ECB6679A9C
+34: C1EAD201EE34BEF7
+35: 9ABBC877CE825B14
+36: 3B211121C0C3C09A
+37: BE3B34FF2E83F5A7
+38: 46C2B3E628A53EAD
+39: B7E7DDE16C7DFF62
+40: 3C9A14C4226EBCC5
+41: C5FD46242DB29704
+42: D45A96723FF62201
+43: BB015D10878CF70D
+44: 71DB021BE398D41A
+45: 06F52D237F06C260
+46: 3552F47E8CCFC73F
+47: 769E33828AD5D88E
+48: 659861DDF080AA67
+49: CF7A13782F317342
+
+
+Cipher: xtea
+Key Size: 16 bytes
+ 0: 256004E1F55BC0C7
+ 1: 2D385C151A691C42
+ 2: F93BFEA758A7DDB4
+ 3: 2A905D97C0CA3E48
+ 4: 12C7C2787B913AE6
+ 5: FB24B1F32549EF59
+ 6: 2A8BFF867FB4FF73
+ 7: 5692243526C6BA77
+ 8: 4CD423ADFCDD1B6C
+ 9: 9B99AFC35EB2FED0
+10: 416B4AA4E07DA7F4
+11: 4DBC9052ABFF9510
+12: 8AF9457F8E599216
+13: BC3CA2B1C7267395
+14: E4BE31DF42282F7A
+15: B344CA8AA57E9E40
+16: 57A1F94CD2F4576D
+17: 96177FCD28BFF1BB
+18: 78A1F63A0EBAAC33
+19: 5F3FCBCD7442B617
+20: D6F7CD5ECA688967
+21: D92EDF70CBDE703F
+22: E2E2C2EE5D18E58E
+23: 4BF00478CB7833C3
+24: F9936D550815FE8F
+25: 19A3B07B3E47D7D8
+26: ACA441F099A7E30C
+27: F70183F199988E3F
+28: 0A41FC22F369310A
+29: ABFAF40853A4A38C
+30: 6B5D29DB1155D96B
+31: 0DD0C08A27561D66
+32: 4C56E22292F17AA3
+33: 3F925ED65613DF4A
+34: 521B4C97081DC901
+35: 2B1EC3E1C8CF84EC
+36: 2A412556F42A48F6
+37: 0A57B8A527DFE507
+38: EB55C9C157E3C922
+39: 6E6D6E9AB925ED92
+40: A4C5C90A0D4A8F16
+41: 7F9F9F658C427D55
+42: 9A5139994FF04C3F
+43: 9054771F027E29BC
+44: 90543E7BAED313BD
+45: 5DEC1EBE6A617D36
+46: 19AB6A708CDB9B2D
+47: BABB97BB5CF9D4E4
+48: 2C2ADC05AF255861
+49: 52266710153E3F7E
+
+
+Cipher: rc5
+Key Size: 8 bytes
+ 0: 04F6B9B18E6828C1
+ 1: BEA50D165E50EA04
+ 2: 6F3728FE19F09B03
+ 3: C682C26278B372FE
+ 4: 78BCC81E144E1B0F
+ 5: B62775716366450F
+ 6: 5BC49690F97CBCFC
+ 7: 359414E9EACDE379
+ 8: D3331D8ECBF684FF
+ 9: 13129FB10EAFC82E
+10: 7F29218421CC4B5A
+11: FC225A4F31A75162
+12: 29BF8BFDA8A15D37
+13: 6854AC5BD98EEE95
+14: DEF05AB6D102E992
+15: 317C3EA6F0600016
+16: D6F3658B2E80B77F
+17: 7C1DF7ED6C92C23D
+18: F8665145BAFE28C5
+19: 9D8059C34B79F0EF
+20: DC8D1617D3EBC7DB
+21: 2D8FF59FCA19BE6C
+22: 5C6956743715EA13
+23: 91160BE1F4F3D4A0
+24: 1D482C2359EC93F5
+25: 9C21D1A3755A7251
+26: E48D1BB926D51E63
+27: 08A054946263F617
+28: 9C900BA37199B7C7
+29: 0C6C58743EC83082
+30: B24197EEB5603D3D
+31: CF5B735F8A492E49
+32: 337C504698BBE553
+33: 3A2BCCC88BE9ED51
+34: F3E9241743203ABF
+35: B67BCC625815C585
+36: F8E96E4EEBC2566C
+37: E27D162006C67C8D
+38: 08CE8C1A5E3C169A
+39: 0CF8AD04125EFCD8
+40: 6712F9F044864FAA
+41: 0FD465AFFD64085E
+42: 6BA8C82B3974391F
+43: A5FFF24CE9659357
+44: 0947F81E1EB4970E
+45: DEA966CA50243067
+46: 1F1BE4866F48E39F
+47: 03A7D7CE793F52C7
+48: A1FADE3F801B414A
+49: DE7DA6D14A50E305
+
+Key Size: 68 bytes
+ 0: C8704ABBDA9624EE
+ 1: C719C645E301FC16
+ 2: 32D82553B0E35EF8
+ 3: C63C77EE6C2A6E36
+ 4: F84EDA1E77ECB5F0
+ 5: 382C1E72AA1FD1BC
+ 6: 6B00939F535F9C83
+ 7: 3CE0825AE10C2B0E
+ 8: 1F9E7738602BDD0A
+ 9: 9273E7933CED0B0A
+10: 4CAB45EEA45C32DC
+11: FD0208C6A89FB519
+12: 520D8E6912E9551D
+13: 5B88684544868BD5
+14: 32AA2A8EE58135D4
+15: 281045702DD38766
+16: 26D68E073C996747
+17: 23DFB9E174D86192
+18: E32FD5AF5101E45C
+19: 3DEFB679670A143C
+20: E616394D859BFE94
+21: 217B9BE0ED47DDAD
+22: 4F7901A5620EA484
+23: 6654C042783F5737
+24: 752AA74BACF9BE65
+25: 2FAEBEB8B325F89B
+26: 6FEA020B058F32CB
+27: 2A32682A36691665
+28: 338C8AB628A30105
+29: DFAE9DD082DFE38C
+30: 51B451C29DBA19C4
+31: A2993DA9B8C1D5FD
+32: 24D92FA331E2F93A
+33: 821A961C0524C89D
+34: A07BF305EE8964D9
+35: 981652361262C5CE
+36: 3DD770C3761B695B
+37: F36359AFE1C8A07C
+38: BEBC629B8938F4A3
+39: 2E31DC53F77898B3
+40: 52E4104C4E8E6901
+41: 75C912DA610525EA
+42: 2F280F70963F82DE
+43: D7E3FCCA75AEE5DF
+44: 8EBC7E825A14A2BB
+45: C1138701F64187DB
+46: 1294E21ED2550DFA
+47: 577820D772BE2C8E
+48: 48CE93C46BFD33CD
+49: 3B50D264382E03BC
+
+Key Size: 128 bytes
+ 0: 236CF0A207576E8E
+ 1: AC12D8F1AE55F057
+ 2: CEC4230F747B547A
+ 3: 61EA1B510D033B26
+ 4: E064F51998E20804
+ 5: 6247797DF02BAEF7
+ 6: D25A766244063A7F
+ 7: 2C2B3FDDA0E07067
+ 8: 04EED646C3F6FF90
+ 9: 05487E7702865E4A
+10: 6C0A92AC23ED07C5
+11: 6E54E768C797F797
+12: A7C53BF7B252A884
+13: 731052795E12C80B
+14: 3E4DAD15A826C43D
+15: 10B1191B4012C2A0
+16: ADD244B33AEAEF7E
+17: F6CC7B5F0885E056
+18: E23489F3B7BE438E
+19: B0C27661692FDE4C
+20: E81CE014DA769F07
+21: 7A8BE0D2D52623A8
+22: 082F444E00D5E127
+23: AE42F684ADD1DAC7
+24: 9061BA686F76A450
+25: 9BEB7141B8F6F5F0
+26: 38CBA9933AEF85E7
+27: C66F4245901CB341
+28: 8659AA47E6B06BC3
+29: 357AB20DCE2DDA3E
+30: 236689C2F36976D9
+31: 331EFD7D5CF7AD50
+32: C373526C2D44DB80
+33: 79F7ACBA770F5C92
+34: 64325C5A67F364F6
+35: DF2F720829FF1694
+36: 9EE17F47ED487BC6
+37: C41067896AF4CFC5
+38: 5776E1E5FBE59933
+39: 07A05B1508B739E0
+40: B19EF72A65B3C035
+41: F8BF5FF4095C0173
+42: 7F1226C6CA7B4072
+43: 8A6C8F26A97DD33B
+44: 62948A9A627E98AD
+45: 9EC58E3F8A477D21
+46: A656F285AE0684B4
+47: 8489690681A53EE5
+48: 940915E733721837
+49: 1221956BCEE0143B
+
+
+Cipher: rc6
+Key Size: 8 bytes
+ 0: 6533F7041D69B9B883A5305180A85520
+ 1: 496683D6356950E8F4AF4582630BE46C
+ 2: CA421828FCFCEF2F042F6D81F14CBE76
+ 3: 92DB67F2F057858FC806E071D239F245
+ 4: 203CDFE0C36434AEDDBE2DA68ADC5EF0
+ 5: 8EB23BDBD58A279C1F3BF75199FC9E34
+ 6: 8FA8BB4E772E09DD1EFBE03090E77FF8
+ 7: 2018803BFD91D157AE20C6E8FF1894B0
+ 8: 267319634294F0684AFA7B26EB612B3C
+ 9: 108745E1F2E80864D9043582CD5550EE
+10: E4F9EFE5A6C426BB719EA17174890D0A
+11: EFFD4CAE649740B3309692AA19ACA227
+12: EB909E6D0789F649538E7EA1686FC0F9
+13: 0216851E23EDAE52D9964939DA0A7493
+14: D6A9CD3429D1679D26A9599EBDE5409A
+15: 5DCDECA6E89A7F0EB40649EFDE6420AF
+16: B74FD556B06C07BA8D9E517348CC66CC
+17: 9A22CB5B73EF1DDE68A5AEF1B1510ECC
+18: 77F78557143E08A7449A75A13098FEF8
+19: 548FE6700BD17D0AE247B07C2F1AB0E7
+20: B7DFD8CB428A36733BBE9A51CF45C072
+21: E7E8B7AA2D93E3DE99C543A473CC6760
+22: 3FA5821248B0F0AEB5CF00EEF7958F5E
+23: 0A655AC6C51DB33849BCDA72DAE106F1
+24: 9EE93EAB01E1A1DC57B698C266469481
+25: A7D398720E0ABA2D0D143D8306FD5AC8
+26: 98A46C94125BD2E5600BD26EEA420F2A
+27: F4789EDC3C50BC4186816F14A86403D1
+28: F8AFBA8EC652EFDC3AF5EA5CFE143E16
+29: CEEEBD4B6724A30E1859A5B4EF9B2B3D
+30: 766715B4C4FA7CD4B365A2A67C79E48A
+31: 92C5EB7BE61155D79DE0A6F55715DA22
+32: 42CF0C9B2BAACB085CB1603688037D0F
+33: 6C4BE816F7B573CCFA8BB6E399EEB17F
+34: B6D7E606CC99D267ECCFDBC006878691
+35: 2048B58B74F9A721B2E33D2EB86F5991
+36: 3E458C1015ECB08CC7B8980135E71893
+37: E4E28A032CF2F3C8262CD4BBE7A4CDF8
+38: 701EAA449AD9E5AF81DF3F436AB25620
+39: D1C3FB7C16F5249503EB389A692B112F
+40: 7012790DB65526DC87F9A2BF0FBB5664
+41: B782A3104FFE65DDB340F713ACFFE25B
+42: A155F033E4536FB1176EBDF9EB5FEC4C
+43: 8898BCC7A008127014850D5529327352
+44: 8F4B3BE150FAA0371CDE69891E52A3C9
+45: D371C8283F68DE983C98D98A7563B934
+46: DEB679915E8F0D0B65B37918BE4596F7
+47: 84D74F7FA199304A47BB37B8AF893CF0
+48: 5367B0187496539F6DF6CCE0965B376D
+49: 4B9C6011D43CF2D8FAFA2E7105D85024
+
+Key Size: 68 bytes
+ 0: 6BBF763FF30876A4BBB68A7E7E290770
+ 1: 59852279E82E98B8B680E5CEE12BB99A
+ 2: F96989565E5B163EA483FF74ACA22DC9
+ 3: 221F7A410F5AD73C1C67DEBA99683E0A
+ 4: 55F058D1D9B8C372E2A28AB6E953A851
+ 5: 24A8F7E07620A55D69CC3981B92E5CCE
+ 6: F4D9DA95BF66FE28BA3A84E77E62822D
+ 7: EE7EAC2BD34DDE6F83E6D4F23C0A49D3
+ 8: 4218AA697FB7C5D897E66EB00A9FB489
+ 9: 55A8CDF8608A3B1A6B14275E2258A096
+10: 18D50743982F5C8A5C528BDB5896CDFC
+11: 391403B889F0CEE865893EBE9F1BF90A
+12: F3CA9C30C163C510432D3207DB6967EA
+13: B14B6574DF53257BE4508DBE78843B47
+14: F52F1E5FD6FB19C1F5466276F9C33A97
+15: 9D5AABA86E8B65E4F633B6EDE17516E8
+16: 9038CF746F722DA1A0C34461359FD378
+17: 398E317E9CC074C2293B59598F72EA64
+18: 9D75D897D487DD2B5BC534B4B223ADD1
+19: 6C6DFF734BFB9700EDD6B3CFC6E311F7
+20: E27591407CA9771F227A5B6B3A77C928
+21: 1618F15FFA8E2692A3B3EF8EB6151427
+22: FA426AC6161F31F0D63FC9DA97A6A393
+23: 1281869E9959DED2CF75F50DA7FAB66A
+24: E8BF17E4B76D6DC5C1D07DC80970665A
+25: 9A869B6C5EEF391C7E7C4585FFD9FF3A
+26: 59564F799AFC984D39A8168D1A30C8C8
+27: 1D3927AA2E2C48E6CFEF88D04ADD30DE
+28: 39BF89DE1365DF15A8ABA86856ED074B
+29: 0CCC4A4DEB36A000E7EB271F5EE54543
+30: 26476623D35A514B8833D868426A2BE9
+31: C3C85993EA15AB2D056D670707851802
+32: BF5F7ED18E1320BAD536DCEDEE1A9AF7
+33: 337BDC5FF0F7AD44E6A3F5D6712BD5DF
+34: 7DBA76B3D9C818D0CE1A530BC79E77D2
+35: 20DF55E617CD2598F18534DA7A22B555
+36: B0A0C1BDF9E81B4F07F47D31A9CC8408
+37: CB9586F4B27F759B9B9C6C7DB01D26A8
+38: 1E79A2894906A64098AC43799CEFED38
+39: 82FA120F237EB0B3A1F8B52379B8346F
+40: 3DB9848603E3B1134585E5C9001D119B
+41: A750875900E244996887EC995131D151
+42: 12133748D3745F77C161470A921F73BD
+43: A265C351694574B44517FDAD8816133F
+44: 5E50CC8281C2A69FD376250D99620DD3
+45: 443ABBC1AD5605A0BA05B8E6ABA5D2A1
+46: 73546A87B39C54F0639EBEC118ADA007
+47: 380244C822817453C75405B727D67C4B
+48: 73F1E23DFF05EFAB5D39E503031C4165
+49: 8030071491490590A8913AE4B5D082CC
+
+Key Size: 128 bytes
+ 0: 24B06811BD97AE9512B3799E3189DCD3
+ 1: 92DBA6269E880F8D8A09143D792A46DE
+ 2: F956F459C333DFBA4C6A309C613DD661
+ 3: C31488EA551CC0FC8885F6817CA696FF
+ 4: F59634FE907F9DF9467BD1059F82DAAC
+ 5: 051AF11DD2FCF742169B58A786128CE7
+ 6: 87326A3A4A98CC15B23DFBFFC5AE16D3
+ 7: 58FCDE2E88A79D5682729ADB4D971142
+ 8: EAA787D68EB68CA79CCC6BFAC3BE9247
+ 9: 8BCF6980AEED36AF38B68A50DD454AF0
+10: 4B0E31AE48E903DFF52939800BB16DC0
+11: 19766AA929B40840715D53D9170C986F
+12: F9CAEB36F03CE7B3BB363AC7EB3ACF99
+13: C8E34A6BDEDA4DB836DF3D863D02A6EB
+14: 370547CEA441FDCBAFD281A8653BE2D4
+15: 77E0F33343158A8C3AC3C6D14FD69431
+16: 7A985B1368F842C644538C654D081FD3
+17: 60E0C8933F43D40003030196E8E881AC
+18: 3473474B58AE6BC7582ADD7AE24711B7
+19: 75936C8D46F6D5AF5C7EE0E8DCEB5AB2
+20: 4A04F619FB0E05F7B07C43F4B9F2E134
+21: FD53A5A7F4F0B9D933E38D9F07AC88CD
+22: F62EE43B20F582AC77879AD7E66FCCAC
+23: 4436AD771624896683D7D29E8879F89F
+24: F88F3C0EF2B9FD0CA997BEF17787DA2F
+25: FF5576F42CE9A0665A1D6A2420A691D0
+26: C077D6AEBA65B61CD1A9AAE17FCFC04D
+27: 84D0D7C52D6DB3979BC3F6F34456CB91
+28: F163121D9EB7569CA7DE3B7619E0BE51
+29: 727D23FB43215467B57DC67A8890CF26
+30: 60BA577F3C6627267D7B33E693FB7BCB
+31: 82C66B23586CCEA2AE1480B469B3F3C3
+32: A65092726D6CF2F77CE00648E2D117B0
+33: EC30662CBA891A3380B846DA6C64024E
+34: CE1B253FBCE36B217ED1EFBAAAD2E783
+35: 9D963CD5E65A9ECD2DAEE93B6C6C1178
+36: 1B8E3D07E7BD4BB4248B6A7DF8935980
+37: DBC3FD5888B80C4CEFC6C5E170E271CE
+38: 307CA8CDDFE5DA152B66E10346BB2E1C
+39: 8858250F933650D978B403A4504EA581
+40: F06005FA6E56E0C0D96988A3FAD359FC
+41: 816CBE37FDE3719804DBFD093E3FD87D
+42: 4878C07B127D696214393DDC66F5EB36
+43: EFBA6045243050C0D8D82046B17008E8
+44: 3D30C3E5892D32BA3C685DC5B186E959
+45: D4A4C41F0E6687E4021FB90D7A8A9F81
+46: FE1057B2013308C4CE839B4186F43B4C
+47: D7333AC65F66ED6D4BB8D069E265020F
+48: 33C262F58BF0D91DF2047E799BAA5F37
+49: B960A18764D7A6E17FA1F88487EFF192
+
+
+Cipher: safer+
+Key Size: 16 bytes
+ 0: 7D42607880B424C27E5A73A34FECE686
+ 1: 1A99D469F1946EA46523083FBAA79CBB
+ 2: 831385E400FD681C8A30AAD9477F1ABB
+ 3: 5C1BB8F259CDEC2C1BE0B803C7D9447F
+ 4: C57C1CBB18D87FCF72A87B247392752D
+ 5: 1625183B0C595A33FE0E8AE0DCE40ADE
+ 6: 4AF3A9D6733DC4FFF3422AA5BE5ADC94
+ 7: 853133894C87A23318DFAD2B247FBFF3
+ 8: 8C7F68E01A8413D19B9A479246E54722
+ 9: 8620898ECD3BF91A47CC54E6D9987FA7
+10: 33F12ABB7CC6A9041543A2073AEDFFA7
+11: A096E46F2834F79C096D0B655EDC9A63
+12: 3DD0D7824A87C9F5D8D25F5AF57E70B7
+13: 6B7C99E5CD29AC1C5A8D66AB460E5AD5
+14: 95A9F6009AB4DD2AC7E8E45F36D91E9C
+15: 60CCEFC6630329C341782B17365995A2
+16: 0276C96A7B1191BC16C8A9C98468DB05
+17: 1F352CB77C21139C058837B8194E3E64
+18: 2DB8E340F58844705F217551782F6B4D
+19: 34E99832E0722C5AE8F0CA1A50E9E7E2
+20: 7E1538DC10C1F56C3723A87BFD127743
+21: 36B9714A8ACDC8B8A17E85E2803A8C88
+22: 11848329B0DB9DC7768C07D95F0CF662
+23: 93ECEDEB4C6369AC56AF1F49345720A6
+24: A3ED7F9D17067C2650728E266B623124
+25: F33574590B435D1DDBBA925F0D0EA8AD
+26: 87E542DBD40DCBD80C4AB52555C264C1
+27: 6D806991AB8E3604C8267AC1EBEC2E21
+28: 4B7333F87EBB46BB2A8ECD392C85A12B
+29: 4FF49ACA62898F558AC065B66CAD0234
+30: 62DE7B2133B09544EDD0DF66DC4F5E2A
+31: 82195B39FF7B8A85D7F0EE52D19E510F
+32: 24FA56176A4F0B37F851CBAB176C9702
+33: 85FA9230D9B93CDCC0752FC738211703
+34: D441132032BDAC6715F4453CBC2434D8
+35: 438AB9BEA8A900368D84EF870EAF7E84
+36: 433BE5BFE1529BFA7C5688CFE3BD4DE5
+37: 2A79FB6F37AA08533445B8BEA5098EA2
+38: B9C986EE45D204B6A1CA152944912C9F
+39: 8289C9F78760D02AA71873FD97E2ECB8
+40: 48B0D1244523165055BE9A5E95CF852E
+41: 471E211E5E784C2AF476DB3CB555CF35
+42: F290CBEB1F1009D250F7B12E044B80C3
+43: 1B9796D80C3976FE3071B1C01154D42E
+44: A80E21A1A1007B69E8BCAE728BBE6A92
+45: 652058EF0FAF8549424F998669660931
+46: 89418FB4740E9801F6DFFEDC593FA32E
+47: 907561A69CFA117F167A52B88777D89C
+48: EA2EB4B1EE739320F99894B476A8A51E
+49: E627E64AAB6E2FF6B99643A7FBB84BFC
+
+Key Size: 24 bytes
+ 0: E8975F94A8B1392FBA78CBDDCC8E8F08
+ 1: 708CEFB68A0281AEA424B3D4698D2F2B
+ 2: 21A0DE56545BC950FCE4DF209C96CE6F
+ 3: F2CA4103B703264D46CBC09E13D5B8EE
+ 4: 2892101077FEE427C434CCFBBAB598B5
+ 5: C2F191CC5C681CBFC098B264C479B2AD
+ 6: 308C3B794C8A7971BBA96FE4C727F48E
+ 7: 8A4F9D4463B5DC4DD461ED0763CDAEA2
+ 8: B7E1BBBE455AEDF18329A6EECD6E222C
+ 9: C80DAAE7FBDF56DE05A897FBDBB53DEC
+10: 6A3D38758BF0390156F22F83C20F0262
+11: CA493DF771E37A93822D6117ED14B60C
+12: 623012748826A08F3C59B71FF3D66327
+13: A283BCB126B9795D306B129035BCC2DC
+14: 3790A6704BB0F119139A0264F7E8B2C8
+15: 9B369BBC095428EBD712517B2C4D06F0
+16: 0F488018162193ADB11E4C39CFDEE0DC
+17: 8AFB7C6FD7D6DD64C2C77DA3A0D91EE2
+18: B8BEFA241BA339BF6F059464C533F9F0
+19: E76141C8CD54200FAB2F8C2B76AF5FEE
+20: 80B4FE57851C0240D81E78DA8200F195
+21: 8BF1C690EF5FCE7ADC74E31C24F83F5E
+22: D30C4F78703BDE91750E0E49FA0E8982
+23: 86C5D1E0B88EF0AF9B899850510000EB
+24: FDE727442BCC0305A7B06E6EE179D836
+25: 0B4A719342F9226FA680796887A98FA5
+26: 980D4BE9AF3E3CF9D4558478D1DD03AB
+27: 03ECD11992D3D5864B8D1987966BA544
+28: 8DBC2931D7D17657BF38E3931F486850
+29: 76AE069E39FA7308BBF507ABE35BC1E8
+30: 9541B59CE18EA255CDC06DFD3FFCD1C1
+31: 5A382748AE3641ABF6D9CA24A35B2002
+32: 9B7A49DCC2CFC5A6078AB41E6F62B4CD
+33: 91B2EAC878E5628DBCC7C876B91B73D1
+34: 31125CFFC41A0D3528FB16BAE761C47A
+35: 916D2A769DA002ADCA8C87F8241BB50D
+36: 681C3F601EE5D82F9B040932F2FB4AEF
+37: 6B6F32E5EAC2F424074C33F7C988D5FE
+38: D15A5FDC2A4956DE61BA6E1C98867242
+39: 0747BCFE1B979E947EED5225FAFCA44F
+40: 133B43C85CCBC360DF8649BBBD2EB45B
+41: 052D943062A6D475D30100EA412C30EE
+42: BD6401C591D585F4A82CDCF678679D5B
+43: F95D1A5E338F56760C425D972D67B57B
+44: 9B1569308608CA00BB1E2BC9E20289A7
+45: B6454C52C64F64D69F1D36D2D224A222
+46: 529B5B013AE3F37E38BE340D1D200A64
+47: 1B65904F177212AC8E9ED4D8DB287810
+48: CD5CAC56236E0B9A25A5D306F12D8C4B
+49: 01DF7E1D0F5F7A5DAA0B379388425126
+
+Key Size: 32 bytes
+ 0: 7FBC212996ECE9CA2C4D5BD88FA0B3D9
+ 1: EA3D788C25CF3BE7F4101EDECF23455B
+ 2: BD0B98481366AE0869ABA11DB18D1E95
+ 3: 53393E2B757C90489EB6B47F67837337
+ 4: E1D350640CCA6C13648C3B57BE00B950
+ 5: 951E1EF99E6DE72744A9D8D9EBFBA94E
+ 6: 433E4D4E64B41818097BD5E2EBA01D8E
+ 7: 8FCBD07E303B381B2935FB82CA0CBF13
+ 8: CF46569005BD968B9310149E892B4D69
+ 9: F1B672657C2657AD53BFFE2BA5DDE1D2
+10: 0035337210703240F9CF2F5A9184FDB7
+11: 773951841F77DCF8A6730109DEDF3E9A
+12: E47DC0FB381DB86EBD208A0D649E7B03
+13: 0D9E34ADB257146EAB95AF14636301D2
+14: AB5D5C106E52AC7662C26F9F27F2CD55
+15: 6938F205DC23C3500B7723281E9F626F
+16: 3CABD52558D7F418CAF6B41CEC334DAD
+17: D2192F1E5AFC3B989C42C396B3764862
+18: 59D32E3A41141C6CAA2A8F44FD587D94
+19: 483CFECF65D71CB2994E1C12A1A7F907
+20: 8F086AD81B1FD5B13195EDB4DAB7DC73
+21: EFEB1328CE7AE6A63E7D8B3ECA9E12B9
+22: 362AAE308B3BBA588DBCFBB7197E693C
+23: B817A136EB30CD127B5015A85A7B6E95
+24: 03796E7F244CC916BE02AF61E5FEC42F
+25: 5854F2889CFF44B0688718C23B0A822D
+26: 0F772AC6E37364AA7B844AEACB33F4A2
+27: B3E95F5195BA646DAF333AA89130451F
+28: 911A32AF7CC44309B37D75E158A4AB18
+29: 232CFE228EB72A949616B307C2BEED15
+30: 7C8989F135B8DE6FD26C7792B8354F35
+31: E79231779BFB9F792BD179C0625280A8
+32: 015F6CCAE8A1275A2E836A207D8254EA
+33: 4EB94709245CE1FBF7C6D9587FA92D40
+34: 63D82005320F974EFDC4C021FB73ABB5
+35: 0F15B2E8E389C2D59289D7DA41ABD07D
+36: CEE7FBBF766540D4E39903D0494DB797
+37: FB564C18A15D53108C1954FCD3518FC1
+38: A67C5F4A4A95AF2BD8E4FC1182B2EEBB
+39: 0D354E664C35B9364E4EE9DB8DE0CA76
+40: 3295826D52F3B980B50EFF3E9317F1CB
+41: BC65592A9C0BADD84F363A175EE6BC54
+42: 58DE762ADA621FE2A7A6A83F68E93213
+43: AD774FC8402F7DDBB881B703EC836057
+44: F1C95AD5E004AF35AE315AE88A2577FA
+45: 968775A2C3485875B024B008D96182EC
+46: 623E736238B5800ACD9B67D76C84D236
+47: 1C5E9F65D43343D743E50C80D0E0F648
+48: A62E4A197E15CF90C2569DC38D9FC915
+49: 165B139BE483A71381B9A8E93D9473DA
+
+
+Cipher: twofish
+Key Size: 16 bytes
+ 0: 9FB63337151BE9C71306D159EA7AFAA4
+ 1: 8CC5A931DEC29B4C7D85595D24FF8405
+ 2: E867FC0E144FDEA24FEA88D22D8776EA
+ 3: B450A2969C67D93E1AE3A4093BA4C48F
+ 4: 7AEA41F9956149F336612E868E42B3C4
+ 5: F201FBB730E6E58CF9E5AD1DC4844C4C
+ 6: 13D8869E66412C6C288B5D7F37F2D94A
+ 7: CD57DDDDB782C0A04C40E47D920799DC
+ 8: 65371C8ABC919EC09004A7D63D9302BF
+ 9: CC31DFD3B7DCCC86866CC79D45A89C3F
+10: 541D548D311714EF8661BFA721568D16
+11: 269F3AA2D2D10DBD3DD3992BFEE23C05
+12: F86DA5D73AFBA94A9D592D02B5855D25
+13: EAD8D785B50E036437E39F3B27DB4657
+14: 2AD0A13C493B9F3EDD259E11A495B205
+15: C05F9D72AA384F05B28A3519AF218CA9
+16: D442072F588D38AC8B9D447762E9FCF3
+17: FDD3BFB91EFD127196FF9F19ADADBF28
+18: F56717661B424E41D7DE1CD13E21DF89
+19: 0F6C952D9BE6CA49B5147EFD44455A92
+20: 6C214935726364F2766BE7B4C2B64362
+21: 5D5316D7E057FF481CCC10C7452D1A17
+22: 56C78DBD802CC9B040446A3EFF3F12AC
+23: A38CEADA8448DBE29C2D11DF2A487715
+24: CB2F786AB8063350F3FAE11EC8C65A5B
+25: F5B7298B6F558E2C4FCC11744AD22653
+26: 01BF89C1B48C5F6918FC6BDC10B12A21
+27: A031F25AAFF294EE79220BC76E73E52E
+28: 42C94B50E12499DA35F14BB6BB6E684D
+29: FD68B6840DC9A271CDE2032EF0200295
+30: A9863C1B04B3FE3945D29966F67B87E2
+31: 6226D4CEEC1E8AEC1B7B3E13D80A83FF
+32: 6100A71B1E3ABBBA48A9ED280DD1617E
+33: 5CE93A26D4EFF0CC7DFA2DD43A511871
+34: 282D165BFBA0F7F229161BE533BFC4D9
+35: E6AC479970891392972B2845C949A068
+36: 4E4A887368F8443BE51FA7CD16CF0B87
+37: 121AFC81AA2750572B35D100BDC34DB5
+38: 7C41FA7E0A18A87E44BE488F331B35E0
+39: C8847D295E1F505C04E2F5CE2CBF5E00
+40: 4686EE8628BC1BBB92CE825F04B1D5E8
+41: 397DFACD19C283B3FC27D3FCBE952254
+42: 815B6C69608B5A379E3C9E67FB1BA15A
+43: A73E72B912EB3AA4929E9EAF73A448BB
+44: 5BC4E2C88512BCD55408CC5AEAD15A91
+45: EF20B2BF297456DED1F4AB7BE0747902
+46: 3D876135E19BB56B98050450C6B0FD06
+47: D68100E1BAD07B438786337C0957471D
+48: CE85A91938049B5E21C983F7C45ECA3E
+49: 9FACEFFB9D08BB65DDC34E3C575B8442
+
+Key Size: 24 bytes
+ 0: 95ACCC625366547617F8BE4373D10CD7
+ 1: 99AEB25CCE73B3796C351A19791ACD52
+ 2: 56B9D6689830275C1A3E4266B3D56D53
+ 3: 2F5F822E11F087BCB8A0F428414855A0
+ 4: 65400F729990FE175AAA894BCFBB1A59
+ 5: 947BA33D20194BBB0D4904023FB32FFB
+ 6: 116B0C6744D215AE98DEB1F9FF1D36C0
+ 7: BA6964C101FA044ED06877E46D540850
+ 8: A36B18526FA0004CF557C99A3AC1423A
+ 9: 573099674B8AFC2DD6424A2E4C581B89
+10: F46169CFE9496A2696A93EEB7EC561FB
+11: 2C64BC052898F3F3A2B78F2591F2BF1E
+12: E8A0D40B08585459199DD6ECC108A490
+13: 47927989BE5EB55B9A0F294C04FF035F
+14: 54A3024E3AD86005A2C44E4B8BDBBEFB
+15: D0AD51D1DADFAD7ED0EBCC756DBCDCC9
+16: 5DE698B7014C34AA6F0099CBB5937A20
+17: 9BA30F49470C6DB9632C5EDE34F8EE73
+18: 0BDF558A2AE9298288E60616442D3408
+19: 25F6DD23BA4E090E1CFFA6EE3487AFA7
+20: DAC5FB99E299D2672F79F0C38E177D83
+21: 58CB113430895C9890D96EA60E3DDC23
+22: 48A0771F0049B776A44AE8877B57EFFB
+23: 2F12B26A4BF7065076417530CDEE14CC
+24: AA6ADCB0176D5324C4C1FFD640D502EE
+25: 384B52A66F4C7A70ED36091BC3FEA09C
+26: 2AFE7ACF071C6B0FD69930A09D6DD5E5
+27: 9A2DB9A5E7712A5BFB095D2C09453CA3
+28: 716C0EF522A13EA05A48F16BAD3FD10A
+29: 44AB46F3CCFD02BDD2C77A332293A4D9
+30: CE6AB27A0F60F410B1B3CACD9AB923A8
+31: 69EAFAFC171C55D1D90ED1C6E1F3A48F
+32: 5EEEB0B7833121AD7D27BCFAF2D4F8ED
+33: 47133445A4EBCC60E27B29FCC160FA75
+34: 9F1BFEB9715A20D5FA7BA3BFF1A27BBC
+35: 516D4615F07756B4DBE7D37EBBF4684E
+36: B88744E53073BDA0F1B115E3DB224E83
+37: 1B77C3D067BBE00420450BA5CD9A83CA
+38: 94B87AC96F8CBFF36B01A68E0651E591
+39: 52ACE87A1A8E46655935536FB3701290
+40: B406BB632D5B7985400EC78D621C8801
+41: 20F9ABCBF97A9917EC6C5DE3CB2C925B
+42: 539A8AF920833F9E81A20A6D10543176
+43: B79AFB8BB39B0351094F37C6EC93F8A9
+44: 5830BD21289FED3F95C3E3740AC6C5BF
+45: 86C4AF5839ECB9860B175642ADA32895
+46: A6427E5E08CEA2A50B8426B063AEE189
+47: 2E872129B5BC5F535BCE2B81F013A103
+48: 2203EB9B2BF51FC2025549D0BF1924A7
+49: 6A5E383A4FC78F6E03B9B276F81195BE
+
+Key Size: 32 bytes
+ 0: 8EF0272C42DB838BCF7B07AF0EC30F38
+ 1: 9F8801E94E41A7DC875665663BFA7912
+ 2: EBE2CA6B45A0BEE83B54402E1A843A3B
+ 3: F6C5A1187AEF4B5A88E97E866CD757A1
+ 4: B3E62CD473E53812EDF9ECE875F39F5B
+ 5: D8C38B1EC23264BB7C42B5589C1300B2
+ 6: BE315EB75B944EC9E51F5EAE65F70BD2
+ 7: D4275409941A44993037364886B60598
+ 8: FC34F1D4E9C4A634C1349F6D4E9AB94E
+ 9: BE712387C59A40A8A35F854333A0302E
+10: 1F1FE164834BABC71DBFDFCCA7D2B4B6
+11: BB2413CCB5347B5157651819E698D988
+12: 6EB5523A968ECE965D9AA4B975D7C2EF
+13: B5DD49AB7E269F9D8516FB57EB47D57D
+14: 74F5D81856F192D49A70B3743945BFC0
+15: 95437BB00D57CD88BD52DE0A66D934C6
+16: AE4804A975D67C6B6F99176F407AAA3C
+17: 5E5B2FB9B2A028A5467B56F8BDBA6980
+18: 8C617FF1F9C50A36BE2EC19A629BA96B
+19: E3401F7CBE177A1D224117894E7EA08A
+20: F8451D9DD31A08BE828FA9AF39708921
+21: 5BE66DD577826804817B85A07BCEDE28
+22: E426227780943AA1A830B7E7D7F7CA0A
+23: B39C7277C3A5CA21897563DBD8DD6D94
+24: FA9992385396F959841D1E0E68CCE00D
+25: E1DE89B1DD5CC31685558A51CC731E6C
+26: 64618455C46C6FF117F19FF300B3B557
+27: 882758C02B3C11D406A21012977D4BF8
+28: F948B62F8038D3A3AFB73041B2F263AE
+29: AE3BF626020D2877052B90B31E70B8A4
+30: F1C6DBBC166985C9EC2E1A3A61BD8E75
+31: 82C343FA36B6D4E9E7AF6D0B7741FB09
+32: 0BFB756EC55AC63BEA71E4A8187C2B10
+33: F1941AD10BE60DAD3FBA33CB899B63A3
+34: 18236A39CD34743DE7B60B2575A9B204
+35: AA37FBC2525F74710D7561D316E8D90B
+36: 413E0F72C2B349FE2691554F77162B5C
+37: 5B9E6F98B2CA0F637E463BE4A6EFD39E
+38: 1B4A4CA36DC60D51BA981392D6070379
+39: B1E26163A90F339E33F86D252EFBAB99
+40: BB98F9F844FA81B25ECC89A8482404BE
+41: CE142F512A42A28F4788847B971AA7E9
+42: C5CE782936F3D28C69C2BD45FD7BC117
+43: 9B6E142582E0A309EDB550DED51238B0
+44: 0D9D80C01612977FF3A2C7A982D0894A
+45: A7630C752B1F787B07C382693334C6AF
+46: 9F24990F270D575881C746481A59C245
+47: C38B5E11479C200B5ACE1D6522FC6B1F
+48: 99118D8114D24B6559CC5D9456F1BEDB
+49: F8B974A4BC134F39BE9B27BD8B2F1129
+
+
+Cipher: rc2
+Key Size: 8 bytes
+ 0: 83B189DE87161805
+ 1: 7DCB9C9E50D15508
+ 2: C724D535853CDE79
+ 3: 113AFD4BA7D3D7E3
+ 4: CFA06CFB93C2280C
+ 5: B3F291C1AAD9CB07
+ 6: 606F74D9AAD4FA71
+ 7: 1CC3F7AD551C5F89
+ 8: 43F8772BA6C6B60D
+ 9: 2F933E12F57689DD
+10: 2BC1AF0D5571D17E
+11: 4123AAFABDB254E5
+12: 413E0AD5C709DCE0
+13: 6B3CF01A7542BD2F
+14: 1E5E2CA0CD605999
+15: D0F7C9DC472A0709
+16: 00482798857A2BB9
+17: EED583440CFA8B48
+18: DFB377FE1EE5E055
+19: 30511C4C565E8F75
+20: F74A72482B43B99E
+21: 1EE4EA7849B0B070
+22: DB7A4ACF022706FD
+23: 2D7EBABC8C8E4DD4
+24: 6F0369BF66A8B637
+25: 59E5D13B247EE0F6
+26: C7BAB430AA89A5FE
+27: AE0F03746D38138B
+28: 942DF0B523D02482
+29: 929CE0963CFA46B1
+30: F8C68A91DC53B7CC
+31: 5735395C63E15094
+32: 7821605C18D83D42
+33: DEC892FD743BA6DC
+34: 77AC80C1177963D3
+35: 3E223EB4EA297456
+36: AF63B231D671D9DC
+37: 665CA287AF32E92C
+38: E451EAB337DC1EB6
+39: 95B179EC950992CA
+40: B8937115492802AE
+41: 355A6E5EDF40A939
+42: 353E77D4A5A28D79
+43: C958FA5903F921B8
+44: C334E296BCB24ABE
+45: 4F37F7F652FE31ED
+46: 77304A655B03ED67
+47: 3548A4209ACB6EE2
+48: 696E712B1911B695
+49: E4B63641D22A3DDD
+
+Key Size: 68 bytes
+ 0: 7ED68E8B30A7D5DA
+ 1: 867E18AE64B783EE
+ 2: 032E554D6AAD7055
+ 3: 26BD785D0DDAD48B
+ 4: FFBD4009ABF53D03
+ 5: A71006E1E30C3855
+ 6: 92638EE741BE65B5
+ 7: FC8C5F28CB38C83D
+ 8: F03F145CBCC4CF80
+ 9: A28A7C63F67DDE7B
+10: 3089486A2247B72A
+11: CDD6E6BA5ED53A8D
+12: B75A2DE8CB96A267
+13: F74D72A2CD68CEF5
+14: 3865AC8D170EEDBA
+15: B1B520CE5FC2BA39
+16: 658DACFDD701B4EA
+17: 6B5C1DA9484FCEDF
+18: E3CDFB5755BDFFC1
+19: 56DAFF7E9A908880
+20: B6F8B970F68BC2BD
+21: 7A00DEE6977A91F2
+22: 6C0CE4FD2D02B36C
+23: 8EDA10D868504648
+24: 76FB106689E66EA7
+25: 67F45BB28A20E110
+26: 5F3207099AF93B07
+27: F5E382F7266AB342
+28: 0E31AC2E4CEFFBDC
+29: 8DBA1B2FC6980FF0
+30: 311368E62EC2A9E2
+31: 50DD1F7A319727EB
+32: F0DE146C9ECF5662
+33: 81CE0842CE223F15
+34: 4C442535A8BC9AD2
+35: 06EE8869DB91EBDA
+36: 4078E7CAC29DCEE7
+37: 115D619FB705F289
+38: 3D3F8A380DCB8FB1
+39: 9044E5AB8049D21A
+40: 66327F00B07CFC76
+41: 811AB23A4AD3F132
+42: D4A507E96BB39BC2
+43: 51C9E4C9318F87D9
+44: D2255C13DBD09E88
+45: ECB76BCB961F812D
+46: 83D7E39727BBBEC5
+47: 415540F0AE34DD65
+48: 232D20F9E188E2C7
+49: EE37261ABA270B22
+
+Key Size: 128 bytes
+ 0: 8A8F8E5C5A04C73B
+ 1: B197CF922883CE71
+ 2: 8AF3F896460CC597
+ 3: 755F313AEB18D3B8
+ 4: F1DB52688BB879A8
+ 5: 29D68EA6456B1CF9
+ 6: BE7C444267A7925D
+ 7: 46A7BF7DED575933
+ 8: E2C7AD7C902E5E15
+ 9: 90A38AE1DD69C2EA
+10: AA95FA050CD3388C
+11: 23822B6AD5B83018
+12: 8FD42F0DBFF3FEE1
+13: 645098BC94FDE21B
+14: 7E43D43EAC50E992
+15: 2F540FC66A9E0F43
+16: 453E52EA7B2D1F92
+17: F6F731E8C5A32C54
+18: B1E89646504E4D7C
+19: AB8168452A7984E1
+20: 044BB0758DB5435B
+21: E9BAE7C99A152BFF
+22: B758F70708B6597E
+23: 23A1EFD0AA925D7E
+24: CA60DD174CBA23DC
+25: 5E916F2DF7B6B3CF
+26: F2723A9BFD82BB62
+27: 2BC381F6C048687E
+28: 573BFD71896A4133
+29: 03DF7250C3D69801
+30: 8639060454669BCB
+31: E31945F0A87221AB
+32: AA39447BBF0A77EA
+33: 174F1B65BF6A34A3
+34: 2712F966022A9589
+35: B6358876D6D56D16
+36: 2A92C131E68B77BE
+37: 040C6935F4CFC43B
+38: F23503C74121C660
+39: EDD120883F1F813D
+40: AFC6500D34BD9D33
+41: 963117444417BDD3
+42: 2FC3A58861B4A58E
+43: CFDB70ED8BCD1173
+44: 91B75760CF38B8D5
+45: 93A59048B78B3415
+46: 7E60C5E75225D45F
+47: D4212C6422878FFA
+48: DDD1B241E0E0EF6E
+49: 20337DB931078078
+
+
+Cipher: des
+Key Size: 8 bytes
+ 0: E1B246E5A7C74CBC
+ 1: 9262AFD8AD571E2E
+ 2: 36D2067D960EB870
+ 3: 319834DC66705192
+ 4: B4508A7C5F012C93
+ 5: CAD1DECDDEE81342
+ 6: AE9E1CBB71C719E6
+ 7: D7FBB1CDAFD5B2C1
+ 8: BE1A70564E3BFB5A
+ 9: 96D9EC1407A1BD34
+10: 05E4B9AF3A4DABB3
+11: 0DC77419E1F12C02
+12: F73E62369190A5E3
+13: 830C1CA7820ABA2D
+14: D2574B6AEED0A4F4
+15: BC08782E293546A1
+16: A35DCC9AAD1EBFB3
+17: 79B2224667B33706
+18: F9462FFD2808233A
+19: D6421CD0D9697DC5
+20: 57CB2173D67E7001
+21: DBE2DB0BDC07644F
+22: 014E72E7E99C969F
+23: 37901B1963D0B29B
+24: 8E12C23929125686
+25: 73AA9E2A60C327A1
+26: 54A19D07D941EAC2
+27: ADB8CBBAEE1848D6
+28: 3997E866119856B5
+29: 4D647526FE7E1E27
+30: D574FE7342104F93
+31: B84383E34A790E11
+32: 322214BE9B93BB6F
+33: D4C8E0B7AA139D68
+34: 2B9747CD280E48C8
+35: F92EB2E3711FEE2C
+36: 5CEE84E124B7882B
+37: 82427488597FF618
+38: B1E8B313D2DC76CF
+39: 03E237CD40D7F214
+40: 8C8DC1299293E15D
+41: D6C7463FE86D4EF8
+42: CF1550CACE647779
+43: B998B3D32B69F00B
+44: 1B94C342C3D91107
+45: ABD4551B27F58BE8
+46: 2B24D978D1BFB3DA
+47: 85361D36950635CB
+48: 448009F38F1DBB4A
+49: 6B901B2B79B6950C
+
+
+Cipher: 3des
+Key Size: 24 bytes
+ 0: 58ED248F77F6B19E
+ 1: DA5C39983FD34F30
+ 2: 0BD322177B935920
+ 3: 9D093F3174EDBAE3
+ 4: 756B1F2CDF02B791
+ 5: 57C31C2A913C1126
+ 6: CF936257517C53FA
+ 7: 5F06305849E5E158
+ 8: 9A85DFD788C59D19
+ 9: 6392279BBE29DC1F
+10: 76B0AF835D79C4E8
+11: 7073F36DB1E31464
+12: 276258605F2CAB3B
+13: 3B69E97811FDA996
+14: 3E6E491D2862A1F3
+15: F8F3F68BDB006520
+16: FD376E66D401A097
+17: CA2FE47825804996
+18: 6F5C256F84FD14AF
+19: D7B07F5C40FF0CDE
+20: 73F2E074F1324496
+21: 0B2A35016F24BD21
+22: B040D2E3B311C193
+23: 3938DEA347112E2E
+24: 9D7C1703CEC0BFAA
+25: A07949F76BDFAF68
+26: 43087EEF52564C4C
+27: 11132B599734AF0E
+28: 62A04C819FDD9A8C
+29: B74F0E5649D33690
+30: 8E77E5009B0AA322
+31: 5174134B9A1889B9
+32: 053E33441D11AE63
+33: 01EF381013F86E4C
+34: BCA358DEF35DFD60
+35: 5908A88513E2E5A0
+36: A3214C8367E04B05
+37: B2CBBE851A54BE9C
+38: B271817F63B3B76A
+39: 08AFBF82ABB97D8A
+40: 2CE02ED014186B86
+41: 63F3011C97F6E990
+42: C392351F432738D9
+43: 0534DDA50E685725
+44: 1509456871F5CC20
+45: 2383029935901342
+46: 8714F1A53CCB213A
+47: 2491B2FD3CE6A7CB
+48: 4BB02399D85BB66E
+49: B8AC2CDFF7AC22C1
+
+
+Cipher: cast5
+Key Size: 5 bytes
+ 0: 9B32EF7653DAB4E6
+ 1: 48AEB06B1BDB2397
+ 2: B530927183622D58
+ 3: 0ECC8F24BA742216
+ 4: F6352F9B6461D82C
+ 5: AF6315AE98E12A71
+ 6: C364D4B506EF28B9
+ 7: 817061BEDF5E0A5D
+ 8: C19DE7B1F2066C04
+ 9: A6E1345E3AA1B79D
+10: 06B036B04785428F
+11: 244DAB3F7223F567
+12: B9CF3791F6C79F4A
+13: 86C5A02AF0517C5E
+14: A16E3198F1317E04
+15: CF72A44C01E36DDD
+16: 199C72ECD5E632ED
+17: 0BC66BF05EB7887A
+18: AE1F696F3D6B7952
+19: 685C92084F600885
+20: DBC1353A95AD2097
+21: F481E98CB36CAB3B
+22: 8F1C06A482C70BB6
+23: EA087739954A9CE5
+24: 6D0AD727D8E4EF9D
+25: 61CA0F7965FEE246
+26: 0D664CA16BA785DA
+27: 2359D363755605B9
+28: 6B6E3A216ABFB55A
+29: 6FBCCF7B0342D3C9
+30: 3431F4572E2CBE57
+31: 36D84FCE6D5D8FE4
+32: C234F6AD41E34E76
+33: 522F12E8D0617263
+34: AD8199B6E94D4E74
+35: 56DEC7C21C83B2AD
+36: 22CDBFBC5B476E69
+37: 70BAD497381F378D
+38: 4584F15DBC0EB7F3
+39: DE0603CEE19BCFCD
+40: EA8D582C1CE62FC9
+41: 4299C28A912CE568
+42: 7208AB000E3FA9D4
+43: 7AAE6CB398D01665
+44: 33A6AA42B6D7949C
+45: 2AEC5640AD535D69
+46: 74D37D9DD7B67248
+47: A5300FFF5CF85833
+48: 834F83398D591C38
+49: 85C787A8B7E519DB
+
+Key Size: 10 bytes
+ 0: 95827CB504BD43C7
+ 1: 8FBF4EBCB8413ABF
+ 2: 5CFF411BECED9971
+ 3: CEE2AEB4415E0A5D
+ 4: BB3A8DF7C54FA88F
+ 5: D508B933EF335111
+ 6: 993745722EF0D8D3
+ 7: 04EFB233AA88E796
+ 8: 478A7DCEAF243F90
+ 9: 269CC3D138ED48E7
+10: 88EBD14D2F999C89
+11: B7441626D4487A20
+12: 46A6E2CE6C66058E
+13: 60687D2D5381757F
+14: 885D05ABBF187B89
+15: 5032A7ECD3D51521
+16: 50BAF36BC5C14A8B
+17: 8E805499569FBB0E
+18: F8359B18AF3E69C5
+19: F24E415CB4D2AA95
+20: 361805D4E45B56B4
+21: 3172336F01E3530C
+22: 333A551E0A03C4A3
+23: E2B991995A2D2962
+24: 067CEEDD8F213B67
+25: FEC3F306851F8616
+26: 4B80DAE6AB11894F
+27: 250C26E21A8273A2
+28: 313F2A505915C909
+29: 42E0DC3D4816B38D
+30: 9FAEEF0510DEE721
+31: 3BB5F5EF74B4CD7E
+32: 0FBC9007F462BEAC
+33: B9D1467B0D7A1043
+34: D9B991C9348DF321
+35: 061D577806C50742
+36: 48AEA67AAAB6FA23
+37: 22F7910383BDA87C
+38: 9987087EDBA56FD8
+39: 2FCC8341B69BAA14
+40: 29DEDB6C2A433F50
+41: E067D2746B99A9CB
+42: A5C9CB975A856D57
+43: AAFEFD3A82D6185B
+44: BBE8952CC93CCCC8
+45: FC08CE0934EF2E25
+46: E44E642DBA7CF3F0
+47: CC26F0E8E85AB372
+48: D95D63B8389082E0
+49: BCA941C921B91E16
+
+Key Size: 16 bytes
+ 0: 20B42D77A79EBAE5
+ 1: 96CF6C91E5183CA2
+ 2: BD87E77A38DDB4E2
+ 3: E7454CA30B69DE2D
+ 4: 888F278D219384EE
+ 5: 972CB887CDE920F8
+ 6: 49BEC1E7913F3CAE
+ 7: 96A81B37FEF63CA5
+ 8: 408DD23A6DA940FC
+ 9: DA86E92BB735755F
+10: 2032F2D972F228BD
+11: 8F9EF7DEEF74EFEA
+12: 547C92025DCAF9F4
+13: 80CD440DFF2EA62A
+14: 7D6141D102E1B941
+15: 307596ABF5C9A6B2
+16: 82E3F1B17EBD52FE
+17: 5917DDD11EDB55A3
+18: 2909F77166F24F9F
+19: 88BDE9D686328942
+20: 8F987B737F6A011A
+21: A74B3D1D6433B9F4
+22: DA8F95DE949482EC
+23: 953BA9B26B9AC476
+24: 76A52FE193CBFAF9
+25: 4BB7D2597A78F2D8
+26: 5C8BE951251F4B1D
+27: 6E8AB32A4A279D84
+28: BB94BC9937B42848
+29: FF0EE686F97BF8DB
+30: 4146656AB1477E13
+31: 1BFCA7053E6DB8AC
+32: 4B9A6A349BFA926E
+33: 3B5F6FDD127B0A87
+34: 53C996E956598599
+35: 62C142E63C28B5EE
+36: BBB71D6548F32693
+37: 107576AA26352455
+38: DE32E31FFE02B6F9
+39: 4C5DB81D1715FF5C
+40: 8E5C706206F493A6
+41: 4BBC51E184A67C92
+42: AAE216B413DE2A06
+43: 77AE26F467233B06
+44: E8680D0E71F6AAD6
+45: 7061DCED4BC94F78
+46: 06772D63818C7E86
+47: EE5B9CFC06CBD639
+48: 5784B3EFCDC28DD4
+49: 4F962107A2EF843C
+
+
+Cipher: noekeon
+Key Size: 16 bytes
+ 0: 18A6ECE528AA797328B2C091A02F54C5
+ 1: 2A570E89CD8B7EEEE2C0249C8B68682E
+ 2: 828F4F6E3F3CB82EEEF26F37B26AEA78
+ 3: A3CA71833499F244BF26F487620266A4
+ 4: 333ACCE84B0A9DE91A22D1407F9DA83C
+ 5: 224285F3DB3D0D184D53F8FFDC8008D0
+ 6: DE39E2973025FE9EC1ACDE8F06985F91
+ 7: 2F00F45A01B1B0AA979E164DC5CCFE10
+ 8: 43775F3CBEE629EF6A9BA77CA36171D9
+ 9: 1E6A67ABF1B6ACF59FB484866AC15A86
+10: 70490989E2CD2145730921CCC37F0A17
+11: 67B0DD0EA903486B1CB56591FCF42678
+12: 774AAB71FF28E49A30E1E718D98114E8
+13: DF4797990E1C65C9F6735BD967164D45
+14: DE2779DF26FC1B99F576ED4CFBAE76CB
+15: A13AD17440641B3460A01175E3274AB9
+16: 1166499165F2A1196CA2DB831F264E77
+17: 35D24A385416CF2A44AB97A4AEC45E14
+18: D3D0E0DC962B1AD1AED92F57129088B2
+19: 00EF3E246B32634ABAF8BEE31D5C592A
+20: 79BBF3F807675B9F264BABC67DF4C2AB
+21: F391F2D58F0998F24BC9E5FA75DB9E99
+22: 066EF13C2617E97E6015B86BA1E059B2
+23: 5B0E2D7AE1E2734B9D5734C87F7BE272
+24: CDF7020212B7CF21F4817829386A6F8E
+25: 24873E1A0EF4908DF85114ED9BDB0168
+26: 99904360C843472F71AB86B26DC78A00
+27: BEE70B3735A67268578FF107C328940B
+28: 97DBB283536BC8AE8DBF56F3474C7740
+29: 2F4C903975EF709E004D24DC132A8A51
+30: 3EF0859A281782F905198C607FBE5C43
+31: 2D9CD48BC6A99E86468CBDD2A55C7D5F
+32: 5518D3ED18D5E5A62752CDF0846D0C77
+33: F751E9CAF107BAD8A1F1F9C374277A6A
+34: C5BA4DE907C41221FBABC5EC43710D0C
+35: 5CA48836330870365A10E7B676695C9D
+36: 937A964E0EA4D246E97293375B167EFD
+37: C0A876CB6957717541A90CCCB034BFB8
+38: A57C93A09F9160A28D3D4DEDC987746C
+39: 1FFA1E0B5EE0F0A18425F62717254419
+40: 8411C87262AE482CFC43C3092BEAFD90
+41: 0B9BB379FB3587A9ACEEED4771D8DC20
+42: 3B32EDBF9557E1DFBCEEC269B51FA494
+43: D1104E2888679A9EF6A13AE00ED7E1FB
+44: 0EC9849BAD58A279B42B5BA629B0045B
+45: CF206E8D3399918E75DE4765DD743060
+46: 55CCEB28E27D4DC7CE2546454FFD2C33
+47: 6E2339281583420B76E1750D35296C12
+48: 7800EC3D8C344BE7F2D2812F5AFF3DA4
+49: B80F4B0BDAA54A04D5A26BCA185F4EA2
+
+
+Cipher: skipjack
+Key Size: 10 bytes
+ 0: F62E83484FE30190
+ 1: 03B4DFE5423A117B
+ 2: 8CE4DAA2307CF018
+ 3: 77D8C958DAE4336D
+ 4: 00D367D5C1FC95D8
+ 5: C1F1305A5B01A474
+ 6: C3956225C846F695
+ 7: 2A8977DC186749A3
+ 8: 433AC6B56AE5C200
+ 9: 10489A7E87F803CE
+10: F176DF022D02D136
+11: 1395AE1C0C00AA1B
+12: 0C1C3FF32E93F789
+13: 901EAAD562EE92DF
+14: 59D55D9EE3EA0154
+15: D9135CE0BBF68AC7
+16: 90A8E4A8E76349A3
+17: C04ED52AA69D1ED0
+18: 19E842698B5008A4
+19: 26FCA0FA3AA7718D
+20: 62635FD1A542C7C0
+21: 5A3695398C979E40
+22: 34998BB72108D89F
+23: F889CF892998D689
+24: 2C6A4D61F468F19C
+25: EC70D59FC906349B
+26: B95F11FD098B34A6
+27: 32F86206BB4E525B
+28: E6BE51063B60CB9A
+29: 8964E47BAC22F995
+30: B1C297883819747B
+31: F2AE1F39F55FB6C2
+32: E633EA2DE342767E
+33: AF1F0ECBCA788A28
+34: 6A898F4407696B27
+35: CD9CB5374EA080BD
+36: 15881B0200AE6A42
+37: 579D05E5F5DE7840
+38: 86F8C683D23EB976
+39: FDAC7DC6C8F7777D
+40: 10D6F7641409F027
+41: FCDAA0872D1EC61A
+42: 7A353991A81344DC
+43: 43661187956D3F8D
+44: 5190FDFB904A78F0
+45: EF651E67F65CCD57
+46: 5E539C61748BDE3D
+47: E11E23BA8BEBA42E
+48: BAEF0956173B32AD
+49: 0AAB29DF65861F4C
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/eax_tv.txt	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,331 @@
+EAX Test Vectors.  Uses the 00010203...NN-1 pattern for header/nonce/plaintext/key.  The outputs
+are of the form ciphertext,tag for a given NN.  The key for step N>1 is the tag of the previous
+step repeated sufficiently.
+
+EAX-aes (16 byte key)
+  0: , 9AD07E7DBFF301F505DE596B9615DFFF
+  1: 47, 57C4AC75A42D05260AFA093ACD4499ED
+  2: C4E2, 26C5AB00325306772E6F6E4C8093F3D2
+  3: 16177B, 852260F91F27898D4FC176E311F6E1D1
+  4: F09F68BE, 700766CA231643B5D60C3B91B1B700C1
+  5: 8472705EDF, AC4C3359326EEA4CF71FC03E0E0292F2
+  6: 14C25EB5FD0D, 8DBD749CA79CCF11C1B370F8C975858C
+  7: F6A37F60670A85, AFBD1D5921557187504ADE61014C9622
+  8: 1AACFEAE8FBAD833, 82F477325D6F76BB81940AE25F9801C2
+  9: 069414324EC293697C, B980E21C09CA129B69E9032D980A9DC5
+ 10: D8174DE9A2FC92B7DA9C, 1E42CC58BA2C8BFD83806444EA29DB61
+ 11: 2C087DEA30F8B7EE510990, 83DB400A080C4D43CAA6EC3F1085A923
+ 12: F36B93C272A703D3422C6A11, 1370C3AF2F3392916364BBBCC2C62EC1
+ 13: A0F33477BAE2E28E6747AA3193, B626DC719528CAC65DB0EF94E35422CE
+ 14: FCF5193506052E8BFA095C1A5205, F5BD02E0B3C91CC7D6FAAA8A9A76CE6A
+ 15: 3797D7F8599B8EEAB39C56241880DC, 0B70003E77146B903F06EF294FECD517
+ 16: C4BAD0E0356FFD369110C048D45D81BE, DE7C2B1D83BE2CC8EA402ABE1038BB79
+ 17: AF5C358BD31CDCAC2F0EA5252F1C3BE1E4, 2D700986F93B22DFE6695C2A243B4E42
+ 18: 7DEF9056FBDAF491D7206B26B19DEF617AA1, E71A7D00BE972D85C77931D7591B2151
+ 19: 6E9B2C0A90BF9D38A6EA3B5D2B9B2D97F938EB, 5B483D7F15C39602C2918181E57DA341
+ 20: 7C5F68DEE9BBA3B04F11D5FC7C9C7FE6E8B5025C, 0AE6A12D37A9C10BB1A494E16705DC05
+ 21: AF0A886BF673BC72045FC074F06A0176C96105E2E6, 06B2DC9A2868C23F86D710E01E37E07B
+ 22: 5F228A986DFE4301EDBAF07A02E114F1B30932995CD1, 74EBF68627C78B1FD024A59B56B2A8FA
+ 23: 911322F60555118CBECD8DD82F186AC19514316E8D48BA, B6A8BAF2F175CD0C71B63B1EF37E185E
+ 24: E7F52730CFB808EFDB376A5D5DF31A7EF8292DC5FC37E9BC, BA2AD158A2D2E5CE01296402B592E1DB
+ 25: B3F8D7CA47D8D86E94D670AFBAFA3B8D9E186C97DC029D4705, 709D2D2B9975D4729C19D4EAC430E65E
+ 26: 7178FEC027AFADDC2C03518E75CF34D207CAC2EB1537A0DBA520, A315F034CE5E66601444402520F55DE2
+ 27: FC230B2B8522F53459D0B968421469BBA7E683ACB0190393B2870F, 48679A78E470E175CF3D3E9B46CEDFCE
+ 28: 35A641127C78C721ECDC50866C21637FDC9515E41CE60F09015EA713, 0062987222F6412B7AAF8A9ABF6FBF98
+ 29: 3D42D6C113421743C08A6F682CFA0E517D5531BB66241C02EC4DCC26F7, B1AAFE11FA2D6E0C870177DDD7F98FF0
+ 30: DAD065B4669B7C59C8392D8E7BD7E64BC01CEFFF27E335B25A328D356F0E, 8973B9B9ECF26DAB58CCF0787EE928E5
+ 31: EBE626F9E241FD233D9781C359430C982667AA26921B62E98FAEC502C01B0B, 2AC0D7052A2CDCCE8E26FEA7595198AA
+ 32: 64D842B66796A797C2B4C6905742FDF2148FFC445E192F9E03B53810C082F788, 9778B345EC12D222DCC6DBABD2651750
+
+EAX-blowfish (8 byte key)
+  0: , D8C4C23A6AC0B7B7
+  1: 2A, 5E0E4BDDB60772FB
+  2: 7695, 7581B16CCC9C45F1
+  3: EB14C8, 6223A121CFA216C7
+  4: 5A5C809C, 4A47658796337D6A
+  5: 8BC2041181, E1FBA8DBA00571FC
+  6: 89C666F015FA, 2B4A76A0E699FCFE
+  7: 86C1FA92484AF6, 31B3B738A261D6F5
+  8: D1F401C145C9328B, 4C4A045EB489F59C
+  9: 70C9C7753698324A73, AB298B5B20567EB4
+ 10: A50D9D88DC101B6DC8D2, 529DFCBFD13B8E6C
+ 11: 7CC2885C2BE79C44F28FF2, 566255022B40C81C
+ 12: 6902D58347C29250EE07981C, 34619AF18E14C690
+ 13: AB6C3C4AD3EC45143392B642DA, E6D2DD323DA175BB
+ 14: 7065B28BA8AB67B2FB7B6D5E3FAF, AEDCAA54F4B0772F
+ 15: CBBA14A74AD4ADC0EF036EDAE42D51, F2BFFA4D81BAC034
+ 16: 60A315193F58144F5701D547C79FEEED, 912FDBDB05467DF5
+
+EAX-xtea (16 byte key)
+  0: , 86881D824E3BC561
+  1: EE, 4C3505F04611D9C2
+  2: 80C8, 6A3428BEEAD60738
+  3: BF88E7, 04F1E99E9F5906C2
+  4: E06574B7, 33B0153AAEF9776F
+  5: 42D950AF63, 4A0F415640322FDF
+  6: C30F6AD46EC9, 9646FE909D2B95CB
+  7: A0049FCA856A14, A0257289C6BBF278
+  8: 2814B0C1358440E0, C4B0A2354925E887
+  9: BF4F062B52C1E489CF, B56442A3CA57A041
+ 10: 63DF433956831B8780FC, ADF9ED0B46DCA19E
+ 11: C317FD079817F50E0E8A16, 2EA0EC993FC603AE
+ 12: 2BD12FDDD81EB11660346D2A, FBC6F69125BBA88D
+ 13: 85D356536FE2843C6BBE60EDBC, BB2FEFD04F230E79
+ 14: 22493009DB01B4746F4927A8C4FB, 64CC08471D93C9AC
+ 15: C0F3C0DB08DC93FBA725D1E02DE084, 77B762213DDCCFFE
+ 16: 568B66D3112556BD98FF9339E9C002E5, C8355F508219FE0C
+
+EAX-rc5 (8 byte key)
+  0: , 169C7954341EF44D
+  1: 22, DABFDA9A0B0BA067
+  2: 2E54, 6A3D6D9AA5877C5A
+  3: 2A6ECF, 2A34A3AF5DE8919E
+  4: 9CC5F84F, D3F673EDAF75E3B5
+  5: FF5611756C, CC647FAAC8D49BF1
+  6: 74C939BEB31C, C335999CCFE8F5FA
+  7: 7976B6F7709B5F, 2A7969C5FD063A88
+  8: 421EEC5022276174, 2C9BFB1EAC3C54A2
+  9: 6A4761CD266B1C0ECB, 3EA3CCEBC85FAC4E
+ 10: 7C09201098E764239A2E, 8043ABA9BF4D5AEE
+ 11: 8CE26277562F646DE33C88, D72AED48895E3B40
+ 12: 52150F44D37D121560DA87F6, 58E865E22B485906
+ 13: BA0A73B45F93ECFBFC3AB3D8D0, 683D52FA47FB1A52
+ 14: 96546CBE01054AD24CC95DB54724, D80D0D530E5D1DDE
+ 15: 61E654BB18CD26FC36C09F874DC2C7, C65884CB9D9FEC1E
+ 16: 1D77B8BF02CDEAB4A707C07628826D5B, F18D1730C3D64701
+
+EAX-rc6 (16 byte key)
+  0: , 1DF8B0B92A3F0C951C425AF4830E63FD
+  1: 1A, 8A2959EBBE90180999994DEB7036DB85
+  2: 435D, 7EF00CB57DB7B4155DB530D75CE6B025
+  3: 08A6CF, 2ED6AF0F2D5BAB05F623D389480A01F2
+  4: A86E54D3, FC69547C8BD922A5BF2F7B26C4D20F98
+  5: ED0822E439, 0007A3C6DEFC6C912C0E5B853B520368
+  6: 7BEFC7FD4054, D32C43A4D1086D57C5BCFAEE04EBC600
+  7: 5235E58E79287C, A27E9C781327C0FC7C55410EB0C828A9
+  8: CEB5EE99BE521F4D, 547F46383987F2A3582A81A3BCF9B280
+  9: 0358B063D5F99C3770, C0A73730512CDA6AD49599775D59EDA1
+ 10: 434B9AEE07DFADD0A332, 499BD88881E558E09A8E822BE27D2496
+ 11: D47849E650F350BB622D74, 638E37A84E7FAAF8F5D77F1B061773DC
+ 12: 814592F568284085E79A024B, 9EB1405E8422FE50BC0D88D837A2C650
+ 13: 6F2B55EC91B591082053AF692E, C48F91EF01AA43A1EE3B36D233DDD48B
+ 14: 506CBDD2901838EE2F178B6953DA, 03778957F536509BFCA577B23A18F726
+ 15: 446EE435D3D1848B51BB8C5F7BE4A1, 1129EAEAADE534940546D43242A4C839
+ 16: FB9D2B150C42465B1685D8F069CC06DB, 41E2940F5DC63CB4E2FBEC25ED8A31E6
+ 17: 9684F683260107BE8FEBBEE1D3EEDAA7BD, BAE7C116F7FF96631F4ACEE95C65CEF3
+ 18: 5082B1FE48CD3AB58F63C2DCFDD4069AC736, 19AC7B8EE315CBB7131A283851B32266
+ 19: 8C72AE495B6F003A3C784D144E84E88885F78E, FA4CEC023740A8D670E351FBCF62C1CB
+ 20: 815D6361C7AE34C9D796ADF9C71ABC46AEF88BC9, 9A1F7288C61A6623B9A82748137ED7CC
+ 21: 904A853E2E96BD2B85AAB3F5DFB900E9B3642EE667, 9AA90DBDD461CAD20495DCFBCB513DD2
+ 22: 79D738A462F727B3D3C529ED999B6FDCCD991D1C5A4D, BF0987BEDDE650D73CAE7D380FED3431
+ 23: B2DEFDB7D503A84E83155A04B8DE8C8DBB68C2FC475007, B7CE900CF43CD518024123C76F6DA328
+ 24: 9E723E15439E12F6C46DF8A309AE1E97B6FD18436259CFB0, DF8B6E1E23512CC4CF5FF531A1908F69
+ 25: A7F0AD03CEBCC9202718AA164886E1026975306A664C5AC7A9, 4A771BF8B9A4325705C85E5499FD98E9
+ 26: A53A92AD1C6835F28E04EF591E783D36F3D76E489B31B87BEB7A, AA263B52A6E6A043DE4D7029D4DC73F5
+ 27: 79BE3C38291A7F77E932C8A9DEAC08DE6442EA9B3895B101A14E7B, 33B84DE06342E675E019CD0237292ED0
+ 28: FA108123C5A69571CFDFE8C3D00535121FDE3096DDC0D700F8F26A5A, 764025D7CA1A3F2C54D28956423B0C77
+ 29: 36EC2D67FD977BD2B73DB6D8EB756B3EADA13690E1B6DFC12A4781B34B, 4BC6B38DE3B02283D92F4DF19A5C48C5
+ 30: 96D3243C945905C9732B5927E46F00886D511463B38C86002FC26B65AB8C, 5B5511CDEC35687AB8425AB22D58B4F1
+ 31: 9CF83B87BEA3374AF7722E999863E3DABB858B0383383EAC7757F5B80FD44B, 1E0CBC961940FDA93B73A92DACFD67F3
+ 32: CE3BC3C9FA5EF4AFE5272B3EDD24B1B003FED2C2E501528CFF44D3FABFF52CB4, DC94FDDC78AAB2B7CAA1E1EF149AC355
+
+EAX-safer+ (16 byte key)
+  0: , B120C7B37450C46189712E4DFD1F0C44
+  1: CA, 82BA1869C5FF1EF2A4F6ADC1E7DC1F1D
+  2: DD20, 6BD5601B16C9943A84AC1F99A176E6D1
+  3: C1C09F, 0911DC63AA414C004E2BD825BECDC93B
+  4: 27E43F59, BD858F084B082F76814DC385E1FB20D1
+  5: 2A9A92F246, 5ADC4A32491934AC0BD00FCE686B26F1
+  6: 52C78C0CD6F4, F35886F46C03EDCA10B3D01CF07B1E0A
+  7: 23E0D3CED3795F, FE33D96FC98B78A30C0A412C60E93992
+  8: CD3FC9961559F239, 9982364A61609FC41068260267231EE9
+  9: 6EA46CB7AD7505C1BC, BB15053EF0F78B9091B3064118F3E9BF
+ 10: 05D9BA230A56CCA0703A, 1338E68E3DC992B6EB2685C668E75869
+ 11: 7AAD6049DFDCA6771AE42B, 35267E431051E1812495615324C4CBE6
+ 12: 8695091532B83B23C296F620, 7B2EEA861E9A91E6B6A911E10FC3FDD1
+ 13: D909DA4BC7372ACAEA78E6A0EE, EA6C1CD16180DF0B07F4E204A4B4FACB
+ 14: 7DEC8443600D0563AEFE87A2064F, DA454728069B3B409889664783588189
+ 15: C042FE656742CD2FE5D9C212D18C6C, 5929E4AECC2CA047BAE948E7023FE4D0
+ 16: 0B84D3CF59EEF7319633F4A397D47CF8, 31F892FFDB7535DF5D9143456E404163
+ 17: 8C9E57AAFA7969B142742B63AB73286600, C418231C44F96660DDBA8C26B3BB3681
+ 18: E9EED66D370A3A6A39C7E0E570D96F807EAC, A4AFE8D1D3C31B956A3BDBD043E7A665
+ 19: 1A5D47992DA5597D1449B4C8DD47B7404C7657, F3ECEE5182014FC3365FDBC4C33CC06A
+ 20: E7C7945FD1AFD3F5DCE666D8A5A2E8A3C11A7A5F, 86D78B2FBA7597B8806BED505B52BDF6
+ 21: 9E2165B47B29CBC4ACD50660E011D691F061209969, E9B1E860BD02085177E1A94E1EE6F3F0
+ 22: 48EA2945C8DD3FE09407BAC8973A861DB15B788C8FFD, 502926712EDB1B3DD13806052C6C75D7
+ 23: F37D46B35B60819EA52B00457D79155C04B55972D0DFA9, BB2B7D210BF0570F422640BF81F39B9E
+ 24: 12E85C0C78227205CC682360C79E35BF58EC6551CF8FE2D0, 042990D7A58D458C570A15DD375DB4E7
+ 25: 4F6C15109DE980DD14A7F4C27F48671E4787C53A564232F427, B097A5990D8067DD89C21473150C070F
+ 26: AAC472E49DB101B564A8A01E2C80C0C6AE9065D332C2DE79FAB6, ACDD587A7DB86542E195DF73AF1C1CBC
+ 27: B9912CE18019C31692A1F7E11D9CCB20297ACCB9DC62C47C01D2C2, B0ACBF028CA5B15E0035D2EB8CA916BE
+ 28: B4F2B1FE14A1ECDC9C8EA1A0120395E6ED1E69D3FC85DD0F3F90F350, 9A561EBC769369B95B9CB74FC6AC27D3
+ 29: 3FE397C8AD02689B7437A37861F0907AF1F6014A293B46419348771C5A, 6B7BEB9BD5018FECD71BE5081C7C2544
+ 30: 5019089142199F7207E1B7731B8B247A18A685B231499DF12A73F5D67D37, 307E93446777005BA1B088F178A0DB6E
+ 31: EAE8F9F02F8DB3D70B78B08CFB0949D99F1A86C958A8E3823736BCEAB86BE1, 6C94F48591C18BF9C450515B73379973
+ 32: B9C795F7A87305B4AD36DBA10B3B1C70B329D29E49C8C6A932D96A74334AEE4A, D18E6E233FEFD6E5C7148BDC1504299C
+
+EAX-twofish (16 byte key)
+  0: , DB0C02CB069E3773296D3BD4A87A381B
+  1: 99, 7D21D19E9C440F68E99F1F2EA2668694
+  2: 0696, EA590EC417C88E23FD23917F9ECFB0C6
+  3: B9B082, 82D4C9B68DDB02C906496413E13A2D68
+  4: D6B29D74, 5BCE5CA4F662E883BF7FCAAE5FB2CE01
+  5: A59C9CB009, CBFB04226D1029A7EC9D64A48A6729BE
+  6: F4924FE3E355, 3D85B3900DECA0528C815F1447A1F209
+  7: 679C88D52FB519, 931C7A863C3701D8015FDBD8696C6C30
+  8: 26DA41C0D115375E, 7627E23E791A4DCB0FA5ED71B1ED2288
+  9: 8FEC6EB7016AD2B178, F65ED0286A724F0CB2EA317D5022B0D8
+ 10: B5F22415B1334133C531, 87C4F3A8991BBB85984BC4D3305A5CF1
+ 11: 23E1D0ED2E820AFE7DA2FE, 100499F1093FAB2ECF73B643594E98E3
+ 12: 79519ABA91F46B8DAD6D5335, FBDCD1FCDB20AB99135F28A714C6992F
+ 13: 5968D0B4198A0AAD3D0395018F, 781F22E2DA98F83398FCF911B2010057
+ 14: 4E55B14432B601E3EF2EF567CB15, 8BF6E53D7657E56EA3DA1BFD9C9EC06E
+ 15: 6ED89651CE19B3DD1EE5C8780B5015, 131CFD657D32D4E1B35140ADDCA0E13A
+ 16: 2295A968B4D072D12757756247554850, F35FAC95C2AA4155450EAAA6E2E789B5
+ 17: F9B2AA2AA502EA79BBA0C5EAD932B8E1EE, 0ED81AA40B9BF39A9AAEDDDB7A04BEA6
+ 18: 385055F1C1C26C0472A504B4CD225DCA55FE, 24831680B56368231AC54227D737F582
+ 19: 771529585C741A3F8B1C973709892F255A99EE, 2A132B4BF96FD5109DB04459103F5E84
+ 20: E7A2197D9FAA8AB8B303B5EC71AE34AD5EC5DD66, CCAB6518371EC8E0A9E9EE4F7CA5878B
+ 21: 279E54F755EAC6B57375B9EC4406E43DB3139D740C, 7B6F26F2C0ECC9F2DF4EDD7513E6E0B7
+ 22: 27816AA94CBA2BF98E49E595AF5B3FAD12BF1D6F1AC6, D04876C5492D275F15C834E3CF794F0E
+ 23: B5658DC148855F68B282211D879F688F3C142FE555CF81, 4539CDA8A65DB9047AAD76B421B81120
+ 24: 72F0BD4F939C2C9B4FA734DCB0AE4FB9BD342BC8459ED2FE, CEA8469BC0457EBF3418C1114288C904
+ 25: 70568245E6E6BD5D11AD0C74030D7AE08BA05057DEA0FBF4AD, 71554FDE6B87477A51EE4499D78783D2
+ 26: 8702D35BE07D7ADF70684046CC6C72FBBBF821E0BBCCBC973601, 33CC6FBFDA15E306919E0C3BB2E22BB6
+ 27: 0BA23F4A6174165D4A8BA80B7C875340B0F8B2A6967D34E106BC22, 00E6679496714236EECEC84B9AF3072E
+ 28: B9E25ABA84C6BD95B5149E7616FE2E1D6FAACEAAD77A636C60279176, 8D8AD0B9D4C709E1DA370EE01611482A
+ 29: 74759711F6D542581F9F83498FB616638D092732BA07109BF4B5BE045C, 71A40DC777BD09F75362F7B20E0B7576
+ 30: ADBF7E98926484BA2C7F6CD7CD9734FC19265F68AF3BFCAEB025F6296E37, 8DF15B5F69B67F7DABE44E3666B55047
+ 31: 2DC26D449379997D110309B2A0DC2760FCE8CADB4B14ED580F86C70F69C9BA, EFCB60EB2B25737E256BC76700B198EF
+ 32: 2B1890EB9FC0B8293E45D42D2126F4072754AA54E220C853C5F20FBA86BE0795, 1A1B15BBC287372FB9AF035FB124B6A1
+
+EAX-rc2 (8 byte key)
+  0: , D6CC8632EEE0F46B
+  1: 4C, EA19572CB8970CB4
+  2: 5537, 3EDD3253F6D0C1A8
+  3: 206FA6, 20FA88F03F240D31
+  4: 17EE8B40, 702E8194F1FCBFDE
+  5: 2A89287136, 31C5534786E15FB3
+  6: 3A6AEDC7066B, 3C663A4081E1D243
+  7: 8BC5203947A644, 6AAC806C92BFBD6E
+  8: 2E0274BBE14D21A3, CEB0E0CB73C3664C
+  9: 9C4B292B0CF17E3A29, F23CD535559023EC
+ 10: 8E322734308F85662877, 46363D7EFC322821
+ 11: C413C405767FF5F98E3667, E7BA35D8F3678E7E
+ 12: D77806B7A218098B1569EADC, BA67C306E5C0181B
+ 13: 4BE5EF74F9E9799A4D636FEA9F, 4C511C44ADBA4030
+ 14: 7E19969170C2C8D8AEBA8C7FBC2C, 54CC6D466A2DF6DA
+ 15: 2EF1CEDC1DD3403CF440FC5561BE33, 61C6FB277E93701F
+ 16: DE052719153EBACE9D7B19F52AC4282F, 4AC2A96F2FA8634C
+
+EAX-des (8 byte key)
+  0: , 44048B7F240B6F5F
+  1: 0A, 37009B7D4E09953A
+  2: 03BA, BFD2FD7758961728
+  3: 37EE10, 16A6AF96DE888A19
+  4: 07F44290, 100CA84AA0EDAA1D
+  5: 389EF0023B, 9614FB800A533268
+  6: 3F4DBA8AA01C, EFA6B55B7ED5E40F
+  7: 8C7B837896EAE7, C113CE8F664CE3D4
+  8: 7011D993D8EDB0C7, B4C370A919F60497
+  9: 0DEB30A31351B13D7B, 00ABC82DC5F3A1AF
+ 10: 8D3897B2CBE323D6EE1C, 7A2D15627CA1441B
+ 11: DBC002C817DEBFB419F94B, D8EB87F86D6ACDEF
+ 12: 17048E2976FA85AA849E9A80, 229FCD1C9D1E3B9C
+ 13: 30B989EF646544885A478AC198, C1B7EB4F799105C8
+ 14: 5C2E12A7F118A08D6FD585F9C839, C358679FEE6FE7D7
+ 15: 8D1A1E888BBB8648E638C4E74E11B8, 685E006C441448B8
+ 16: 93AE906B8BE4EAC8ED6D8F48F04A7AFF, 71DD7AF752FE28FB
+
+EAX-3des (24 byte key)
+  0: , 8914311BB990B725
+  1: D8, 2094EDC5D03E54B1
+  2: FEE5, 781CFB0EBE3895CA
+  3: DECF5E, 59918E8A5C4B459B
+  4: BD583AAD, 2013BEEBEEA795A1
+  5: 2BC01C6C78, 0B1134DBBEAB5D3F
+  6: 4D5EAF01A895, AB4D17516ECBA50A
+  7: AF229F90614480, D3113C0A9D133CD4
+  8: BCA6F375DF4568E0, 8E9EAEC8E77786BC
+  9: 575F34219E6DD8DB4C, B40C75139E5D1860
+ 10: A199B8AC433B615EC96F, 774AF803698ADE3D
+ 11: 718A2975DD9A872A68AE10, 3B9460F849CBA7FB
+ 12: AB38E148180F6E2FFBB96F91, E3EE3B8FC50DADBC
+ 13: EB10E0233507459D4A6C29EE80, 8D90B46BB1EAB27E
+ 14: EB48559C320DFB056C37458E19B5, 9315F0C4AF8500EB
+ 15: 9E8C73EADA105749B5D8D97392EDC3, 2E749EE66C1E6A16
+ 16: 600FA4149AF252C87B828C780AEFF8BC, 33D7D11DCDC19936
+
+EAX-cast5 (8 byte key)
+  0: , 382FB8F7E9F69FDC
+  1: 99, 20DA959849B3F7AB
+  2: C54B, D05547C6AFA3484A
+  3: 579836, AAA92B2321FC50C5
+  4: FEB7AE55, 639EDF01C4FB965D
+  5: EA8A6023FA, 01274B3ED5CE102C
+  6: B7C4E995121F, 712BFE27CAFF6DDE
+  7: F44236660B0004, FAC51D1DF8EC7093
+  8: 01CD7E3D0BF29E8A, 049C47A45D868D0B
+  9: DAB170493DFD6E0365, 6F3AEDD9A3ECF4FD
+ 10: 82C9EEC4803D9CD11FA8, 32683C0A9128C6EA
+ 11: 324AC59E87B244ECE0F32F, F6B095AAB49353CF
+ 12: DBDDAB11D02C9CA5843C406E, EA728FC46DDD3B04
+ 13: D67376C2A4AD92E7DD80E39303, CAF72B7E7C237EB3
+ 14: F2B9BBEF08036C2982C6DDD06918, 70A29D780C22752C
+ 15: 96E3D9141F8EBF520540C2BC9A9C23, CEFC86A1CD48203D
+ 16: 70CABBA983179106AE7FCD5F1F31D5C3, BF7F9168F4F82F56
+
+EAX-noekeon (16 byte key)
+  0: , 556805EEA595CFB9A30FAD196103D7FD
+  1: F5, 0A7DAEDFB656526CEF4DDBA8087A227A
+  2: 7B8C, 249895D79962D5B4D18FE07366281B72
+  3: ACFF15, DCC489D24832EB106F576AE6B6EB957A
+  4: 08ADE7DB, 0D3215999E9960EDAB29B78744C7F139
+  5: 66139213F6, 505E1E7141D043E903C26EE0959EEECD
+  6: 078B79F880A8, 35B7EB326A55E50332866EEDB682EC20
+  7: 2809E34D9667D4, FFDEC555F68524A09A6ABACA372077D9
+  8: 93D267DE1EC635D3, 4FF3561990A56E4B374618722EF850FF
+  9: F377A4D93FF32F4A51, 91D4070423A90FC54D305169C03F49ED
+ 10: 6244B717E082993EB7A1, 2E3A8A354AFA9473667ED7FDD46BE9FC
+ 11: E917559625D25E6E5F2EDA, 19295C37A70314CC9A1D11FDE8D23C92
+ 12: 1E6DF2EE112A893AB14DFA92, 12C4A89D4CD65F8116A03A135AFD3701
+ 13: 47B18CD762E011770E203CF605, 434909A97E118B20D3AEDC79AFE33A9E
+ 14: 72D9A1A7DA6F33D5E0B927F9F32C, 779C23714FCAA2B2321EC7FB5B03E222
+ 15: DA8B830FFCB3DB274807F780D33240, EDC2F1C8A401F328A53392597730B007
+ 16: B53DD2BB840AD933D36A7B5FFDCCFBBB, 4EC0E6D1F916BF633869239B672B37A1
+ 17: 42936BB9A936C30408660855F4F47F3314, F0DAA6DDA15585E1697ABBB4790B15B5
+ 18: 00372E47F5BA016F1B2A1E680B76AB02052A, CDBF3D241BF7FF96D3DFBEDDB872E901
+ 19: 8AA236B0C8BEF6F67A97C2DF90628F6E5838FF, 731DCD61F7F26004C03519F9500EA824
+ 20: 55338647812FC9D86CBDDCED7120268A4D43F8BA, 0E61B3C835CAD95FD49FEF002C014E72
+ 21: 435820B28E52154B47A04D5E635D8FE37FA47FC985, F6A96DCE4917E8D7C610923627E80970
+ 22: 0D30C15B6FEB4A48B14DD15D41A4B25D442AA677B25C, 28E15CCB74AE992C68BDDC8D87802050
+ 23: D9D701F9AD6B0E13D2CDDA15A5194E7CE8BD2C02137391, 2DB9A15884E9C996C3D6B5BDA44B9598
+ 24: E2390AC5CE10CCFBC72106A52C7F180CB477E3C193CBACA8, 22D3F7DCD6947EA4E78DF57A8E1A9A59
+ 25: ADEFB7D9500658D34996AF6BE6336CD78891064EA1DB8E9785, F239D67D039A15C620A7CD4BE4796B3F
+ 26: 89964C90ABF54A6DF9F13C3681E70C702D80A17BE79F8160F30E, 6336F729ECE1ED7368669D75B7E2DCBA
+ 27: 576B2813CECDA4F905BD5D58349EF070FF41B7EB6BB2B01B061B0B, 125324CBF2ACF1011A44A99A11EC8AFC
+ 28: 430B957481748519A60494F0B5F698F34B1A8235B00AC0D1F0A4442E, 1E80A7FCEBBB8E1E12D6831906154485
+ 29: E781BFE5FCDE0BFC056CC86C4A0B9DD3B815BE8CA678204CF47289B5B5, 190D5AAA9EC1CB4CC86FACE53BF1201B
+ 30: 78BFAC07A9B7B2AE9329BF9F9BF18A1A49DD9587001EFCA00E9AD9752764, 4FB5ECBEEB0995C150EBC66508FA19C1
+ 31: 7D6C20694109DE21F7955855A8FF832347518DD496C2A114DF142C68ACDEAA, B25D4BB34056DC091A7A3950D46C32EC
+ 32: 3E1E4395DEC1AFEA9212B95F37E679B6E2D14DF23C5DE49018C2C8038CC4AD45, 9A6DE7BD41A21918AD504490EF4E581D
+
+EAX-skipjack (10 byte key)
+  0: , 85F74B6AFFB10ACD
+  1: 3F, 604DF8BDD98A0B3F
+  2: EA87, 792374FE07588BF9
+  3: 0169CA, 489AB8AF69DA3306
+  4: A7AC3EB1, 428DAF508E24B583
+  5: AA9028D5B3, C0A44EDA71FB2C86
+  6: DA97BA88A061, DA2EC34077F42585
+  7: 7E25FAA41CEBC8, 36D4987551E06D5B
+  8: F662DA6C9001CBFE, B7DEF76680C316A9
+  9: 6D3F73EC716E1DA897, 5F0F83BAE4D3513B
+ 10: 2A300F585BEE9C889743, F4756C24DEB72A9C
+ 11: 80518B010DD77C82D19106, 50FF5CAA365F4A70
+ 12: 6E579A2173C861B6F37B4CD3, 81E3E5ABBA8F0292
+ 13: 5B04829880A72C38871C7021F3, 6B26F463708A3294
+ 14: 934177878E9A9A9FB4DEB3895922, EBC1C32F0A2A3E96
+ 15: 07AF486D1C458AAB2DBF13C3243FAD, 87288E41A9E64089
+ 16: 84059283DF9A2A8563E7AF69235F26DF, 351652A0DBCE9D6E
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/etc/whirlgen.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,91 @@
+#include <stdio.h>
+
+unsigned E[16] =  { 1, 0xb, 9, 0xc, 0xd, 6, 0xf, 3, 0xe, 8, 7, 4, 0xa, 2, 5, 0 };
+unsigned Ei[16];
+unsigned R[16] =  { 7, 0xc, 0xb, 0xd, 0xe, 4, 9, 0xf, 6, 3, 8, 0xa, 2, 5, 1, 0 };
+unsigned cir[8][8] = { 
+ {1, 1, 4, 1, 8, 5, 2, 9 },
+}; 
+
+
+unsigned gf_mul(unsigned a, unsigned b)
+{
+   unsigned r;
+   
+   r = 0;
+   while (a) {
+      if (a & 1) r ^= b;
+      a >>= 1;
+      b = (b << 1) ^ (b & 0x80 ? 0x11d : 0x00);
+   }
+   return r;
+}
+
+unsigned sbox(unsigned x)
+{
+   unsigned a, b, w;
+   
+   a = x >> 4;
+   b = x & 15;
+   
+   a = E[a]; b = Ei[b];
+   w = a ^ b; w = R[w];
+   a = E[a ^ w]; b = Ei[b ^ w];
+   
+   
+   return (a << 4) | b;
+}
+
+int main(void)
+{
+   unsigned x, y;
+   
+   for (x = 0; x < 16; x++) Ei[E[x]] = x;
+   
+//   for (x = 0; x < 16; x++) printf("%2x ", sbox(x));
+   for (y = 1; y < 8; y++) {
+      for (x = 0; x < 8; x++) {
+          cir[y][x] = cir[y-1][(x-1)&7];
+      }
+   }
+
+/*   
+   printf("\n");
+   for (y = 0; y < 8; y++) {
+       for (x = 0; x < 8; x++) printf("%2d ", cir[y][x]);
+       printf("\n");
+   }
+*/
+
+   for (y = 0; y < 8; y++) {
+       printf("static const ulong64 sbox%d[] = {\n", y);
+       for (x = 0; x < 256; ) {
+           printf("CONST64(0x%02x%02x%02x%02x%02x%02x%02x%02x)",
+              gf_mul(sbox(x), cir[y][0]),
+              gf_mul(sbox(x), cir[y][1]),
+              gf_mul(sbox(x), cir[y][2]),
+              gf_mul(sbox(x), cir[y][3]),
+              gf_mul(sbox(x), cir[y][4]),
+              gf_mul(sbox(x), cir[y][5]),
+              gf_mul(sbox(x), cir[y][6]),
+              gf_mul(sbox(x), cir[y][7]));
+           if (x < 255) printf(", ");
+           if (!(++x & 3)) printf("\n");
+       }
+       printf("};\n\n");
+  }
+  
+  printf("static const ulong64 cont[] = {\n");
+  for (y = 0; y <= 10; y++) {
+      printf("CONST64(0x");
+      for (x = 0; x < 8; x++) {
+         printf("%02x", sbox((8*y + x)&255));
+      }
+      printf("),\n");
+  }
+  printf("};\n\n");
+  return 0;
+   
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/etc/whirltest.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+int main(void)
+{
+   char buf[4096];
+   int x;
+   
+   while (fgets(buf, sizeof(buf)-2, stdin) != NULL) {
+        for (x = 0; x < 128; ) {
+            printf("0x%c%c, ", buf[x], buf[x+1]);
+            if (!((x += 2) & 31)) printf("\n");
+        }
+   }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/hash_tv.txt	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,1736 @@
+Hash Test Vectors:
+
+These are the hashes of nn bytes '00 01 02 03 .. (nn-1)'
+
+Hash: tiger
+  0: 3293AC630C13F0245F92BBB1766E16167A4E58492DDE73F3
+  1: 5D9ED00A030E638BDB753A6A24FB900E5A63B8E73E6C25B6
+  2: 65B0E1EA36CA17EDE2F055E67EAD67B1C282A11A5BA3A8E0
+  3: AB7FB8D21CE3D8D9BB5F1AF1F2FA0D3C277906160DB8D226
+  4: FE2E9D43F74B199D91B9291D73CCFCA0BEA5F068FBA244FF
+  5: 3DF6D672FE9DAAB21523EB04705D8A8B72B78B00AD465D1C
+  6: E05724353FE29957C3E8DEBAA21D0C2DD49CCA22191D5AD3
+  7: 4056DDBF82AE74AB56720DEAF079ACA2F076ED046D044DE5
+  8: 801FB9BE1A9AC7337A81345B3845E4E7C13AF1FBADB73723
+  9: 430156547A82492CA859385304748F65F2D4A7E2664AE2B1
+ 10: FC435137CD652D720A11EDF47ABE4680BA4AD5BD810C9835
+ 11: 20A8143DF47F5715FA0905FE6F9D1D2B5B2D4E26FA98930B
+ 12: E4A2063019FBC034DEB01E2A95296042319CBC039DA69A91
+ 13: B5F0FA570C4CD69A3C68448BE42C865BDF77ED68B93875E7
+ 14: 802BE6EA2CE86A0B371F2354944B19CB3231AF7FB4F00FF8
+ 15: D7C08863B5E5E3D69B5404A116315A698E128EBAF8636B70
+ 16: 5C5288CB0E4E533056BA5293440D9BE6F3C461233BF1ED51
+ 17: 88D3A94F3820E4087DA69D8BBE2CF415466063709C450C4D
+ 18: C07B4B155F9F75805D9D087087FCDD28D08A9D022192447E
+ 19: EE473E569FF3E092CF8996B31CE665EA7D61520D42E27395
+ 20: E13DAE8098139CFCEA755D2060F107E3C7581EDF9F4B3B85
+ 21: B48A9C09F26B379AA28FBC750B50CEF69D0D0EE37FF765F7
+ 22: 574A01456373014F4179CDA14541E2E3C5A1CDDA9F9D071C
+ 23: F2E2831E5BB4AF05914C4BA61BB8D600D1EF071C5DF02269
+ 24: B7808A5B6258CBE718EDA938978C69D3FFC45A222E9DBF4C
+ 25: D8E4E076DDE78950D51EAC9F97D2D1916A0910465D45A55C
+ 26: 4EDECFAAE1DE98B7E056E64CA24003422BBE6F048129B24C
+ 27: 0DE283B5A4953EAAEC6F3FDE50D7875C8EE57FA79BDC70FC
+ 28: ECDD4BA1936DB9E6F83E2BD7F39D23927A1A17B2D52A8649
+ 29: BE11893460E49659F7DF3FB3BD5E3E9A319F85FD3496E26C
+ 30: AEC0DA0F2CC0646325CC03319A0E080F68B46B33F81920D6
+ 31: 8824FD39984F6A52FFFF19016E27C594921452086373F2EE
+ 32: 8B6592AFBB02E227AA451B5CFDC821B84245D34B96BF4F13
+ 33: 960DF9C349EC6619FF37E3F0F4832E19CC6A4E4D68962651
+ 34: F4E2B7AA72BC7D6E0CF6DA1094BEEFAA9C55610327C62900
+ 35: 05FD1B80CA4C7C14FE5BF0ACBD0EA3DAE498DC391DCF2277
+ 36: C5E95F953898C68355B591507BB714F0E5DAB9989D083900
+ 37: B2D4E286CF7EA8AB6ECD650C9E48CA23497EADE55485DB1E
+ 38: 9D51657E11C54FFDF205DBB435097A2BC6F93C4BE8D6180B
+ 39: 3C6AE3911356A343AE3113735F07FCFB5E046ACD47B00FBB
+ 40: 664342CDECC825ED340A7FFE2E57107DD0B5F24C24B2C3F0
+ 41: 4EF7FCA13CE684D81DE4F566D2897CEB407FBB3DDE81FD64
+ 42: 54689FECED63F297B13CD494B85E686680F4F78DE7EC81D5
+ 43: AF434BDBDC7EF90BE03E40A033F16E8A57B41840E1E8AB59
+ 44: A32DB678F44905C18968F5D898CA7992EBE2E4CC3318B96C
+ 45: DEE9D519A12ACFB8A0935A368D6E6C75EEEEE6F2B0D5D191
+ 46: CBC74863472D1C9D23C526F4908BD4D4234E00CBCC99A9E9
+ 47: 6C228A1D4871E802E035C9BB16C5187354841FB6BE3C69B6
+ 48: CAA755C55AA869E633CB3C6D93A561944AC7418154E2B0F0
+ 49: A6835F7C0C6CA8F4A45787BAFA77478AE9ADDBEFBC3052D3
+ 50: E406755957EC21BA6A64B5D3AAF31749CF98DF92F1B1FFE0
+ 51: 0C2D4A44A803DBA99B7A467553C9293B46A538558BD77DD4
+ 52: F04F011B09D275A185528CC040EB719649C8471A87B259B3
+ 53: 3DA8B57FF52FCAE7C32636EC6C80708189CED8113C5CDE1E
+ 54: 6C6C88B8E18DF5CB22EDB61A2D3ED74741A708BC46576FB7
+ 55: 2D48EE2BF85DE234754BECF3C6F5B0E62988B5BF24AEA5BB
+ 56: 0D17702DDCA078ED1CC51B95DF29EA1053CE97F69395C613
+ 57: 9D8C2AD327DE43D5782D5F20881F4A8C433BA19AFC8C15AD
+ 58: 227BA419B760D9D10DBB09585EDD475AC2734FD4539F8275
+ 59: 2F5220A828EF94E327BD51D4DF5C58609F8A93B9FE01FFF6
+ 60: 0EED9F91E1A33A50B8E913DBA0B5E248D263E1FC72C6A449
+ 61: 766B707E999FF3C51EE01168513BA0DCEFEAB222DD1F69F6
+ 62: 85E6710694E7C36A2340DA6A371C0560450F3D44D35AD98C
+ 63: D401F9B13D39C24477C0AE6971C705C63C067F29508C29C9
+ 64: 212DF89C57155270344ACCB19027B0B26B104FA0FBBE0FE4
+ 65: 3BEDE767AA4A7507DBEFF83D1BC33F67EBA9C64945066227
+ 66: 79FED1FB9F17C4980108E8605C10D9E176AC8FE4F6A65064
+ 67: 48D9B7622AB7F8968ED926255F78E8CE461E4C9162FFE8B7
+ 68: 6638C83837297B3F53B0F824C087D9A0B8D9FC6265683B8F
+ 69: 174421CF6D331FF51924F8946E8244555C9020D38E31B6DB
+ 70: 03E42AFB5FFF9B9C3794A3DBEC99FA7E3F7305EF07BD29EF
+ 71: CCAFC68D4B3ED889DC9F28CB9225808A40AA8E0D5CA343FF
+ 72: E824F93B4022011886EFC54539D4D5D51863ADA329FB4E22
+ 73: 7CF0DC01B326687530F42040BA0D0CE93174455E8A990D14
+ 74: 7A8E619479F4F5C418EC041806850E6723CA56AFBC3D32CC
+ 75: 083C5CA90F4B296C42040559C8296149D4EEBAB5EF2CB82D
+ 76: 3581B7AC32FA8A0986FD14F277FB106E112B92D18CD689BD
+ 77: 258E822D9CC1ECA8B55D925BA361BA2D9FC27AF181F138B4
+ 78: A86C1E88A64515FA281A462D467458231494F16E835DF873
+ 79: 76E7F06FE9B8B388DB012F8B4BE2FB343F95913EDDE47A27
+ 80: 00278B4E5690E729EC7118B5BF63C9D1EB1268960893CA75
+ 81: 8DE70E64A31BA1AF4F5C23CF774CCA32FE952D76C3FDD1B7
+ 82: BBEA72C840749BABAF1415FEAC343411B89515B87848A09A
+ 83: C6C3CCAC1B338DF117A61ECF9A280E9BA709784C72B76771
+ 84: AE9813EF4429EAE73EA9FDB5E23D263AF1BB87928CF5F048
+ 85: 68647CD7BFFB8E530D28C86685A8D2F657EE4CD64EDD7E66
+ 86: AA8C35B0E746AF56435F6C711AD0423966EA459087409713
+ 87: AAD5C0D5E980B29BC88985C544717B81F58CDB923A3468E0
+ 88: F60929D14781DE44EA607AAFC0D25FA1B6EF3C6AA0F8B3D7
+ 89: C48087DC75EC43A54A593F24E1B359BB75C581A65C3170D0
+ 90: 11D1372FBDFD9FF514611AB20D31BA62F18856C8D6AE3AD7
+ 91: F2A8076B9017EDADEED41F409C9E32EB3BC090EAE89F855D
+ 92: 702FA47E5BD35E344B5B87C0082106337206CADD3D4D5014
+ 93: B9E03FED752A560C3B0365EDF5BFC4DC7EAC5E4BBB93738D
+ 94: 3C84C52BF51077A5819F56E5A5C1C06209181579393220C7
+ 95: F8ECCA28A525594E138B55C06617A063DF74FE3469D98381
+ 96: 1081C3BAEEC0ADF4980C2EA6593B0906DCBEDE4805754774
+ 97: B5152E39DE0BFE8982D783FC4F0CB7160EB2D69F6F3B3E5B
+ 98: 6A6B760BFB1965C72AC793F9C02FA21B0F1C34BD2640BB6B
+ 99: 1E6DCBFA8BA8D96C29101768A6A39433D5AD5A50E0970730
+100: 733222D3A033351FAFD68C5CE8A4D833BA7420D44103CB6B
+101: E4CD7DA59B215F1DEAA8FBBA850F2C1A7F4C3D495FE6804A
+102: 7BE78C790713545754D4C78A9318ACA4AA058C5C23540131
+103: B71C3809A504BE2F57AE9E25BDCC3921DC665C65289EA55A
+104: 2B8CA39977535EB692EFBF0DECDA8971A8604F7FCBAE75DD
+105: 3CC48B51E4C5DE4F0C2ABE0BE6EE4B63CC564A87C01943CD
+106: 157ACDF7B59FC25966F9783207554364882840E7251ED6C1
+107: DEA1CFAECF18D3611CCD0517131A16DDBC97A12902DD8BAB
+108: 2AD2E990BCF6481284DF44B961632687C2E64DFAE2AE16C2
+109: 838F3A3B28A50A12B5707490A66080DCFA0230E583B6EB14
+110: C8B20315121CDFB3A91BC0EDF11886F283CF6C480F498627
+111: 2B0FB04F100BE9AD51B7D64C76651BAB4B7D31D1D9195711
+112: B6495B6256FF464EC409A4098B622E8BDBB1003411854FD7
+113: 1741A789472E20E1CC89869A2477E4F2807C22182EA5B221
+114: 07ADC82CB3F27389A12B6B9C2B268BDDFD1D9478D9EDA0D7
+115: D9BD6760FB819A8A3CEE75303F8208FCA3E138B517DAB934
+116: 9FCF21A9236C2C12861FD20F1FB15A187CD7EE7821F72BE7
+117: 73D165769B34DA6F151464E61115D0E09A66F8D0FA049726
+118: 74580BFA88EEA03C0EAE722F81997E400D9CC25FA0311DFA
+119: E3C6A369820E267C938D276A858928040C7C25A826501DC7
+120: C20AD90DB0B8BEE0335D069259991060969EEC9F939E4CA7
+121: F3746F4CD6A19CC137C5FCC8F60A4C0A7F56D97190B7A9C2
+122: 63A3B79EAF3DF35180960465059C0ADEE06D45179A56284F
+123: 606AFD833D082628D58672403EE6DB348E6F68D8CD1947F8
+124: 7567EA8E10CBF312F8478B7C51D87B00B6CF3DE82B03DCE7
+125: DBCDC2B9B8589F6C7616B55B059B3B3E38D97A9E6DF1F29A
+126: 15D9909F8D69689E7E78A0DB928194A59623E7253AA9D400
+127: DE39589DCC0C654867943801946B9888B347526279CA15BD
+128: 34FA7C74EE67C1F92C0BE1CFD4B2F46A14FFB999604925F6
+
+Hash: md2
+  0: 8350E5A3E24C153DF2275C9F80692773
+  1: EE8DBAE3BC62BDC94EA63F69C1BC26C9
+  2: 1EAA4F494D81BC570FED4440EF3AC1C3
+  3: 54CDB6D1BF893171E7814DB84DF63A3A
+  4: F71A82F8083CD9ABA3D0D651E2577EDA
+  5: 2F708334DBD1FE8F71CEE77E54B470F9
+  6: E014DF2DF43498495056E7A437476A34
+  7: 9C410644446400B0F2C1B4697C443E19
+  8: 0944DEC40367AC855117012204018C9F
+  9: CE8A6E797AC79D82D2C6D151F740CB33
+ 10: 06DB4C310570268754114F747E1F0946
+ 11: 9F323D5FC6DA86307BEBC0371A733787
+ 12: 3C1C7E741794D3D4022DE17FCE72B283
+ 13: 035D71AA96F782A9EB8D431E431672EE
+ 14: 7ABE4067ED6CA42C79B542829434559C
+ 15: 5E8D0D6F6F8E07C226AE9DD32609035A
+ 16: 2B1632FF487D6C98AA3773B9D3FCD2AB
+ 17: D3D894482F7541BC0948B19842B479D9
+ 18: CFE6B872AC98304524CC6A88B6C45881
+ 19: 1573DD015C8629DE9664CA0721473888
+ 20: ACFE2D3BB3CCAD8AEF6E37D0D8FBD634
+ 21: F5F83499AA172BE8344F7F39BA708AAA
+ 22: 1D1C71FF6321B685D26F7FA620DA6C22
+ 23: 4D7E74B6C8321775A34F7EFF38AAE5DF
+ 24: 351A988C86AC5A10D0AB8E9071795181
+ 25: 970F511C12E9CCD526EFF8574CF1467F
+ 26: 0A68F53A476F7499EF79278A4EE8DAA3
+ 27: D458CF9C8CD0ABA23BD9A8C5ABE495CE
+ 28: C8002E85C3AD9B8B4AFD23378165C54B
+ 29: 0B4788B157ED150A34D0E6E96BB4789C
+ 30: B14F4E31DE09281E07248A17939BE5B9
+ 31: 803EEB99231526D6A33C8D4FCA537A6F
+ 32: 51FE5D6637D2F0F09E48CE2A7F5030EA
+
+Hash: md4
+  0: 31D6CFE0D16AE931B73C59D7E0C089C0
+  1: 47C61A0FA8738BA77308A8A600F88E4B
+  2: 9E7A1DDE4D280E7F389018A5CCC3ABF2
+  3: E9A4DB2923FAF634CBB12CC1F8AC5C66
+  4: DF8FA069C6121801FFC539DADD33FCB9
+  5: 4B3511308F7E71BF6462CF18F1184C61
+  6: 075582A51F87682919E733C84C9FD998
+  7: 20DDA7535A464D13E1763BA61BDC12AC
+  8: 66AE1E305BED186780BB60328D3CCBC5
+  9: 503E90BF2375627262E58D90177220F8
+ 10: AEC6B48C10659E3D6E18A2CDE8F8D3A0
+ 11: 45EFB3704B6684B0750E3DEDBB2BCDA9
+ 12: 7C9443DBCD858138E32604E0D288F7B8
+ 13: 95E5B93F4EA79C082BA1745D3026D70A
+ 14: C913D5DE0BBD1C2F2838E46363732D97
+ 15: ABE357BDC413C82C8BBAA380C39CB5F9
+ 16: 22F840370EBB1DDBEA4FA3A40243391E
+ 17: 0A289FEC69AF967988FA40C47960060B
+ 18: B63D3ADF13B509C95C088F909A0B356E
+ 19: 36E8E07E3202E6F4F7E885853C9735C7
+ 20: 1D363AFD1208A7B8BD486D51AEBFAEB8
+ 21: 75E36A5445AD72CF5BF47301EBED1FDF
+ 22: DA7979688F48A6606D86C762DF0D8850
+ 23: 6ACB325CE624372873CC01A4AA053F8E
+ 24: 94F9BFD6503DBDC58C163E33504B7EDB
+ 25: 3702CB296784290FC46B82445BF7EB17
+ 26: 903510251E7A00415EA21B6AC268A92D
+ 27: 6DF08DB9C33C86CFE8DAF5E5BB865ECE
+ 28: C29C5223D89A6589DE9253AF050D3449
+ 29: 16B935ACC3EC6C016CA1BBF727C272B9
+ 30: 644C01B157A24584B02A32119A424C01
+ 31: 4A3C6C73634759420C419426F7D43E67
+ 32: 7BD627A6B82FF3D797FFF130D8956391
+ 33: 811A69D6A8AFE3C4FE5B4EFD73804F6E
+ 34: 721BE5F4BDDED885BFF842868F62F4ED
+ 35: 76956871B22D5BECAD3E9A459B4A448B
+ 36: 4F2CF372771A13B4C0C1A589F0EDCF87
+ 37: 084AFBAE8D22DF83CC760A61138E560A
+ 38: E1CA123EBA05CC4899731A593833F372
+ 39: 9D9E277FA61993C018C1C61AE09588BC
+ 40: 85E0D0316F0B76578948810039EDE2BA
+ 41: 27736345D0F2B0A1A9576D17C47D0202
+ 42: DC9F788BE7C97BB5E0D2DD49B9F1D2DC
+ 43: 27F1A9A0D166C495493877DF06E9C104
+ 44: D1ACA7951866F58773CD4AFA3D2F5C2E
+ 45: 5204BE3729BD7D318EA8127BED82D5CC
+ 46: 10258B7939D81F5F8E0EA70EE6500B08
+ 47: 4E699952169098ED3084DC2EEE7BC488
+ 48: DF6ED8D604512088FCEAFB21808BF7D0
+ 49: 904D0667C94C9C981D59BE80DEEEE628
+ 50: D83483A47B64D74F9DED5278EE462404
+ 51: 490EC8799A9DE3BDE8708DAF68E6888E
+ 52: 443E4D2D5F800C22D818927A29A38490
+ 53: 48E82AA772E111FCBE393177F3123963
+ 54: B72685D042162D5F30472281278C42F7
+ 55: CC8A7F2BD608E3EEECB7F121D13BEA55
+ 56: B8E94B6408BBFA6EC9805BF21BC05CBD
+ 57: 6AEC85410412FF54078A9FC72A55ACE5
+ 58: 3E69F792BE88478883E46E867F3C93EB
+ 59: 3B057FC41BA700F0E46740B8FF391F52
+ 60: 3E3C6DF9500BFF8404486A3AEFC6F16D
+ 61: F5AD65BA970ACBBB8335F9C0B9D7139F
+ 62: 75D45F8E48406E32ABF94D07FF9B9C84
+ 63: 54BA4472FCD03E99CF28F90EED9F2AE0
+ 64: 2DE6578F0E7898FA17ACD84B79685D3A
+ 65: 3A4F2CA37EEBDF6DC99A6155517B74FC
+ 66: E19DC463C01E1B712B9415202A2B5505
+ 67: 61D8AA0838DEAEEADE2F26156AF58761
+ 68: BE294AFF81BFEA3159564B8B61844EFE
+ 69: BB943319320EE7B3A029D7BCD101F92F
+ 70: 36239791A7BE33AD46F668B51D724481
+ 71: 21DCC9A32031428B7B02F68E1450A0F3
+ 72: 95C1B0832575E21982B17CCCCAF54556
+ 73: 24939E25985A3B5620B19D7889E5E153
+ 74: 3029C8B005386705FE7E4CBAA060E987
+ 75: E8BD97C5C1A0CC9AD1F1BEB3913B22FF
+ 76: 808EBCA0B0E6FD1B30E4BA499C05EF9B
+ 77: 55BD20AB87DE2E536DDE22286D0922D9
+ 78: 2B2E45FA5628F29DA06462378D17DD12
+ 79: B90F1709241EF59F78666AEBB3D5607C
+ 80: 37854275343F079BCE1639C84D74AE1C
+ 81: 444AB5A4F39B765C5D67BB433D4CF0B1
+ 82: 7E30CFA6363F9AC96607783710E151B9
+ 83: 9D9252DFFB2D5023CFE34873EA6C43AE
+ 84: 49A70634AFCED27DC2DF2EB079F7A1E6
+ 85: 4C976C9EF13716CCB468D82BD8C56FE2
+ 86: 4EB382D16DDC18C31E6DBAC6CA83247D
+ 87: B16112D0FF3C6A8ADB19C13DF742F5D1
+ 88: F703DC6100AE23D194E01EAC433CF28B
+ 89: A6527B1B907218063BF196AA91C73F47
+ 90: 61F1A1E947F3F542FCF85AC758BA5D14
+ 91: 12ADDEDCE418E9444AE34A40353ED0EB
+ 92: D1C35142C475D44A52CEB0A8FAEA7AAB
+ 93: 1F89912C1FC59AAB53C983B035661269
+ 94: 2E7E19A4A6635AB5958DDA70B415EB06
+ 95: B700B6739C0AF162D246AF07284A1AE8
+ 96: E2B95AC9F876A38D33CCBBD7FA92D67E
+ 97: AEB4849953750A10BB236BAC8D5AB487
+ 98: 82D738AF18FD4B26FFF61377EE921E62
+ 99: 0E1451640E59CE0461A46934F174E237
+100: AE06EA64074E8C07116563E8E0893BDC
+101: 562DCEB678FBFAB24141E591FFD471B1
+102: 7DD6C3C2884E483E8CA572C471B2D812
+103: 2A4C8E4EC2672C1D54A8DA8F32F04783
+104: 2BFED22E8810A4658060B95B0ADB60BC
+105: 214D8F2DD099BAB68EC17189BFF8A8EF
+106: 98E4EB29797C8E631CD4317AF422FB05
+107: 241A0F826F359A21CA0E6D9154D1E291
+108: A3398C0118A3605E7A7794B8DF7CA152
+109: 5B0A6FC8721F14EB8A03E9A5D87F173B
+110: D93ABEC3EBD5672350C3C36F8FB00E53
+111: 659905751D1F614A78ECBB56D4398D06
+112: 594691B38126E028352DA5B28ADFD416
+113: 7533FBD1FD58C85D54A712EF218A9D53
+114: 654796E7D2F9F2C2D166F23B5AB18812
+115: 5D25B604FB75727AE7EBFF980F54D96A
+116: 426A7709CD61EB6ECF4034EC83E073EC
+117: 62E21CA2F8E39C03BFF56C8265ACB60A
+118: B7C9DAAA89A29F2805DEDE790DCB9575
+119: 9C1067170940CE8F8E4745D362675FAB
+120: C5BB35660E3D0A286A96EA3AA4922B3C
+121: 8F3B6351623A0E482B57525474DC703A
+122: CCC34CC280340681CA5117477DD86AE8
+123: 2F5FB6B41301F87A0490035DE4C1BB99
+124: A16E28DB3F331091E928F9AE3F1ACEB6
+125: 7D2259C98085B9BF7F5E36B29DF8384A
+126: BDDA1266FF3E8FFBA1DE1B2759B58BCC
+127: 2067886DA4BDE10A94B971CD740B0AAB
+128: E1275970EB67D2D996E6E658270AA149
+
+Hash: md5
+  0: D41D8CD98F00B204E9800998ECF8427E
+  1: 93B885ADFE0DA089CDF634904FD59F71
+  2: 441077CC9E57554DD476BDFB8B8B8102
+  3: B95F67F61EBB03619622D798F45FC2D3
+  4: 37B59AFD592725F9305E484A5D7F5168
+  5: D05374DC381D9B52806446A71C8E79B1
+  6: D15AE53931880FD7B724DD7888B4B4ED
+  7: 9AA461E1ECA4086F9230AA49C90B0C61
+  8: 3677509751CCF61539174D2B9635A7BF
+  9: A6E7D3B46FDFAF0BDE2A1F832A00D2DE
+ 10: C56BD5480F6E5413CB62A0AD9666613A
+ 11: 5B86FA8AD8F4357EA417214182177BE8
+ 12: 50A73D7013E9803E3B20888F8FCAFB15
+ 13: B20D4797E23EEA3EA5778970D2E226F3
+ 14: AA541E601B7B9DDD0504D19866350D4E
+ 15: 58B7CE493AC99C66058538DACB1E3C94
+ 16: 1AC1EF01E96CAF1BE0D329331A4FC2A8
+ 17: 1BDD36B0A024C90DB383512607293692
+ 18: 633AB81AEA5942052B794524E1A28477
+ 19: 2D325313EB5DF436C078435FA0F5EFF1
+ 20: 1549D1AAE20214E065AB4B76AAAC89A8
+ 21: 7E437C81824D3982E70C88B5DA8EA94B
+ 22: 2F5F7E7216832AE19C353023618A35A8
+ 23: 6535E52506C27EAA1033891FF4F3A74E
+ 24: 8BD9C8EFBBAC58748951CA5A45CFD386
+ 25: D983C63BF41853056787FE1BB764DBFF
+ 26: B4F24C1219FB00D081C4020C56263451
+ 27: B0AE6708C5E1BE10668F57D3916CF423
+ 28: BA7BB5AD4DBA5BDE028703007969CB25
+ 29: EA880E16EAC1B1488AFF8A25D11D6271
+ 30: C7172F0903C4919EB232F18AB7A30C42
+ 31: E9E77893BA926E732F483282F416FFAC
+ 32: B4FFCB23737CEC315A4A4D1AA2A620CE
+ 33: 5506A276A0A9ACC3093F9169C73CF8C5
+ 34: E5A849897D9CC0B25B286C1F0BFB50E3
+ 35: F54FA30EA7B26D3E11C54D3C8451BCF0
+ 36: 07602FE0229E486957081A49E3F06F83
+ 37: 7C4BBA98253CA834BF9ED43FD8B2F959
+ 38: CF8DF427548BBFDB1E11143FDF008B85
+ 39: 1431A6895A8F435755395F9BA83E76BF
+ 40: 30DD5E4CAE35BA892CC66D7736723980
+ 41: 8EE247A1063931BEDAF4C2FA3E4E261A
+ 42: C32CEEE2D2245DF8589F94FCDA0C9F2C
+ 43: F25FA0E071D1F1CDC6632C6B673BCCD5
+ 44: 370491B643E97577F4F74BD88576D1EC
+ 45: B292BF16E3AAFAF41F19C921068214F8
+ 46: 52921AAE5CCC9B6E8E45853419D0C80F
+ 47: F1375BE31969155EF76F04741CD861D7
+ 48: 04605CA542B2D82B9886A4B4B9ACFB1C
+ 49: FA887BA0FA491FAAACBB82BC5FEFCD5B
+ 50: 06470E932AD7C7CEDF548B5CCB9D4806
+ 51: AD130B245E2DD894267CB0DDC532D169
+ 52: A9EEB95053682248608E97D79E89CA82
+ 53: CC26A3DC608268B98ECD1F3946C4B718
+ 54: 33DD62A2DF6538DAF1CF821D9CDE61F9
+ 55: 6912EE65FFF2D9F9CE2508CDDF8BCDA0
+ 56: 51FDD1ACDA72405DFDFA03FCB85896D7
+ 57: 5320EF4C17EF34A0CF2DB763338D25EB
+ 58: 9F4F41B5CDE885F94CFC0E06E78F929D
+ 59: E39965BC00ECACD90FD875F77EFF499A
+ 60: 63ED72093AE09E2C8553EE069E63D702
+ 61: 0D08FC14AC5BAA37792377355DBAD0AE
+ 62: F3CDFFE2E160A061754A06DAFCFD688B
+ 63: 48A6295221902E8E0938F773A7185E72
+ 64: B2D3F56BC197FD985D5965079B5E7148
+ 65: 8BD7053801C768420FAF816FADBA971C
+ 66: E58B3261A467F02BA51B215C013DF4C3
+ 67: 73062234B55754C3383480D5EF70DCE5
+ 68: F752EBD79A813EF27C35BED69E2EE69F
+ 69: 10907846EB89EF5DC5D4935A09DAD0E7
+ 70: 5F1F5F64B84400FB9AD6D8ECD9C142A0
+ 71: 3157D7BB98A202B50CF0C437AA216C39
+ 72: 70E7ADE70281B0AFCB1D4ED13EFC2E25
+ 73: 0BB96A503B1626C9AB16C1291C663E75
+ 74: 5BED4126B3C973F685FCF92A738D4DAB
+ 75: 7523C240F2A44E86DD22504CA49F098D
+ 76: 6710949ED8AE17C44FB77496BEDCB2AB
+ 77: 4A4C43373B9E40035E6E40CBA227CE0B
+ 78: 91977CBCC32CDEAEC7A0FA24BB948D6A
+ 79: A6A0F1373CF3DBEE116DF2738D6F544D
+ 80: 761F6D007F6E5C64C8D161A5CED4E0AA
+ 81: D44EA4D5A7074B88883A82F2B4CFBE67
+ 82: 3097EDA5666E2B2723E8949FCFF2F244
+ 83: AB247A3D9BC600F594D5A6C50B80583F
+ 84: B229430E3DB2DFDD13AA1DA1BAC14D5C
+ 85: BEFEF62987C6DCDF24FEBD0BB7CD3678
+ 86: BFC3E5C7C461500FF085A66548378E0E
+ 87: A5712194537C75F0DD5A5AB3E9EBAF03
+ 88: 8DAAC097E9044B85B75999D6C3BCCD24
+ 89: B8124DF21129685597C53A3F606FFD28
+ 90: 8FBC4D795C22D958248582A8DF7332ED
+ 91: 36D217135DB136B2BDF1617D7E9C79CE
+ 92: 1B3E6271A3A4B663C509A1255027CA99
+ 93: A25F596574031FF9C34314C1B1F6BF34
+ 94: ACA7017E5BB62BFDD5BBFDED78C8987A
+ 95: 8129E53A694ADD0560B1534B32FE5912
+ 96: DA0E48224106C7535A4CD8DB2AC7B8E3
+ 97: CBD4ACE3D766D8E44F63E0DE8F110F04
+ 98: BDC17A0EF2777512CB402C90E9D13E31
+ 99: 47695AD6AF968D6F1CDD2D8C5C87A466
+100: 7ACEDD1A84A4CFCB6E7A16003242945E
+101: 225489D3D073AC705F7B3AD358EABAB2
+102: 301DA87A7B2EC27514C3A2789D5DBE49
+103: 16222C503718F1420958133C330FE3F8
+104: D778CE7F642AA23355948477DA4CC11C
+105: E873C37F8977E200A594B815E1A87EF3
+106: E8F8F41528D4F855D8FDF4055BBABE2F
+107: CACF3D3D1E7D21C97D265F64D9864B75
+108: 6BF48F161EFF9F7005BD6667F30A5C27
+109: 42E7BB8E780B3B26616ECBCACE81FA1A
+110: 225AFD8EC21F86F66211ADF54AFC2E86
+111: 4FAD3AB7D8546851EC1BB63EA7E6F5A8
+112: D1FEC2AC3715E791CA5F489F300381B3
+113: F62807C995735B44699BB8179100CE87
+114: 54050B090344E3284F390806FF716371
+115: 50482241280543B88F7AF3FC13D65C65
+116: 4C36F27D4786FE2FB8CAAC690B6D62F7
+117: 5A0EDF0B97977EE5AFB3D185B64FB610
+118: 4541055C6675B614D27C537C3BB15675
+119: 1C772251899A7FF007400B888D6B2042
+120: B7BA1EFC6022E9ED272F00B8831E26E6
+121: B0B2D719A838DB877B6D6571A39A1CDC
+122: 800AA956EC16F603ECDBA66C2DC6E4CF
+123: 8827D2778287C58A242ACD4C549BEB31
+124: CFBC5AA0B61103C1A982D8927B26F575
+125: A1F5B691F74F566A2BE1765731084F8A
+126: 80749BE03F5724FA4CA0AEF8909379B7
+127: 8402B21E7BC7906493BAE0DAC017F1F9
+128: 37EFF01866BA3F538421B30B7CBEFCAC
+
+Hash: sha1
+  0: DA39A3EE5E6B4B0D3255BFEF95601890AFD80709
+  1: 5BA93C9DB0CFF93F52B521D7420E43F6EDA2784F
+  2: 3F29546453678B855931C174A97D6C0894B8F546
+  3: 0C7A623FD2BBC05B06423BE359E4021D36E721AD
+  4: A02A05B025B928C039CF1AE7E8EE04E7C190C0DB
+  5: 1CF251472D59F8FADEB3AB258E90999D8491BE19
+  6: 868460D98D09D8BBB93D7B6CDD15CC7FBEC676B9
+  7: 6DC86F11B8CDBE879BF8BA3832499C2F93C729BA
+  8: 67423EBFA8454F19AC6F4686D6C0DC731A3DDD6B
+  9: 63BF60C7105A07A2B125BBF89E61ABDABC6978C2
+ 10: 494179714A6CD627239DFEDEDF2DE9EF994CAF03
+ 11: 2C7E7C384F7829694282B1E3A6216DEF8082D055
+ 12: CFF9611CB9AA422A16D9BEEE3A75319CE5395912
+ 13: E51F9799C4A21BBA255CF473BAF95A89E1B86180
+ 14: F741644BA6E1BCF5FEE6D3C1B6177B78468ECE99
+ 15: FB1D9241F67827CE6DD7AC55F1E3C4E4F50CAA03
+ 16: 56178B86A57FAC22899A9964185C2CC96E7DA589
+ 17: 0A0315EC7B1E22A79FC862EDF79BDA2FC01669E3
+ 18: 32AF8A619C2566222BB0BA0689DABCC480C381D5
+ 19: D35B5AFBC48A696897C084E6E71AAE67C7CD9417
+ 20: 602C63D2F3D13CA3206CDF204CDE24E7D8F4266C
+ 21: A3C6FBE5C13E8B41FADC204C0CF26F3F214189F4
+ 22: 25E480E9E0CA2B610105CD1424B8A35F63FB3981
+ 23: 45412D51D3CA7BCF452D1612720EE88F9D2427C3
+ 24: ED6A95036E3E046931597A457DB7A78B7309C4C0
+ 25: B4FE0256D346700783420E08A4A6F7992B1E36C9
+ 26: 33E1799E98280E5A9ACE5509477A2048607C5537
+ 27: CF193837F6DE43F8E38000ACFCF764FA8D8FDE22
+ 28: 7C8DE247DDA83599AF2EC2EE2D29E20583DAC34B
+ 29: F38A076F70613FC251C4D21E6435AD08341A8A99
+ 30: DCD68E6174BD74BA180DA047A7345E8D111F85FD
+ 31: 43BBACB5F62A0482CBDB564171B04365CA6E27C0
+ 32: AE5BD8EFEA5322C4D9986D06680A781392F9A642
+ 33: EB90BCE364635C4C23B49F493F0043579BC85C17
+ 34: 2942C7AFA65444C43D0592D0DC73CA71DB729205
+ 35: ABF726F5FDA729FB7F3F0484D7C94B3107AA02AE
+ 36: 75DB4F6BCC05A781DDA9D17C46717286DD53654B
+ 37: A82CB42D89DAF5FBC1D4A48476229C495782F98D
+ 38: FC1A69683744AF823CD69E8A1E3F460591714028
+ 39: DC68DB44B48521B0700A864896A00E17777AEA83
+ 40: CC9AD99E917042381B0F99588896CBF236AA8ED3
+ 41: EC7A68484A749C7065C6B746F9C465DCB414F370
+ 42: C627C449DEFF14AE7ED807293D30846F061DA5B8
+ 43: 4782F2A19B6DBB0882D656DE86C3D21A7317F768
+ 44: 02D4EED99E7307BEA39AF5330BF7FB388D48B496
+ 45: B3D99B9D90A69E50FD4365704F5AB2EAB7BC9763
+ 46: 9B1C07176BB227F73E8A4E173071D39302061DE2
+ 47: D79097DDAC552A6E02A52CE7AAF494D2D73B2557
+ 48: DF7F23B160E75B9BAE5EA1E62B43A5A34A260127
+ 49: F598F3780D8C374D97957B9B62D56106E9E0B2D2
+ 50: 0BD98598F9AB29C1359EF5460A206DD1370515E3
+ 51: E6C320834F69D81689E1ECD5ABC808D49D9C4E07
+ 52: FD5EE7588CD129E12B886974621FD29FACC78E19
+ 53: 2A9C28EF61EB536D3BBDA64AD95A132554BE3D6B
+ 54: CFAE6D86A767B9C700B5081A54265FB2FE0F6FD9
+ 55: 8AE2D46729CFE68FF927AF5EEC9C7D1B66D65AC2
+ 56: 636E2EC698DAC903498E648BD2F3AF641D3C88CB
+ 57: 7CB1330F35244B57437539253304EA78A6B7C443
+ 58: 2E780486F64BC91FBFA2785EC1CA5C9E3CC07939
+ 59: 4A7713D44E97D9F09AE1D786199C58AE2BFAF3EB
+ 60: C98714B16F92C8A770E9FC229DF834D1688E282F
+ 61: AACE3DD6F54A2A255ABA920F5FFC8CF04B85A69A
+ 62: CF8563896A3B0A0775985D8289444C4BBC478DA7
+ 63: 6D942DA0C4392B123528F2905C713A3CE28364BD
+ 64: C6138D514FFA2135BFCE0ED0B8FAC65669917EC7
+ 65: 69BD728AD6E13CD76FF19751FDE427B00E395746
+ 66: CE705B7C60D46E7E36FE073DB8822698579CA410
+ 67: C717EBBF6A2BF1BB33DA6257352D5085BEE218B3
+ 68: 86151D140AAFC9A4B5877D3FBB49014FE5906E57
+ 69: 7446B5A6BBCC58BC9662451A0A747D7D031F9A7D
+ 70: C24887924F92ADAC5AE367995D12691C662B7362
+ 71: 5AF83CFD42D61967778889CA911CFB6C14339BA7
+ 72: 587D4F6E6B4E21343423E434679009CBD3D24DCF
+ 73: AC65DD946C5CC432D4D624CAEB53C7363F96B7AF
+ 74: FA71E70750674C0F6B4AA19D0BE717B2936C83FD
+ 75: C9EFE6DD0A019315F73F3962DE38B6C848A1705B
+ 76: D1D05649B952C8F6EB016BE08FE1544AAC5D5925
+ 77: CC3081AC1D695BAE51CFD5B44B9FB3A230733CC3
+ 78: EB9DE332558953792687D9A7F598B5D84BF0A46B
+ 79: 39DE5EFDC92E3D3678F24D2CF545BA4D172D003D
+ 80: 399DBC9F721E44A992A0DEF42D999B32AF449ADC
+ 81: 996A2817C8ACBC667E1C4C27B8F4E9952736DD7A
+ 82: 3EF8189CE1BCC0D65AA182B1A81534635EDFDF2B
+ 83: D676714C6A6FF4E17A60C0511C25AA8B164FA606
+ 84: 4DB6E3381E1B9290267C1539E1053793C8B81FA1
+ 85: 3A34D35B0296FE4D83EDA39B742A9D8F4B13A958
+ 86: 54F3B45304EF1287F54B877FCCE3285E154F9D6C
+ 87: B1EA96216E025377AB5AA845238FC8BC65DD60E1
+ 88: BC6C7488145485DEDE1AE1D43B594F0046BCDA0F
+ 89: 3D9A0619ECF88C84CE86213E9AA91D9A252CBC32
+ 90: 92CCAA0B4CE89E2BD80A61B9BAFD5AC58AB7B588
+ 91: 3EB326B5BF4440FB3A88E3DCB05C1DB5EA01AC5C
+ 92: 989C63E819B13D4CADFB33F8DEAFBC57C1992A12
+ 93: AE944552C20CF16F07A5C357713832C9D72D0C6B
+ 94: 46723E982569A1E2D9EDCED5498FC1F46F7D63FC
+ 95: 3BC5DAE7907C83A0693F87FD8372EFDD1DF53E09
+ 96: 96D281BA44EB21ECFB1663C8AC5752C48686A927
+ 97: FA0EF18178880A72B51C26555C10F5210DAB4390
+ 98: 0C7ECAC32B8ED6D9835D381BF069568722A276E1
+ 99: 649E44ECBA85C0938EC09229CEE4BB69388EC642
+100: 1E6634BFAEBC0348298105923D0F26E47AA33FF5
+101: AF2AF2734BB2BAA288940CB62109F4849DAA347F
+102: 22D14BC045CC9A3794C99BEEE7ABE278BF24D6D8
+103: C3164CCBED75B82ED3F59F4A47FE09B256025549
+104: C27B5BC7CD24DE4913614A769A442E9CC9FB0E08
+105: F44D48D98CAC77522FF6B9E1B9CBB8489E58E588
+106: EA19A71FFBEC9572F6CD65523ACAF865EC05AB52
+107: CDA0EB9D310247BD1E8B3EA10D9B9DEFF6FBABA9
+108: 449DFCE971B9D65D69FBC72940E9A885E8DDE9CE
+109: 96EEBB6B95A9DA99C58190CBD77CD6FBCF638A79
+110: 670F7A869E90CE86E0A18232A9D4B1F97C1C77D0
+111: BC544E24573D592290FDAFF8ECF3F7F2B00CD483
+112: E4CE142D09A84A8645338DD6535CBFAAF800D320
+113: 1C26461E26EB697CCC36A98714EE70CAAA87A84E
+114: 51C5B1C25A71FF00394A84AB48B5733C8955551E
+115: 84803504181C0AE33A511C49AF5015A5B1892BFD
+116: 7CC8BCA120C2635ABFEA82DD203112B5C7E165DA
+117: 44E2519A529D7261F1BEBEDC8ED95E1182CAE0DC
+118: 2A81372DA39C1DF4251539A9922717B7CF5F0334
+119: 41C89D06001BAB4AB78736B44EFE7CE18CE6AE08
+120: D3DBD653BD8597B7475321B60A36891278E6A04A
+121: 3723F8AB857804F89F80970E9FC88CF8F890ADC2
+122: D031C9FB7AF0A461241E539E10DB62ED28F7033B
+123: E0B550438E794B65D89B9EE5C8F836AE737DECF0
+124: FB3998281C31D1A8EEA2EA737AFFD0B4D6AB6AC2
+125: 7A914D8B86A534581AA71EC61912BA3F5B478698
+126: A271F71547442DEA7B2EDF65CD5FBD5C751710AA
+127: 89D7312A903F65CD2B3E34A975E55DBEA9033353
+128: E6434BC401F98603D7EDA504790C98C67385D535
+
+Hash: sha224
+  0: D14A028C2A3A2BC9476102BB288234C415A2B01F828EA62AC5B3E42F
+  1: FFF9292B4201617BDC4D3053FCE02734166A683D7D858A7F5F59B073
+  2: 00AC60F30E9BD1956F914C8E5125B69DCC31A179734E6A85B3F702BA
+  3: E615202185AABE2ACA924BEC29E5A12384F8339EAE4E64C9CBA9F1DA
+  4: D70DA0705EAE42A5C596D92F331DDA2421B4E14F8B3035FB73B8B700
+  5: 98029CB458A39A16355963922D32DACD9439F90E9FD106D42A0D123C
+  6: 7D92E7F1CAD1818ED1D13AB41F04EBABFE1FEF6BB4CBEEBAC34C29BC
+  7: DDD5BABB1B05D8BCCD644ADC393A9E2303C850DA31922C4DA07574F9
+  8: 4C07070802E21052FB0295AC0571CAEDF219143ADAE0627E2850EDAA
+  9: 5D3CA3BFE738D33F841069ADF6DD79B987351CE580ACA23326B3A7E7
+ 10: 6B5373C535A4FA5D56D6C4953575CE64968031BB019B909F8F2DB904
+ 11: 767D0CDC11079BA8DCA276DF5C4B85507DE67DCE47EDA4CD9196D312
+ 12: 02C513977B6242D2FAAC094CAE3C247C6E2745F8A71494A60535A2EA
+ 13: 1F39482310E2209C10A88C7FD7FC1FD567F36789808C37D30045A82B
+ 14: 55BA81EBA644183AB2460C234BB95ABDA898E980BA976584E2977231
+ 15: 2522E2B35A835436C80A122E4676DE64690C81440D42DBDA40EF2151
+ 16: 529D656A8BC413FEF58DA82E1BF0308DCFE0429DCD80687E69C94633
+ 17: A153F81C68D9FFFD4DE0AB9111C2FA86E8EDCA9B294376083077A135
+ 18: 1EC706AEB2227B263A105EDBE2562E0521C96420DA4558012327661B
+ 19: 4904ADADF19D088911EE0EFD20A9AB511F2786C8FD43F1E5E8BE2AC6
+ 20: 6CE245C296289A32F661986FF1C80E893BBD35EB0B182EDC14AB3A7D
+ 21: 33831C459A43CBF8BEB6DD50039750F1EA3688A7EAEF68CB2F095E16
+ 22: EB4BC2EA1F7146E8274A96E874585C401256FB921FFC7E935DDC7FFF
+ 23: 09A266C98019B6B2A4318FBEDBEA5481AF01F0AD2AD16F09991A3C3A
+ 24: 7AF2814CD6105473EE530F2B3DAE992ABB6C801428F33430501F09A6
+ 25: C5BD6127243049C4D5E9E3B391E12BDA86DC7A9856910A757004486F
+ 26: FCA06DDE2DCD212E6C1C11BB22B18B4F5582202655DFB9B6C9960C57
+ 27: 0851998120F8CE47482DA5B2EB21BADF73C9F145921EEFD33459D49F
+ 28: ED36A2092538C5D4769917953E7355A13072DDAD8A6E5E2AF1DE96F6
+ 29: 2C4A89C05BFD09B7068BAFDA37B0314EFCE02AFAE1B2C25DCE337326
+ 30: 1D552A4D06BB8A0827BFE8DA2B6EE56ADBD17CE4810908D572076F6E
+ 31: 997D180912E0655445B07259278AAAD424633F5FF6BD0AFECD4F15DA
+ 32: 71446EA93381BA091F94AFCDC5B938323290A1A027C22A75E88A04D0
+ 33: F77087D6F4AE34E88C62597CEC06220F4C694D2E0EB704820035AE6A
+ 34: 64EE78B0A6C116380A4C16F24489C1E94A578E558453537A9819A2E6
+ 35: F39C1C862FDC9AB4ACFA50FE283CB7595C608F8C521BB7898CF71D34
+ 36: DB482A26C9488A963359D145914612E34B821CC6CDC11113B73BDE2F
+ 37: C7C45F3AA5EEDE664D6CCD510F628D4DC3C67F93973FE05B0163CA13
+ 38: 7F230E3E597845DB9F8D61B44740968FF55F2DF28CA538A68927F130
+ 39: EA52362A9C66B6A5FF3B642FCFEBBF54F793B088D29E6840D7A5CF56
+ 40: 84B064EF9C13F1ED54AD0B8FC0CC28F9BCE5009500E1CD92CA2BAE04
+ 41: A2702281BD63CA745553CB18693DD70AC9A70CD73C01783727707C97
+ 42: 89231FCFFC7022DF20B1846285FAACE44AFCC677685DA55EE02D94EA
+ 43: 4C5B01C50907D097DDBF0923B885A26B58DFF5761C1AEDFB8D5353F5
+ 44: 84E0CF33A7E1C0EAA46F37E99CE5C8B292E81AD61318796D1A9A90C3
+ 45: 27E59A0B6E7B9125D4CAA658810AE5054CE40A9A0A0FFE6E36435EBC
+ 46: C7F21E2B4C89B2A6E64D92F93FC4146EB5886503C1231EE6924B4E13
+ 47: 653CAFF50E077A855992990F0C5F89C75FA18D1CC147F685AF2EA993
+ 48: 6A7BDEA7E456D5339B7D9C244E246AD65B18BA95E0518E201AAA7889
+ 49: 837ADE7F298F8159E6E2408751B0C480648CB6FD6D26C551983F3176
+ 50: BEEF3F6AC40A9DED345BE41242BB2CF924B457A45CACC68379B1DC4A
+ 51: 6D2908EB3B6C8952346E0B65B9406D949B5A340123DB83B151DF5F81
+ 52: 9E75A1D6B4A4D1A9F5AA6F8A48AFD6F3FD360D2D8723B53DBB63208E
+ 53: 436E3BFE94A39359CDF47D35395D34C0435018C88B4E96E68C22645A
+ 54: C209DF2E99E03D679FBA9E14AAF958AC1B0A22076BB3B532A0D7F092
+ 55: 8991DFBA74284E04DC7581C7C3E4068FF6CB7A63733361429834BB56
+ 56: 2B2CD637C16AD7290BB067AD7D8FD04E204FA43A84366AFC7130F4EF
+ 57: E87F5BC938C3B981C197D4B163C635A5049FAC81C4C6467E1251BE48
+ 58: FD9BDAF5CC288A603D1623651D5BA3B8801D1602B0B9221C0B48435D
+ 59: 87F207D9D870EDD7DA61753473A51FC386E2792A3861F949BEA05CFE
+ 60: C9EFF79F4412CE49296C082DC777118F92C9AC4136D4EB32621E942C
+ 61: DDBC76D25D9819693F3597D6F09044F8D6CCBD12F081156F1090AF7D
+ 62: 6411AD13AA3654302BAC8E2BFD1CE76F37E3B3394014BBE260062CFC
+ 63: 049E8DD7EAB3378CE9F823BFB569E5B270235D4B7F9623606971998F
+ 64: C37B88A3522DBF7AC30D1C68EA397AC11D4773571AED01DDAB73531E
+ 65: 114B5FD665736A96585C5D5837D35250AED73C725252CBF7F8B121F6
+ 66: 7D9B844CAAC9EC93AE2159ED3D336C55396216DAC6AC5DC5DECC11C9
+ 67: E1C799109DEEA117F68DD1826B38B514E1D265F11A8B60B24630FF8E
+ 68: 029A0D024B6C0B63E1586F3D34111727E37D49CA12E7F520FA91A926
+ 69: 2EA94F04A72C770A98E2A495D886EE674B7D0FB987B7B5C2217A8773
+ 70: FAF445688FFCA34ED783F948B8F74578503D4845836CAF69DBD5EB51
+ 71: 91EC59AC7C98F9DFB869E11C80027F8A4D311324597E6FC6135224D3
+ 72: 190DFC9C7BDD954E415E543F99B00B5110ED6A12182BFFDCAA77D8B9
+ 73: 8C3AA805FA75625476F3267C211B1DDA52E1810B058EF804E34BEE58
+ 74: BFD0E517E4A340A4E0EF1AC306EE2C6DD1288C77531EF0FD5ACB73FA
+ 75: C621A18D7E09976296CBC39761B020E7E346042FC735FDF106148F3F
+ 76: 27EE5F7E3FE49EAEC0AE0A93FD971EDF0304A4C0513BCF43424C95A2
+ 77: BD9D42F293DA572219F08D4A38081D203E44F612EEDEF93CE0DAF6D4
+ 78: 374CFB6FB12768717EFED2681718C11B22588C429DB9C71AFB5EB562
+ 79: 1CFB1037FC3943559E9F913183DB71392CD4BC68CDFD47D7DEC9C9AD
+ 80: 2537E015D5945E0541BC48320AE4DFF7FEAB911227AE0D579DA1CD05
+ 81: 012B34E1A530B6889E87863A59645EE4FFEB292A33815D2CE11918EA
+ 82: 5242DD4DFEE389E668D8FF78DA9B2D85AAE12D0C220E8D1BADBBA845
+ 83: 4813D70E1D6BB6232CD9257B5132FDBA05E1A4A858E237C303CFA052
+ 84: 0530BBA43AE6393655F21F7EEA67F8E8E819BA225AED78CA8BDE075F
+ 85: 4F7EAF4A9D0000B0E957DFE46DB304EBB2664A32AF4142EC74BE18D8
+ 86: 68CF23B9DC4DC3430835B484648CBF126940AF6BAE51431A66D7F0E6
+ 87: A093D2119C7076259F194F107077061C61C792DC5326C3A4D3A63BA6
+ 88: F4E883F7FD12ACD36E3891986E4D7FF03F3E150F09CD4FB58A023A04
+ 89: 0816862C59CE35E0D78834A221D3BABE21987FDAA81F20ED61D9DA84
+ 90: F415933677BB364C589722E30B958F2BEF8670A10F1F5082F79FDB4F
+ 91: E40C5632490BB8DAD2283B6DBDCA870F4B5AB4271C61127DE999BDF0
+ 92: B2D4E6CD7AFC35A475620EA1446B9024D767890B8593AB50275F370D
+ 93: 948616FD7828F09E8A57F986589948085D18EC3550E0ADA8E0127665
+ 94: 2B115E930333A355A82F074EF261DE6BB2942D9DD64F98BA12D92DDE
+ 95: 6EEAB864B5AD618CDB1AE79C7B1DE31020966A02350AEF71088E6876
+ 96: 676AD81F213E037F3C9BA2310F49DDDA4D6476C28A8EFC0046D3F55C
+ 97: 03A28C9068BC10A6FD87A1E53F00415F8CE994C968DD9CFF60D6B0A2
+ 98: 01D91D084F400C591EDD750B66EC2482C834CE0E140A37E6E142CFEC
+ 99: BCAD899E7C771764CB91FF60AD79BFD629F4803A05FCBCC24E8F3E79
+100: 6E08215B5470DDEB67E44A494E52E259A9C2C4FBED4AF5DC6DB3E92A
+101: E5C45BED6F8BFC487FF7190B108AF5C5B66F6D55D365B5A1BA156914
+102: 0DB55D83B38D42D229CA42D001B09758B5F3F032109F2F999C553655
+103: AD4DF1AF973A2747568A1B8DEF15E34A350A93F45BA84596580D11F0
+104: D4905849C8C4EA32159A431B52BAAC092F90037093E200A0C46611F9
+105: A936D0AA091B827BAD86644C94603068AB34A5B59E29D1E3BAB13039
+106: 46D214E9FA8C877C2791CC8E6716868713CB5B677CC4D838242C9B18
+107: AE8D3EB227AA3558101D5E5A2BF6C862C9F7297A31A3DF24E4502257
+108: 4462C366B10326D4FEF46E71930BCF93713F7D45FAC9963520FF5FE8
+109: 05EFC35781E413ECBCC763AE13D5A37C159CE5CCEE6EAA1CFF7CA516
+110: CDDBA09D7FE081E7A39C4017B3EDF7A9138D1CB857559BA9AD2C939E
+111: 1AEEF583C448A9AE00FBC931B50BC0DA5BB8323E616B11076CEE8B44
+112: 01E5ABF50619B5C2078E754EDDEDCF4DE8D31185A2219313CB91A8C9
+113: B7FF114CA77757CAD67801E6761AF20F4CBB8328AEF290F77EB612C3
+114: 08F43DF4547732424AC7D0390AD8AB3D4978826462446D13B2B468D6
+115: AC3799ED09E3BD9E770FD3A0073E371FE9A3D4E3D464C3A7023CC72D
+116: 795F160C275FF6B575031D4053BA1D1C32744D09F005B3BF10BDD1F7
+117: D2EFD4AC8ABA33151D0399E2893769A6D8BBFBA7B128388BFA65B841
+118: F85910F64FEE2B8F91DEC8064F75CB97E1FFC895AEE912DD3945F839
+119: 762F18C0DF65C3D0EA64126C8A6E51DB4425E76D4D969ED0F83899BE
+120: D022DEB78772A77E8B91D68F90CA1F636E8FE047AE219434CED18EEF
+121: A802D8B618A503352CDBCC1FBEF04EA36499EA72D0E32D314CAF83E5
+122: 6DE1088DD95C9535849294A8635A44084BA36E4EEF81C6D67B98CE90
+123: 6AA11591302A30EFACF874F40AA017F8545D3D9EA68D479965AC0B3E
+124: 3288A475A4817D2E42830C709C1DC18A4BBD59DBD903B43CA702F275
+125: CCEEE7F6EFA60B2F2CE1090FB929D6068F7EE301E7A84072FD163F7E
+126: A45B0FCFAC3F05279B7E8278AED93E37B225E6A997664F92C7555447
+127: 554C9C3F7E92B80F4121E00CC147535D377EAEB4FB1FA8E25C7F81C1
+128: 67D88DA33FD632D8742424791DFACE672FF59D597FE38B3F2A998386
+
+Hash: sha256
+  0: E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
+  1: 6E340B9CFFB37A989CA544E6BB780A2C78901D3FB33738768511A30617AFA01D
+  2: B413F47D13EE2FE6C845B2EE141AF81DE858DF4EC549A58B7970BB96645BC8D2
+  3: AE4B3280E56E2FAF83F414A6E3DABE9D5FBE18976544C05FED121ACCB85B53FC
+  4: 054EDEC1D0211F624FED0CBCA9D4F9400B0E491C43742AF2C5B0ABEBF0C990D8
+  5: 08BB5E5D6EAAC1049EDE0893D30ED022B1A4D9B5B48DB414871F51C9CB35283D
+  6: 17E88DB187AFD62C16E5DEBF3E6527CD006BC012BC90B51A810CD80C2D511F43
+  7: 57355AC3303C148F11AEF7CB179456B9232CDE33A818DFDA2C2FCB9325749A6B
+  8: 8A851FF82EE7048AD09EC3847F1DDF44944104D2CBD17EF4E3DB22C6785A0D45
+  9: F8348E0B1DF00833CBBBD08F07ABDECC10C0EFB78829D7828C62A7F36D0CC549
+ 10: 1F825AA2F0020EF7CF91DFA30DA4668D791C5D4824FC8E41354B89EC05795AB3
+ 11: 78A6273103D17C39A0B6126E226CEC70E33337F4BC6A38067401B54A33E78EAD
+ 12: FFF3A9BCDD37363D703C1C4F9512533686157868F0D4F16A0F02D0F1DA24F9A2
+ 13: 86EBA947D50C2C01570FE1BB5CA552958DABBDBB59B0657F0F26E21FF011E5C7
+ 14: AB107F1BD632D3C3F5C724A99D024F7FAA033F33C07696384B604BFE78AC352D
+ 15: 7071FC3188FDE7E7E500D4768F1784BEDE1A22E991648DCAB9DC3219ACFF1D4C
+ 16: BE45CB2605BF36BEBDE684841A28F0FD43C69850A3DCE5FEDBA69928EE3A8991
+ 17: 3E5718FEA51A8F3F5BACA61C77AFAB473C1810F8B9DB330273B4011CE92C787E
+ 18: 7A096CC12702BCFA647EE070D4F3BA4C2D1D715B484B55B825D0EDBA6545803B
+ 19: 5F9A753613D87B8A17302373C4AEE56FAA310D3B24B6AE1862D673AA22E1790F
+ 20: E7AEBF577F60412F0312D442C70A1FA6148C090BF5BAB404CAEC29482AE779E8
+ 21: 75AEE9DCC9FBE7DDC9394F5BC5D38D9F5AD361F0520F7CEAB59616E38F5950B5
+ 22: 22CB4DF00CDDD6067AD5CFA2BBA9857F21A06843E1A6E39AD1A68CB9A45AB8B7
+ 23: F6A954A68555187D88CD9A026940D15AB2A7E24C7517D21CEEB028E93C96F318
+ 24: 1D64ADD2A6388367C9BC2D1F1B384B069A6EF382CDAAA89771DD103E28613A25
+ 25: B729CE724D9A48D3884DBFCBEE1D3793D922B29FA9D639E7290AF4978263772B
+ 26: B858DA80D8A57DC546905FD147612EBDDD3C9188620405D058F9EE5AB1E6BC52
+ 27: D78750726155A89C9131D0ECF2704B973B8710865BF9E831845DE4F2DCBC19DA
+ 28: DC27F8E8EE2D08A2BCCBB2DBD6C8E07FFBA194101FC3458C34DED55F72C0971A
+ 29: D09BEA65DFF48928A14B79741DE3274B646F55AC898B71A66FA3EAE2D9FACD77
+ 30: F2192584B67DA35DFC26F743E5F53BB0376046F899DC6DABD5E7B541AE86C32F
+ 31: 4F23C2CA8C5C962E50CD31E221BFB6D0ADCA19111DCA8E0C62598FF146DD19C4
+ 32: 630DCD2966C4336691125448BBB25B4FF412A49C732DB2C8ABC1B8581BD710DD
+ 33: 5D8FCFEFA9AEEB711FB8ED1E4B7D5C8A9BAFA46E8E76E68AA18ADCE5A10DF6AB
+ 34: 14CDBF171499F86BD18B262243D669067EFBDBB5431A48289CF02F2B5448B3D4
+ 35: F12DD12340CB84E4D0D9958D62BE7C59BB8F7243A7420FD043177AC542A26AAA
+ 36: 5D7E2D9B1DCBC85E7C890036A2CF2F9FE7B66554F2DF08CEC6AA9C0A25C99C21
+ 37: F4D285F47A1E4959A445EA6528E5DF3EFAB041FA15AAD94DB1E2600B3F395518
+ 38: A2FD0E15D72C9D18F383E40016F9DDC706673C54252084285AAA47A812552577
+ 39: 4ABA23AEA5E2A91B7807CF3026CDD10A1C38533CE55332683D4CCB88456E0703
+ 40: 5FAA4EEC3611556812C2D74B437C8C49ADD3F910F10063D801441F7D75CD5E3B
+ 41: 753629A6117F5A25D338DFF10F4DD3D07E63EECC2EAF8EABE773F6399706FE67
+ 42: 40A1ED73B46030C8D7E88682078C5AB1AE5A2E524E066E8C8743C484DE0E21E5
+ 43: C033843682818C475E187D260D5E2EDF0469862DFA3BB0C116F6816A29EDBF60
+ 44: 17619EC4250EF65F083E2314EF30AF796B6F1198D0FDDFBB0F272930BF9BB991
+ 45: A8E960C769A9508D098451E3D74DD5A2AC6C861EB0341AE94E9FC273597278C9
+ 46: 8EBFEB2E3A159E9F39AD7CC040E6678DADE70D4F59A67D529FA76AF301AB2946
+ 47: EF8A7781A95C32FA02EBF511EDA3DC6E273BE59CB0F9E20A4F84D54F41427791
+ 48: 4DBDC2B2B62CB00749785BC84202236DBC3777D74660611B8E58812F0CFDE6C3
+ 49: 7509FE148E2C426ED16C990F22FE8116905C82C561756E723F63223ACE0E147E
+ 50: A622E13829E488422EE72A5FC92CB11D25C3D0F185A1384B8138DF5074C983BF
+ 51: 3309847CEE454B4F99DCFE8FDC5511A7BA168CE0B6E5684EF73F9030D009B8B5
+ 52: C4C6540A15FC140A784056FE6D9E13566FB614ECB2D9AC0331E264C386442ACD
+ 53: 90962CC12AE9CDAE32D7C33C4B93194B11FAC835942EE41B98770C6141C66795
+ 54: 675F28ACC0B90A72D1C3A570FE83AC565555DB358CF01826DC8EEFB2BF7CA0F3
+ 55: 463EB28E72F82E0A96C0A4CC53690C571281131F672AA229E0D45AE59B598B59
+ 56: DA2AE4D6B36748F2A318F23E7AB1DFDF45ACDC9D049BD80E59DE82A60895F562
+ 57: 2FE741AF801CC238602AC0EC6A7B0C3A8A87C7FC7D7F02A3FE03D1C12EAC4D8F
+ 58: E03B18640C635B338A92B82CCE4FF072F9F1ABA9AC5261EE1340F592F35C0499
+ 59: BD2DE8F5DD15C73F68DFD26A614080C2E323B2B51B1B5ED9D7933E535D223BDA
+ 60: 0DDDE28E40838EF6F9853E887F597D6ADB5F40EB35D5763C52E1E64D8BA3BFFF
+ 61: 4B5C2783C91CECCB7C839213BCBB6A902D7FE8C2EC866877A51F433EA17F3E85
+ 62: C89DA82CBCD76DDF220E4E9091019B9866FFDA72BEE30DE1EFFE6C99701A2221
+ 63: 29AF2686FD53374A36B0846694CC342177E428D1647515F078784D69CDB9E488
+ 64: FDEAB9ACF3710362BD2658CDC9A29E8F9C757FCF9811603A8C447CD1D9151108
+ 65: 4BFD2C8B6F1EEC7A2AFEB48B934EE4B2694182027E6D0FC075074F2FABB31781
+ 66: B6DFD259F6E0D07DEB658A88148F8253F9BBBB74DDD6DB3EDBE159A56BC35073
+ 67: 8FA5913B62847D42BB4B464E00A72C612D2AB0DF2AF0B9A96AF8D323FA509077
+ 68: 7DED979C0153EBB9EF28A15A314D0B27B41C4F8EED700B54974B48EB3ECAF91C
+ 69: 1CF3AA651DCF35DBFE296E770AD7EBC4E00BCCCD0224DB296183DC952D0008C9
+ 70: 5767D69A906D4860DB9079EB7E90AB4A543E5CB032FCE846554AEF6CEB600E1D
+ 71: 8189E3D54767D51E8D1942659A9E2905F9EC3AE72860C16A66E75B8CC9BD2087
+ 72: 107DE2BC788E11029F7851F8E1B0B5AFB4E34379C709FC840689EBD3D1F51B5B
+ 73: 169F6F093A9BE82FEBE1A6A4471425697EC25D5040B472C5B1822AEEA2625988
+ 74: 2087EBD358AE3EA2A092FC19C2DFEE57C5F0860296BC7B057C14E1227C5CB9D1
+ 75: 182AB56F7739E43CEE0B9BA1E92C4B2A81B088705516A5243910159744F21BE9
+ 76: 081F6C68899A48A1BE455A55416104921D2FE4BDAE696F4B72F9D9626A47915E
+ 77: 5CE02376CC256861B78F87E34783814BA1AEC6D09AB500D579ED8EE95C8AFCC8
+ 78: B93E407404E3E95F20FD647365E0E7F46AFABE9AF1FF083AF996135E00D54009
+ 79: E81FA832B37BE8ED8F79DA29987AA4D61310DCB14B2859DEDF8FB1DAA2541FD3
+ 80: C56705FEA5B110B8DC63688533CED21167E628017387C885423B835A55EDD5EF
+ 81: C2226285D08A245A17058ED2D24AD095B714F608AE364FDDF119E0A7DF890540
+ 82: F9C270DA8793221A6809AC685FDD4F5387E0FE1EE6AAF01C74F1E0A719621614
+ 83: E69BEFD6EF7F685C36E343AC1702D87AD6A0E4AC8C0D5C521D04AAD4EF0B7458
+ 84: 4E3033562AD74A7D43EB5FF5FC2382622C6307CB10E245AD62DA77C4C63CB178
+ 85: 2EA17629472564A59E5EB845A2CDD04F442DF2FF26BCC866E400F77158D612A1
+ 86: B90223DF74DD49A8A1461F340F2D7A90F96903CCBB5BC3C74EA3658FC8948B20
+ 87: E0209F42B927EC9C0F6D6A76007ED540E9BDD6E427B3368A1EA6C5E7565972DD
+ 88: 10D9BD424114319C0999ADF6288F74060CD8918EF1228827A6269B2BF0F0880C
+ 89: 7D1978A65AC94DBBCDC62E3D81850299FE157DD9B7BD9E01B170156210D2815A
+ 90: E052DFF9E1C94AAA49556F86FAD55029A4875839FDA57F5005F4C4403876B256
+ 91: 58D29459B2130A2E151252D408B95E6DAC424C564062EB911CC76440CB926CA0
+ 92: 4E4530C392316F598E1BD07F32166380A8F712A33A48E9EB4247131EC5DC05D3
+ 93: A09C9D3E42342C7DEA44EDB4AEB48CF6727CACD8032A12CF77A25829FC249D32
+ 94: EB978D0F1AC03CE5C3510B5F4A16073A7A2BDC15C4AB7777DCF01030CC316667
+ 95: 7D1905A3ACE827EA1AC51C4FA08C281ED3BE87E7F4E928D696BFDE35C8F2DC0F
+ 96: 08359B108FA567F5DCF319FA3434DA6ABBC1D595F426372666447F09CC5A87DC
+ 97: A7B3830FFAB0F2BBABBEF6DF0B169A7917008BF238880BBF8C20B8E000077312
+ 98: B4F5D9B1555994C5EBAEBD82918D560A3BF82962A171A1614E7551939E943366
+ 99: 014ECAEA1B378900F1212898C6DDB01565D81AF1D0EF78DF5E28D46E9CAF7CFC
+100: BCE0AFF19CF5AA6A7469A30D61D04E4376E4BBF6381052EE9E7F33925C954D52
+101: 4565D7B898CCEA3139AD260F9273115F806B30079D7683218C4E3ECD43AF3B33
+102: DDADEB660FE8902C9FB2DB9B6CF237C9CE5B31753398085C4367EB5910B9CC13
+103: C15A8928131F6687DD10F3C115DDF8D7C8F2DF7E18D12C08C4FD16F666CE60BA
+104: AE8E3D799B1353A39815F90ECEEBEFA265CC448FE39FAF2008CB20784CB2DF9F
+105: 98545371A3D9981ABE5AB4A32A1D7B2FADD9801D89DA52A94A4F78A42740D21C
+106: 6323DCE2F8B3A04DCEA8D205602348C40403CB200C677EB1A1C0FE37EDB6EB2F
+107: 8150F7C5DA910D709FF02DDF85DD293C6A2672633DE8CDA30F2E0AA58B14B0C4
+108: 44D21DB70716BD7644CB0D819FA6791805EBC526EA32996A60E41DC753FCFAFC
+109: B9B7C375CCA45DB19466EBD0FE7C9E147948CC42C1C90F0579728CFB2651956D
+110: A47A551B01E55AAAA015531A4FA26A666F1EBD4BA4573898DE712B8B5E0CA7E9
+111: 60780E9451BDC43CF4530FFC95CBB0C4EB24DAE2C39F55F334D679E076C08065
+112: 09373F127D34E61DBBAA8BC4499C87074F2DDB10E1B465F506D7D70A15011979
+113: 13AAA9B5FB739CDB0E2AF99D9AC0A409390ADC4D1CB9B41F1EF94F8552060E92
+114: 5B0A32F1219524F5D72B00BA1A1B1C09A05FF10C83BB7A86042E42988F2AFC06
+115: 32796A0A246EA67EB785EDA2E045192B9D6E40B9FE2047B21EF0CEE929039651
+116: DA9AB8930992A9F65ECCEC4C310882CAB428A708E6C899181046A8C73AF00855
+117: 9C94557382C966753C8CAB0957EAEDBE1D737B5FCB35C56C220DDD36F8A2D351
+118: D32AB00929CB935B79D44E74C5A745DB460FF794DEA3B79BE40C1CC5CF5388EF
+119: DA18797ED7C3A777F0847F429724A2D8CD5138E6ED2895C3FA1A6D39D18F7EC6
+120: F52B23DB1FBB6DED89EF42A23CE0C8922C45F25C50B568A93BF1C075420BBB7C
+121: 335A461692B30BBA1D647CC71604E88E676C90E4C22455D0B8C83F4BD7C8AC9B
+122: 3D08C4D7BDDA7EC922B0741DF357DE46E7BD102F9AB7A5C67624AB58DA6D9D75
+123: CC63BE92E3A900CD067DA89473B61B40579B54EF54F8305C2FFCC893743792E9
+124: 865447FC4FAE01471F2FC973BFB448DE00217521EF02E3214D5177EA89C3EF31
+125: 3DAA582F9563601E290F3CD6D304BFF7E25A9EE42A34FFBAC5CF2BF40134E0D4
+126: 5DDA7CB7C2282A55676F8AD5C448092F4A9EBD65338B07ED224FCD7B6C73F5EF
+127: 92CA0FA6651EE2F97B884B7246A562FA71250FEDEFE5EBF270D31C546BFEA976
+128: 471FB943AA23C511F6F72F8D1652D9C880CFA392AD80503120547703E56A2BE5
+
+Hash: sha384
+  0: 38B060A751AC96384CD9327EB1B1E36A21FDB71114BE07434C0CC7BF63F6E1DA274EDEBFE76F65FBD51AD2F14898B95B
+  1: BEC021B4F368E3069134E012C2B4307083D3A9BDD206E24E5F0D86E13D6636655933EC2B413465966817A9C208A11717
+  2: 5D13BB39A64C4EE16E0E8D2E1C13EC4731FF1AC69652C072D0CDC355EB9E0EC41B08AEF3DD6FE0541E9FA9E3DCC80F7B
+  3: 4F895854C1A4FC5AA2E0456EAF8D0ECAA70C196BD901153861D76B8FA3CD95CEEA29EAB6A279F8B08437703CE0B4B91A
+  4: 80AE432E757826025095CA1FA4F89C06C8BA6754B1D883A8E31A1E65FCFB820BD74ACFACA3D939A574EA408A74162D1D
+  5: 561C16404A1B592406301780C0C2DF6AA0555F504F35BFBEAC810AE36A343B776858C5E0DE56BB79607A34D2F67108F2
+  6: 79F4738706FCE9650AC60266675C3CD07298B09923850D525604D040E6E448ADC7DC22780D7E1B95BFEAA86A678E4552
+  7: E6CE1896C9783A70AC4C90276CC37B37687D7E30C753975762F961AE37118D9A610242716E8359EFC4975AA98C632DCF
+  8: CFB18F81F4BB672B03214F1FEDE456F882A0DE40120212A1FEBA8FDC48F763C86ACBBFB684D34B70F99F4D8D81FE3A28
+  9: D075AE1178210804635AC02C656309311527FC8190835C8AD8196577C3332AF4D87F056023F235DB893C69AA87B0CFB9
+ 10: 182E95266ADFF49059E706C61483478FE0688150C8D08B95FAB5CFDE961F12D903AAF44104AF4CE72BA6A4BF20302B2E
+ 11: 89BFCF569AE4AF718510DA78C67414109F5739BB5C40D51C9C8C50E2B2CEE86F2F80C8B9D68F7C01201A0714572FE602
+ 12: B635441A3721CF190B39D23703C5B77018FF1A56C94F8252EE95C217E3477F093E8EC65C6AE767179A7872C8DB9B2141
+ 13: 48DEBF56626CC86DFA47AD6FDEC73FD182434621DA8BC6DB23AFF067BC36DC8244D3071B1F57DE4B716F63D9820DFB23
+ 14: 58475B7CF93FECCB2C02B588F1552A359E7EE9AC45D9AE50B2D7C22021466677D70EF24EFA5C492515164458E9A24744
+ 15: 0AA75534F0F58756A01E3366F78E7611BC7F432364C649C3F50547F7BCA3E5489531B8AB129495FEAC834FF0A0B45DB6
+ 16: C81DF98D9E6DE9B858A1E6EBA0F1A3A399D98C441E67E1062601806485BB89125EFD54CC78DF5FBCEABC93CD7C7BA13B
+ 17: FDD3C4C0F87EEC0CADD73028A06B01E67696C7E04960936B30C73F004CF6B595D644533F8B473C8E63B02D593A64B041
+ 18: 445E4CCA1A03480D149F38014C14D28DF8288F2C6CFF047F45D4F2580AE85EFFB3BE009C9D2ACC54B51467F83A09FBE2
+ 19: 8305DC56172245B82AEDCE7F9C7DC88C0E62CBF835A2AA133EB579F415FFD15BABBC30BB98E55DFDA0F9E80275C92BC4
+ 20: 8A48240E1C85E80651EDDC88599273444839A952CACA2BEF4400576E65B1EB6C19C47A3067B63AF7CDC4238ADB9A8DAD
+ 21: 8F2F7669C27A7CB1CF7A84A2C4F050D7141852D8B429291956B85E2DB5287741A3104E7E99CA5D23A5EEA59A68A4DDB1
+ 22: 32CF04AE2A4A326FDE2FBB887F47FB7A2C486E56088D85B45F0C7587591F44797FE0A67E36F571809695E05F254884B2
+ 23: 713A04A3A6BA8D2FD821F1CDF9FACAF42795E4247C9A26F0ADC5E0E6AACBAFFD8F4E02563733C6BDF1A863A787949B35
+ 24: 35D8A5AA0DC9AB4C9A4C62B36E0E1013977C198B05CF6B92CEA25C08309DAFD282AA9A4862958593C06BA46919EA8019
+ 25: D3FB60C2E981A5C82F1B1BCB3D4D7AF62C9A32A9F0D87E0532C9D3AAC083D70133EFF63A1E2CCB87360BF032C25FE9E1
+ 26: B119F9AC74E58BD081E24C0CC1E090012C192996EED67A8ECA33794FE7E1920E26C0EFAEB866EB5AB82FCA3188A3B05A
+ 27: 5B29543AB0F76F246B7FDE6E8E5D3DF6017A39342BB08351A4EF609AE00A91ACB7C5D0487B3760B34CEF326F63C84572
+ 28: F8E1FAA657BF829C9D2E4811805238CCCD11F0C1AB7619058241BA5606E7BD5E4816163E6E8E82E62A43CB4943A41006
+ 29: 0855B919786B5E5C87B85A6C17A46C550B2BA81B3724389088E2B54BA89D82B8F9841FF442DA5DB8D54C9B2AC108DC3C
+ 30: 7DEF8CAB7C80CEF90FB38989ABEF6F1A5EC18379681E484A1B4DB6624818D2E486FB9C245C1F0DDD85A846D4268344B1
+ 31: 04AAA180C2CD24F0FB150B1AA360F445344150DCA13E1ABB8117D42E25DF7FE29246D9F00C7473D20CEC32A71E64E1F5
+ 32: E7112491FAEEFD57786DA73F367B25A6F5769F5C98FA7B704D8D37747724A647371989E8B0FE8D3CB23F9EEDD528456B
+ 33: EA27126D0B96E00E428943EA94F4B03FD22D56C4FF4636EED139D027E6D45EF57AB86093A7342B3B3851FD3BFD1DDA23
+ 34: B2BD337A4BDD48D25A5E3FCE3E0948EC67829B835A8E3DD0D9F4881D10C766369B079028C6060B7263603288D8FA4BBA
+ 35: A9E940504AE6B137BB1BC88CE3A9AE53DCB63AFDFE5FA0C652003A921F582C08662425C7FBD5B1E1422E39E645D4A757
+ 36: F033150D7464D49A076C7D4BB9E2A5488132786CB4851A4C81DA5B0FCE66D775D3C1766094AD6CA9482DD9539F28ED9A
+ 37: E64D999E7258ABBB4CFF6F74AF7D6A1E9B044C17E1ACE0FC61B29E7732763755A9C1D3A380B080AD968D2228DB731DE7
+ 38: 9030D47B57ABEA93B51162556FF352DA61FDF501132A9FD94E6CB56690E7A805CDB290FB4ADE36BF90A53F20922C9B6E
+ 39: 4473396BB0461EDB4712880810A3F7252725AD4FD6092021A40559F453A1C63ACFFA8A02C85CC8DB86560323DA0A0FD9
+ 40: 095FDD130278B3C8F574D17283611E4D6199EA63A0F1599E01ED070CD0B115296FE353477582BF279D622355C89A23E4
+ 41: 7EE600CEE8437531C6A5BEC313D53371F9B56425D5662C104624D83D51111E5C9F4B83000B8A3EF150E04AEDCF67C237
+ 42: 676D2BD2500BC527DCB51968FE8742E40D2965047478E69155AAB9201E0C9B0F6BA9BE85C4734B0DD556B5FA7608BE83
+ 43: 09F5FE433D1FB8F62A76E5654B54CB6A9EF505D2465A49DCB9669EAC9A30B2532505E4500F842EC9FBE79A382C8C2F4D
+ 44: 075821CA8C547E66AD94F4C4ADF866A2A7554E08D2B0F0B3576801773EDC85DF76107E6912904E9757EBA753A77CD0FF
+ 45: 2172C22E7E48BD0B4A73FF02803D6FCE776CECBD95DFC43CA0763A0B375D57030000B12E59F9CDE81DE58E17489B2C41
+ 46: B9A15689BA4F41BE46855775B46A5DB9D6826E0CBDBC3B292DA6D57B2A179A3D393A8E1B55DE79438E5221580C604EAD
+ 47: EBFA57C946831E2E370A6B1BE46E27C95C512297499B8BD15722622178E00599DEEADD48F1B4B08EB649A137805CB786
+ 48: 25866C8288F9FA319FA9AA2470B4FC2595DFFA9154E607444EA3247E81D74A2AE0957D6B7E050F8C96AA7577BEDCABB5
+ 49: 3D28682B90022C873CEC78C3A47FD45B5124E49ED07E2F0FB41A112A63AACC9E7614ADBB007D129C0673B08C51210839
+ 50: F76D9B7ED868085905AE806CFC5C6DE994999E379922AC003D53F00B65467AACEF3929392F1F2F56C621D2F552544A22
+ 51: 324951FA2432B63D1765C21F98325BC4AE2FFB25F411047C53ED5A3D550B50E2B8F6E79BBE65F2C686A5132E5B982AC7
+ 52: 320CB033AD533AF8EDB3E664E34BB85B2327AFCFC583CE9202C0B11F16425A58FD895D7435E8953F9506A25DE7BE6EF3
+ 53: 6065D55530ED8339B09D7A4D9CB1919004F69ED9D6B119E78E1C39C7AD2AAC029A3F266F7E48350966B845C4D7D92A72
+ 54: EB6E866BDC0B5089301D89B870B75056ABA6D5FA6C7406A8D6D97CE5175102479647D3F93325A2CB648A3F40CCE38542
+ 55: DCEDB6B590EDB4EFA849C801E6B6490657A5C1E64F69269F5F63C9267F6223DE24CEA7AAA6B267D9BCECC15147B6C875
+ 56: 7B9132D597B8873AD55BBC30F18ED3F2C9F340E7DE69FB5774056C71A06D9BC2B14137E9E1C68B6B645FED28B188249D
+ 57: 0901B1E5B13FCE000486BDA64FBE45C79FCE15F38A4DDD9335A521D98829D267ABCCD84284BEF1EA3C2D4E4687C6D3B8
+ 58: 4A9375DBAA878E2C1C7BFB977989E6D39CC00F890ADC425F7084AE3761BAEFCB9384C8B9EB3ADD4C3C838A6D560DF788
+ 59: 908682C3E0D97A4943063EA9DD0A0F55EFCA203ACA3004010D3D7EF94593592729B523EAAE4160C3EA2241EBA236FD65
+ 60: 24586F75A43A08D6CF116B87B86CC43300FC4132523CC4824B7FBB3F54A5B41C7D598B40639B25A99732D575A5CFD355
+ 61: 7B4CFB73E247E941570E70C7308ACC5166F123187F003B1CAA9BCD17DDA8ED5535ACAE443C9ADE93C5567090EACE29AA
+ 62: E97EF4578822DDC79AF60514A188F8C719E4133B58E5EB134261AA7E89C402EA7219129A06B395E5E1D2738AC23FC876
+ 63: DD66B519F51A925814407A449C60B34C553D7652D41783EE903A810A4C9F833B8181C91C7F12283EACD6A5F8A2639DDF
+ 64: 9F2C9EB7116B3D7A4BA84A74A4D4EFF8A5EFCF54B6D7B662693C38577914C73A214766F0A175339BB0895A863824FC0A
+ 65: 14B0A9FFCE149426BF5045FFC24C057451D2473186DEB4F150117B855911A7641651FB1E15DF406EB373D71151C46F25
+ 66: 286505FF7A9EF81224988A8FF1E423A2AD21F6B339E91B89F7F1540F14CC9A603952564539167465CA70FF0B523BECF9
+ 67: 8CAB08A79BA16F3D7CBEB942C7D8676F8D0295B5FAA01F3C850DC4B5FE913AF00F2E938BE0B442187B135BEF1A36C34C
+ 68: 4D12FFBCE2E770ECA1104BD2F29C65FE95534E390A138C30CB0ECB6436A971116D82C6321D2EA2C0A735AF34E5E3E3B2
+ 69: F8617A35FE9116A719441F82F21C79B8868E5FFFC2EA737FDC821246DB7610E9868D870575F19B29F2FD259D9242A497
+ 70: 932FC435B590B1E1D49C34EB3B627DAD5476216518250B1FBFE772476437872B8DA6CAF6D2F33CE7AF8648D956CF717F
+ 71: 3F63DF48C2D87CEB2168BEFBF6B857A415D8BFB7062251E8E1AB0487483EEBDE5E8E8B8B0E3AD81ED4AB15E81FD5E448
+ 72: 4A71E4E737DE74F78E72ECB9DDB580EA5AC96E5BBD5E52E11D4A41AB3B8303E3AF3458A8AD89B39CD9F4A6D5DB3C9E2A
+ 73: CAC3A81A98103BBF08C440F6C8F61AC010DF8AC05FDA77E2ED8660AB73A978B9428BA0458A5C64DFCE35D87F0DAA2A6F
+ 74: 6E5D162C60A451B6257781FA0E36B3BDD9BC42A7BCFEAEB75C18E541A4DE00967E6BF575CB32374C1E9FE7B36D92048B
+ 75: 04DDFD71893D0F4AD2A0B672A057ED2795D6811AEAFDB7136BC8C20A55DABB3AE4B62B8A2C722C1F53E18FFA5771610F
+ 76: 555D5B51C2EA17659516A67D31CE2CB302979F80BD7056908C1A152403FD902EAEBABDD066AB3F7834E7213A6CE99EEB
+ 77: 44797CE4FEC66B26B52A4249C2B267AF891C912E55221EDB6CAFC4E2F022A40E8231931DF0B19321D5CCB2AB8A4F256A
+ 78: 51D7AC85289FE7E4D9431414B2BF3760BE65FEDD1A0B34BED0E1562A73495EE10971B5141835DB454C865039154BEA15
+ 79: 2E31DAE50A484B7E11E2E621D0552803791E07279752E09EDF4C884EF24C79C33D9572AE0DE6E0B6A20271F1F7AB98FF
+ 80: DDC65ED22CAE4D159D35E129A1602D8FA50D7AA53E209B0D5442BB121DB0D5D102441054B2B321675F3722669FECD06E
+ 81: 200E0BC495311E2FE524A1579490D843011A592E4E9B927DEB0727E5481898C557CB2941F18AF0F2725A1B19DE045BA5
+ 82: 561E1875B31DEAEC4DB2FF5BFA7856A6F0ABE1294CDCCA1DA12CCB1786D9556881A768ABAE50F7243921ACF993AAF18C
+ 83: F6B88007732D5B9F75209F9FE107B9917010D5960184FD239854AB4611CC788D1455B113A5565A87326B3CE6CA190DB8
+ 84: B4E703169169B07AC61E76A75ED4AACEE4115F6A43842BF136B514824A05F5C5ADB68F2E525D8C9E8BDB20D3BCA21155
+ 85: F72E2083B296EB7468C97749D3AA1B08F418EBCD9A2E5CB4117C5A034BBEA5E2004EE1E43E26A98E4F25AD4306AF3A57
+ 86: B1DE9ED0D5E5F7FDCDF530041D7320CA7376A64590F6679971F84061C42AA03F0B07C7EBCB806EC8380D9FF0E182293F
+ 87: 30ACC02AECEA9B91F3C6BB0F4CA8EEA1B84A0BA6BBB8F7749FD29C9BE5C5E28AFAE5A33617DFE3FC28CE3A78D1A19CDD
+ 88: 5B2DABAF662B86DC4B1DF6A2EBDEB5CFF1F63C65ACE5E1237DB507DD3FA2C27FF46517B0FCD6F32F25DCD55ACDC07FA0
+ 89: 33BE80B29355AB16AA0F05A45A8DC15A5EF7F9FEE60BCBE05E106BF6FA0F196BFD9CBB8D79298360F760DA7B05135F83
+ 90: 048C648A525FAB61CF81E087047044130E407B71DDD27293119689C8516B19DDC4F276E3B4E93E6AB80A79BB2700DE68
+ 91: BF18EA9E00E6C2262D802FB66E04FFA21DC5C13640BBF27B2C22592DE4AFE31C18147E6EBD2D45669C36F9432494A000
+ 92: 0A1A114981A785C399E2B21871A532B2A747FC67B4DAA287C14F2F449FC6F7C6925DB5E884E6E041D08BF6BC69295124
+ 93: AC6705C373300FCC09A291CFF1834401FC30FAD512569848A05171AA02426B7034EA2E4777AAC2DDFF48089226A4884C
+ 94: B7B08352FF8988C0FFE3FE0E27278F068BDC88AECBA8D7ACD8919850D7400A2C0A0A8519B264F61102290C9AAAD3C2DD
+ 95: 8F78C56A93B3DC69ECC5827F8D591195FB683A9951175754926A8E19F81FF859DC1904DE12BC8482A760E998552D28E6
+ 96: E606004ECDC6878B5EC15F4554017CCF962E92CC6EAEBE4997BA34EC0E53C67D564C8461C013701A401FE347EC0F721E
+ 97: AB7D7116F436ECB13ED2EC42347DDF902E0FD766EA8978CF93625F56B2164E2E630D6383EB03602A8DF27F28F580E3C7
+ 98: D716BE6974E46F19A606486BE576AC6E250AAE6AC2ACE7CA9A924C874790E6B4C94670FD884A6EF770EC5E5F3F264306
+ 99: 746EEE51375E6695BC4B66190172DC6E86C18E144267C7B0133D6C2ECE05F75B862E4C4EA5F813DD927D60C46E2C554F
+100: 3D20E33BA4D52A8C374878F1A624A907132264D0C831C64FC51ED8E1CDB75D11C3FC78D4C3CFBF99D7F0BEA9829B725C
+101: FE6A6EBBE30EEA13CE04B1C8FA4199331B77566D2AF420D4EACEDCF22C23B3D7AD2313175389A0765AD60A79C0AA85C4
+102: 1806469C58C028D7FBE80F219DD45333D440A824032778DEFC0A89CF704D40745F0F449F7DF82D228E1718391C85F318
+103: 20CD15E37F6371020B78579210FFD7756B42BD01EB829C1320C59AC382781AC4224439F1F820E215EE907091EE4F028B
+104: 7967636E73E440EF1F8751441ADE0F4D169167AC270949A758FE0FFE0B90C2773435623160E4BEA5F23DBE0678E95ED2
+105: 754F6D73A11693E07A2E5F05FBE13514C52F04F904131E0544202354D30917C333DC649FF7C33557005BB19B64DB777D
+106: 358D83F883166A6D2972C63F2A46EF893D2FF0F577A53830B3B8E2CB28D1EFE8405084C145EE4E0BEE5DFA9AEF739263
+107: D74B6FD707BCEC9419F032A9C21A7C79CD38F42D564057CDB956485FC5C2ACAECE9D86BE8E12B9181018EA7871343147
+108: A517359A64226F2D08B65203593F3427DD42852476A7609C7F6423C304FBA6EA83981470B8CF171F71BF02F688BB2448
+109: 62162975F98C8ED1B74ADE5B2325EC3D185F7BF8D9DE6C08BB3AB052E54C28399AABE2BE4295CBE12003A03924D4EE3F
+110: 8F1E4237FBB668D2705FA6964FF50014F54AB6346A7DECC8DBAA282B51803DE20F9090E7AF2E6B40FD8A138AFE25E1BC
+111: F5F9FE110D809D34029DE262A01B208356CAEC6E054C7F926B2591F6C9780579D4B59F5578C6F531A84F158A33660CEF
+112: 33BA080EC0CCB378E4E95FED3B26C23AA1A280476E007519EE47F60CD9C5C8A65D627259A9AA2FD33CA06D3C14EE5548
+113: F14FC73C4192759B70993DC35FBEE193A60A98DBD1F8B2421AFA253DEC63015A0D6B75FB50F9F9A5F7FB8E7241540699
+114: 72B9E34E0E655DCD7D9C288D11839A4FD96292F76F69BFB2E7D4F848E498B842CD4ED6486E77E30C603D218144AEEFB7
+115: D71CBD531B25BA65E319954E5AA670C8055406A595D006F0DCEE11AFAAF735CB1615EBAB4CC98061645FB70F31CDD9AA
+116: 1F4398793AE7B2C4975AB102BC054DCEECB238DE4307B5DC54F6D7C20E066F638A782E33441533276DF9DB1AD0EAA75A
+117: CCD908195016DC596A78C6C10C92EF6F272C6251F3C40B2E7DAD3A4538BF3FF585D4E44035B49EC397D1476E9DD28D02
+118: A8A26DDB23032BBD4432AC857383A5DE280202B21CE173D864E19C4A52984E159BDD006D95605A4682458137FE6B71BF
+119: 0C8D3031D85CEFA23A09E13CE03623F0E648A030E43700C82AA1C8AA7E3EA9CECEF3029A23815AD940CC39ADB7747D2F
+120: 0577AD6090B2A39FFA1C4A25436F9E958890C55A5B23CF8CEE8195A5984316D81D6CF0B5916C0AD8B1F512FB39826C6D
+121: A5E7C31DCDEC53D8898DCB27D52A5C1774115D8DB163543A330AB502FE31D6017FA4BA4C65ADE0CD911972C5A1B7739D
+122: 2785C149B798E41E6ED600DDA5257E2F31484BA4D14D35C8353BA4BB3BFB47F6E2CD9B64C940E3C1F83AA4587DC29CAA
+123: 977756EEF1A7C1D4CA31A8E6936E7B8884968A22F2846F20B38F247345B1CCD47405040F727BBE2E0FFCD159206F5E87
+124: 9E4811F182E5D6734EA097FCBC77892EC48F09DBA138AD5A5ABFE67F2E88AB61B0A3ECB29028B5528180191754231765
+125: E964C5CC45E8356DCE9FFFE715D01AEB3935D644DC9C2603ACD175A04E8924DD84A4D88A1384D6BAA8AB3F7F7D52D122
+126: 764EB963850537E57D0969C9914355C5AA67AA9722644569B7F50E20DA8461CC9C6CA5958ABE10F5469E4DC1ED27619F
+127: D5FCFE2FCF6B3EF375EDE37C8123D9B78065FECC1D55197E2F7721E6E9A93D0BA4D7FD15F9B96DEA2744DF24141BA2EF
+128: CA2385773319124534111A36D0581FC3F00815E907034B90CFF9C3A861E126A741D5DFCFF65A417B6D7296863AC0EC17
+129: EF49AE5B9AD51433D00323528D81EA8D2E4D2B507DBD9F1CB84F952B66249A788B1C89FCDB77A0DB9F1FEB901D47FC73
+130: D9B681BA08EC0D0598DD3A2A37F909D01A231D22DA52216126534402A58A072DB35FDAE555B99159894BC823F9DACFE7
+131: 961E792C94027A091DF880A713ECBCA94E7699FA392CCA3E4B9988CB95DD46C894AB6CFA3DE91236188F7A372B1C60C0
+132: 779C845CED9623B6558577C06C6F22768E4A01CED2A9722CB8788FCCA89E0B5CC6A8925533FD097F635997A9C191D59F
+133: F8A6FA1C730483AE488191E5863AB3DAB4BBDA1722710E519A2B2455273E78A382C60DB0D21E3B497EF9EEB2780AB384
+134: 1DAA34486981474A57029F0B1FF5150A144CEC7939A5D0C3D7DDDC4F471225D98E83E8A0DE880036F1A265E24CA1E674
+135: 769694D69D701764BCF81C053E2899B232344506C08A39DEDE3D838F85870818C3A8CD2DBC8695EDAF8FE34B4A5CC35D
+136: 97E29E4AE7C7E461196C1D698B5D1186822BB66ACA3B3E062A3AE07DB9DD0FED83A345014D3E5AD89E9046606AD2CEE7
+137: 6B57593EE18186573F92273A9B722F9FD77A4A512164FE3756BC2D9F665768016EB2766C46D473A103D7D7090073271F
+138: 35235261C522612958048B7FB8E48F96462D2B8B52AB2455C7C142E442E4CF643B367ED466A30BA97D91C1C8C0070E05
+139: 67004A5E74598981A79984B2662FFF8C8F49F8FD13C8A841F68DBA18DF68015E9C1EF38D6522D44F89DBFEA8AF48D2D0
+140: 8ACD05F9738BBB176E50C7419A05C8200E1BA84B5797032E025ED4B55D7A61CEC4CE3662432A4E0BA938D8C9143D5254
+141: 9963300C0CE5F2D39C2B899E47988BFA914D2EA2DBB972C15B3CBC414E41DF3A2FE793597243D46CFF937F41C0D83136
+142: FBEE0F5E072237D19170999D02BB95F6F8F48FD0596A982A4FA2D1273872226398DF57A63E1ACCCF6343415DF387D89E
+143: 32A65099C47EAE3BCD0F68645845C0171417385B15DB5E5F7BB5AD965F66C98CDC39B7534198AF70AD5739C8A2F2B8DA
+144: E936DBA2CED7F65DE3450BA7ADBE1030D7AEFAFCCE0CBA94E671422790B45B49918319A90FAA7692780CAB4301D9833A
+145: 1E20D13B4D71ACBDBD5D2AA129E98929510C795119EA8A07EC63917114315E2756B45E7AE42E1A44C5E410ECBEFB3661
+146: 02A0571C5C3076CACE7F061BDB108D7CD9C7EA51D0FBF1D00F202A0B5C87F22CE687D1CB15F798ED164CAF1CECF92CF2
+147: EA07C4A1DF1E5CB26DC7A7BC76FE518890FB8C424AF3B1C76B37AB21445D9F7FBAB73C7DB35E85337A8F7A0D55121F34
+148: 7829712876378DF986A63E4616DCA38DBE8833B14760168897AA808B96D8FFA4460CA3C1A9B674A0FC13E0625537C45A
+149: A7CBB3CD50AA663BD2C4520CCEEF123F7D314870806291DA26A59C003D041E46E6B563670F27BECC5F838A273D349AFC
+150: C14E7F70D28E17D3546EB40EE96D239CA5EF7EBBBD0DE64B964C145A5F2980D408A6AC248D651E4583E25093042EA286
+151: 19F87BFFBFF4B1E195612F41E67E1D4CD0393E73FEDAC1C36550C2B1A7323D3E7D747EAAB9844F45F150F8DF0FB72E80
+152: 6BFA3BC29FFF3A92FEC377AF8508D4823F4E87072D6F2F16370B7DD30789A944EE5721EFDA7ABFD47A512EA2D4984BC0
+153: EE10FDDE70EB0A11462DC00860AC4756B21C83BFF0066C431B17BA57CCBB9ED018E8058CB9EA44CC11952C3C9BD15F09
+154: E6A72B9D2A0FFCA41C3122C767A6FD9CFA04CB5B1D1D94B79A0B2C592A584F731CA0523AEA8F2DBA35FDEF74CAF165EC
+155: 59118A53C4479070DC728D94BA36D211F4ED5D35F1B69E4DFC0543F07326F982D2B81DDB020F2CACCAF1E5E9832624E3
+156: 63778B7830A3AB7421912A52B3CE9303A53C2A6655291042F428691A633FB9FF173937A8D8F59B21F72D490F39A9AC06
+157: A702F15D9483BB767FC6BE9C3BFC64732277CE936AEBADE4022B24B4822BD1B0FA1213AACF7B4506BF8F330FB7643955
+158: A3FBEA92041484F7F46B380462C5114B0243A79FEED89ECF8E6D8306D60DBEBDC5FF1578EE7E94B5527EFC5707D2B7D3
+159: 1EAEA2602E0B6B328D008A5325C5D4F9DFF7AB9BB5D36816D3EBFEE733BE664E35170506667BF5A24D00222EBC5DCDCD
+160: 92E4D41594E15628BEF06CA61E644D2A686C113BF8E3F9A8CD2CD8261B11D01B081EF2941D5182E565B70C566D461B23
+161: 2F08DAAA98DE6DB4E85B81E32C651D88075DE18B7F9C3F633BE1F29C89F24968525B1B357DE80C6EA8D9570E003C75DE
+162: 5DF64E7960C755D40BE78F0BB7C1A185DF8E505F0B421BE23563472843E3B5CFC7DA0F40908BF56C6F3A6244581C1DE6
+163: DABB5DCBC32FE7298C811CE22025E9B1C0B87DA5E7931CC3614E3EE39112206DD8422A5504F11599436B806C9108B01B
+164: 31AE27382E330115E009474FB5AC750A278B79EFF63755E323E3478B0761E5E946DA6D2436DC44ADE9F4578A8FBA9896
+165: 6804CF0314E455F499E73BBDF4FAA22CA49020330E74C55B1CF4A2D2F4C57D7149B41916002B2852ECFA0713BA91A094
+166: 7FAD2AB0972D8059D4306F0B63F25D9ACBBD8FD95EC8199CFA89D4E227EEDE6052AF0C53C703C7E319047DC5734C9F4C
+167: 4635E654950B173D3EC81A8212C1E65605C85835CFAD8607C829786855636A660D6C3045FF17663DE465BF2B152879E2
+168: B40764D8F066C897C3A8FE54BF21DA294C6B3F1B35255F68C8AB325AB3B94EE8AE2E5173936C17FDC95C9B7C3D3D3A58
+169: EE7E424C550F79BA82043245C3B7D0AC32A41B876988C322B9997D87F0A0A1FB8263726B953B43B4616285A239994936
+170: 627DCEEACB27F39552AB683330A67A316B2F53842BCE8056FCF3988702955E3BA72FDEEAC2CDB53F13627858C1BBC51F
+171: DD13F3B3E9C79958B20D1986650A79CEE1343F9957FBEEDE18B2FB5E543E3B8839EDF7A57EFD818129C4F00F505D2112
+172: 0A7061C0FBF1EE8CCB0F4A1D0DCAF2F200291AC06830F0E38D05E1CA2429A2BF57DE5BF8DED5A7CECC3A4748FBCB880E
+173: 3635AEA9152337FBFA4C2824C5499B9F3FD32061297C4121FB0A44CDF5D3C8D4C6EFD760A0BF076DBD1801C416949A9C
+174: F9C58AF2259C719B0B852FC68299AC9F17A802B49B34CBF5FBEB85DB3C68767CC34DAE2CCB536FF90BAE49FDDEC0CFE4
+175: 3541EB8602A4C84545F4476749EAD54E4542C4358CC78CA5B7C8B6BCD9E9A3E649CCB243FE0B3D02930CF1CB7A507FFD
+176: 4AA26C2565531A52811D30A1C59152BDE4C61AE2CEAFEF9642E7076EC44C7EBD50F1D1853761B4097D985DFE6878A701
+177: 32F1DD0B4AF205B4891E2F43D772EB5E4A5EA3658106FDC8B8CEEBD2D502F8048B583610A419E1A60020C8C2A5A02FC8
+178: DA7403FE3C3D3139893522C5DC8E4F615D36A0F7B7B8AAF150D1337C8DFE70311544E54880D1C575D664E9AF979984D9
+179: 39F8450D4A946ABC6FCA804AE11935CDE846D999BCFF3091F1E6944EAEAD504F77139A919F915D34DACC13757CCE0157
+180: 45CC03085CC3278B8337096BEDFE6F1D645994690660F23A358C4EC728EBAFD6966C487B9492DE217C17823B16589852
+181: A2150F3BA3349E3AA0ED97B1A02A58F31EB5731012393EC68846D95465F3B787C272852B6945B1CC0FC2B3BE999E0E46
+182: BF9392B085B3C5FFBDE70A3FB64AAB36E39BDE4816F1C9B2A608269336906303F7DFC15F4701D3FAFA5D7A8BFE316A1B
+183: 21BDA179D5B80FA6B9444AB1D1F7E06F89F670DA4A038E7E83E8A63CEDD44AB6C1D069D12C6F538B45022EF3160D396D
+184: B4216CDE6BC1C27A5C1EA9AC79E85776740F93440AE438D4D9CF51BE8A83AD44565586FBFB58DD743782724A440218E8
+185: 5C3D5C00381BCCF77FC2103C262F373592FE34C2B2895F54BCFD1F9B3C87026288130822B2B451D716FA9D4D7FCC93F5
+186: B927E3777D4BE05FA85D0CB707FB00F08C576777840634531795CD3D6818F192789977AD6425018025E10F5892FFE708
+187: 9C6976E1EDFAEDC32378C8D2758D1B0C5B287C500442EC5D19560BC87C75FD2A7379A3E64ADC1421B7410D1ADD6456BB
+188: 9C20482AB71BBD8E985D7891499DB526BCAAE11D2A42DD72FFED664D7BF7F254C2F8DDA2E340690FB83E1F5C58378B72
+189: 7899D5AF410188A3D0D0B12D52437313D786CE7959FC4D194D6A3ACA85729B60ABBDC58AC40731B9E833505156BEFE24
+190: 4F958FD1841D2B790A199EE3358F4DCEEC64CB34D0886EA91AA5E38F8600FBE13DEE4D6A55AC1273B3730CC62A3611B7
+191: 66572F61FE6C34B440AC00C8D3992B9CDE3FC465FCBB193CB7716B53E8032C743718D4F8245D94A22A9AE125795589E0
+192: E7AD49861960D1460A77F4F363341ADC2207E205302957250612C7E903802AF5C9423414C52F4C1AD55CC1C8B2922EF8
+193: 62BE3AA3A9D08CB41F2CA3ABCCB96E2E91A248E569FF58F58C8BECDDA5B4B25FF46BB30EB37999E6131D944CF3253302
+194: 3E082F7DBDF5BBA5F52CC870F2C6E9C63DFCD5D547B183F3FFBE392BF0A1F8F4970CA21E5B9B4306792C138D6B2056C3
+195: 5CC36277225DA2EDCC6CB603EDE9C629E5DA823E6D233AB7833F70FEA2878B2F8D08F361BD5B4C7609577329784D87DD
+196: 9555EEEE1EE60EE981CED3FB6BF74699E5383436ACC283BDA0F9F6FFE20561ECE75ECE2C5A82C0A158C071A3BA59CF58
+197: 0B975D2ABD0551BA987680C4890F80DF93AF2292FDD1E47322560B0AD3BDD38A67D3A78497D78B3C38DA597846C5159D
+198: 016CE0B8AD1628C7FBA358EEBB7C3667FA93566086B99F20EA6F87FBACB320E7BCEEBABF0008550A59AC1E6C3B4478DD
+199: 3D138114480946A2AA1E2B78948B6BFEA95F53BD8BED81ECCE166062A67FD111933A696E6FFFBFCBDDF71041955C98A0
+200: 7EA4BB2534C67036F49DE7BEB5FE8A2478DF04FF3FEF40A9CD4923999A590E9912DF1297217CE1A021AA2FB1013498B8
+201: 80C399C975ADDAB12FA20B3C3D04F25218DFEB678B5A87F9963A462F5474732C7C5FAFE0EBBBAA94662789CC10C9AACB
+202: C27E28A5B6C7BFBC7ED372B5BD2555EF1370FD96043753015B3FB9AF31D41E7189D4FA8860B183703560A298D90B6E75
+203: B792B021B3FA904B5948AFB4E56BD4C40119AC79E57EB24C32A7BF0A1A889313D816997E35F2CA192B34D2FF9B05ED9A
+204: 7828C6235E2B8AC46E4BCD7F7C7554EA81B5BFC046133EEFA0C4E64AAAAD7115B04EE09E33CB4EA1FF476960C64D9A36
+205: 06678F9A2F238953A8D6646F859FCC3BB0C29BABA669D7F891142C2C3A0BAC1220200B4EFF8C17F5D79E261128C58248
+206: 0FD4448A47B6620FE90551A9AA06DD991AB13DBD2AF18A4F17AE4A9A24D9A83E7653D5F5A2C54633C42ACCB0E5915A35
+207: AABBB8857DE60BDBB21742DE7ACF7EB8D9180D5D0AED23B7F708F09006C6FC56CE85DB87D9642CB909038E70C15C1574
+208: E1BF933A4F32AF56C929911284F9B05B79F0216EF3A150483D74B2D4DCD78885190EB1601A320150C860168221C6BA49
+209: 9074B187372B0535738D4606AA0478BECB5251EAEC961699C2795FC028D641D60230532C8F6A096FEF419A46B0DB87FC
+210: A63532A684A1851050E2861F7AB94296D131F768A94AB0019A941734E13842EBE8AB1F42DB4D0A84E261CB4707C74290
+211: DDFD64103308F0537ABD8D4F2209D8920CB42FA9ECBC93318D438C1493FE11B6134DDFF95DBE3FC6B8AA31F833E305A6
+212: 044ED56EF3129D29243665545A59FDC12412E137E1F55A543AACE511F9F86CD3202E3D24807B0FC878BA76223EDC6F42
+213: 2E470AB58A76690755AE6643D615039E767B84AE9E68480DD937913C44AC2350A27FDB45D6FADC242BD5F84809D59E2A
+214: EC0ABAC477B5AD5F6B11DB4B699283FD4668D84C2BA7F8DF90A5BF83C0E1E224623F0D2BB3F2DC6EAAC5E41436035D58
+215: 9FEBB6C1604914837F6D00F9AE23A3459DEDCFD81EF755B96A3CC1F63E4CD2E67F5AC2605E594DCD2610F4962EA6C277
+216: 3873BF1A102F1609A624F1A096E420CC459C02590600808F7DA5E3FD49F5B491269C1116A2AC74185A3105B5E9606126
+217: CD7E8C16B59BCEE5888DC7FFC28E65B72570B26F3A0C85885BBCE81E5A6B63D781F953E497399DCB506E8C4F5E237169
+218: 3D24BC91A4932BF6D631EB7698549B03E7F3930662B8527EC122FC2C7AA41E330862102557F480273864FF9B06628BB2
+219: F0B21BC919A3C6089BE3CB7CE10B55D76E31552E759F0465086A89D1FA435E2671928AC329ED7B3D7C1D7121C158BABE
+220: B32F9A1FD8A97E6E8E701371BF1A017078B26C3F4C58E342ED455B2557BDA16EAFAC00AEAC1ED7328C65D7C1E227FB83
+221: 5468F1B9192244C738EC20FA979F746CF6929FC48F69C79F43E46859AA022CC42E65203CE7CF77A039402093A1552EC0
+222: A58151FE3211C27651693B55E67CDE0E886BB0D8F2B6D9066615124CF1DA403DFA014C6F19C1B10DE7D3BBDBD0AB9880
+223: FE73FD3276463D27AE6A9F54877CD9BD3410C4A40381D25F5A915194538CA8C4F4B6154ECB9CE8B1B7E23953DC64F664
+224: 0D4EA680BA7CCBB9D88C09F6DAA6BC655BDB0B2A1C8C3DE0BE895328027794E223A45969AE594C7A21FABD5C92BA6530
+225: E6DC0E64DC804FEF91563B550A83BE7ABD50F51D3BFFA785A428EF9436775DD7E3A589793CB2717DC6BAD8B531CFC922
+226: DE168B8F03C0CE8143FD14BD2D294476FBE8DA85B09BF26C5D846E2D19957F87D6FE150B278EA4B3BCD36AE52D251FE5
+227: F34472A4DF2D3B529CE56E9D2A721A839DB05DB7B66BE8AB7202B024DEFD46ACF493973DD1FE88D8EF6E70673914DAA9
+228: 1F5E8FFB4678B3889E7FEB2288358A5F1377A97F76674A8D3E5EF39D185D02F6A1FB60E43BCC79C31E6974B37E74E50F
+229: 190AFF1D363C413BEE16C78C544AFD20678C7B1141D3917B6942E4D1486EDBCEE90EDE8A50E441219ED3B11BEFA09F18
+230: 66BB67FC2BDC1D5E8E4366958804F459AA689E04D5FCAFA8CA222656D568B23E976086E2BBAD979EA0973AAA1FADEB8A
+231: 0E14C70C02205AA29303D24D6491CC84B648EEB80AE9CC2A0997B7BB646ED32C69D2AE41C0DC007AFCEC514D7B04BCD6
+232: E38C413F3FC12764415F39A9F3638AA1204D3E818A43CF2EDD9F2CE01936D36C6720CF5BE8ABA362F92AEC81386A4800
+233: C3ED0B3697A84B388AA83DFF8EAA65F5BB12EF00315AD462F1F6D85D410D021BC32E77ADC763A254F7D9F1FB6EEEF1F3
+234: 8DC2C3F8C13C43709AAEBD408A679CEC524DA8C8F4157DA4BE551EFD687A395B33577728EB73EB498ECD0AD2487058E8
+235: 8AE817F2056903661E4EBF37D7293200D8BEE7AE0CADEA671E4987624A43712FD2C392E37C17D8E81EAEEBEE8E96653F
+236: 9A622BC18F3A09C8BC1C8603B55260BADF32AE7ABD8DCB6CDD980C5E7A5B8A38C6D287A63FE88567BB9B0481743C06D9
+237: B74C6303DDF9F0AD7CBEE923F7F7F1C7FA52C84EF609F2BBCC07B9911C12F3D1A9BD818A9F36EBB40D4B400AA4D0FDC1
+238: 5B1AD3420ED592FA3D593435CA6EBC700583AC5E3CA2876887E5F190EC2109A1E6DD06AFC6C9D7ED0E8B0272B7F9114E
+239: 2556CF077A788C49BB6D600F4A3CEE635C4443832D169F761537AFEE2980742B9F34AFBC87F598DD0AEDC4A826ED6A73
+240: D64769AD58F5A338669B935F3431E5BEF31667D0A2437BFF78F1E5275075F434FFF675F9833EA04AC4E5C2E2C2C99B8C
+241: 3264CAD70D24B53CEC95269B980DAB85A30D24CF8BDBD68F0FF8A45C6208F05723A4B3270CD095FB8B2D9A4167FB3D3B
+242: 4D564117E87700C69AFE5A4D90FF50DEF8A54A9BF19382E4290290D2BEE101355EBB2DFB2A9D6D044A6D12D6DDF7BDBE
+243: 6AAD71FA5D5D7B63FEA64D94E211155B01F8C9E4B3D86C3B9C014CA4BB6C668037C4739A082F37B2EC5FF6D85F0A58FF
+244: B36D529E55B5CF0FD3273F204F798E21DF533BE466AD1AF35EF80082132640493FD89A6CF41CA68AED066E93181A9EEA
+245: 78814E883A27D6ED3A5B122260059CC00D31B8A0E933F3C377BB99EF33F47B13B6AD825B740784BEBDD9917879C2DAEF
+246: A7978D0C79070B208F070241867476AE622EA887D26B0F6703FA8A455F411649D8919E6E12C540C59DF60CA9C05684CC
+247: BDC3E02D31DB1EB7F04CD9FB8876AA9C7CB1852BD3BD62F56E062E216BE648A34FD327B84E3B6339F44697470711F661
+248: 9135E6D4B1E2356C3DE16A85E4AF57243CF6861DFB6C53CA13D9481371AEE285B75DCCAFC1A64499F1B2CBE4A3CD82C8
+249: D1F9BAA4007BAD437509DB6F6DCA22086CB786026553244A6F480C3A6488F7E26C416C6AE85874477BB5563BA0AECF2E
+250: 49E5B7521794B6C73004BADF3D039F4185BE9BF8499FB08B9C8FDA2186B6C4BCD280AE2D2051C6775C19ECF1C776ACF6
+251: A7534C1716B59AB1C7AF3DF0AE32F22CD02A1823F61B318F36DFB536B8EF4515116A099F8DED19B00EE7B2D243539960
+252: 0F01FB323FADD9380A5E4EE6371E8BDF6FFB1F70C4D4A1B5E8BC9B281582AE0531AB354EA9F58A96568826F6172FC75C
+253: 145C9D3926904D8418B75C8D645D43AF651684AE7FAD885AB46141B9EAD2D9727731F44D5AAA0204395E020D1B52DA96
+254: F663682EF7FA3F300DFF0B4D9C0D2D126F2BBC164F3B88C8A2207C3799464ED2086CDD324C1E88DAA6EF2D53CF7C190B
+255: 98D7AC796C4CFB5D98A1C323656A4BE8AFAAAD168E5EE72B6B7A3FA3260461A043E27243120D41584B58F1AE4463121A
+256: FFDAEBFF65ED05CF400F0221C4CCFB4B2104FB6A51F87E40BE6C4309386BFDEC2892E9179B34632331A59592737DB5C5
+
+Hash: sha512
+  0: CF83E1357EEFB8BDF1542850D66D8007D620E4050B5715DC83F4A921D36CE9CE47D0D13C5D85F2B0FF8318D2877EEC2F63B931BD47417A81A538327AF927DA3E
+  1: B8244D028981D693AF7B456AF8EFA4CAD63D282E19FF14942C246E50D9351D22704A802A71C3580B6370DE4CEB293C324A8423342557D4E5C38438F0E36910EE
+  2: 80536C6170DD8626DC081AF148D39EC2FD5D090CC578A76647E7903FD34BD02E4333ECE57B0E24FF116F43429B6FF541834BD40EF0C8D3563ACEF5ED0FD254B8
+  3: 8081DA5F9C1E3D0E1AA16F604D5E5064543CFF5D7BACE2BB312252461E151B3FE0F034EA8DC1DACFF3361A892D625FBE1B614CDA265F87A473C24B0FA1D91DFD
+  4: 4EC54B09E2B209DDB9A678522BB451740C513F488CB27A0883630718571745141920036AEBDB78C0B4CD783A4A6EECC937A40C6104E427512D709A634B412F60
+  5: B7B70A0B14D7FA213C6CCD3CBFFC8BB8F8E11A85F1113B0EB26A00208F2B9B3A1DD4AAF39962861E16AB062274342A1CE1F9DBA3654F36FC338245589F296C28
+  6: 2F3831BCCC94CF061BCFA5F8C23C1429D26E3BC6B76EDAD93D9025CB91C903AF6CF9C935DC37193C04C2C66E7D9DE17C358284418218AFEA2160147AAA912F4C
+  7: B7C0B47F42F7202BF7D28D6834BEE365FC01CE3F0C8C8DF24B4D940406C2E9C230BA88854E946EBCD786C18C748969FDF012362B7C96400604B6058950FEAAD4
+  8: 8A414C5860CF1BE7BC8531442F69A65EF2ECF0B7CAD9994BCB407097EB74CCB92E93AABD24BDE60331123B4D900684CA7BE6027099D4946BF537F4D6C6DF3D82
+  9: 8B5E5E7FB6530CCE1BFFFD1B1AA338D3282E8483319BF028BB674BB6AEB8200DA389647E3D8631503DC5C487BBFA7D074584493615B036849E0242610EA4758F
+ 10: 0F89EE1FCB7B0A4F7809D1267A029719004C5A5E5EC323A7C3523A20974F9A3F202F56FADBA4CD9E8D654AB9F2E96DC5C795EA176FA20EDE8D854C342F903533
+ 11: 8FFAEE0CCCC162851FAF051AE38667EEFD423C0164C50055F8ADE00AFC3705E3CDEB9900004B0E426CA66AB63AA3B99B075273F44FD37C22A3555C6FD1F37CCB
+ 12: BA51B2A9DA2F26FE81FC3EE11524255937EC6BEC48835EB437C598C55674E15AA50F88922DE7584332A5E4D24787090CB14DFC3ABDB39C55AEDF6EE108F95354
+ 13: B6E30A4016029486F9205C5D141344F885B3DE2468EDFB0B870545F1775CE82597C2A40462F385C957790C20822D9E920EF1AE230878D6B23F221B0182879CCC
+ 14: 79D76024A31CDBE54CA951D264C46E78F6F5AC5DCD018BAF89AA586333BE82B2D5CA2BC64B99CA2A99D95A984F2DC0D6C07E7C96059DD346BB3296ADE3AA33C0
+ 15: 4236736D08F26244E75B51614091CC2C2907D5DD162F8497B14D58D0D954A777C8397549BEE468F30E480252D9B893175DF7D2BF415A128CCC79407D9D5FA536
+ 16: DAA295BEED4E2EE94C24015B56AF626B4F21EF9F44F2B3D40FC41C90900A6BF1B4867C43C57CDA54D1B6FD4869B3F23CED5E0BA3C05D0B1680DF4EC7D0762403
+ 17: 7B9AE840AAB8BEE45B038CE398D15A8679DB92D0BA46FA67D1B8177986E41EACDE915C6552FC2AF8678425B8BE81B57E0F7EEADCC93B56C58DFC38B4D33BF25D
+ 18: 0EF6A8C19E19A466DBA3139E2A401175BEB9EE01FB56A8FC11A3E53B345F2327959F6DAACF0CE6121987D2491251DCF550C95F6026F93A1D96A0F4164CB1C642
+ 19: D6221AACC88CE14EB7DE0F15F2260EBF4294D9AC3D75B87465EF7AF9570C959077860EBBC5C8153000507CE1E39AED5D007F2286210EFFD26A118966ED15C143
+ 20: C9AC4561A7503FAB9C6B71C843AF6911438550BCDF4881EEC18DDA06E4D8B820CCA9521DFA9EF47298CCF6308FE4C4F2F5E34DFEC2ACB78FBDC04D2EF0A5A09E
+ 21: 73C5D58B05E1E6FCE4299F8D9294681416BC3785F51E402DCEDC0E30C0671DD48321A0248CCC13389A012B52513F1B5BBF820E91EB4F616928183485B4F1EB22
+ 22: AB1725C57427DDF93B34AAC62C26F3FF1E49CAD30DD41AE7B5FCE23894245E7E889E0FCA5EC076F247DC7E929D72FB965B45688E57D8CD54212714A17480BE0E
+ 23: 456F6757A82F0589040996BF88F28E61317C358135A9AB6E96E22F5CA68E2A6438D13D176B01157ACA1FEEDCE3C1A6D5C3A9B1D5A471691917392FB94D0834F7
+ 24: 5330241E6F01A49B21AB0D01A9C76AD662E97A325BF8E24C4EB82C6F3B7D2538ADD98F62307F36F900F3934861B80FC9844B761BE15460A1B102C26CF0410E83
+ 25: D8DDA603DC21C20A6DD3C6A4F380C297679F035D27BBA82554D02E1F95ECA2EB20496164F96DC4B84B9BB0942B96A3796AFF6125BB9E8711E2674B440176E91A
+ 26: 81E5A3AF460DD2881353D006AF37478C58AFFF16022441226FB04439783DA920D09FD03E19F45BC82F82735FBF4F2E5F588F11AFDB87B69DB91123CBF05F7F2F
+ 27: 25AECF7D241EE54E668DDD345582DB777F9F631B9D2432CE4D32119BEA3968D9FA3E184B135364DF62247AB74BA7B86AC3542F63D9F18653D86B9B47944AB96A
+ 28: 8A372F722A922E29CF5CB22BDABC6D284364F376DA355CA65BE36DAE2FA6F0335744CEFA9089DE55D331AE64E9B2F1037E73608B03B978758A20A012924AB235
+ 29: D57C54ABB87AD2D518790B81230DA336F551A0D89A57D0A3CFE2F4ACC55B4B210261CD1482BC436F62D3FC96D1536B82A2E93E9A3DB5CD0F1822EEACF307460C
+ 30: 6092F1E76F04A5926F6FCD149B18DC9DBE8581BDE6D2A1468145280463472B636C711FF61F5CCA84FD2F044697BD1DD18340B3ED0A131F4BBA35F839A2DD9E0B
+ 31: 0674A3CDF5F7C18C1B7524C87C36037F3D0267512D11E052F453DBC097CFD52BC331950880CF904656C70758B2E25E21FE2C7E0462E861112A2DC9D0636BBAFC
+ 32: 3D94EEA49C580AEF816935762BE049559D6D1440DEDE12E6A125F1841FFF8E6FA9D71862A3E5746B571BE3D187B0041046F52EBD850C7CBD5FDE8EE38473B649
+ 33: 301F1CD7B25B097AE4C79A97E92BCE359D1289F6754E76B71E7617A06E7783A3CC30F5290209BDA3E6AF239D0DC0F3D1CD4C5E866F4C5C3209EABBD7AAFB8058
+ 34: A8C7114B292CC6F46D73824CB073CAEB23EB1ED5EBB37F064A0A76AD452D936D1DF41433FFA337C3F7CD53F5CC00658ED0633252B69DE192E61D9F002B0F133D
+ 35: D2F92068E07C9AD0572693CF546FE75070E574807C02F5483A31B8CB2105CA55CC6AADAAFE74977F581CE90F43E2AB48260BD7E273D4A83C442EC4871CD88AAC
+ 36: 1A4133CDFA6CC518387D392814029744D6FA71122EBDFB70059512B89469CDB9D9B5E45900E99E67DBA54B4708036298A94835751EF583149F06AB272B2BA355
+ 37: D30DE790B4905717C956A95F60D9ED5948F9E509BA27607E1C5C8FFE35ACD83F719AE04D63364C0BCB72BA529AC79C321ADDFBF7AECF7CA3CAC840A372E6F6CB
+ 38: A25F5D4BFFBC5F0E3D5CACC3A91870866D8C2D22573556C9B9FA0D24E1D68C55EB42726B1895DF8E5E870DA33755DDBBAC130AF2D96D84DD0D57761D25FDB64F
+ 39: F44001A74D0B087AF2A143B778DCDEC1554BCE5992C9672E3D0F6704D022CA1E78F087543569CB99D249B820E683138A2DDC5DC178D585167FDD269D17396A89
+ 40: 692F36EB114060FD04CD38555025251DF985DDF681A0636FBD290EFEA6FCAC5226859373F3E10E8CB07AB5343547EB0A543C18420D70527D2BBD90040F8DAA52
+ 41: 4B1CEF875A025624398CD06DB876EF9AB34FDB1B6A75A07CCB591D9B20EA66E24BAF323911B5CE8B67904945A36C28630B36129939D23D26218610CB049D7AED
+ 42: DB3E80F11517AB797265829371F245A7A0A384E36A8D43E72852C8D47F8CE37A178475EEF44CE8BDEE5AB054F47EED502E76D49B9F4A5AA392077ED1E6F43EC1
+ 43: BD08551AEA7759911B37E9D45748219B47C4EC17A2D2A306D9B8FDF982A9E3106BDC1ACF3F47D383B6D16E85910BBA08128E35EE578E7C55F2E9B9B59F611298
+ 44: 3BD8A709DB9A4E0B874B113564B11EAF8270AD1DA3A9236DBB16F58F43285070344962394C2231B3917401924A3F688150B9A9ED3B410547DE3F56450739592C
+ 45: D0206C8577202C617592B47AE178DA867AC7DAAE4E65B912C771C5FB09585FBD10C36782064E83ACE749BE27045508D544532B628F67DF00A6B7DBA9775D3E06
+ 46: 745083E5994158A0FEE4D849012F43A822D19F068AFB327B372A7A8BFE8347E579DD29424EC95319BF75A24B4DB4280D9C16CEBFF5D930D61D34909061A478AE
+ 47: 3527A5E1E5E5953EC57F309C6513C34405531603372BA0DFD5725E68B9510E5090CC6B317B2E7359D2ABD5ADD353AE1435B85535EB5B0B8F2E09D4DD1BAF3C8B
+ 48: 622BE417916F1B0E9CE8C952171B11B6D2E2932D6197CC17431B9FFDF03FD0ADB69B08DEDAEBDD0F94812BC2C670C894D65165B31D2F2879532F2C14453E6A0E
+ 49: C2EBDADE0368F1DEBE44F8E1B77E66BC1C25E7F0FCED7784D615811E2C01192DBC21253E10709D0BEEE746DE6EF93CF65AA39BA29551E11F602ADDD27B196019
+ 50: 5ACE0640F0DCB25871E1925F96BAB48162D692BA134C9C7052A37FDFA4895B90AC56C7FB0E7FAF155D147A467839500D980E9D4ED1CC96661177ACF0BA8D4167
+ 51: 5D43600C04E52BF6524CDCB9DAD89B1C7563912E7C7E2CA3D34B27B3C1D07D85D35EBB7A65AF0434155AFA3102A580AD557468CC23EEA1E151BFD4EA817FC5B2
+ 52: 38D7538AC3E51DDFB6724F57B29A5E46D15A8C08FB29D15FB0681A4315B03FD6747B85D0EB2B9E5FCEC709F365DE08D61A1EB363094BF292B5154671D15D61DA
+ 53: 2DCE13E5882A31F7396D970AE72E89FB59270D78BF7B4579D0855C4E8BA231D23E5566B77E79CCDC1146762DAAA74F49D82F9EFC0D4FCA891E78F9FF86C61300
+ 54: 6D7644DB575C5C238DA02CC4259996CF163A3A3B5ECCC4FC62442DDF01AA05EF0C4EDBE3E6D220DF189C984AA55726A4922EFE004832F2D8887F0B8A9267DB40
+ 55: 6856647F269C2EE3D8128F0B25427659D880641EF343300DD3CD4679168F58D6527FDA70B4EBC854E2065E172B7D58C1536992C0810599259BA84A2B40C65414
+ 56: 8B12B2F6FE400A51D29656E2B8C42A1BBFE6FCF3E425DA430DB05D1A2DDA14790DEE20FA8B22D8762AFFFE4988A5C98A4430D22A17E41E23D90FA61AB75671A9
+ 57: 92CB9F2E4EEE07C7B32B06CF4917FBE54365F55247CC9B5BC4478D9FADA52B07D1C302B3959D0CA9A75A629653EA7C245A8FBBA2A265CDA4EA70AC5A860A6F3D
+ 58: 23417F93C499DF9EAAF1BFD6A62AADBC711BFE56682943DE5D94E0DAC32F732B763BE28C32AD5F01CB95E5B322AEFF8494B111D7CD8BAB50E7C602695EA6FE42
+ 59: 4ADFA8837BB499605D38716F8305FD50255DEA2EC4BF3EEB07560B3C93B5E3725C5A598277A32502CD5C8AF6C88D55756DEB03B69CFC278FFE2BFB3CA202B0F6
+ 60: 981A245B249111B4CDCD565AE60C9DEB69FDB552B10C932E8D0635685904203C37CC65D674292405DF24A589682B8AA69BD0E16F666652290BD79AC10E3A9B37
+ 61: 15DDF1E434A88F27DEDB8435ED837FE4F1F3BFC5B6FD387A98E93D1C83493D326467C7C53EFEEF158F6B9CC2081267D9761A32A5094399754C0FD62F4C72371A
+ 62: E08026874830E0B911F5CC51B81599A4DC21204F5C9381CB5A0DA8F452EE99D9FF7590B798805C2743822572E6D2E47C2C1F2D428EF3C28D05297BEDC5CAC4EF
+ 63: 9DC9C5598E55DC42955695320839788E353F1D7F6BA74DF74C80A8A52F463C0697F57F68835D1418F4CE9B6530CD79BD0F4C6F7E13C93FEB1218C0B65C2C0561
+ 64: EE4320EBAF3FDB4F2C832B137200C08E235E0FA7BBD0EB1740C7063BA8A0D151DA77E003398E1714A955D475B05E3E950B639503B452EC185DE4229BC4873949
+ 65: 02856CEF735F9ACEC6B9E33F0FBC8F9804D2AA54187F382B8AE842E5D3696C07459AAD2A5AED25EA5E117EB1C7BA35DA6A7A8ADCE9E6AFE3AD79E9FA42D5BBA8
+ 66: 371DDB96ED5BE6521379457AE8ADD707A866732B629EE00074904D73858F3FAE827D84E503F3779073490B274E29D644D76154FAB18945222289BCA798BA6438
+ 67: 96A693A22256D39A0596802319CB7AF997DB4BFE311577E38F8423DE81C567A96775D063471438F0982EFAA6B75B4AB173D9D3B3D4762030B522FA70DCF3B27A
+ 68: 7D8AB6155AB31F29740042D82788A69E880FC642E600BEDFC89098B9D2F4F98BC11141FD420870958810295100DE66F50C96E1E4F6489DE98F9BF2D4A9AA2237
+ 69: CE561F8F679B4EEB1DC97DB0F72632B9DA1C5B5C0292CBF0662CAD981374BF8C9A0BE1355657FB18196F980E6685D52FE601DD45C6B0FBDE7AA5C9D52E7E5973
+ 70: 10164CFD162CABC44C56D76D369096D759954074B0547FA7310C3388F0FB6BB2AA295FAF1E22C44CF59959A37EFE317698BC29AA718D57EBC831A14144F4E48F
+ 71: 658B337A8FA873C73AE4D19992BBAAD10E1325AFB4DC8B5733F870761429B4243A7982AB375E529C1FBE6339A48F9FB9E8FD6A568F9CAFE640E102B9F398A330
+ 72: 4EBDFA0E60E1A3E7FEFB8DB424A5C3A52365F325EC7F51389A4955EE3453BBFC94692DEAC3FF6A4E94105C27D632DF26250FF37314C882FDEB65D53534F8A961
+ 73: DFE9D2A6B0AD5DA802D695B3B91745852C97B0283D9A033F04D79D2CAD4FDE50048AC7D82BCF8C402B109E785D39FC9FA0203F7CFC620EE43577688BCF3E69BF
+ 74: F21869E1EAC3774F3878570AF0DB9A94F464373C1A92E097D180A331C9028A18A68BF4624D8E620B2216B03709F03FB6CD10004F77433ED605B0F771161145C5
+ 75: F1F928D322E6852301AD6FC901E91F2156A3CEEFA204044DDA3B4B76A63692DAAC479FFC6D83EEE3BE028A1F651D3520758DD395A1B251E6C261B7CCE86D0481
+ 76: 37954BB11B0AAA67F803973DDD2709A73B947D0A5FF8DC46C2D3C6918C87069AD0DF907589F3026A94B071E0F00230F00CF74AFE8010C24E489CC8AF9B8BD646
+ 77: 140DB04BF46A194E44F07F6ACEE8326573AA0591F8370A79DF320093C45764A2ABAE531E5A742F496544657FADFEDB7F04D4BD74C347AAE237B5EE59921BA87D
+ 78: 6D0D30BE796B6E1039739BF24CE26D8DB954D25813F8D7F7444617816F93FC7488B71C69D96D77C65007EF6A2BA313AE0739302395F3D9EAB0244E372AB96961
+ 79: 2B92E0D915BC7D56215651BC9F769544C55E2A27080EE726AB14FAC0A43AC51CD378EEA356DFA70EEC3C9146E08E98358C61FFFA3D477CCAC35FD6724A44C23C
+ 80: 2CED9E743D84F8EC5664A99C6DE2238464E61129B3C856A7FD2CE08B185F4D447A829F287870AC5428114A7234E41A78801C19EA5C6246FEFF961DC6A9B55835
+ 81: 4462303D052C70DE76296234B72BFF1AF173E7B63D1CC0E26C518D103BF3BA78D9AF4BA88013192CBADAD83801B8FC29D0838A144AA3CB721AC859EEABF019C0
+ 82: 880FEF79B74C109F030F3FA6FCB82DCA034528CCA68A23ED1EE4133C10B3E443434A37C436F079F3F3A922A8547549A39854120723791519DBC166936C239AA3
+ 83: 12DE996C9DCE152C83BE6C0E69C66633FC4244B412066A5FE7CEAE27BD4A109FEC95332C60E87DF08A1C714D9D2ECF28A8A81F1CDF8BB3CD2CEF71011BF5A5DC
+ 84: 748405D18FC05F0AF7F61E0CCDDEFD8055D86826038C77F2AB230F7D97C89D0EF09CE82C4352A7491729C9FD704B279449D0DD7D86CD2FA52EB3B5A582DC2057
+ 85: 746653CDC44B4C86B29DE5B28254BE9198C0271249F0690615B05F23AC0456DD66CDDD13D2F22924DF530C78FDFD3699E38E29A550E2739A803FD1FFBEB29E59
+ 86: CED0B3E4011A6DA0415C51E37996EBBC5041861FD1584E3D948E1D4DBD7F8673EF93910A10797490DD5C62245EE7EC03D7CE8B8C38FAE21EFAC1AE6056AED143
+ 87: FD4BE7DCAC6984196FABA1D88D0FFA9F33CAA29FBAB3E38CD3DDA7FBD94866C944F91B405B3EC613044E4AF11BE7187B15D5AFB4067C54FA09215C3BAC4FF080
+ 88: 46836D5A579D5158B9F49D6EBE9A43C9F4A55C768869C3D542BB615FDBAEC8DD34FFCC40288567F8C5E9363852EFF44FEF0EFC0904BE178D3F78EA1B61B9E98A
+ 89: C05B8745D68BB9647E411E5AA1F924C2C9B96E7DDE71D190A3B8709ACC2856ABFF3C2DBD7093B25F81C6B9883D377E721968632FA4D566F7F72E1109BDEF2D74
+ 90: 647A0E15CC4BB5EB3333919CC828D68C5352F1FCACE6964F23FCEB46D0D2408AE896D3319B202EC687F3F9E55126C05705FDB909CD8CAC88304A61B69ABCF65C
+ 91: 2DD1C321E3CFB58C2E883F5DC3D87F01936ABAB3F1F27648B6AE563333E3852BCCBBCBF4822230E8F0A0DFE32AB6D8DE92A2B8B2271E17DEBEEBF00D83046B75
+ 92: 38122D8324807E25DC8A74012CA9C0292222604303CE8B66D7329FEA394D85B7BFBE0F656895EBFD26BD60A3B553A6E3E4003276157B31B3A47779E1633D89D9
+ 93: 27FFBA5DD09485E141B659E218D2924AB0392163CDE296D4109F3AEFCDB02241CF0952F0A38E2680D5CFA35363391A324E12519B58C04E8ADF0E9C7A8B6E1712
+ 94: 69DA55F3BDBB1C7397CB382B7E8075F615794F6F8453313C0933D33656A3BAB07C42FF977850625B11CA302494497B0EF3A51F3D2EC2E4AECD24BBBC661C6513
+ 95: EE1270F6FE6223C19AD4814F0549B54C11AE7B43A8F3418B0F7BAC42BB5B093024DD4F3AB0C9AF5FD2025D50D5B8DC3505D8F754F98AC3237344A7C14FA50815
+ 96: AD8ED48E056378B1AFCDC0B3D5D3936AC825F96ABE0953E9BB85B00EC16084A4F0BF12A2B0B73F0A29ECB9841A1DC7F003456016203E891ABA1BEE13FFD19BF0
+ 97: F6EB6972CB5FB156FA20A93D8695AE1D9DA8BBDECCADBA81123E7ECBE917596B51E4A6CF9E1458D882B76B33AEA8F3286CC7CA1085F09EB3DB9B9263095339A5
+ 98: 40C54D468FE760A7094726B9EF12A98A1F0FE5E7112137ECFB3A88DB04B0758EC581603EFDE3610B1D76AA879EC31933CB6AAFA2DFC559C59BA31425B091FFB1
+ 99: DD0324C4DCFF798F024A32A13063A05AF673CB5F8F03E08A0D931406C868A86B5071BA711F6DA80D7FD2F7D3CEE1B7DC12EA456A1EBE4CBCB25ABFB27492390E
+100: AF216A7122D29D6A7DC7B89C8B41C111E7C9A00781D4A867A1D75110B48A5A9C92A15D1DC2AEABB53B83BCFFC50F44CFDCAE29DC9984C8C84FEBD0189322BE25
+101: 1FD96E1905B024D5FA883B3BF76C00A0235EE6386EABAE4D9602B5C5E5EA81FE3A1DD0D81BFB0F904ABD4DA7FC71EF7A2BBD0DC6A766902021CEB03D2578B204
+102: 31B75B047B1214B915EC56983E284D14C214D567F149EB467A1A324080AA0D80264ED771E2F91104B2642E9A8312C0C001652CF4E55308A870A77ACFA088D7C0
+103: 59B8D11078C8B65C5DF4F39D1C532BDB9C6E8F2EF121B97DC5BBC29CAF76774A7DDCDCE0F3BCCFFD4779E57D9B23102EF596B8B940480079355CDCF7EC52D47C
+104: 3F1702458BA7F28460E84A032BA160430126221AB5320AE028387B60AC53DEBC42FD169A23714AAC3009D52BF9F9485C0878C06A98BB42D1568E7D038234AD23
+105: C8DA7ABB93D370CE8BA6F2B58F91ABBF1302F96799544CCABF52D5D1EAC3318AD4EC853EDC99CF86DF9341D6D794B57B68CD1FBC5E37C03AA10297F9828D5D0B
+106: E1680FAF315911FB7588AA2F02D5F96A3FB02F60DC3C93117B97E4F00E2CE6862DB06117A6627B14B11B9E4C61BBEEF09134E1684599A370C61721A3B086942B
+107: BAEE728FD37CBE1DAB3FD5A922E58111BFBA9BB47E107909FBDEECCB1812DE27D2D87003FC6F9F67977ED592EBFC734470CD1E907858F555F21EAFD6E64F060D
+108: 891AFA38F3094E487BADAEBA012F11D3109EF19B858394EECA4C7F0C2E8FFBB3B88A7105C7D73E7252E67BBA518ABB6A312A7B8A11742D31BF53267CF3B09E5B
+109: 6E6E3BE3956224A97F813DE55B3594EC5E2F4A43BAB873D902025699AE58FB43DB71DE1DC159E83F7A7EFFC19CA5A03C1EFFD27B026EE9AAAD92D1D58104D3DC
+110: 51F2BA331C24541EFEC042CC66398D388348C4FEDC3F77A4DDFDA39752AE2880C68E0465C15B07ABFD93E16BA635AE7CA7D7E144018ADE57607DE8643992F50B
+111: A1A111449B198D9B1F538BAD7F3FC1022B3A5B1A5E90A0BC860DE8512746CBC31599E6C834DE3A3235327AF0B51FF57BF7ACF1974A73014D9C3953812EDC7C8D
+112: C5FBD731D19D2AE1180F001BE72C2C1AABA1D7B094B3748880E24593B8E117A750E11C1BD867CC2F96DACE8C8B74ABD2D5C4F236BE444E77D30D1916174070B9
+113: 61B2E77DB697DFE5571FFF3ED06BD60C41E1E7B7C08A80DE01CB16526D9A9A52D690DFBE792278A60F6E2B4C57A97C729773F26E258D2393890C985D645F6715
+114: C02CCA2EE8BED9B4AC74438D4E8B39619347922DDA5CAD2BC3EB9E4CFD4FAF7CC7EB9F6B21ECCA2C55CB60D11EC450390EBCFBA18312E49598D2BC52020DA9F4
+115: E528ABD6C315EADE09A981E4861F6148C9DD4F2FCE0EA54CD3E9796F17033A3751FE9A223AA23CDE0E051A10C2BC27C0298BE97CB87C7110667A115B6D30657C
+116: 1B0BF23602D272A06BEC3E86FC675E16DFB067B2AB662181315C45733D191137454BA22713B51478B096DC51D3FC7E9730504324655AE8B7BDFC184118933D36
+117: 12D5EBC3016C77ADCD01F1DE3F792C4230DE67C0B50102E03FBF3B6B80BF913CB66C3E72530C644719003DB2FCB15196803812D89761E0B781E8AFED7268A35D
+118: A3527C4E62349394274FB15B30BD95FAC27472E1E521514775D2E667A5480C5367DA6EE526AAC8D0D1226C33EDA1358091C93EC6B1B8464739D25AC4795EF175
+119: 43E497279C2CE805903A33B54B746EA92D607F7C4807986C849823B81097A9099B5896AC7CC66DF3A93EDC8A91B6F3971D6C7F5688DAF635737760BD080E27B3
+120: 9636708964C5FF6600510319E07BF3FCFCB1F4058FEC278EFB677964BA1E140C1632505452F802E99BCF09DA3D456DC3868D149A0788A730E49D239CE7415145
+121: D5D17F592D401CB111FA7C34CF5035BC08EF6B2E0D3E64DDAB08430DEEFC8B9C09C20EB4E8F98D8EBCAC6F09AA2C1DBB7C1B3B2EFE792377CA6600F703643700
+122: 0EA053BBE2E72264AE4F54512C621C733120F777D3CF8FCD8A7CC1ABCAECFB9BE93EE821A15D19467D249A27961E474ABFC433B8C7132321198789D5C2A50896
+123: C64291C217E37E754F6F57C1316FCD8A7C2AC2426E86786FFB69797C0645848CAC41DE345FF90B72FCDE918B7CFAEA4D661687E6F737A088E9296EEF4C3B4F31
+124: DEF8A3CD4921127815F4D1650FBF8B3EF16EF724A38045133749B7359FA68BDE3EEBC9CB5190FB6720EE3D24473286FC046DE0646C6C0042EA1968B48FB6BFBD
+125: 6F3581DF30AF789E44C7459356E1C248749B4A5A389759DFF37826BD278D293BA2264BB808A71C453E22A2962DD33A9C03338AD060B3783713EBA8CC8B43E2C2
+126: 2681BF910DDFA680B7204037294D00D0FCAEE84A3747F6E302A16704B3B08EFBDA0E57DBB8E61E92348C8D5FC5A59EAB74C77949A74C7740C30412A9FC65BF34
+127: EAB89674FEAA34E27AEBEEFF3C0A4D70070BB872D5E9F186CF1DBBDEE517B6E35724D629FF025A5B07185E911ADA7E3C8ACF830AA0E4F71777BD2D44F504F7F0
+128: 1DFFD5E3ADB71D45D2245939665521AE001A317A03720A45732BA1900CA3B8351FC5C9B4CA513EBA6F80BC7B1D1FDAD4ABD13491CB824D61B08D8C0E1561B3F7
+129: 1D9DA57FBBDAB09AFB3506AB2D223D06109D65C1C8AD197F50138F714BC4C3F2FE5787922639C680ACAD1C651F955990425954CE2CBA0C5CC83F2667D878EB0F
+130: 90272B89212C81B9700897F611F13AC1D291C33A437000C1423336B4D962DD39CE23413160F023963E12F4CCF90D2762B31BFC6818EF865E8A7CBF918A94C1DB
+131: 325638D30C9F63D7CDBAA689B7AF8D23826BFE8593B361C7042D3293926146C65C2D6092F20DB5068262359860B3E3D502B6034B9EC8E7253A1FBE4B2007B77C
+132: A3FEEC20C69CDAF1936795AEB9052DC525A26F5559045FE458D4B24697E260BDAA45BE8C940A06AE39FDC1F9365F32BAD7DE824FE7722A444E469C7BC198B7C1
+133: 3F80B7BFBFC9D45073FDC2ED93F7C19F01E4D49CB912BD2568F248561F9C9ED1B6762270033D9F421C977F8BB8B4A73F9A99D580C0245DD4F64AD35D68C9847E
+134: C292EF04844CD7C3E477C2C2FDDEF46FCEF97E5DEA7955FD4F418C7B4114BA0CA2CA230D0F73A585EAAAEA9277D72B83DB74AC5E887439A225C105B0BFB5A38D
+135: 9F0DDAB7986DA54E65EF6B536BB4F7BFF468E0F310803DE28D3908492343E4CAA855B8CAC7409E3A8928E63B9C5D1CAEA7A408ED061809DBAE1AB1A67BA1B926
+136: C58867D309CA48AF74B4D7E49ECED514C89FD433F9DD842F9B50FFAA6C7810BEF35348D00D26DCBE28122BA1CE33D4CD00D09BA76F982A598B8F65790368AE59
+137: C8B1D6B4778932BC21EDDBBE4E48F7711D7E97ED5354DCF11BE98E3110510FB007948C288FD2F7AA71B2E41C86330DBBCA2ED472D15B444828C6DF4282815879
+138: F1C0C057C974E4C27E497EEF52A02963D5957EA02C7E1CFE06423048799AAF74475732A7352220A914BF32EBA6A0B6FF28C77D25CC3CA1AFBDA89870F4EB55D7
+139: 092E121F2C7A2621AA36AA9B040EFE4435DD649E3F336BA82788D57B9B164184F5B5BA644DB4076B46FF9F3A6B9F58D775CE94FEB648A372D960471A663B74E1
+140: 406A5382E9A563E60FDE5CC47F52C6DB86CEE271BD3974AC6E274A1B8C5A7EB369A9B7CD312C301F891D4E3A601A80B9CA06303C53CABD5D3B7834DBC5108470
+141: B2D3EFC2390CF7A1093B93C52B76D0DD74BC277F3D67A85F41635F89E923AEBC960B2BDF8A13860CF3083AC3FBA13D4FE5E426F144FC988554E89ED7A0324748
+142: F1F7100636AEEEC8AE93A2CAF1F4852F192E1EC1AF13697765CACE58FB40B9D9AFC3BBE7E52EDCE649F53C1BAF653CA20E75D3E4AD549D05EB33A68DD11E1898
+143: DB604416DFD0A7DC509DBD2C83D5FEDE5E31D641EE6C14390CF599CDC7D841660AC700D3DE4BE35E07006B724B7DD1BAA21EFC3CA6D346B3B858384FF691F913
+144: 87AE00E496649511C3BF947A65805ADB5D237AE8486CBFF01EBE52D5D5062A99DB3434EC22A37DFDB4CBA1A59AF1FA5825EE3DB2A8524BDEAE07F3264989B85A
+145: F442BB697D498F2026FA2A5FFFF9AC5ACA0052F6D200E10805104D91BDFC71A3764CE0277009229B9E7C945222BD7C9085163987E4CED02ACC7420A96B0F9587
+146: 1061588877909CAABFA37D4915EEBD6E517B8D3EFD5660F872019050B3C1465F11FC9B44E72610219F3F5F21772933F101D9D58B5C5F79FD7457F95749BF11D5
+147: FBB4C9BD6821A04CF154DCC7A7507A2C655739F3636B69E8183418E2C33D951DE6BFDF2C3CA603694C44DE44057665EA4835281A2773CB8A84965BE02DF1F3E2
+148: 08D54B05F901FE95EA5B56BA19DF9120C66AD004F98BF8FCBDA9DA0874E64978EFC34877B8224A024DE12D7B926B5D83068E8A704EEF0F738A5061E5F8462F54
+149: B79F53A5117503B5A0316F801B8D448079F38CB90CC39BAFD4DFE169E3C931D622AF7E26835C9AD4DB25C0D6A684E7DAC4B88B475663E05601A99EE9FC8922EC
+150: 2209CF6BA43F61D7E579651EBBA0890686A9CDC1E045255494DB0BC732C9512ACBF72158D5738FF63B500AADCCBA000D25A521D41AB4EE6D92D38E8077B79C07
+151: 8236F7CFFA68B49BE5C38A7A1BB67B745430D1511A08EF347383C32AAE1EF4AB2E7F63A20C9D8E5CF2198B32B7BC79B470D36BDF12E7263D669FA4AB8605B75F
+152: 228BEFE5788090066D493CF87F75C666BC3C75E0B7BC63E80D38340CF9176251C6E185992B244D4A5B1CECFA42128DAE6EC3ED535AFF039769E364048C442DCF
+153: 59171D498BF80731E2E35D0A32DA356419E69B8BAA5B1195D690CD8A5B11542087A007D8DE3FD000BFB03A0408C08E92A0C7712924373FD67A65218E4A4E0F68
+154: 4F94A8F6A136E49069C88DFDEA9361B34D68FFC25724F836CCB021BDB74E0AEE9DDFE80B938A5C12B01F0F1CC49C500FE7709C2090F809D9E0256FC93D93122F
+155: DE5E17A668F75866262BBB2089C9DD86775100C77974161DF46BE02A9578855E7C81C77263105C473FD1A2D55483063970C0F643CB25AA4B4AB45A40888F61FB
+156: 3314001C825DFD2CD1CE08C746F0BE5C451027F0FAA401431AC84FAEA51553EFD9E0646FB7E9B94CBC672DC98FE9870467C176AA648EC72BF61334B13E479E4E
+157: 3EE80B1422E3572B46F7CE5841998BD2B6DF3B591FB5E46851B4D54BF572A17DB5963A04EC6AB98BA07C943475AC088B4D201AFD684F30F45C8037400A7C9510
+158: 3743FE18BD6AEF36887EAB7BEBCE36D5D3B69DFC306B58B1E8C6241E81A9D38425BA991A29C3B07D4F4B9C5CC762B2563C9E5A05B199CEA5833D9FA0062D161A
+159: 7F9F71B086CC6D6B63052767CCD6D0349C076289F63483241CE105076B7549B3187897D45D7B5FB2147E54F056530347A1F9265E6F37953B5941272A29E2FAC6
+160: E09CBBFD3DDBB24755CBE8E51C8BFF1BFF36E571EE72E6C99DDA6D507AFE3C562D437E8612B50859AD5CD608424DBE625E0162E6CB7B838F20E7B2F93F40ED91
+161: 2E2F91BD5FEB5C79E98ED97C513E17D2D97B02A844780A0190264773C3040A2CF07FCB0E6424B7A0E88C221BA3824C1906FC1647AB40DC13E2D0CC507CBB6BCE
+162: 8D4E87F66B3418105CD5583A92A2D2EBE8824E1F9150CB872FD3DA9C93D382C08065C818E1AF9B25875B142E70676D9A525D901EA2142E42D813A221D21EAEF5
+163: 0518E420BB5680B74367F8CFCF7DD32F3AAE009A0067FEC22456CEAD0832BDC2A60D8AA7B0A2FDCB9072C0F1171772BB665C0B28CD184609F63AD53F89597F9C
+164: 247197FBCBEE77B8EAF6358F71A49D784CB43FB44D99910B0599E69B29E31C4019E830F322D5A7117A996BDB4D91E5CF323DB354E902E4DAEE8057B3F78ED5B7
+165: 35A7D806AF0C8167D1505B25EDB565E931864C453BF60AD7B6695035D7584E7714E21F377B35A5F3A69878835617B951977C209F5F3C5967B7DD9BEAA75A7CAB
+166: CA9B60EA8DA2D0BBF46742E31AE882F5355688B071883F690AE775C4D949DED8077170F26E89A18CFC251662EA8D1FF43F5A5F28E3FB41ADD741AD2E28341A79
+167: A861DC64C745B0F5D3EFB2773C51981A836024BC420B1FCC564E03006163B491126AD8633FADB6DFCB25C2EF92FD82823FE2C7F1161A78C7766B5E21F96BACB8
+168: 1EE6CA0866F227B27678326FEDA4CBF59934AB0EA2E874E9EA233AA5C67141A05C1B4C950044BB6C9B9D146520C2E3779AE44187BE0DC1CC41FA7F72500B249E
+169: DA1032057A25DA7EF987A2D7CF28B927D3DBD956979679F5A6BF4EA20FE1080BD8AF2DC8B1C7E236E7601BD82CFD64DFCA7D03A03087475ADD57EADFFEC2CA85
+170: 22E41325474C7C7EE980314D7738947E9CE3A970B2D28BCD69D545D5E795ED50A5A1839021645D000CD4779E181A65974171C15B9B08B349205B87C150688839
+171: 5FC5AD1B8B7622C4D17CCE23679FC7E0CCEBA00C1FD7178245206F866A6BB198F26A05A3D429E2C508DAAC6D0F698FAE6C0DE7FF971EACEEE84813110672F3AB
+172: 2264F674AFC9743A46180CE4E4AA6A2BB33D6BF2F62AA14648179400806D718DEE8FE57DA48D88DF5D57B42087BB2FA62F833BFF87B6678606C6336CBCF34B3F
+173: 65E9D1187801C74FC23C4F19698F6B93405C681B93A80D23D427D9F2CBFE63F7E2959B2AAD6CD7EF6E987A5FFD585E1BE8E314A1D502FAE80215C5331F8FFC2B
+174: E0436B17C2BB096B08698F4CB448287D69322C34814776E0B1B21486A2D5B6906889A5B198FDDF699AB285BDF58783DE7913075F86ADA977DD35FD09AF336E21
+175: 857BE6485722B4BE445B72C7A15A1D0BEE6C7FB2AD541C2B4F0035DFA1EEAA10D4F0BA5A124F985DEFA53D0A0554BB258B2832BC2CB5B7787D812E96A55A93DC
+176: 7B2298654B95CD00307D8D983A0079CCCFD89E5788180CAF352B6C965B9BB5153C9DE25C4A0CBB5E578859660696C887280EA378A2E02B7C7F9E6CC635509EBD
+177: C7ADECC928EF065C263A97A273CE8CB30485BFC035F2FC02C78AE2AC6B7F7ED20E93897C0994CAB8D584EEF9DD475AA1613159A0C862FF179C67120F6B4C72C7
+178: 041A03CCE6696653ED5F367749AE1AF3C2654E8A9C0E70E467261E60023876C7271CAE545D114C32D38DA75389525CF0CF1FC0FA9A481ECF43FA0B1F61B868F7
+179: E652E4A88EC1A9C4678F8CFDBFB1D758774600255165E2B4DC15F61C18B9ADE14C5ACE7E8AE72D3062B7F1787583C55B14B347F642344E71D6E00FD6F4C56808
+180: 903675FD8C70BEBE9FD0DADAB17A638A2DD8089AE63114E36D28F4C75D951D75B0BCAB5247803551862720713AB45A932DBE141E48E9BF3ED9E76201577DDD43
+181: 6E61016D474D2AC2984E4EAD44ED82B7129B0B7FF0B9AAF5F45CA68B0529A736B846626CEBCAB9E7CE374D744E7A09C51BBBC746D989806F1A00703A002542FA
+182: 20085D4717A204E896F10C5F7E1FD429C9AF848FFF608A2C46D3738EE4FFB944381880A7A455FEC6A1A21754D9ECCF3F1390EA22EC17FCFECE2B86E361784045
+183: 37216CA069259BA3244DE3933A3AD5F35712F0AB7B9C81D64000F0B91DD4232B53748B704E7ED0DD682A77D84BAC1B943D2FF7A3DBF5FE33DF455DDB10D11632
+184: 1F2467A57006D96FDC75A8BDAF98907AE72AD330C0418B06513C33D86DDB800AB6A51738DBFDF1C44676038C094EB5F309B5B590EAAADA4DB09FE7590FF04888
+185: C45893F92AC3E3AA3BC86A9ED659797A7C7DB949A66552ABD046DA2AA7DA9E52FF8BA2673CB44B2CB0481D599EC70020B6D5079296F2C19DB162DC8CCD64BAFD
+186: 9919574ADE9B8640BB0EF45F98D1DB6FB7242C433D86CF6D4BD67AD14FF15D74A13F796429E312BAC581552E6597BAD2792F31B2488ED300C6118891ADEE9FB1
+187: 034A92D00A172A5F0CE717FC38AB8D68019F500493899401B563845EB604ABE0907749AA830F91B53AA7C89DFFF86664F8B123AFF4721D790A58CC22F36A560C
+188: 54714E69859C60B07C7FE34859C855A37A82204D723F1A695F78D7765CE906D109FA6144EBA9E7E7A7D8343A99495E72D160DD468BEFB794D97659B8E2D8F1CE
+189: D6CA476F7E68095DFCEF4338BD6466FCA90DF78A17DE9E29111D4645B0DAA0C6E98F156C0EBF9134BC28EF9E0EA67E6D839027DD5CB084E9EBA899DD3413E222
+190: 86EB8C026D6BF090636F01F623CD98B960D08E521E44697F364BC1AE1655B9AD6FC3EA38C929AC9A244D18E697342594F3E7DFE605954579AE4042CA69E65AC3
+191: 1F63EE615E9B809E3661C77B5029C78A92DC4BE3CC4DFD8BBE78DC7B7D990BC717238004969A8B854CBA04B4D9B30AA1A1964264C47F23D9BCDF45C74FFFD918
+192: 0351F475C711D068BE7B0395D65343B5E249FEAA3C3F3B6B87100C50306EF0340F60EF36233F0E6287057EF7BE8634BFC4D46B49E4A8F2CC4839F42F486A16FB
+193: 16645F9C0ABBDA602B7436DE3B1C55AAFD1E844057D51EF80A96CBC2FAFF6E3B2706B45069C90A52D779E101793EAF4C9AE85CAD0A5A394164F0BF34C189A2A0
+194: 821E46199F4FEBD9C118D49B1CE9FFE953113EB6E4E33DA9E39C676399A0B3F792C2990A9F75D729E58EF750857C07336526631CBAA5EE0643699C8E7B7EEA13
+195: 64CB83ABF2BB0A94451F2B9C3EDD76E4A15F9D1F9EE32C0607F5E0951084377E484A8259B3C64428293396F78E6674CC3C027CED1BE12F5671D328D131740770
+196: CCC1A68114DF54BF467EC49CB15CE381EBA7E6FF06A93EFC88F442F8A35827D5DC6494A4F39E8423167CC1C3269A3EE6AE68825FE3E2E40EAFB75C8D878FF88B
+197: 94D38693F1B1A8F1013544419C5B3BA0CD79B72478A91CF3AD325E4C3CDCE092AB667572233A4F8DFF132401968BC74C553AEEE96D530CA4E5F6D427F9D2C422
+198: EB080E256FA9A5D51C3DF577509B877563958704C0F1DB645F75CE24005D3B12503BDC26FD3A66E8F6882D3491428A4932EED6F5F58532FEAF521BA5FE05B70C
+199: 9A43D7D0C42D7B5409963339C9D9805BA59ED8A63DB144165A3C759EB9F5D756E6288308DD2FE460CC50DE26E1A1C1747AA165FE6C8A1FD5B0F7CB1373E28CAC
+200: 986058E9895E2C2AB8F9E8CBDF801DB12A44842A56A91D5A4E87B1FC98B293722C4664142E42C3C551FF898646268CD92B84ED230B8C94BED7798D4F27CD7465
+201: 9FCCC4EEF7571A2BEEE06981856228CEDAF3BD412E777F4AE8524B81C373FDBC210795C1E788EE7081BA42EC3FAFACCF2F386A9096AC719E6565B4E384E390E2
+202: E4E8BF0BF40249236FB88C442E6668E3067ED6001189053A3A81EB755798911258E25CACF7282811DD5E5147811844C4B5BF52FC24A6862BCAF9407F2E38EF5D
+203: 317ECED703044C1BCE944DDA7114DD1E36244DF6A533790FAADBD0B8DDF1AC0D198B593F0479A038198F4B94AA6ED294168FE0EE800C02E769EE78ED45249945
+204: F5FA1EDDE359173067E463107FCDF00EF227CBBA0EC5EA02EBBABE2C79B12E793B98FD3A90A72BC26240D994F53DED65FE22C6FE87EAFD01B8478D1E8569A882
+205: 6323E2A8E380CE86433D5B8FCC5E02FABA4ED7F9CE5BD194F7CBFA36F65844B61A7BDF8F131CB4B28C56ACFDB99CD84830557C571FD369650B4608376BBE4FDC
+206: DC6BDB69D1C6111E280F993635BB59CD6E7B189166DE593B71E194C5F218D67B00EBE0D028E944976D6538DE410C4D86A2B6F272BB94FFA590208C644F99240F
+207: 2428590D2043634FB10268435EA90ABD082D45317D2C54D065529F15E180438AB18FE4CCC9129584804EB04EA1CFF646FA881878520BC01AFF392B6D7D9C0369
+208: 1A29341BEF679E5351911809DA190BAB8E665A9375BC2D477742176A70A6BE8ACE4A35645BF8DB97AB9BBAF1F0313004AF8B4CF10ADB26AC0198AB1D45D05C46
+209: 0EF4FCF3B2010921C58056B2BA367B4C09F5325E6AE9AD732AB277281D4BA797A847B1C6A74D81523DEA163AB0E556FB5102C14E8CD94AFBAC0AB0A921BF1A25
+210: 73C65AF2A53E8860BEE63AF0BD8A457B0AC8D3C5D243FBB1BC3D67624727CC175F3CA133B26342C3401D75DCDDDAD9A692D9A2B1264E90CFFD4BB9E6E775DE15
+211: 18D3DE049396E2EA541E15C31C0EF0E0BD90CCC6CA35663856B94F6F18160D616667C55F3ADC1B33E749F60BE50514A4F3BE48ABE2E18FCA10F85ED0266972D5
+212: 34DED45ED26FE224E0C5A66A193C11A2CC0786E61D421034B3BB16175019C95453F20BDE865DEEAC5C2BB5C86544641482B51C4E61D9DDACC238D050CFC35776
+213: 025D211B55974BAF086B139D8FA1AEA75B627CE1AB894D52F8769874557BE5944D27FD4BA3606266BC7F50D1734436C53D4555A1D2DE0DD2AC51D7F2FA373867
+214: 08CD521B1F13440D57001F30BDA0029FD8AA17FF26AFECEFA2CB7EE1812FC79A694ACD0BDA98184154B72FB7CE305FF4897F466CBB3972B4863FC88B3DA52C28
+215: BA3BF464071BDF124034CD122451D3374AACFBBC916C858B93E191006235F4D741564BA1DE70372269C122D360121DD3D427853BA76C6B450BB46F4156EA7524
+216: CB0B3250639B4ED947BE0C83EEF67D370DE76AB901F607F68FBF1BF8ADA15984DDA7BECAA4D7FDD55FBFE479EEE3F5ECC9CDA7BAEDC9DB7D35DC227411DCF20E
+217: 8AFA4024BD96BD50323AFDCF92A7F3E7BFB4C927108CF81C01FD378F61C55D850020DBEB88C6528B8FC141C37EA4852481C14902878AFDE51A7F1EA1612D0324
+218: 27057269EEB73333A1A8059D6C9D6FD5AC89EC26500F6F9838CACEC20E93F1713CF5569E820BD80969547D77E56AB0CBF57F03182EF45AC8BDDE114470C6DDEA
+219: C79C3D4A4608C7CB4A3D0C14B28CBB96364F44DD8651F36D908AE502E547AD7AD5DFC10DA26CA26C6D9E51CD40F6D7F1BEA0A03358967D867A97333DA8ADF3AF
+220: 9DC3B1EF11D85FF8A57330FDF91D5B5AB142FB89A72D880DAE476E020755C2F3B4CA58C9ED36239E8807C059BD66F826EC517B7A44187E7216E48B683B567076
+221: D11A97FB7B967E90C2D39EF42EBE49327CD58EA6977C84275B01698E322DD97024A40FC3EEDD96207310708F737E81B79659A6C7202E96BE7AA34D18D4026F63
+222: C9BD62C0FCE47736ADCD9275B46845E4ECA23B73678693FEB8E21909EB8405D4B057AF2AFFD7E667E047A07E6ACCADC2A58D7360C17689769DB009F0A7795560
+223: 7FAFE6ABE7CB8C109B18A14BC4FC2E4FFEADD55A43AE7DFC58D89B9CCEBB4467FE4CC163FF6EB16C8C71B8EFF12E7891D11D3DA2C6DFA8152DEC52B232267B6B
+224: AEC37B2A1157708142BDACFE77E5204174F539D86A12730BBEF6386FCA098AFF2A5C31EA1AB21D3B4537531DDEB27CA9DAEA22F5CC8C9956B2F2595F53BB931C
+225: 6B005CC923D9AFF56334CFC7A5E3ECD70E97C4247EB372A3180E7DC5BEBE676E72E2FDFACB74277B70E15D871819626F46661285DB04B3F825C49EEF42391B5E
+226: 509B5C993CDF61F8F507A84BBD7D6D7AB090970927400043D39E5F47DC23AC289F5BBF9D3246EDB174D9C5D72BA7A066DC13171EC15FF9508911464F8730D395
+227: 00A05302C3A60E58C4C52847F47379212A918060931A72BC660D88E7BF5599DF6C38DE92452B4823B4725BA3EEE866235CCF4D5903E91714CAA230C6D6EEBE45
+228: C4FA5EFAA31CA205A732FCD5DEBED53C09A4F30C5BD9ADF27F8C1DCD4B2730925BB6AF176E2E680B2BE325F7DDEFBC9EE6C1CBC4F0426ADCB5CBF18D1437EE6C
+229: D125006B8107FA63C375A79AAA0EBE82017372B7CC65C3157CE078DDBDAEE8C569BB84FD8490F2D66D15FE73C6881245761AB2B1D4F056637ECA70641745CDA4
+230: 01C7D098DCE4E40A69DE14682587FF2A40BAF9833BDCC6413AB54DB0E64262F290D584CD5B21C6558682C50E1E27BF53A18A16D72ABDE878C3522156C9F04DE3
+231: E863DA51CAE09500F589BE05CAAD5788587E2017907444D76F547D6F30632AC658EEB8585733BBB815D2E19EA046369ED3B81AA773FBFFAC316162389E015A71
+232: FD8232F7B79BDF9CC52FF0D5DE1C565E9D659BF19769096895D182A88028C1CDB7387DD240128A7ECFD2708EBA7E9E3C676D6E2A036E1B993940F5CCDF1A736A
+233: 3BF8572CDC7B825CE7F3222A3DB87F1C52FBD1A8229B957ACFEF2047C560567483C479603A3C0B0F1B2DD265BEC257D1A32C651508D7A4DF501BC015657DCAC0
+234: 23FC530B031136A17B8B2FCB55046DE7271312EE3E77851FBDB05F78A294815CB2169079168E07647A2BD5D05C1BC2B1EF1B64B929DAA1F9CE723D448C936FEC
+235: 83D10057C7FB494FAAD289B4FE5F093DB2A0C7D79A298173DA735CD5063232BF9E5327A7B4AA795C99F323045790B554476F37EB9D04FE3DF40C047E4113A720
+236: 0AA201EDF4124F421D4515554A1A642E3B9D18C70E09E83A886D6F0CAB0750D9BA1FFEB9C587F3ACAB0D8B9C1D83D789102F0E2A6CFF885C50F485929DF4602D
+237: B85CC52981751513B917F58305AFFDDC7D901CB3BB1D1BF5DAB058DEC9B8CDCD2DAE543D73EC6AE0889C9D785F9178D207059D994E1C80706EB28AE65AAA100C
+238: 068FED72E55444AE108EEFBDD59A96DA4AEA3D81A6642742C38BBD4EAAEDA6EE21FB8702C2F95152F1F997A5F40F06C54619481F2EC343AD33400913D6FDB4FB
+239: CB4C7FD522756D5781AD3A4F590A1D862906B960E7720136CB3FB36B563CAA1EA5689134291FA79C80CCC2B4092B41DF32EBDCB36DBE79DB483440228C1622A8
+240: 6C48466C9F6C07E4AB762C696B7EEB35CFE236FCA73683E5FAB873AC3489B4D2EB3D7AFCCE7E8165DBBF37ADED3B5B0C889C0B7E0F1790A8330D8677429D91A5
+241: 4F663484EFCA758D670147758A5D4D9E5933FE22C0A1DC01F954738FF8310A6515B3EC42094449075ED678C55EE001A4FB91B1081DFAE6AB83860B7B4CC7B4AB
+242: 81A70404857420638D72672A2DF5A49D52B9F9F38B385D8C5129D6A2B82A682CFEAFE6509266E4B00F6B6A07341C2F64E4D4F2152583ED143E3DCFB14C1C216F
+243: 31F655A1334E1A45584F12A22E03B09E3C69ED0E1D0FD573AD0D56F9C86862299E333ABE78590E97EEAA5C2FB14DC9F34FEF6DDAF6E7A9BFBF68CA6631195CE5
+244: B62C5102F97E5C4D7554790A4CF53A58D3EF44C83142D6E009BD1F6FC8F3A19AA1B89DA8DD9BD1310827A5BF662BE7CAC750C48E6ED91313E940D7D9E5EB9C22
+245: 380023C0BAC4C9524FF6778BE80CDF195E36FCF460E8CF1BF04E5C2FE08E38C35F183FBCDC3726FF26423F351C507279F6258F2319EA1403B6C8A3DCB384AC7F
+246: 473FC167C7C4BC40B17DA039EE09FF3DE884879557E40C52C1981AC419CE021A090BBAE014822D05714077008988D74FF151C927AA43E88CD63FF2CCD2012AF4
+247: 006086E61959B1D66C72E754427EAD5E1D6C02D8409F5C32B2F5AE448F54682B504A1ABC0346CCF39BF66A8C7B69081E886B47A7D0B02291462391C95351EE40
+248: 3828B2ED548CFD0B74BB34A1FEAE030E267222198D7E387E7FE3ED503905A25D4C3301A9A47E78372F685B05847062476C507708CDD75580ADB579E4CDC79AA0
+249: C26A7D5BB103EDFEAE2F1201BE58AAC127F69AE378DB04156074E991745D4AA5AAB3BA064407DFDA8D34E573B7EC1F9F37CEF01ADC17FAF393C262A09F2C4736
+250: DCF82307195035A668097514FF1A10E0BF0E802B4945A702D2E17AF6DE1D3D9BA49616DFD16D802054B5219CA37884385E87A713B4EF5C7FCB69661C7F56D5E3
+251: 46049EA0DFA5C49429E15626AF4AF2CE0A9DD2F308B99BA6E6E3F3088250A146870FD0B53228D5A1F1BF9859480E1B7A3D3DA180AEF4D5D41BD2951C4E19426C
+252: C0A1FB6C0A65A0D1AF46A5FE86C8A88E8A86F83E36317F435542927C98E74833C887CA3AB5E792CE5E3E21CC6C6AF437349F5A66FAFC4DA79742491C643901F9
+253: DCDD20CD47B7C7D011E9DF7855B08336BD5007C4435208BD3B914D7E503B8399164A155697E68A1B88A0600BDCF847A114D98FB773C81FEC817B92057A6998A9
+254: E2DA07644DAA73B66C1B6FBCDAE7FF28E3B9024F0BC5408FE02C18E3744CF9BD6DD54EA7BFA1F6F3A81C8560FB938FDFF9A38A29853A3A819B58D10213A290EC
+255: 15025C9D135861FF5A549DF0BFD6C398FD126613496D4E97627651E68B7B1F80407F187D7978464F0F78BFEEA787600FAAEBBE991EDDB60671CD0CE874F0A744
+256: 1E7B80BC8EDC552C8FEEB2780E111477E5BC70465FAC1A77B29B35980C3F0CE4A036A6C9462036824BD56801E62AF7E9FEBA5C22ED8A5AF877BF7DE117DCAC6D
+
+Hash: rmd128
+  0: CDF26213A150DC3ECB610F18F6B38B46
+  1: F069A435C14A8D4B02A7BBAEE02D0BC3
+  2: 48456EA1CD4C51DD8E1130F625DA4F8D
+  3: 6E41F2AE95605779C74CB5ACDFB361CC
+  4: 0C7A6C73E99A5C65B12D3EF47ECA9D2B
+  5: 3B80361C079D1B67933455D00AB1428E
+  6: 0F74C4BFBFC740A027B1D5BB9CAAAFA8
+  7: AA54ED5DA34CE9205B64D138538C0C1F
+  8: 08445C3C3E71434DE375CC2071430EBE
+  9: 1FE0AE641DEC6F8C172F0E27E9E73B9E
+ 10: 4E8152B7EA8F7A31D8649A51389260F9
+ 11: 0F851C98C2B997C2459B34CCB209E481
+ 12: 52D27461FD7E095EE3C6ED43BC24EF23
+ 13: E9F3489135F3D90EBBADF9F916C34920
+ 14: 36D527B693D6531A5E4E15BDE9E4A670
+ 15: 57433A07CC200953B7FD440253D5E476
+ 16: 4A91FFF90756026A90A83927066EC911
+ 17: 5A247C26BB1BABDF1009B6B4951FD76E
+ 18: 002DA29AC9F51F065A1E371660BB67BE
+ 19: CFFED09ACF01DEC9D3891033C0973953
+ 20: B78F28AD3460C99D428AF24E2787EFE7
+ 21: 5E203157AB6BAC57660F3D25FF615C95
+ 22: F128F5DEC3A24AF34AD3E7F3883C8051
+ 23: 2E05AF10A6CE9AD1E0C0FBCBF69B1C9E
+ 24: 67FAFD9A5CEA5D41863D03AF2932C5CF
+ 25: 5ED7E86651AC4BD0EEA718C773812977
+ 26: 6BC74F78256A98761981882C3CF7AAEB
+ 27: 44CC573B964002D877E79B75E4433E41
+ 28: FC02FF53665B52B58DE38784E2C28E92
+ 29: BC4D69312DFD24EEA219F29FF2AB2072
+ 30: 0355E82F130341EFDD997EBDF4469221
+ 31: 453D500D997FC85F6AE16365D83ACC05
+ 32: 42DF4C5A3844F00F77ED84E125237113
+ 33: E782D7162BB54E735F7B9FDD75A3F14E
+ 34: 78993013EEEA7B14999DDD3979191D74
+ 35: 27BFCEF540F0782E9A28328E8DBEE59B
+ 36: DCF00356DCD264B7E359F02D7D2CDBB3
+ 37: 9EE0BD7F55EBD844A8D114F83B3E8FC3
+ 38: 01EF8F3154BA9B9B817AE717FEA00A68
+ 39: 4DCBC2AA56D785CE7249761791442BBB
+ 40: 10282C07B870BCCE0C8DF9E68B4C5DAD
+ 41: 0757B359AB2D1D121BA01BB345A12A87
+ 42: 450AEDEE570A2E9B1A19D5B4747B2AC9
+ 43: 2C45713898BD259B10E2352BECFD6DE8
+ 44: 3E92731175E510FCD07D28AD47DDA0CE
+ 45: 6A8E5690AD4AA2180966AC1503A81A18
+ 46: 820BE195E2AE85C115BFE3C341567030
+ 47: 9C97E1F0E7DA29A0527AC4F59D520100
+ 48: E1257842EA15216543BFE84521B9FDC3
+ 49: 42BA484CB70A58EB3EB5DA43F1D5D5D1
+ 50: 2C674397A81CA35EDF1FE77B442BADD3
+ 51: A3E07C012A7C67D2B6557F4A8B4DD031
+ 52: F01789A2E0379CE16D87EEDE671171CB
+ 53: FFF1657EC846507BDECD2DD829DECDA2
+ 54: 1673DCE23D430948AB818D47E83BB5CD
+ 55: 37CEC696967031AB2122155998A07F51
+ 56: 320B7D4DE17A731B9BA5CBB48956D605
+ 57: 1EB07088E5F563DBC5DD988ACB84B048
+ 58: E4DFE704E4C25D06224D2560B4650467
+ 59: 6C072AD491BEC80667A6D71D9C8F2FF8
+ 60: 53DA8AE3F36FA8F85072A89962F39B76
+ 61: 40210D1C7A728A27E1B5F92057DA4765
+ 62: A4C4E5F271F3BDD74C560787718E8816
+ 63: 4466033447F1E1C9BB107D152BF06051
+ 64: 406C6EC2643CCEF38F964864D12C9191
+ 65: 19F725CB43B171DFE18EDCB90A9DD900
+ 66: EFAC3C9FBF1AB0C0F3601C18FE3F0212
+ 67: 9B9BCD32F735EE353D33A657C2292475
+ 68: 68F4A4294C640BBE4B1E90FF107E05AC
+ 69: 3630FD1C9542A56C851140A7D76C0D00
+ 70: 21AFDFAACDD8FAB91027A61F8DAB6C91
+ 71: 2C7AAC93B6CD1F8E23AAFD49F04C69DF
+ 72: AE4C5124059CFFB3B823E68FAC8CFB33
+ 73: 79E95CB7E752863AA87A7693D0677D89
+ 74: 1B491E33A96D9838398A4F624E773DAF
+ 75: 1F3986FC593D8A8E927C82DFE1F538F8
+ 76: CE64F09024A907E76726E29E1364E606
+ 77: AC98817981B59789E7C7E9CB9F70FDC3
+ 78: 3827B4B077493B289C25EC3E91B36D26
+ 79: 75295EED68F750E506C60A780B7F0285
+ 80: 4FA47F32992EE6C96C3B96B6A69A6656
+ 81: C52E142B7838D731FC036517003FA73E
+ 82: 3451812871ECD1C09E4A95CDC80369B2
+ 83: CB5261A793A55DB33016ED27A35A20F5
+ 84: 2D06368ED98E266E81A3C6491BC24890
+ 85: 677F6509BDB3D44BCFB088A81BFD96D8
+ 86: 6990256193FB0697862AB5A45FFF082E
+ 87: C88D698EAF83E446C025EA915998EA01
+ 88: DB8F672EE8129BF4BCE25704DD57BFA6
+ 89: 807F491456D7E28A36AD6E934B053EA8
+ 90: BBFD55A483CBD0F9DFE18FEC5070A166
+ 91: DF7735106411CC29535664D85ED81603
+ 92: 24FE3535DFCC295C2F34F3F88CACDC88
+ 93: B80CDE220C4199DE303BC97FEE125048
+ 94: 8C252310E9A71C7BC40C3D2011E24EA6
+ 95: BBDB705F5660C50C5B0C87CD812B76FD
+ 96: BD517928591240C7E63C8D9F957F6A4A
+ 97: 78A534AA0F4250EE83D752F3E6940148
+ 98: 3346EDA882F00D6073D133CE609D3B83
+ 99: 51EB1D3235CD35A2386E314F815588C1
+100: B4860192E79C1233A08FE595C084315F
+101: 79EDBE3E80887B4F741199295347117E
+102: A2793EA5F25492D32D315B3923E945D3
+103: E398223EBEFC56D3437AA5FBC5345CA5
+104: D3E6593D69B24069AF0374671E466930
+105: 12D63F5AC48F99BD59EC863B61952C1C
+106: CC99A81A22B62A0FCAB4AE889112A8DC
+107: CCC82CA5D35A421FFF313F90B9D1A675
+108: 5B4A2912071CC36CEA626F9AAD34F257
+109: D21FC82D78AC98C5DA436388AC9AC6BE
+110: C2F22C7C16DD2E1BBFDD2BE7915B869D
+111: 2B5AE5D14DC053558A1702959367760B
+112: 7A6A3A6553B2C3387BEBE119E80CFB2B
+113: 7E2206BCF666B89341CD7615D0291E3E
+114: 93D87A658259C7E9FDD0BCDF93A24356
+115: BDBC0B062FA3D743C1B070F2AB43D180
+116: EE0A575AFFC966F58B91BB66CC1E6B6A
+117: CC24CF8DF0798ED2CCED077B06AF1BAF
+118: CBAE264BB4AE635A15D8FDCF7F9A6852
+119: B879B9BBF61B6F291A8E4645B70EE06D
+120: A6F88AD4A16F789A58F178799279B40E
+121: 3DCB6B1674608B11F496F45C9828F90C
+122: FF34A1C7748C5B5F2F014ADF57241C43
+123: 1A77E2B20ADE5F286705251495AF04BC
+124: FD47EE73738626733CC63327D4F5EB7E
+125: B9438B50CC80CCE0303244713853A0DA
+126: 040BC7876B31E22590F5898068B19859
+127: 16ED82C338495D067BBE1D4AE73345FB
+128: FBE1AC0EECF0AA2671A6F25733E9711B
+
+Hash: rmd160
+  0: 9C1185A5C5E9FC54612808977EE8F548B2258D31
+  1: C81B94933420221A7AC004A90242D8B1D3E5070D
+  2: C0C355CA556CFE356ABC0A5595BAB1364BD86444
+  3: 6D8D360567AC2CC8C4EC11DEEDE0ADCACDDA388A
+  4: 04DE53FED2BBFA80FA79698B4C5627536FB620A7
+  5: 9538F24F7432E952F030BBA82C9F744365035197
+  6: 817ABE77EBB7EA159AF7BA7DE1EBBF034FE6CAFE
+  7: 340835AD791316DE50DDB59838F3EB13F5521228
+  8: 64B7269FA971B162612265C73B9911F53EF43B63
+  9: AFDD1E7F8E39C63DEE7104014AD9EB32B855E0F0
+ 10: CD2E472470BE8FD70A306DAEC5C59F485EA43929
+ 11: 550844206034AA74E37D813FF29973D3000C1DBF
+ 12: DC24FD5F309A7BEB9A7CFA7A354F2DB2CBC15AFF
+ 13: A814B4CBFAD24B7B92AF0E16794A793DC16D10A2
+ 14: 6C316617808A930BD29972B1142C0AEC89EF00AC
+ 15: 3286BABC7C4635FEC52F67CEFF1471E122D50258
+ 16: 696C7528A3545E25BEC296E0D39B5F898BEC97F7
+ 17: C87DA6F87A65CBCBC4B02BFD6D01E26F8047B5C4
+ 18: F1AC2E0951EA5875B71723BA1A2158DB49EE073D
+ 19: 091A39765126ED406254E7F810F02E0A6124C6A3
+ 20: 4002C0305550C5A726705DCF8D3880C54FED0453
+ 21: 2B59904E1585334B1298AAE6EAB06526CAE5A232
+ 22: 0EF94DF816593728611664F4ED6A0C4DA28C5AA9
+ 23: FE7AB8A5B0CA3C86B6524E3333490D0430E9A4A0
+ 24: E748023DDA7E4B77DE8A4424744331EBC62A6590
+ 25: 96147FE511BC64D9493C795ADE8FC71A78FA8C23
+ 26: D81D7D3B46D5BA875EC2604814616230D7A075A1
+ 27: E8245E6537FEF146A2CF6AF9BC54472BEE6213F5
+ 28: 231CAE27B96A78767A0915A529ADB6B72A8006B6
+ 29: 4D6BE5BB6D29A15A259C8B7BD4827EA82F514425
+ 30: 3B00599329120E535A5D1A46F35AD03CCA27F9D8
+ 31: 2AF4160DADBB84707F7355177A4644E4CF577DFA
+ 32: E6BABB9619D7A81272711FC546A16B211DD93957
+ 33: 1E374AB924A652FA36B395D654D226BF901B6A04
+ 34: 67281E2EFADF2EA6211B549426D3A598B5E1F291
+ 35: 993464E56DC035716064577245BCE99ED175356B
+ 36: 298D2CEC0A3887C93501307B51F75BFD5CF0AFEE
+ 37: 2A0A02BF4D63CC09978EAF3B3B85A4DE8470B025
+ 38: 6236F6FE25D5157BA95BF49EEBA8987A6A301D2C
+ 39: B4DD7121567E8A428F16BBD5A8832FB2EE68BC0A
+ 40: 5FBE6037F8D8EFAA9A315C070CE3373080244496
+ 41: 04D5E112C47EA03BB60CBCEB9FC8ED7D92A68C0A
+ 42: 658797C7756256C98E04E6718D9F8952F90DA672
+ 43: 6A27ECD40BDA4CC81C599DE94D0D2904716FD457
+ 44: EF5AC5B8E7A00560E79DB54AAD4B97E996D2745E
+ 45: E67EE5275910B48F7D248A8B844DBC041257D695
+ 46: FFD256BCBBF0F3BB4DF615B4236C147FD09F4F1B
+ 47: E83A4B18C347F188301DD3AA78265AD3AB3C0311
+ 48: 13968583BC017CF0C5043364A42EC0D97E923711
+ 49: 39C33EA7C4F393C4DD4B882F73FDDAC2D7FE1EDA
+ 50: 50B0068D46AA025615053132BB53F88DC062DB2D
+ 51: 434198200766DB6CF48C993906FEAC2B47224A3F
+ 52: 004FBC3820002357434D6B8ADCF79BFA6F9E3DD7
+ 53: 13F7A8CDDDE021BCA6227EFF1A71DE19AF399B66
+ 54: ECAB85CA0C2AABF18F5359F94AAD7578A08AB5EF
+ 55: 3C86963B3FF646A65AE42996E9664C747CC7E5E6
+ 56: EBDD79CFD4FD9949EF8089673D2620427F487CFB
+ 57: 635B0D05BE254D82503A9E1DB7647DD1B5D5D6BF
+ 58: BE314B818A657DDEF92DF123FCC17C1DAA851C04
+ 59: DCFBF0575A2B3F64B24DC203BDCB46290B21791E
+ 60: ADA425E87A8DACF9C28B67E8BE4B204A31960004
+ 61: 35691DD184E08A80230467ADC6E68599B7295A51
+ 62: AD1CAEFC7ABDC90E7877D376957532B7D91D7434
+ 63: 6D31D3D634B4A7AA15914C239576EB1956F2D9A4
+ 64: 2581F5E9F957B44B0FA24D31996DE47409DD1E0F
+ 65: 109949B95341EEEA7365E8AC4D0D3883D98F709A
+ 66: AC745186C82DF8697458326051A6CE7E4E9C1C1A
+ 67: 5DE50BBB11C62ABE22E7EDC288B7D1B6A1CFCC60
+ 68: 7DD54CC4E8C70A4AC55F4C0485A4DFE139253757
+ 69: A5E0EFB95E6162F9637D58D3E4836F9661D6A34A
+ 70: 6C77DE7607A361D22852385E663171148C0499BD
+ 71: 3467662275B136AF096D84258B17CA5F23BD6397
+ 72: 1C56A69A826F95B8971635AA709978A441E75836
+ 73: 9094727596F086BA28956A6BB69CCBF3B2B29FA6
+ 74: 8C0B6183C33E902C22F17D81D18144ACB7B66FB2
+ 75: 24ECF7598894FFBBC7D30FB1EA47092F03C398CA
+ 76: 6A02FE0041D98AB7AA6916A5245BFBBCF6635C2D
+ 77: F3021EDB24459533488660512660DDFF7F451C3C
+ 78: FBB7561C0065C90D7B8182018EAE73A18288E968
+ 79: 32784F0E354A20688359B6EE7FD3874714C48677
+ 80: 8BFBA0972D36739EA808C37C07F2E320ACB4114D
+ 81: 74EADA88C8ED0B649FCCC36DE338CB538242FE10
+ 82: ED812B77C12856DB371E6F7DDF15A59FEBDD6962
+ 83: 27021F491E923CF0B191E13ABCADDAA72586B769
+ 84: 47664874218C135C09ED40DFAC26E06733AD02CE
+ 85: B39E492616FDAF2480F13D6E46CEBECC1FF5CBA5
+ 86: DE967F65BF6DF26150AF866FADCA58C45DDC337B
+ 87: 8F2E2D23CC6A2B52B904032119CE68649406033A
+ 88: 247FB8B2BD1BDC35D0C07EA10FD9686A19E4723B
+ 89: 9D1E80D5695569D0DE28587D37103BBB0701E462
+ 90: FA5C338E7506AC5418C4FC2C04AA933588892D4A
+ 91: D6BC93880FEC0163E3F223C8A64BA0879BBB0AED
+ 92: 8F27EE9C8A923C9698584786B5227CF17F0F557E
+ 93: 4C10ACF2F404236E2DABED0BB48DDC6D00AC4B16
+ 94: D5166CC6B779EB2D45AB3222181064D05FFB5E23
+ 95: 13042EB8245A8C5DED69CFCC1F1DB264889CF5CF
+ 96: 07136FE8CC1A03673891BC614E29BE79EA02D627
+ 97: 73C50B2751C502572492C801C28B02C7E9F61B76
+ 98: 8BE4B71D50C2D2895B9CA359ECB69F90CDCB1DD5
+ 99: 36A669D7C1DA8E23D07B29BD6769DC324EB6D6B3
+100: 8AE5D2E6B1F3A514257F2469B637454931844AEB
+101: F16396E005FE5ACC34EB53E6086F477415794BF2
+102: 907CD2922CA5F62F79E17B28AF389A38066E2C9C
+103: 62C9351A21A50F2150367F25D4C166C63E771C32
+104: 8809CB529232A0CB22D384B70462B64D93B0EC1A
+105: A85E4B4260A836BF0DA50B83BE1080D98CEF8A17
+106: 21D2A0D78435B2590B2C6366439939B9B15246E7
+107: 204FFDFDFCA5D46CCEC5FA96A778BFCBEA70BCE9
+108: 01DC05D6006E12D2F63A8F061B00D18CCA135D41
+109: 30E67D3FC0A0A6D2F257AE24EA8C168A4B0E0F5B
+110: 9B9454E2B42908E57403871A64EA5E930F35B70A
+111: 9F72DB053BC5370C786E34013FB8DA5958000D5A
+112: C1BFA4009BFEAA30ADA4D940FC40F97FFEA3FC39
+113: 26FC30BF64087DC3FA4CA394637D15F73B7687FD
+114: 36106E0DF24B7DEF46E9AEAB7CE0D784FE619D9D
+115: 0D82262E443C3C56565EE35776F95978E16F1757
+116: B19E6C73E94401020B14ABBF19A15A6F0C9061AF
+117: 68ECB5552C7B7B26940A82B6A67B0F4C62EEB871
+118: A834797B79DBB564AE587003EC4B74914A1580C5
+119: AD430B4283203A7B7F338B9D252DFDBF807402BF
+120: B89CDC109009F1982C8B34FCA446953584D3F6C4
+121: 8030CC5A4F55566958A5BFCA97CB6F40B9C19279
+122: D0CBD1EA711E2D405DA5ECC2905DD8A3A3E83C37
+123: ACCDC924549D314019C4FD1AAC6AE3CDFB81BC84
+124: 312933643FCAAEBA4DB9BDE6EF7D6EFA70E37399
+125: 47F11AE47E2E693EDC0B06351E935C9B5DA42A35
+126: E4C6AA211767C15E90935DF552E4EEB89F23AD50
+127: 2BE8E565E24A87171F0700ECAFA3C2942C97023E
+128: 7C4D36070C1E1176B2960A1B0DD2319D547CF8EB
+
+Hash: whirlpool
+  0: 19FA61D75522A4669B44E39C1D2E1726C530232130D407F89AFEE0964997F7A73E83BE698B288FEBCF88E3E03C4F0757EA8964E59B63D93708B138CC42A66EB3
+  1: 4D9444C212955963D425A410176FCCFB74161E6839692B4C11FDE2ED6EB559EFE0560C39A7B61D5A8BCABD6817A3135AF80F342A4942CCAAE745ABDDFB6AFED0
+  2: 2661D03372ED5C961EE23F42ED9498B451030EED2FD01F29178955529B2F8A758F0444087C82AED85540C8217E959EB8CB43EBBBB77A7E0D2980D6406AA2190B
+  3: 7314E8035788304E57E68AC9EA89544ACE6D2379035697D91B98B64B105130DC814B67A4B46B4DF6C103016B8F7C7403E0B943F0291ED6909E2219B6E18E89D8
+  4: A6C01D8CB93A5CEC17A9BDD270B24C8EE78686CAFFC454F253D9B8DAD5398E52304CD57F30F2111BE78FD98338DD3A41FD8A45124C940C4A59F270100DD6CB6F
+  5: DB22986F9FECA154CCF0E7DAD914AE8C0851E170D116E9B550C39B373F109FD073395C0711745E40233226F96B5FBF6C8EF1D7F8E2E4AF5375821C897EB18514
+  6: 793498B98970BB3CF187B0A28D353AB2EEC8F6CDA12E6D484CBCCDB96B2BFE6B5278CDB38C9BEDAEB59A8404645DBEDFBE1FE54227947E226EDFD36114067F34
+  7: 052A7C4EC5AD200B6B8131F30E97A9A5DA44899E1C6C31BBE078058630D5E208FD6F2F51A796F814F8AD048D759F8DCE442C405D96D6E1B1A197AD908B366E98
+  8: 219B01987262C597603DBC495792F2423E24A4BCD38825A74CEE8ED91D55935296D80E73DB43A78FDD6119233A31DA5940C6E335EB22600729478A20F61A56DD
+  9: 4BBB8746D1D754CE91C27F3A6262ACBBFD4A38D100A65ADADD3174ED6EF8F6AD343F0ED2DF28309A6E979E02B12E732A3E70371EF1E0935E8A30B7C55146D9AC
+ 10: 81BE2AD26A90BF502C9514F46681276F927E916A630FAC442D823FE4D8EDE0FAE2E8384F3C267B56126F0C009BF8689D475C53425322BF8CD7F6C80CD2C725C6
+ 11: FCDEAB03C0FAC7939E8478FD152EEC2408D4A6C0D829B55AFCC5184C50706C253676CF68DA3ABC1C1AEEB5822898C5194AC801881B8CBCC8DB15930EAAEE9373
+ 12: F943E5CD2DF74699913B25EEF0B08FCA6BAE9E66BC073DF0BD950CA02FF17276F4A28393BCCCF6E567024CBC6C05C94EA912F1B07034AA375009F594B25D9542
+ 13: 1260728E085D172EE82065B3F878FE21F550748598E72A40F4FAC3F54B72A99E6B3CFDA7141C7E5BE123757AE4332C8320786408523DFC8655D7E1F7010792B2
+ 14: 67EB4E93961EF18A82152DE2882CC5AF4DD1254732A8FC1959147268441A80EAF0E0B68041F7CF013313ACAD044BD440F1E06D3E449D206433F3B52BE2C9E7B9
+ 15: 9AB90A3384DA32A03B31DDA21732B398358DD40D7586E836CFA047961360CEA2F1E3DD0CF2D90CBB57F68C4334110694A6C1BA17B1E9E533E6CF3A3ACCEFF84E
+ 16: 112C2ED4CE732E21334D7248A30E683246BA602AD3681BAE365E857AA840F1F80FCEF1B9ADA33AC1F9BF6FB75045F9E61449B26F9201E482E7F2ADC8ED9A1D80
+ 17: EF574EE7B498AA64F3ACBE1972E42B873C6FADE053A1459AB52D5E5B49C0AFA0C62FE901ADC3FF07A7D0ACC459C3DDB3F6D499C70B63F68B60B02E2784BB9AC4
+ 18: C6185B5836DD3B160695E5E27058AB266EDE91A5417DC086988EA5181DF5BA0C51DEB11F6BA14AF2847540BE368B6C561CD976809E2D9982F4D49F96E0AF4F7C
+ 19: 8510D305A5E1AB3A0832B242ED402BEC2D70C24B41BD840B8D2DE436A6B4DBB7CB5F7F9F1432E694F0CB1239EAB0DDD92E6D0C7E96FDAD5F8E465E286D7588EC
+ 20: 926800FF566CAFAEABACA9990772EFEC8AC956C3C572A360194F95AAAAE477F98AB7750B2710E262D039D8584BE79D93E9E6405BA25DFF6DCF29C54D748DD655
+ 21: 0F0B98CE94E2CC67D36086D153A2DF48F20283413407C3CD0570B619871DAC188AA37BA30BD706AFEF475BDA7AEFAB63055ADE8B792F025D088B51A08E941B01
+ 22: E6538F3479D33979F046FBC88D4BA785B072EF58877BFC9D1214FA8374B78DA6895D5A4F4E50E6AC6A237E48A73EB18E4452E7C8AD50C82238FA9B323C96935C
+ 23: 378E83B88847F234A6A2FF7304ABA759A422E6823334ECF71E9C3C1F8B21B016D9A8A100B6B160772FFF12482A50613BD832EF534DBD1D4D055F3227C7513F11
+ 24: ECFC0F6C168962197E181C27FC9AA1975FED01E655B3D4A7857872451D6AF810783184534C401709A63BF6BE6CDB1D1455C382CBAA6F68E8180CBA9E0CDDB9EE
+ 25: 8523B737250579A3787BD83E5DCC57F7038B393F003223A7BAB98EE4D040441190622290B164F32FB96682730DF62CC366FC33126DE2F7DDE3A38C818C48F680
+ 26: C6BE341A28878B733C30F50D67F6933D3A15A0950CAAB96B9F3D7D78C95C61874A400CAB65A100302D9E2DCEADC4A0C043834EB0433D5D684C187AED93B5EC6A
+ 27: 4AE827A36DA140D2271F74DF1AF4303DF4B1C319428F8BA94EA28BD3765BE4535275053DA49B630E6B754097ADCD7F17DC7C16158F43E2C1851951EC3016CD8B
+ 28: 6D3F01856A8A28E28EADF60401E84253C3F7CD13F3A9FB8F94D8B07B74F7416817F274903C135BA0DA4509A78D004388CBCCA75B06132C7CFC0156C03803E85B
+ 29: 07CDC2BDD9CDC49853384FB647736B50D788AB80A0A54A0969B86603B683C22A1C5FD32D3AC92E73D378F379C4BA30A48E7D38FBB867E981271FB3962C745659
+ 30: 9DC875BF987C55CE646A709E89CA89E226B0F15666D5174771368FAD768BF3318B8BC7D8CA80AFB5E6BB7FC0090B5559F11DA165DE51B940C9DFE911D4790477
+ 31: 58BEE92BE003CCC34F9CE8C0B323C6BAF1297460BAAB4998CB3B52D2BBAA24D1B06CB597EB2E609A008572FF93710E3A7F42AC53E3FF09D4733757EACA41E20C
+ 32: 888AEB1BE2BECB28598556A128AFEA037D0689C8D13D9894F1416B2C48B2551CB2FDA321A26CC4D7E1C87332D7A3C18FFB455C92C0E7AAF829FA40B8A28BB656
+ 33: 19099B4E8ABF225DC7BD1C1DC6D52F54E8FB7E4EAE0AB19293C686E6FD2828221A1153BBA4C143795D1A718585D9255B6DC911C0EDA5E0042A10565AA5D6D8E7
+ 34: 22B3ED65F64C8E51257A922FF90DC09447224B9A8C7B5A6A94D68601F3D4C7C1557BB90B91DF318EF9F8BB367E838D36A3CA82FDCB85721AEA20A8A2268D90AF
+ 35: 0D2B24C6FD5D772704BC17D2FC8C011F1511F92491104F3C22470864882656AA40DD07C0C329C8BAFD90ADEA7F473349038CE475D352DA41E24FF64723070566
+ 36: FEB43F7DCDE56A2EE963236C234E5800C011FC54D14396288DE5A7AC7DB2A72D1E8F63F04D1DDB3C55CF3BF19F4E0FBA4B79405A6B45ECB31254C9F1951C632B
+ 37: B8AE2C8427A750F34647C3529A05D44691B8DE0C79525D9145665BDA5C0C396C00E936BF2493F12945899B6FDAA9F61E6E7B22846023D140F873EE7D48D76BC8
+ 38: E80C49D1E29F6FAF0BB5C7B47F5A85B3A0EDDED84418890748724792CC83B53AB044B051722F1ADAAB713E5069E883C1D172CE0EFF6EE6AEBE05B1FD77DB652B
+ 39: 1FED03FA70436EF45286648ABF39057C33815E6A80A19E22009B89C809DD6F0099C944B882FF9DF3DF08DD51295F3F02FBAB40F606C045BD4395969E27647D24
+ 40: 2E3630EB519F6DD115B3E4818DB4429CDDF1C6CC2C8548F8CCA226A24F87A949A27DCBF141803B87B2A2C0F8AF830031DB1FE084E3996D8834F8E7D29EEA4AFB
+ 41: D54509526805DFC0871CBD6E41ACE395C64373E8F57146A657C28BB3ADBF7E57A152D27BE24B8F30F08329C2E040359B119690D9A1118BC14A3B1883D093466E
+ 42: 0AB062968EE4D71DCE807EFAF835EE11588854ACA0959B5341DDFD10E70BA9AD427D92168B31B8E6EF81F58615AF9215A8708CE1F144EE29901D1FC282C3F78F
+ 43: 45862B0D0F0AC5CC1C5769C29D786FD3AC788CFBCDD6CAECFB120D05D71F2575F4174CAD5E5A00D2D740D0714E92822427085F044A72D66631755BC55E5BCC8E
+ 44: D3A9EFFA759181346D8FE53130F05B2C65F96E1D5908A61DA8FA3A9BC551A7781ED7B1A6CFFCB2F742DDAE8D22B0EC99D82B14EB85719253693FF920FD5071D8
+ 45: DB53395A78DDE62A406211955EC56C6F7BEB9EC2275501C35CA955268C3E2D71BA246B4286C76FAFDE012F9E2CAAC8601A74699B466023FE9F8B1BA26F65042B
+ 46: 9426FFB7B70DEDF1CFBCE6610583CDCD91AB421FE39DDC31F4215CF7604B9050C84A3BA29C4B236F1CC3B09F53D29229132FDDDD9B468CBB6338BBBA6193F84B
+ 47: 3D74F17DC6FE057703C72452BC7A078EC019424A89783F1FA40003657C323997DF30BBA38CB4B16BAD8FDC43260956090F765C26AB1FC88BF7F87EACA1821B52
+ 48: C6EF119085EB17EC1B9F74791D95E366FE916F5397C20857A8966C52512F4EE16E63B53A28F7632A867EFC7FFD8080B173D5E2E33A2063FEC7D1181ACF8C7824
+ 49: D878B30402FECA5EC93362105D5E183D658DD2FD38B8173FF609740CC84239C4F8F533AC3451D369001CCD4AC78814058DE0F7E1F93D167A46E85E3002F4F386
+ 50: 948C4254AD2C5658A28D42DDC3CB4FE4CF731B4180B8A4A183C23C54CCEA045307422547600598CCFFD3C6229DAA6CDD006D3C782ED91AC61172059D016970DE
+ 51: B74FDFED0388D5164BEE25E37C6687FA8D5C069D4FB0D42A7F1A270A676F83F24FD1C9048EC0D49F7BE913D893E0015E0A3F724653B3F0AB0017683948712E46
+ 52: 497EB803D053D5DF498369BADBF8AAD57ED1B072CF361D3DB2A528D3DB16DD962887916E9D21FFB439DC2C025CDD8C21ADCC98A23C8C5B0245F2D71CF728F10F
+ 53: 63F4098F650820EDCEA3E7C10B65D3B0F1949A28FEA323702F27C7D311C7E6BFC82D4C01F4FAD06FE0288E410EF325DE192F78B88E04075FA9581AE2B031A68B
+ 54: 337914B013B8056D7849E42ADB47FA761B5AB05696CB8FDA6B87FFF88B0477902991AD81664727164053E4E47ACDF880DCAD0E0E67F7141123DB494450CF0B61
+ 55: A385FE66F8C852638F5BE44503B680298EBBF27DBD9F20B1A0447215C0E2C1078926002113A71C78148D5019FB22C8132DD05356C78A1A8D8E4EEC5A6442DBA9
+ 56: 218336585A419E9877CB63387C5E759FC93F0FE1A7BA717B8BE9B2302393E0D14DEF2F749D138692D0A0296F1C792B567F40037DD2B8787F1F47FF363CF34F37
+ 57: 7EB842771A61A9AF779C8794CA055518E7F38CD13F61638900EAAEA000B12816D52C593B62B9DAD79DB7397A463AB99A9D0035E7A1369B0556D593DB41EEEB6B
+ 58: E41D1492D3472FBD42F2460650F9DAF2ECCDEAEF5F4516B452D940DAD516F5168439154B4BA76610461B343BCF1E7DD7DD8C285EC0CC46C17CE3C7E14103042A
+ 59: 88057C0B8442BC5763283EA17FD1FE1AE011A988E1D7E0F914004CD3AD2E06FEEECDF59E309B9EBDABF19559954C37F71FA98C14BB19F7B91CE5F827C1DDE1B5
+ 60: C5DE99AA273D1971272263C740E689739B39725A0B7C48B41577F05738A24F5EE2C0B673F93BD52A083798DDDC6E70A209213B58C95D49ABC5BCBABDD6AE7D22
+ 61: 68296AC346BA3B14C038CDC629C5F5700CEB9F5DAFD94F948C6B991C0F91813BFD02660A2A05A02A61D8EB03BC93601F9F6A38196650047E1D7DD1071CC6974D
+ 62: 1CE0E6793B0ED59C4DB7D5F24FEF75A4ED2F28CE4AA7E5EB25919219C2C04935E4B15841821FA92FC7537DE2A538871E5A043A773CB1ED061333113223248C18
+ 63: 37BF321F66ACE827B66ECAA651CCFCAD30AB627E717AA4FE441279C4FA48555CB7784B0AF25A73B86375BE71A1E3FDDEC661E0EB8115E0BB2B9A7FF81DC75DF9
+ 64: 5C3C6F524C8AE1E7A4F76B84977B1560E78EB568E2FD8D72699AD79186481BD42B53AB39A0B741D9C098A4ECB01F3ECCF3844CF1B73A9355EE5D496A2A1FB5B3
+ 65: 85A19923268414DE6A10A2CDEF7917D7AA01E68DF9D028CBAB5C5236FAEFCED836BDE9CF90D8A214013056202A1BAE5CB73606078C5572D8FE85C36002C92D70
+ 66: C2FB9763A6F86225F6C66F55ACC8E7E17C1A2664416B2704D64AAC2CC5B04A626030B5243CA61D62076DDBDF3C6B3765C38D0CFA01D4D45C124EA28DA593F84F
+ 67: 5083280300FA5A1B172D7B5CCADA5CECE1EE5B7B5D382EB4A430179EB133970B0B89F6BB6DCBB1F38EC9F13F5B7D1559F114DE0EE26178EBC56CBE31BB26A91D
+ 68: B3571E8C1CBC0C58E23094B39352D554B43F9E7DD0FF981C12A01E0D8BBFF06A39875D90BEDA7F345550E6F67935A49E0183456B9967BB319D74AAD87CCA3695
+ 69: D11537B780D458D37279D00621F646EBAD3244A22E4D45DF11AC5D084FDF70E7A32F897DF727E65EDD1019DABCC05DF0B5E015FC5CC1184129C5DDFB14F62154
+ 70: C146458EF40E6F1944BFD863B2862A97145BA580D47C7ACA67E797EAC6790841C57D68A74930AEFCD49031819FBED806A0C033DD529A203B4E460F357BA1BBFB
+ 71: 660F3E1D5CD3B2AFD95DB0D8C258F6AD74DD40DB688A37AB4A24D720766541B1CB928001EF6D67CE5429039C9C1490613DDF90A27E6152BE7D42E1614C590056
+ 72: DEC468EF73E98F44B60EB994935921F920DC0CEEB7498655F0FAB7607A77A7A3D9462DD8BAD46CB408EFA81FF08D7E9508BC565C1578C37C2B87D41A0A32A549
+ 73: 070D4C36A0934C5C12E6B65FFF385404E49C3871DA8674D93D26E3166A7EF9693D946B419F0E10C9624964B37493DC8A46D26D8AB8942E60143036659CA4C91D
+ 74: BB8935CC84E08E6B4E7C6233E41D880D70CC018D1668EE64F19906A83730495D01AFCE1A4EA8129A98B7F9E074FD35C0BA6D5667625DB63A867BAA67BDEFC190
+ 75: A0A7A0B619643115C582BB6953D2A3EAA942451F631FC56C0933B535313D668FA4CA7D6BEC4DC9FE2AD7528DD6F8DBE68478A040FBFDD2F3DC3AD7035DB67371
+ 76: D6C57C3FB08D07A30A622B25985A52A6E552499345244725B1084E41691B11EB31D3B9776940A9A7E6115D2D1A93372D3A7388D87B01D13BCA726E8823E89729
+ 77: 413CB26BE2B1BA8ABE930ED1B9978BA4874CF32B38C825CB6DFE9C21A87C0BD115D3357198FDA0A5B7CDEB4235A354E9C2F37D11B33AC6A257DEC67326830E23
+ 78: 748E4648FBD009E4848E44A284D0CB2088300F50CD5215A285826E968B9DA59B6322E1987F78447150AF72CE37E516BE9E83B05A9817AB7A924ED8B09557CB5F
+ 79: 0A8111FEA824D43E0991C22FC3B1368A191D0C73308283494309D0762AB1EE5AF0CE2DB8F0562DECAC636128688540E845D72BEA3852A19CA2ED22D6C1E82CF1
+ 80: DB1067879F014EF676471D950A81DA073D676DE52E85F67890C8471FE6144078DAF940CB6F9F097BEDB8FAC94C737C5B8A3B4217CFF4A56DC349B2AE845AB25B
+ 81: 6165F19F569BAAA3A3ABE6D6108D07E1ECB22092F66227DC27173DAC097118C2D927F2E5F7D20C8CEF0F99C6FE6C7AA46BF18FBC452F6FDD733728030CD0A4A6
+ 82: 1D4AA14617A4BB9E48DCC1A7EE5DF65298AE45FB193F077FDB6D1C2B3252E1633AF86A527C29861661CE155A47E5BAC91D9B07715E0FF7E08B39A3128891EC42
+ 83: C2C22B53D6BA460954C2D826FD3DEEE60E33AF2EFC87A61CBF2AA021166AFB90967ADE2C564D037518E4141BE9C0D0BC0B4F95498D5AD920BF28CAD4F5FE700C
+ 84: BB5E9CFE19C6A2D14EA4C1F6BDE51855DF61D650B23330BAC30A5072EAACF86CA02AD31FE4C146176DEC75C56A56C2B868177E0E365414508D2E7606AB9E8921
+ 85: 6B40A13C5486396864608BE7285BD4D1205180BC41E10E537042A1CC6CD12FA7737B5E73D768BBC5D687FCCE41880A8D9773C26316ACEA2D78DA26FECCC11E90
+ 86: DAD0DC8A7D78E29B12182D36F47B93CAB562C44FD6C5B1718651022CDEEC30133437431D13C43EC1C02DCE776F459A57C29355B3FA0D67C6BF84AD26194A8854
+ 87: 8118AEE5DFBD7FD9F94403FFD3C6BEA08706D4C4DC78CDE72F751A6C4027ABEC7786A62732819ADC036B787E25E151AC51B60BD2381A64F05A326800D7514B15
+ 88: C64737334A61872EC00C8A3F1B1EA931FEE8D80203CE6DB9F1ABEFEE2CD3E652971615AE4F9A23400B9E31D861BE6B7E0F6DED28ED74B45D6AE90E70AD49508B
+ 89: F927B571B03B892B46C0A16148F13A2E6B80630CE41BA7DBE311F9ADBB5E8F23923CF0CA527DDD20BB3FE42BBE805066BEAD569F6FED12A2722A8629427ED841
+ 90: 2576A445CCD8977F24F50EE30EA7A51F0F3F49D41BAA663BD1C1734E02367A382E3D0E8C07EAED0C6A47CF662FE573BAE5593D9C4BA8FFDB4AF024F6064F7A89
+ 91: E85C73AEB638F35565BDD2523AE2A86B573C339B4D5FF8498ADF71BA587CBF146AE63B8C920B2F0A166F802167A04CD0D7F7A842D7D058165894CF9188289032
+ 92: E74E2ABDD6AFFF851EF78F8A866DDE9B9F86D906B298DD1E3630E1D4A30B6FCD7FF91943A57367A00E2658A84346F53ABC896EDAA395167E5EBD12C954E0B820
+ 93: 6827226985276BA731A9AE2E4DBF2D0187C05D566F06D098E05E3F425DC058958B50F09B4CE0741F1375E9B522F94A61F1ED8A43A8D03A036D2ABFCEDD4F0C1F
+ 94: 19A71A12DCABA1BA185BA38BCC0D915584A801EA49F975393B25AFBC456571CBF1A6F9121CBAE89A9B438092C65532489A95A0864320102EAD9A2EBD30D41F6F
+ 95: C70F19BAEA7420A7482C9C54CBB689A9AB93E4F8538EDC2371A1EDB3A103DFB7176E04DF170FF71EF46DFDAC1E8F9CD6FF96115BE1EFC271A56BDCFB67D29E67
+ 96: 8BBCCFC8815786ADD9F108F4381A2B084179002AE940ADD4C42AA2550C353CD0351C2F7F1BD544D8F268FA332B0E803838318A39079E9D93269A01EAF9CAC967
+ 97: 5266FA966A04B8A2450ECF3826C9E1516FEDC33EE81D4911A601351564D27C8BD4A11BF00E0DE237E50D75421CBE475E38967F28E6A1C5D311A2C95B84898D1E
+ 98: DF87823E1E02AF34532C5F3A08CF03CB9B2017B835525B3E3C448B1ED15569935D9A1DA19A6B1E8D056FBC868447ABE6226B97F256F6B638B052B4BAB3BD4808
+ 99: A1317CAC2364B10EABBD3540B6139D337C0EB3F7A740C050988FF9B3584213DF5833AAD81D36C30CE6CE76962A9E1D45F08667A314036A299454F25F73EB067F
+100: B752B6EEB497A8BEBFC1BE1649CA41D57FD1973BFFC2261CA196B5474E0F353762F354C1D743581F61C51F4D86921360BC2E8AD35E830578B68B12E884A50894
+101: B0BB23AED2CFC9C58C8BAB019CD10DBE75717EE8F04AA45FD8D84748E3F05C523FD2F70DCC460F7A18DF7D28A224BCB86CFA4C8164D081D51F3487A7BD0C8109
+102: 0FA46C6A759DA9A3649679780A28FDD51EDFD3F99A4B801C5824247B270A137CF40006609E149C919CDA0A6C856A9A8E855A670A2BB2CD5211FAD42E84F6E365
+103: C4E350267BD335848D00151AF2C380E49A323E63AA264D534EA1BF7A860B764A78993F7FFF34ED93ACB1F5A5AB66758C462B4D2F2F4E14225D29FEC0C102E772
+104: AFA0F1DB8A321FC6C4EF7C65ED2ADC4B094E928E230D27295699DE68FB5C1657FE0E5C4E66C5852ACFC45DA94BEFDAC89CF0D4174B262E6FD51CDC3E7FFFA5CE
+105: 9A86A440FF8A33DCD38C69D7564EF827F614629CB699B7F45E7FFF1CFF4AD5E27EFFDD32EF1D0845987A6A273EA34C19374E9FB606BB2E3B909157CC6666D29A
+106: 1FAF8C564575D654133B0A452EC43959C9F9E20C044724B74EFC90D2CECE4C49A0512C9F4DA2E999552E3ACC04CE0F0E2FDA9826C2A1FBBACEC4330081D5CA43
+107: 8B35FFFCD91E617C8A49B13CD0FFA2199FA1F20E5633AE6E95881BBCA02B1E047392DC9A4C0F0A4C39D3984E78ECC4DCC1B5C94A26ACDC1F69C7ABABFFB45175
+108: 6C8AB69E946FE86DEF6F14B955B8F1977686EAFF8E384CA45F245CCC0EB1C80AF8E62B0E7387C0DA52BBA31B1A01EBB00CA26CBFDA9D8069A773C3B62F989A2C
+109: C3A243B45B7C3C2002CB197BADBD84C4900D504FCD277D2DC6C06D34B1317B41EF098BB980800FA9D011C0363D074308835AEBCF3393B1C925045E97E14831C0
+110: 803E065AFEFC6C48EF9F701233AF512465729E81B0DBFF99A2E7FEFFB542831E1D3B30230BFA2F30343695C060AC8140C37CC8D1E25E95E6A1139C5522F4ED28
+111: 86618429B8720ADCBC8B9FEAED8BD44E0848572CB6137213273563EBFDA859240E17DFDAFF68B09953F1853C9E7EF217875E7BD6959E76DC3A1CE5F548B76CEB
+112: 96439A93295B5C479F0310B28377FC10DF81B593AC233556B15897F1FA3886C940639AFF2ECEB29894DA884626B4811254FE2622EC7B4577087D9046C96AA556
+113: 9F7BAE13DB80C72A434BC4704998A73D7E546CC2590E0D0EE511CAFC63C622A8B2A296426E42754606D02B6EA060892E325EA1AC13EF0B523A3551F4D25BE241
+114: E999A862E5C479B7BB21EB52E4BD301571A8A39B712EBFEFAC720F28C515025E98CCC74B950D57CF3C3B34D788D62CDA0339AE0DA02C8A107BCDD797C4751FF1
+115: CD00EC5142CBBCA87BC15D69EBE96B5222F25BE1576B318208178679B13A9A8BA4BBABE9A488BB38C4EEF327C9A4DEA4225DD30C0F70B97C18C5C2FB19FC2134
+116: 1289951D2B62112BA590D8C0CF9EFA38AB77737F994060596738612E6BDC41EC8672F50A027A2C049299FD39E1776BC3EEBFE3E66CCF4009615D63F0A4C43ABE
+117: 451A46FBDC954FB76E744AF3DA8429C881197F6BC12D22412438729288AA4540843B9FD4CD1BDBA5E864FEAEF0CD6CFF045A37510B3759FADFEF4697E9BF9240
+118: A267FCDF72D9160DA2A01E781E07701478F95A38C262ADEBFA194EA6D5A50A9CF3E04D32AA4B492580C6E8D8FAE1F813F3C17F82B7F47D8CE0C900F0F3052F98
+119: 3D910AB6579455653EFC939BE1B22D993537408086361008EBB166724FAFE3C8578EF4BE0378BC28ED883FC0FF3DE5A9310CEDE65FAF3AD9590A13B3CA4F81C5
+120: 47386DF4D41775737BC4E52D7CB2EFC11BA335A5D59597B5DEB3DD0A35032461F5DB4779D48BD6F3A10C5503AC563C790235E6F54EA79CEADB6A56AFCCE890DF
+121: BA59044EF3A242974F074337CBB6840FA0506C2227A429498F546B2CEBE0644DFF1D442190C48CB54BEE72F960670F71AF1F8402AD5ABE8C1482DEFA881FA903
+122: 89B4F35E5C8C19AD61CF1600BA80C1A1BBCFDC86AD9F8066C967BA10F62827FCEFA1EBD07C90C82B48082A5B7D6A72E0AAFD230DE05955C7E8C081286B0CA96D
+123: 0C7F94250F4EA7647F91E7EA8B8612AE8E7BFE4F5BCDD90CDCE564BC9842F6987AFB4C3661D8431440FEE18EB2EC70BCCD34A6B61D209CB72BE782A0808C08E2
+124: 2C8B8B17820085795BC6A2720B5D0BDF5407D9DEE1CAA4270FFAD010AE9555DFD2B74A742512BAFFAA1D5B4F14ECDB2BD4BF37838D5981A317C7287805974019
+125: B464C5A9D040F11DA45D98C4BCA9295D0F589DB11EE5603410C62BDACCC329B9AC14567C3A6F3BBA4B92CD3B95BE58AD4DA435199CE62D8BD61269F8BEA38FE4
+126: 2F64554FD54AA4A04ADE3793AFCC5C968B1C3603F4F71E1BB5342BA4E951D79A4580BF57736E7FC13A43604A057E9C360C099AC5B3403DA8AAFDBBF417FF6ADC
+127: 3C9A7F387B7104DF19CF264B0B5821B2E46E44ADC79262546E98FFA113EB3D45799EAC78CCA4643C937FCC3C1D249A212FACB34C63D45EEC81069095D7CDCE7B
+128: 803A3B37C89E84FBBEC75BEE3D00DD728FFC4246B5A5E989DC8DC2CD0F7937966AB78C79E1D4648EE6EB40F3D70491CB46B8AB42E155672E2AB8374FCF70DD79
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/hmac_tv.txt	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,1736 @@
+HMAC Tests.  In these tests messages of N bytes long (00,01,02,...,NN-1) are HMACed.  The initial key is
+of the same format (the same length as the HASH output size).  The HMAC key in step N+1 is the HMAC output of
+step N.
+
+HMAC-tiger
+  0: 2EF793765716EE48A671BDB5F002103C43734304C8717C85
+  1: AE61B56C82BE9FF96DCFBC20DD02B4BEA4FC6B6D5F4EC412
+  2: B54ADBFB404457E6C5AFCCEC27199D1F259EE1994FFFE99F
+  3: 08AEEC38E88403BB854935EB6F1464CE95B044F4B4202524
+  4: 4C9DAEDC1929E22128F2A7ED5F3556D8A6D3A8315A7B556A
+  5: 764794ED9EE1F94891835CC3A361FE75C600C7951A07F450
+  6: 1A4C447A0FB8826A0881ED2E7BD89499EACA4B6C49F96060
+  7: 1396A21D8B465C6B898511DF94846588EE8E35C0095AD90A
+  8: 7552EB03CE26A8F079AC96B42F556FEAEB756014B8FDE622
+  9: 835B7CCA9D9F13BA2A36CBD746E5C92D5B2D123CA2EC848E
+ 10: 7CF4EA88FF8B9A5A57E5ABB6B35278EE9D8653F624D662FE
+ 11: D588D953C6F438D077A1E302F84E25EF31AD99B9C5FC9DB4
+ 12: 86EC62CF1A08CEA9171AC742E8E615B3F0C7B6FBC95DC3C8
+ 13: 6EE7C51E26187F86370A26811C75136E28B0C39A113D80F8
+ 14: E1326D54123BC26CF41B30F9F2BA2E732203836AF8A74273
+ 15: F211E4C46862E3AC8B8E69976A705582CF6D1B34A6D342B7
+ 16: 0C6160FEFE70C81C71B7465F42F070F30808CDAE448D1974
+ 17: 492FC6BC091489F926F0F54CBF3E3F6C8CEC6ED14DF2DF8C
+ 18: FD166027ABD1BD9DBA13E3908D16C403E1691FF173328CA4
+ 19: 28D99C64CDFFAC1E6F7B33C8E675E49749CE835A177A1C63
+ 20: FD7BD55BC2A684F4875C811143A2997356AA87A300345843
+ 21: DB8968E787BF65C00992ED9DDE974EA71BA947395111FFB3
+ 22: 4C31B2FA4E6F7F40DECA589F85BB69BFAD1815A73CF9EB23
+ 23: B4D8D7FCB314942F171F85EA0953F7816DA9F07D72AF48B5
+ 24: 9A6A70BAD76203A7A1F64D1EE34375EC8BCB21810ECE0B68
+ 25: D21D7E5EF6F1579C84428AB5D574468933BA037C9B0C34B6
+ 26: 3C5292C87B24626241693F0EBE20A96800905691C5945E65
+ 27: 350BEEC075258BA7FE0314E6803152B021570F067AE0D4D4
+ 28: 6881F892886F9D66E68B937BB3A71FF5CB064611C722996E
+ 29: 07831F1B2D00108386339F192729687B2F57B9DAB2B1210B
+ 30: 38DE8DE8398EEC32939A239BC0198B0CFB18D12E4F2A3023
+ 31: 5B683578F81867054089AE2E1B20E02B3BD92334CBB01FA9
+ 32: E30A80BE07651BA17E2DF0D43A583A9DB268DFF3AB7393ED
+ 33: 42341B1EC4F61E90571188F5599FBA9ACF884B1E15694921
+ 34: 7D98297D65F5FEA85CB967F22AE0707E03F305BF1D2249DD
+ 35: BC8EE5CE0FA8F9E6694406009EC9358BC420B7E5DE07B6F8
+ 36: B8095DE6770CB4CC2127FA672F93F39CA4AF0CCBB9805DDB
+ 37: 20C0E981DF1B763B6BB47D43F66765AD434127C1FC55F829
+ 38: 59795328D40D2CE6CFDED8DD5089F2D5B796C9438E7646CA
+ 39: 0789CAB229AD54416C82CA5A2E667EC7CE66019FCACF766D
+ 40: F7C81B1AE705019FF9A9905972AFD72484A70E11FB81B278
+ 41: E72F52644BF5EE59BE87DF692EF0070D095115B7664BB53A
+ 42: B9A5DD984358D0B0F3C2781BA60E9BD3473C1C89C7982F23
+ 43: F7BA22269249759F1A87AEA0A125D4DF9B58E93714449008
+ 44: 5D2257317F8978576CD7D2CCD346E861A59FE949F74A3D82
+ 45: 199D8D5B0B5C5B61E046F50E0E389DA6F19CB3A7A37C8588
+ 46: F489CC6CB2D3E9F741D6C9008265CCA97E7E54D62F5EB85F
+ 47: A5E7CB0787EB7E62A9CFD8486390A6628C9876654B9E85E4
+ 48: 22FA78EA17F0D29E16276C70A564D234BC4ECA7302301528
+ 49: 4422534FB9EEC601CE7662345D6B6FF932E54BB0483C2F62
+ 50: 5D2E2B90B460D393F36BF32B2F491E224EF388FA72A48501
+ 51: EA5287BCBB856BF04FC785541079087CE24783E9310F3090
+ 52: DEDA3920899FA69F913AE50A4F0D7119C9D3CE8F4E6D5BB2
+ 53: B2F55D8EA64C9842BFEA4FADFE616664CD44C57D53998C58
+ 54: 3D2C72F26188E1EF5C0F0FC8B541224066C4DF455FEE78FF
+ 55: 50BB36BD8A8D97E4D6CA78DDCDAD0690FBBC93DC9A66BF18
+ 56: 48140E192FF8AB74FC22676AAAA186C1A7E2FA0166E986AC
+ 57: 40AFD540C40EE7E598D26AE3FE5A47939299B5DD46B0B4FE
+ 58: CEBBBD763B077342BA16D4B20412C9EDE0F0508ABCE3501B
+ 59: 0FE4DFE539160F5924C324B8B43DACB4F220195D286C6FA1
+ 60: A06D135075F943CEE74AAB1B8DE08B772055551B1E73ED48
+ 61: D4E1B5EBBDA5CDA5040DD697BB96DD702C6730CFCC012992
+ 62: BD5E77B67B42C507C4912130C8880A9DBD66431DCA0C0038
+ 63: D81F583A9B4DD1F48028CA602CC0F131D60561FA34F7B3B4
+ 64: A41F0481EE52842CDF676177F8E43BC1F1B00A5682C63E15
+ 65: CDB29E274ABEB20EECC8378D5BD806997502E4271AB56708
+ 66: B8366ABD45565BB3D26CE46B6F419F74B34851863FF4C336
+ 67: 5AD2C193D6D51C9C7E56C5BFF55C1D61E045366B51E7F619
+ 68: 9948E3AB7D121B15A6CA8DFDF4EE5377C957F0DE891C3575
+ 69: 095676D61096853635128A80570BD1CE803AC7249C0A0F57
+ 70: 354F4CCC1E5112770B2AB035AE07200A6CDC0280AD088AFB
+ 71: A8723395E80BED25DFE8F9ACEDA942A77D225D00440302D2
+ 72: 0D2BCE0F8CF396FD8277C8BD9B19D54965308D3ED04D2F27
+ 73: 54B1939E9944F499798B3DCE3479AC315F2C42A1EF231984
+ 74: 5CFF726EE4B2596240E6CBBC66D7C737A4D12A702B40E81E
+ 75: 82996D7F3F27B473BDA647BBBA7230DF217288F2D1A38B99
+ 76: CB95F63E0E7A2EC4F26E94B81A3C8C757E04EEEAB35A8C2A
+ 77: 057DEDF45207EA885A0BAC5B64240DD21CB9D99CD8F38FEA
+ 78: 27DCDD1ABA459506EF98E5C8D567692264C4153F91FDB269
+ 79: 911C83660F7EE8CFB5F54890AE98CCA36C4C12B8CC771DF8
+ 80: 67CD07209988C517FAEE01E64AC4B5CF261B6035069508FA
+ 81: D9A40C407E2BA852684770A5EB08D8502DFD264F2DE5A5FC
+ 82: 9AAC50A2BCFD74BE3DF85237478AAA833484FA3DF912A3AC
+ 83: 38078488F6183B5A94B655F24212FC9769450D93986C9208
+ 84: 2EFFCBFA4CCCAFCA66BF8B368FB1FEFAC280C20416BB90EC
+ 85: D626FD6D285C49F20E99B88B9F82640D93D9E765CA55B5B0
+ 86: B1DD178943B26AA241D34031D3128344C6955F6A942CC5D3
+ 87: DA0C850E2067F9FDAE433C1230E0F629700FC8896ADDBDE9
+ 88: 58E393E353BD7DF75A591904AA99526E94FA45C98D095E21
+ 89: 323D0E04D239BD70192B2ACCB9ACF06E2F8C3B07565893AE
+ 90: F9C4147C6921640C097534BB08020540B420AD569D03665B
+ 91: 5171DB964AC815B3A6D058419FD47833DDAED71039966E6D
+ 92: E7DC7C574AFC2C9A59E46CB8ADBD03330A5321B237DF7899
+ 93: 97074CDA9FF8D40B0501E9F632ED7335D6A7926101A34C0C
+ 94: BDDCD4D007DE39680B80F9AF9803A9F21C836EA971250CD4
+ 95: 0DBFF45E3155098D4B4C13815FB461D3C4BE41E9E1A68757
+ 96: FC16CB95478E4D23A7AD15CCAE3C24BBB3D0FBDC8A00A144
+ 97: 93A7CB506481D6A72EAB14A2BA544F8631542B55903CCAAE
+ 98: 9CC1FFA19736AB6EB36EB4A2C1624FCB6913B255D2346795
+ 99: CE3526A088FFEDEA4345AB221707848823B16DADD19AB487
+100: 1E1D790323586DB8A306EDCCAC8C64A6F29A36F772B8D61D
+101: 8C403515F2B9014E9519EC04769ACCF23E522D3E22DE7F41
+102: 6B6A634607634804988301240CA5AB029A9E86E51281D64E
+103: C7C3483CC8E6B58520B554259EB08866AA7980B53FFB6B86
+104: 96E429611C9E411321947469E2095CD9B0EF29578030E40F
+105: 5C5A7F2B7F1F9BCE730BE2779304A443188FD3B31DD2BF19
+106: 70933F999325353277E0AA1F543B5CBED3F28DAF4FC70A57
+107: 5CD6D136FDDF4AE9CE42F008301FB6647096D5007E79973F
+108: 1162BA742AD199AC17FC707285301A82BA9CB12C09BA229D
+109: C36615F6D5E29E6CABB7EBC44A6D3F7B024DAFBD338FEFFA
+110: C29FEF051D1606CEFCE3417BD571CB9188BBF0FA8AB98679
+111: F925144EDDD27244E19E4B6E433F312C6CDE43EF4F9B84B5
+112: C4230A59E54A34D0709F3F1DB02C18EC8AA270078DE424D5
+113: EB1699CAEC36681CCF8A9144DFB5050566042977D15FD1F9
+114: 9FBF0D9B2DD9A6E87240E538590E9799B76E22604D22AB75
+115: 2657EA06D69A78A5895A9169F849B3DE111B31E5673A8E17
+116: D1F9E1BA4F4E52CDAAFC388FA4C366EF4BD5F440608D86B0
+117: 049196BFFD9F77175FA936066C3119293EAB79D1E0028C8F
+118: 9CC1BD2CADDEC1D82FFAFA7031F2E5C9B6765CF1727A0ACB
+119: ED00438670D68A70CE2E0729997CC9648947EEA35809B8C7
+120: A520A0089BC16C84CB8E05425B330C6D261108EE3049FACF
+121: A55B470483E547D2752EDC3C4FDCF3B4C48A1990AD857941
+122: 46A78E772C533EC8EDA60EB4A127FCEBD35E7D0E7F183241
+123: 5EB9A774124D571FCCC83D1F36C603D9C387390DFB3928B2
+124: E904066FC77F73CA41166297A8FC631FF59634B659F0AED0
+125: B85B66AEF7D9904356F1CAA5583757D1D69EEBB8AB1D1420
+126: 6639F85214BC798D71B757FCD480CB78D325881781A3A073
+127: C5B72BBE80917B55036A9AD6908D59293C49373F0BDD104B
+128: C0BD695F6B9B42DAB543C31BA73C9497A6AA6419A007A9F6
+
+HMAC-md2
+  0: D39AD9DDE006587A8BE949B11B9288F8
+  1: FCB21B5348C95E8A8DCBEE50A80302CA
+  2: 2F26B6ACCD0E03FE9B21A1B0E75FF665
+  3: 17CF85D985D0D85F545897CD42C6EFE5
+  4: 1537A6943B4F5AC1272E4161225D987B
+  5: 83E17165D62CA6E4B9ED67DF1E599954
+  6: 7A3195C863DFF86A98968F254E128E61
+  7: BD05057AEBFCB92FA4B07456085EC6C2
+  8: 23AC0D307BFC2E87760F8BDB21851DF8
+  9: 2CD26A2F2994106A375BEB0433575BDE
+ 10: 1F63BFC44FDBE9A966CD90DF82265EFD
+ 11: 72735FAADC3819CC24CFCE1D589BA311
+ 12: 28B589C3C8078B8FFEF1C8297E33C1E6
+ 13: 70A6DC014CAD2752931A47C0879D2371
+ 14: 81694317A37FFBA816504974F38B4829
+ 15: 72F26208B3051F1B938EA7E03DD8C107
+ 16: F945F57FE0696A4C81EC59AE69384FAB
+ 17: 54D8DFCEE33969486956698495B4BFD0
+ 18: 508B82F88A234E753A9E305E15A14D82
+ 19: 527D77D2AB25131693B02F653ACBD90E
+ 20: 4868AC540FCC3A896D5A89F7A0444D36
+ 21: 6189807C5FDDDD68D20356ADF3B90DC2
+ 22: 0356362F2BC4206F2B930C4282213758
+ 23: 2F59956F19B3CAD687C66C4EC3CC916D
+ 24: E30CEFBDA3FA1A8EDDE3B72614ADDEDF
+ 25: 33E0E6BFCBC9581BBCDF13F4D3F26724
+ 26: B11C6476F9775219A9F18B5E88857790
+ 27: 49C7A9D7F56344BD405E53BE927E3A58
+ 28: 99A06874B0F0CA45C9F29E05D213195F
+ 29: D21A60A18F061FC453AD5AC2A519071A
+ 30: 2F735E82090144C036E3D12DEF2E0030
+ 31: F9539EAC81BBCD0069A31E2A3C43769D
+ 32: EDCAA9C85A614AB6A620B25AF955D66A
+
+HMAC-md4
+  0: 752E874F35085E497D5032112CC65131
+  1: 6B2CAAEE210F970AB481D6D8EE753114
+  2: 2162A41522C2DB0B8AF1F0C712C19A22
+  3: 7C2106C3CB687F35FE2658BEEFB497A5
+  4: 3715333CA3EB74A15B4B1802A1A78921
+  5: 403D9A691A130AFFFB81A655AAE1D956
+  6: E697C3CB42716CA1973DE0D15486068E
+  7: 99676F34E42C61E396F0E76BCB77BEAB
+  8: A2B2CE8CF8AC151C5556A36D58894C61
+  9: B8614BFF1DAAEA90BF319F333024976C
+ 10: B8759E8B97DFCBB2DB94D8CBE2C96B20
+ 11: CFFE6119EB0C649831459339C1B0C82A
+ 12: B2FC0DBA9C4830CA66423728599D3660
+ 13: 454749F1DE579F1918FF046FC1CAE7F6
+ 14: CC625178FEFD46481B7D02618AF6194E
+ 15: C26D523EFCC42C4AF7EEC2EA4B45B719
+ 16: C352DA2D077FA3F493A5CE0E9A79CB87
+ 17: 570DDE9FD220F59867F17484605D2061
+ 18: FF5954A163CBA61CD3C8424CC71682C8
+ 19: 1240D12E3D6C07F6FE1CD595C847C038
+ 20: E87A4D7958C43CA71791B13E16301036
+ 21: B2CEDE4A15F8D64C53D243F8C5763C05
+ 22: 54A9E9EAE155E7AFA6FC8A7E05D7FA9B
+ 23: DF0E79F27CE25E56ABCFF5E74D1212CA
+ 24: D9BE454A95E5D9127990577F7EB7183E
+ 25: 26F9221A8B854767861BF0281303B89E
+ 26: 92BD4CC81A673B254A4AB493864BB014
+ 27: EBC3851E0AD28BE9876BEFD6B0A88B44
+ 28: 1134BC8A40E1D2FB038B67548AC2040B
+ 29: 954700135C4E7F232337C84130B43360
+ 30: 8C3EF2D8F896C8D252851A1543F72493
+ 31: 52817E79D2B0B3A37DC08D18D3519F92
+ 32: DA661A428B9659DD59545E3B09162F8F
+ 33: 3FF5BB67B48F87B4B642DACCD2E4001E
+ 34: C674F95BB622D7B8281FFF34E9EF3E7B
+ 35: 3A4D25E3BCABAD8CD4918CE650EF00E9
+ 36: 2D91248C51837A8B80898E2CE42CBCB4
+ 37: C0B3BD2B36493F0EAF9AAFEFDC37064F
+ 38: 9B4723B091102B480B2B59069317F292
+ 39: 0F8EABB489254491FE19AD0E328A483C
+ 40: 25469BD482E1405E51AA021752394C4C
+ 41: DF1DF50EF9D95892D08DFEFB79D6552B
+ 42: 707A546964CB22710482C478E58C2E0F
+ 43: D1E243DB14E2F946D650C811030ADE9A
+ 44: 11A1AEA678E98A65420747DD6CF9293F
+ 45: 66E735F658BD689A9F1BA0B526827CF9
+ 46: 98170734E67F576CCC3D01D83965A6C9
+ 47: 399D99CB7979E80F6D3B5D5BBA5871CA
+ 48: C26651C32EABC76289CD0843D3BCDD92
+ 49: AE0F50954C90E8897BCF504592D0626C
+ 50: EA3AB701136862428EC326D2551F8AC8
+ 51: 4AE98E5A1E6B1BA8CEAE844E34934039
+ 52: 7C9826187053186DDC2760AE6FB56DC7
+ 53: FE0F555B851CAD830BAC9FBB40705671
+ 54: 221BB509584BCC7E10F3B4FAB2AEB1F3
+ 55: DD93EAFE25EE27C6FDC2CCDE7D273267
+ 56: 535472E1ECD49FAA75CC6621BE7E6210
+ 57: DA4554FF7D5B289A03D195F94154AF47
+ 58: F15A3F547B5A3844BFF713CBCEF701A1
+ 59: 279DE06FD5644C520BADD3B97D96274D
+ 60: B933E929073492EC1E2AEB78071C7B83
+ 61: D1DA2335654AB4CEBAE5C2E78CF27553
+ 62: 06FC50285F4BA5C8B5A478E9C02D6434
+ 63: DB66A5D55224DDB50337B7FEF9A808A7
+ 64: ECFCD0385FB49553EC89DD94AB084D23
+ 65: 4187B0B79E6CB916F747B857AB2F75D3
+ 66: E03E14F5E00B2DFC0614308608B929B9
+ 67: 5F61FC3005167EB3256DB549DA8BA562
+ 68: 21A4D14DF8E934A858569D8BA7F151E8
+ 69: 5955DDA4CEF16ABADE2B551841C69B8B
+ 70: 8E77066A973B60DF64C27DBB93EF204A
+ 71: 2101EE9DC8221FF17D9D887FC39F41BA
+ 72: 6574A9DE32B7A673B5BA20FF18EF8C93
+ 73: F571B14C9F5C5C1858D48AA944A13050
+ 74: 0BA4BE0A5E853D07F79B2D29BCF046B5
+ 75: F240C8C38D71131F510369D79FA32208
+ 76: 920C294DE37C28803FF3C49A4135CD65
+ 77: 38796D25822AD8F2AB4D64E4A65626A0
+ 78: 65A203170FDF794397FD1090E318C5DA
+ 79: 965A767FE4A75BEECE26BAA79D816AD7
+ 80: 0F4B30947B790C47924657648FA1D88C
+ 81: 74B05F7B7D006F7DDAB31DAE251C3BB3
+ 82: 61B0366B57A8F46C2F6C16F935DA768F
+ 83: D4CB13CA922B542980F854C9780A1951
+ 84: 039B2F23A1CE410FF4696D9C35C40C08
+ 85: 2D734E28F995C2AA2A7AE2412EB99A10
+ 86: 1A55FE47703ECDBE446033F492412812
+ 87: 6AF4CED86D0181D6E99EE6AE57F295EC
+ 88: 69C239A875E0352D20BCFBCF8D5CA19F
+ 89: 62723FBBF0AC6F397438589AF06625A1
+ 90: 424EC9353901795251AEF7D7BCFEB8BE
+ 91: 9BBE4ED6C8BD14F85BA86E553B1B8152
+ 92: D7840AA82F788B7D58712E29003D1239
+ 93: 4AA55512DCAF770FE4D9428FB318B0B0
+ 94: D040BA08BEDFFB20D2C499FEB35EE12A
+ 95: 0F295EDEFC85546547860B7F7CDFB1AE
+ 96: 720FCD871B7D8824EE6A7DE9FF1A62BE
+ 97: 2FE3AD14E24C441C36186673A0D60767
+ 98: 943FD502136B66D0313951198680F746
+ 99: 4EE6829F3EFFD0A87115512ED28C85BA
+100: 6EE1AC28A320246CA5C37F981E22D294
+101: 36BC623D6573C3ADB164F8A6F02315AB
+102: 08B3AAED34FB0A0F99C4B22714B9CEAD
+103: BDCD10B66096AB992DEC5539773EAF23
+104: 6DA36A53A79FA2C68E5060C0D2D43E13
+105: A3E886199532C025074D4646113F9C23
+106: 00D67A1D2ADCA77A20441CBF593FDEE5
+107: 2E4399F5FB44FF5573B73D01C5B248E2
+108: ED22A18A8824A30B68EE0EF9907B2B91
+109: 36166824634304417BECCC9519899CDD
+110: 0757DB01193BEEE90617AA8CAD0360A8
+111: F7691CBEF4ED2E9FE4EB992CB3939970
+112: 09DC2FA975CBE8CE828919957D110EC2
+113: 7DDB74DEC57AE8C318AA5CCFB53872F6
+114: A26B7DD0AA30EAAF1F4F8314AB7DF16A
+115: 088855527BEBCDB67A40FEA4FDDCC061
+116: D0F8ECC0C32B7060CB6128279F57FD80
+117: DF5B79D3671CA5E5B44CD395F6FFA551
+118: DA8999EA059C463D5F05D04020EE867D
+119: C0EE404DD8447AA70D3725D5634E2B53
+120: D19D1A725F5E9F0DF21871B31900CA73
+121: EC202984BE149C93CC1D440CF6D29E1F
+122: 422DB7C21B1348983B75498E270FE6C1
+123: EF136334BC30C92DB9082A9654B391E4
+124: 0B3526430AE734054873B14DD696CB3E
+125: 3BEB77C0F85F8C6F21790ADF30EBB812
+126: 4376F8C8EAF5A94871822DBDFBB5F88D
+127: F7DEAF52378FF735B2D171B17EF573D8
+128: B4FA8DFD3AD4C88EABC8505D4901B057
+
+HMAC-md5
+  0: C91E40247251F39BDFE6A7B72A5857F9
+  1: 00FF2644D0E3699F677F58ECDF57082F
+  2: 1B6C2DB6819A4F023FFE21B91E284E93
+  3: 04B0ED3E73FBB9A94444FDFFAA530695
+  4: 1557A22261110DFB31ACE25936BDE45D
+  5: 54C5A67A9CB4544CA66BBDA1A2B8479E
+  6: F803D9E43C934545AF078FFBB34BC30B
+  7: 32F56EA655DF36D845E430D637C85D17
+  8: 14BD2095F4A478C10EEBFF379DE76DD3
+  9: AAF6867B3FA01DD26312B0DFD6371A2A
+ 10: 0FA2A6FEFEBE7CE3C31A38400F8AB260
+ 11: 54C37BE13B7333287D0E74AA9D9227F6
+ 12: 385D75A58B0C95E5CDC059DB168BD1D2
+ 13: E73003103ED65C08E62D46AE1E1B771A
+ 14: 278ED4A4EBEA1FFA5EEC874F198C0CC0
+ 15: F65CE9EEA7FDB90B9CC603329D3FB9A9
+ 16: 8640836944EE0009B2CC6FDC3F5C39E1
+ 17: 7819A99F82BABDF060AA51AE109629DB
+ 18: EF26336668486C76921D1DAB67ED5673
+ 19: 13ED7BC140F1496E09AD29C644586957
+ 20: 5FDD337CE9C4AC8D910833FCC2BD837E
+ 21: E9470246ABF7CF4D37FD378738D8F763
+ 22: 384A75C33EFFA12EB69187BB80DF843B
+ 23: 63866A5406B9EA0341032FCFD0244A4B
+ 24: 8042F8572C8A9B88E135ACB83EF1FD39
+ 25: BD1BE6AF2D022F966F612569E191F0E9
+ 26: 9F70C839533EE4C7B3CF20C6FB65C94C
+ 27: 800A5CE92CA4FEE6F1D353F496113873
+ 28: C35E93E1E54C84C4389D2DE71E1B9846
+ 29: A130EF5F91465F5A56999F450E63F4F9
+ 30: 5F16564E05285A099F628245DF9A3C2A
+ 31: A34F7E3DF06DD84CC67E8A922240D60B
+ 32: 945E50753B6E6C920183822D5F280F10
+ 33: 2DDD269DBCDF5C21A1C3FD540FF4ABA9
+ 34: 212FE3E2CEF7DF74FC01CC2CC83119B8
+ 35: D98B2930011649F16C08BC8C0178D838
+ 36: E39E21026111C1EFB0C491C0FDFA841D
+ 37: AE46DE06C3B0D2CEC35352C95A1003F0
+ 38: 5550EE50BF88C9DE5ADA34567FE044C7
+ 39: 6BC486627760373EACFF508F7032BF31
+ 40: AE6E0B8DBCFDCCA4B3449B57647D5AE5
+ 41: 6BE5A0F140DFC4B75439630E6F9A36EE
+ 42: E3E4E735BFE79397D4653A6243DF1925
+ 43: 68C1D9E8973A3F6B92B588469D68A2A5
+ 44: 956132D512118D5F446C8CB912B924D9
+ 45: DF5C2AD650B3CA7A89EBF92EE618C845
+ 46: 14D375CF7E4294ED99135E4237414F01
+ 47: DB966D40B447692E2D13CC0C09C1B495
+ 48: 53DADCF1C6B99BD403052A1CE1ED0D14
+ 49: DEC4A3C1DB8F6AA4515C512C9299C4DC
+ 50: 3B3A51DD83AB1DC56A7F0CBE1C71923F
+ 51: 03C73353B3203EF9CDB95F9DB8750AF1
+ 52: ED9E15FD86D66DA2D546D2BFC55041AD
+ 53: 81B649338F9DB1C6E592427D38221C7C
+ 54: 92E170E13BF40FF65E3B4C665F222DD5
+ 55: 00D5E23F5F829B21D454C4445851AB53
+ 56: 39057029AF0B3F4391A7BDC6DDCE4D07
+ 57: 2DEACEFA698F9CCAD5198C4E17E69A93
+ 58: AD35FD52EA199E26948009DF3546D3A2
+ 59: 4C42CF2CFD4D8FD9A06E3F73D02FE818
+ 60: 4D7C893E4313FFF72103854463414277
+ 61: 3F04E8B32AB56EAF216503E46BD7AEBE
+ 62: F015DDC3EEF41ECC93E944FA3577DB52
+ 63: 31F77A50A2ED96ED8E4A3CE04B9DAA23
+ 64: FBF481373481756E0C88978F7E0809A2
+ 65: 7D8D793B287C04E7D2896D76EAA5CA15
+ 66: DAC74AEBECC2385DD9D0C3147CCA1F78
+ 67: F6DDE50D37B460FF5E8B4C03A0854BD5
+ 68: 5710D6A54A2124E06A6DADBE9BF76119
+ 69: 19DB5D13A53E57184759F33976537AA5
+ 70: 848DD8D32130626FBD11B0133C2A29E3
+ 71: 4F75BE04BF2F6DD85D048DB82F19C38C
+ 72: 4AE9436540ED24BCB5EC62977AC90789
+ 73: 859D1A9FC2B795AD60F24A37EB9EF890
+ 74: CD45865317FD17B652DE9F9EBBBA16B6
+ 75: 52313319D395F453BA2C0A0159CF180B
+ 76: A7B190C0EECACCA4DFC5B45DFB324718
+ 77: 23E85CAE85B50F45F7F48EE0F22FDE85
+ 78: 6A80DBFF139A5345235EF76586CFCBC7
+ 79: 850E638FCE5A2F3B1D1FE9C28F05EF49
+ 80: 797CDC3F7E271FC9A3D0566A905D1CFE
+ 81: 030CE97A9A0B1D5403E253D883FCAF12
+ 82: 648FFFF44E416D9DE606BA0DDB751194
+ 83: FE15098E0DAC65FA8EE45CAC67121CC9
+ 84: 17C90ECD390A8B41046B4C7FA0354E4F
+ 85: 7D149DFF5F6379B7DBF5C401DB6D2976
+ 86: 8D055A4701DD51CB9D1AF8E2AE59BD21
+ 87: F3481CB07B034EB4A023D00D4FDA9A86
+ 88: FEB22562FFAAA9CCE5CDDA34C29E55C3
+ 89: A620AA447216709D8CE5C5F23474ECF8
+ 90: F25FCBB2BF7440C5E3C5B53092B8C828
+ 91: DBBAE1CF60BBCA0B05EDEA0B362F0A33
+ 92: E18E85BCB4633A797FAF7975CEF44B84
+ 93: 1BE27EEC72C2EDE151978705C7C7DED2
+ 94: A15D36C5C5BED77699838832FC225DD8
+ 95: 08F31E68BFBBB420742F80B20B69BE8C
+ 96: 5E9B4B5B3228F533BA8EFC3C0B9AAD3D
+ 97: 1239BA6D941D1D8AD2ED561BF517D4B4
+ 98: 5233F50218E0D097EFCC68F1536F30AE
+ 99: 340B47C78B003272EAA4B9D22C3B0542
+100: E7F11759FE8A897364C21767570885BB
+101: 054BD6ACBFD5421C0290B0839C0A0ACC
+102: CC0748F7B2CC921CF5FA019F955066C9
+103: A4DF167697949B1AEDBBA3226A334BAA
+104: 29893B9776BA5E750A9FCEA37B0116AE
+105: 2DC25C935F006F7965FAB3256D77004D
+106: 24089811FFF2189FB9AF38651F43977D
+107: 0E048569D634BF652CD8EBF859C9B69A
+108: 00386B569DAB73844A708BA5B48BBAA8
+109: 8033E1AFFBE1218F81C8331343FBE5B5
+110: 9B82008A34F3847C1204ACA89F3D57D1
+111: BE1A529F88AA05A42AFC40F663E97849
+112: 5237637AA645E83B0E56A1361AB80643
+113: 15BC4405E891ADAF48FA56D4356705D5
+114: 0820087438832B63AADC479CFC88BDBF
+115: B1E3BA7E96605D5FF614B1BEC1F57AC1
+116: 838A096D64E6C0DDB069DC89E4C3F839
+117: 934BCE159F3959A933C87AB497CA8D42
+118: CA501F1DE619A570DC38FDCB8B3F7722
+119: 033B27D5994A6F5D5F6800539B69E876
+120: B447FC68FEF4E3CF9290B06EB6AECAA3
+121: DD3D3F72F0F1FBCD030D839DCFEE457A
+122: EE73C4C996E0150D93B3144F20FB2C1B
+123: 5AF9679D2441542391C6A903FD8C1626
+124: 2BD84B87230511DAE7256B62A46AA45E
+125: EB159E5694C191F7708951EBC0AAF135
+126: 60F02EFE1DAFAACF65F6664A2321B153
+127: 14E5A0E90D4420E765C4324B68174F46
+128: 09F1503BCD00E3A1B965B66B9609E998
+
+HMAC-sha1
+  0: 06E8AD50FC1035823661D979E2968968CECD03D9
+  1: 0CE34DEAAD5CF1131D9528FAB8E46E12F8FE3052
+  2: 23924849643D03BBEAC71755A878A83BD83F5280
+  3: 6119DD9A7024A23F293A3B67EFA2BF1D82EC0220
+  4: 379DC76AC2D322FD8E5117CCA765391BC0E10942
+  5: 7897CC86CFF17A3F95C7AF02CCA03546F5CC2368
+  6: 1FA1EF3980E86B8DF2C8E744309381727ED10E8E
+  7: 03B2B726D71DAC6A2BEE63EAA09631DA78F5958B
+  8: B8CAC4C104997A547374803B5898057B3F8110A9
+  9: E165E07F8D542FB288C7D367198D0618DE3C9917
+ 10: 18125F046C675F434B3C53A28C301FB2D91B5D34
+ 11: FAAB993F2FEAE442D28FDBB613D2C768ED13342D
+ 12: B657E7EE3A65C6484D007E21484813D9AED1264C
+ 13: EEEC2BB7BAC158742711ED13090FA20462A5E5C0
+ 14: 12367F3A4E1501D32D1731B39CD2DB2C5DF5D011
+ 15: 57DD9DA36E7A4E567A2C5AE9F6230CF661855D90
+ 16: E37110DDD295D93990C4531D95564E74C0EBE264
+ 17: B2115C4E923EC640E5B4B507F7BC97FE700E12DD
+ 18: ED20C67345867AB07E9171B06C9B3B2928F43188
+ 19: 6CA7DFC9F8F432DED42E4EFE9F2D70D82507802D
+ 20: B39EB4D2C190E0CE8FA2C994E92D18CFBCD8F736
+ 21: 91BE5ABF1B35F6227772E36337F258420CF51314
+ 22: EB957199EF666C6D0EACC64FC4261D11C715BB23
+ 23: 2A18D8D4AB1F8C528C9D368BF5A7CFFC2168D067
+ 24: D4DC370D482D82932701DF8CEAC9337682C2551B
+ 25: DB9665A6A26DBDE20238F04E9F1A368D26564E4F
+ 26: D5AE212C9E543F2656699B59DEED54CAACA9A071
+ 27: BE8890F9DEC6A02AE2848D8505B6408E884E6D1A
+ 28: E8D9DD9FAA3080560B0EDE798B745FEE2A1E5479
+ 29: E219219D2CB8C363C2687F578446ADE1C0404287
+ 30: E8E7767B35ED8D0965F68272ACE61924CB044262
+ 31: 1B26689C1EF55448A61DFAEF98B6E7206A9675EA
+ 32: FE850390864E98A17FC43C3C871383169741B46D
+ 33: 3F63068D536A282C53E5C003BCEEC96646CF7455
+ 34: 2962C292CE247F11ACB7E1F981447C51E9BBE63C
+ 35: B28909A2B7B2E0E13FDCB1124B0BDC31D7D2FEDE
+ 36: 8DA0FC30C8322DABD67D61E82FC92351894789AC
+ 37: 543DAC6D449FE2DDC3201927D08695F68F832905
+ 38: 371540F3092F77867F0CA9DA69318C7673F68388
+ 39: 7EAF32204EA5993C87E9A12C67ADA4C85D253281
+ 40: FC4994BAA05F592901085ED7DA188EC3A9BF36E3
+ 41: EBFE77592EF34E81BDA05305876411484DC0744F
+ 42: 25F64E8F076305D6F5741EA58232F68B725B8F6E
+ 43: 5DBA03F7E4B4226666F0D8D5BF49FEE77951D121
+ 44: 98E1D56D723DCACF227D2AC67BF2D6E7FD013497
+ 45: 53550BC55A367D87416FFA25261362E7D4618DA2
+ 46: B18434BCCCC5F08B35397C1A6684D60F4F3A452F
+ 47: FF2BF38DFC6909B46A01E055D173F67A7E456341
+ 48: DAFA445432ED37FEC99059DB8A0BC528E788E95D
+ 49: 7FF823C570F8B4C0E483165C076AEA7B5E727632
+ 50: BC4FC948AB621FE1419CF6006DC04E7D7B32FA23
+ 51: 1678AFCC3FBD1063E7C82CACAD5B6A933A93091A
+ 52: 97DC2F9F56738FDAFFD555BF09274153FC2FD009
+ 53: 74F5CB4F0900441B7AFFC278C01A3038DF3D60C8
+ 54: 021F66143270C9D58F26AB193DBA81A811917CBC
+ 55: F486D1C8127813FEEEA8A693C4B8ECB5BB53C3A2
+ 56: 8397CAB8EED5B2164FEC6BE688971DFA2138934E
+ 57: E4477CE9BF8CC5A4CCDE039B4E3000F1A0F4153A
+ 58: D6D2D1E3EE4D643AC4B38836AE54E846F99B376D
+ 59: 9545B2C6279371D4D928AEE24328121D43DE1E5E
+ 60: 947ED38EC087C4E53F417E8216408863A8EBFCB2
+ 61: 32518A2326ACDE1E962B3D0D2BF950F318894E83
+ 62: 5D21D368FB9D879ADC27B341D608BCF860AB14F4
+ 63: E2BEDD94D565A51915B1EC6FA9DE18C62D12533A
+ 64: 15ABF657DB6473C9E2F017C7A2F4DBA3CE7F33DD
+ 65: 0C9DAF8D959DAE3B66FF8A21A94BAFC523ABC462
+ 66: A36BE72B501D435CB627C4555A426C4ADAF3D666
+ 67: 1C171979D67A014A0422D6C3561C817A354CF67D
+ 68: B75485B08ED052A1F4C3BACCE3C563DF4BA82418
+ 69: 17297624219C5955B3AF81E5ED61C6A5D05BD54D
+ 70: 38A9AC8544F0EF24A623433C05E7F068430DA13E
+ 71: 1E9EEEAD73E736D7B4F5ABB87BA0FABA623FB2E5
+ 72: 4B9D59879EAC80E4DAB3537E9CA9A877F7FAE669
+ 73: 7F76F2F875B2674B826C18B118942FBF1E75BE55
+ 74: 1716A7804A9A5ABC9E737BDF5189F2784CE4F54B
+ 75: 168027EDF2A2641F364AF5DF1CB277A6E944EA32
+ 76: FBC67DED8C1A1BEBBBC974E4787D2BA3205F2B1B
+ 77: 33DD26C53F3914FECF26D287E70E85D6971C3C41
+ 78: 97906268286CD38E9C7A2FAF68A973143D389B2F
+ 79: 45C55948D3E062F8612EC98FEE91143AB17BCFC8
+ 80: AE1337C129DF65513480E57E2A82B595096BF50F
+ 81: CEC4B5351F038EBCFDA4787B5DE44ED8DA30CD36
+ 82: 6156A6742D90A212A02E3A7D4D7496B11ABCFC3C
+ 83: 3040F072DF33EBF813DA5760C6EB433270F33E8E
+ 84: EE1B015C16F91442BAD83E1F5138BD5AF1EB68E7
+ 85: A929C6B8FD5599D1E20D6A0865C12793FD4E19E0
+ 86: C0BFB5D2D75FB9FE0231EA1FCE7BD1FDAF337EE0
+ 87: AB5F421A2210B263154D4DABB8DB51F61F8047DB
+ 88: 1B8F5346E3F0573E9C0C9294DD55E37B999D9630
+ 89: 09DAA959E5A00EDC10121F2453892117DD3963AF
+ 90: ACB6DA427617B5CD69C5B74599D0503B46FC9E44
+ 91: 9E1BB68B50BD441FB4340DA570055BBF056F77A2
+ 92: D3E0C8E0C30BCB9017E76F96EEC709BF5F269760
+ 93: BE61BB1BC00A6BE1CF7EFE59C1B9467D414CF643
+ 94: 19D693B52266A2833ECA2BB929FBF4FCE691A5C9
+ 95: B99816886D9FE43313358D6815231E50C3B62B05
+ 96: 7A73EE3F1CF18B5E2006A20BB9E098E98B6513CA
+ 97: DEC620F008EF65A790A7D1139ACE6E8B8EFCCA5E
+ 98: B6BA0EBD215CF1B35742A41EB81A269ACB67C9A4
+ 99: 3A0FAAD14D3B64BE4EDB9D5109DC05DFFA7680E2
+100: 12E62CE53283B5422D3EA5D8D00BC7F0AE8A127C
+101: AA36F0CC6B50AB30286BA52BCB9BB5C1BD672D62
+102: 55120C68B419FE5E12DB526D4ABFC84871E5DEC9
+103: 372BF92A9A2507509C3D3932B32444B7BE1C9BAC
+104: 7AB4B04EEC091F4ADA0807DDD743609BCD898404
+105: 20CB412425E88482E7D184EFEF79577BE97BAFDA
+106: DEB91399A7BFB8323BC8E6A5F4045125277C1335
+107: 6769F41624E553B3092F5E6390E4D983B851C98C
+108: 716760E4F99B59E90A4F914E1FB72A6D2C4B607A
+109: DA0AA5548B5C0AF0CC494F34CAB662A30372DD11
+110: 17A0E2CA5EF666EB34E2ED9C10EBC5DDCD0D9BBB
+111: 1B3614AF749EE359F64F3BE3650210CC3C3498ED
+112: 346E604622CF8D6B7D03B9FE74E7A684AECCA999
+113: 629E46882D214F9BD78418C2A97900B2049F1C83
+114: 765F86114E942214E099E684E76E94F95E279568
+115: 002ED578F79094B3D7E28CC3B06CD230163F1586
+116: 52CC9748778AF5C8E8B41F9B948ABCECF446BE91
+117: 9326190BF3A15A060B106B1602C7A159E287FD4C
+118: 18A5DFBAE6E7C9418973D18905A8915DCEF7B95B
+119: 6D25BF1E8F1244ACB6998AA7B1CB09F36662F733
+120: 5F9806C0C1A82CEA6646503F634A698100A6685D
+121: C3362CE612139290492225D96AB33B2ADFF7AF1E
+122: 3D42A5C1EAFC725FF0907B600443EEF70E9B827E
+123: 7FF97FFC5D4F40650D7A7E857E03C5D76EDD6767
+124: 3A92F2A18E8F593E6A8287921E15E2914DF651EF
+125: CDE6F2F58166285390B71640A19BD83CA605C942
+126: 21A227A8DA7A9F5D15C41354196D79FE524DE6F0
+127: EBE93AB44146621BAAB492823A74210D3E9FD35C
+128: 6560BD2CDE7403083527E597C60988BB1EB21FF1
+
+HMAC-sha224
+  0: 6E99E862E532E8936D78B5F02909B130AB09806B2AF02F7CB9D39D12
+  1: 1D1D08669FC34CDC5FE5621A524E7181CD5B5BAFCA3DA56D2E15FCD9
+  2: 014A21F82D0CAAD15EB74DD892187D7AD93F2BEB549A596DFF2C9AA9
+  3: 5F600F19EDED821AEED09781792F9435458A32A60FFC1B678FE2C905
+  4: 8D933E18052E7FD1F98E5E7D02384DA60F3E743801032256282AE2CA
+  5: 21362A65B49C33568251CD1366EB13A4E683359855C00F3AD6710896
+  6: 1E1814B72BFB185265AF94FA622E4A1A70826C06F2BE2EFD96E4E168
+  7: 118F2E1C2F1AB8AF2BD17842FCBFAC966F5B21A81996E3CBADF76442
+  8: 2C6C72703E33A20EA0333629503EBCC41B64DB829064A5C7897C465B
+  9: 794046ABC3BD8165D12C2453FFA3FC518D1A6498A48C91053BEA2966
+ 10: E6C3B6E2DC215702960633C976B86B8378D7780FF884910454032C7E
+ 11: DE7CFF6E85D9411FBD58B28FACF72DFDAFA115614BEF3119F6527104
+ 12: 11CF7495ADC07EC29EAA7B3464F772D49999A5E1832F71FCE18CF7F1
+ 13: A7541E63945FCAD62D2570B015079DF0422E96075986B45772860F38
+ 14: AFD3EB7EBFBA79CC68E4F6F6A2D758969B5C5C014FFB53CFF21C2841
+ 15: 28D942E37CB92EDE2E6F994E9EEE2BA01077D099F3562FEF97A8CAC6
+ 16: 34C7562962548AC9661759B4FC347D6A82CD47991EA06E855571CDE1
+ 17: DA76FA12D69D1FDBA5E544495BBE45F620BE147B73D6AA64D3B3C298
+ 18: FBF1911FA019CB7ACA20E3F93ECC0D5E8D60DCA0A1A7420C63BA1864
+ 19: 565FEDE0EE20842B82D59644929C2A1A426E397B38FAA772781FE018
+ 20: 7B9C2BA77B2989904F194021D308089E23F00954275AE9AD87306A31
+ 21: 66CBF93ED8071FFA36B61F3AABFDBFE714C3C055B2FBDCD3CF369025
+ 22: D96F10ECBFAD7FDDDF60BF1511E94869ED1D992051539E50D5F32831
+ 23: 5473F93F0D979D77C3C6B9CEEB2F3DC1058D81401669EF4AEAFA17E7
+ 24: 5B5A75A7D99C1B40961533C345B95FBF0AFA916D6E133967FCAA15F2
+ 25: 2A1E50E18C37AB7BD928AE14C206FAC9B3E869173CA337FB9374565D
+ 26: BF2B241659C96007ADC25D9567947BAA740555D066636731EEAE3C97
+ 27: 6E1E7B64A70B190BEEBDB9DA82C8E4B160CC73B8FFA224A6B92180B3
+ 28: BE36A5F8DAE9294B3995D278CBE9273E66F04D46890B44EC55028C3B
+ 29: 9983C289CE2F806F41182752A753E0A890217DAF3778B3AD2ED6685E
+ 30: 8B0F08EDF2CBE25E8F9EE4D2948BA6BF81672BF4F509530328A8BAA2
+ 31: B65FB77E6CB86E5F409EAC2F1B5A05E1910213563F816121AFA8CF14
+ 32: 5D15E17C8C159EA5DF5F126B12ACE777EAB36A0082C57DF71E4D9609
+ 33: DCCB3D17C8756F2546B3E5B24B1678438959D83A56524415666DAE05
+ 34: D28DAB7CA715AC86BF4469D743A0005AEE0101F339350661D46A1684
+ 35: E7A1CCC4B2B300457DCC64534152119390B69610C7FF9DD3A683439A
+ 36: 29380148DA403AD5911C7BD52C783EA97EC306F2B32BC426C4D7FD35
+ 37: 56DF59CD635F025925A968591E60DF2CBAB22F98B67C78122F3CE868
+ 38: C20EF10AE9CD99CBB54C94C971780E0487899D7A810FA51A6553DCF5
+ 39: 5B78837F366097CAB6D31624C06B099BDC71286E3AD8873509ABF4CE
+ 40: 8DA09589C44E710B9F84014FE553074E72E0A86C9418EFBBE420D2C8
+ 41: EEE18FA2BB5A5CD16017B4621ACC4211EF7CD60613A8C879B0AFC0D0
+ 42: AD9670FCD043E6F91CE986E6F55905337248B72E7B8551AE72ED32BF
+ 43: 97FA4FBA4815DA49F6127C96C969574AA9543B338F93BF9171D2547E
+ 44: 838D5AC81EA6BACB827327E8EFE96CC2B14D92C55B40CE58F4DA181E
+ 45: CA99480DC8480FA07784EF02074453664DBC92257366514060F07C93
+ 46: 93B0E493D272470F9F274DFE4B9DDF183B26011090E15861FA21CAF2
+ 47: 770CAE487AE5890DC0B931EC17623293EFA5B22EE1ED496A37EB9FCE
+ 48: 6F1D5CA0446E7B82DA02847ED1761CF02D646E56FB0CAB9B120E5282
+ 49: 2A8A1254F6CCC3D656397A5F2D64C266412FC5207866B073B77DBDEF
+ 50: E8CB788AAA965ED87FF2C7B5F3107684326DCBB0E667217E0EA62C51
+ 51: 85BDB6D1486F27827D5870812BEEE2C3976E0DED4BD2F994BBEC12AA
+ 52: A14E0343FAD6BD78E0A8E3BCD6D0B6C83B1220FE6C89F57F44BC805C
+ 53: 2C60D71F2D4BEC90CF10804DCEDB9311637B34D62E9CB68B8503162A
+ 54: 36397D66B434BA744174DA541F080CF6582F10322C7FB1869A100141
+ 55: F612E4EA307F56447112CAB5D2EBEA7D12C7C4427D9155D4085687FD
+ 56: 9798B420980748993BC78E3601B8AEEE2D2CF6E59799C7B07B88435E
+ 57: 50BED37F1EE78FAE16D178FECEC2EBE4776C8E5FC738F9506E8AF676
+ 58: 2755438A9AC457B81999D9E1E479C36DD9AE1F920F5BE6D109ED7431
+ 59: F3DC2238B13BA706A048253F86B79045B72EF767CF25DC62F96DAEA0
+ 60: 11900A3154C4DFC49B941258A134C9201DFD280728BDB3F8BC7903F8
+ 61: FC584202454DD7C9258F72A6258E42F3C2669FD138FD7AEE6200C4CB
+ 62: 185355C13E146EA89387C332225DF31CF114AEC0BA3A5A5B53667709
+ 63: 8194DABD2F7A02DDDD7B752AB5669821519640EE3B0059FD333F3401
+ 64: 2CD6946C6DB676ED1EC272AE34735A0546AFB8D996323272C39A814C
+ 65: B7A344BC5EFFEA97AC49894A85B96F9B570E680DFBB28C76F7F9A180
+ 66: 9011B80655A9CC7964CBC4BEE1CC03074003CCCFF5DA553B289ECF6A
+ 67: 6BDE25371B7EA9ABE31A524E49CAAE40DB220E405463D93FC7F66904
+ 68: 35694194E10D0EBCA6758099D09C99C3CAB37AFA52FC4F4361C510F3
+ 69: 4E7A79F362D7AE5B1680F30E6770CA46FE6264C9FCA566718C01EF67
+ 70: 9DD18D21E413AE12112AFBE16684BFD4FAED7467A2FD5904EF0B493C
+ 71: 7532D374B66B1E5B17EB49810DC3C04264553E4C36F4550D1E860B70
+ 72: 35EB09C82A624B1E3ECD965ED8522E9572EBF26791EFA667B4DB952C
+ 73: B9C17DF6F2A6506FB1DFCF1A9089974C45760A438330AE7547DFE685
+ 74: A7DD0267C15B36D8BD1879F879E894FB9F33F254556B87BFFEDD71A0
+ 75: 68A354D120CD63A5D34EEE84B7E5E5BC1E5DF6E021F712BD4270B781
+ 76: 441DC4884130D48BA134E2FBA86AF643C8EB79CD1AA4688F82E0D3DC
+ 77: 17A3F16DEAFDBC1DA00BD14D9C24497BE765F41E2EC79578421ED8B9
+ 78: 8756A267D0CAD54BFC848FCC4D6B6C94D39CAF07831EE35324DCD35F
+ 79: 004EBADA70F19BAB48E6072E2090941DEDB5CC0A7B624E4BBB671382
+ 80: B7F8D35CB865977423710FA1E0F939808E68ABB54BD7EB0427DA03DE
+ 81: F3D0AAA2F912FF95251D3CF51EBF79B940DB56839DEA8BA5872D1FDE
+ 82: 0835B2DC376BEAE873F1FA337D75C72FD1BF0F72A81669AA891F2722
+ 83: 7CF9A7D57CADEC3F013D4BD87C00B420CBFF73670A9CBB072D18EBEB
+ 84: 68AC0A34930329F5AA40137987208481E34D8B9C08EF7A85AE3AB38B
+ 85: 00492F706D84B903D5355FDC0B68C2C33B484A95A173FDC4AC945028
+ 86: 6F6C509CDCC84CE1C36AB76C9BF30E4422C90C869C164C64696AB5B7
+ 87: 4C0A35D512BD0DB15915DE08FEA8E6027063A1780C104F6273CAD5C7
+ 88: 27087F6425878D64A56BD5ACCC0E303F803B7208F20AEFEF75501F03
+ 89: 4EF78140430EF60F3CA12AAF8132674B0DDB154F495029B4051C2A36
+ 90: BCCA3153EF93AAF21CA02D235A23D3013976295E704223CB37E860BA
+ 91: 20CC8D4C64E09B00ABF23864BD7EDE542F5BE480AFC4B9551B301EBA
+ 92: ECA3F86DA00098D91F866C58558BB7B00C9E4239CF83C5A3E76291B3
+ 93: 7AD9AB198858820D20373C45173D76AF8D68F829D9A250ECADEE0DA1
+ 94: 3E1C202F2D589BDAB015306AD063784E5BEA48AE8D1DAF45D571D2FD
+ 95: 990C44330D56EBC9EDD951F8CB92D5847F4BD3C6442906F57A828FA9
+ 96: C92F9FCC6220EDEF52B6F842635A83914B236862F6CCBED16F4899DE
+ 97: 0E41C85D5C6D625E1884EF7438DD9EBAC818AB50CC265A73165928D0
+ 98: AE087D57F9CDBCDF4DD68A3E8D5BDFEC709A532A4A646CB31785506C
+ 99: 4CB03AEFD24C833B5350996EB261E803F6DB698FB81F37F8A5C3D891
+100: E680BD218AE972999BECDC905F4D39251ECF49B29CF0A13AF5FB09A1
+101: 64326D6B692B0A17045434BFF13282ACB91E7B690339F7FCEBCC9AE6
+102: 20CD91504AB04E2D3CD849808F2362943BECB310F4A0BF6E3BD47751
+103: 80F607E2D79E1EFB0458E47C8E5726CDB8387BC05F42D6EAE3239A20
+104: F83C023D6F539967AB24309DD28321599782ACFCFC76B77186307300
+105: 70164A250799DBE6C5BD3EDCDEDB16D2516A9FC1BBA294C49F753824
+106: 1883397C9C4C9D33FB9E1E03325EDCEA1606D7ABF86C4387DABC449E
+107: 1355DFA06822CC1F216C131F2BAA92A10BBF109BA3E648419A35C0F3
+108: 9E35B9B307990B7D664B9EB7F06EFDD23037F859ACB6B96A5287A846
+109: CCCA26C8F8405FF62421558255F2DA06F73F17D1AE1763A0BF8430DB
+110: B4FAE909368405206333491674559B9094DA4C48913D9EACA28AD75D
+111: 3A5E7D9273F91E10545FE6861D4FC223A5EB0F7B4FBFBC9931634C25
+112: 96553CF0C5C6F6A17FEED04024FCE1D292C392E60B3595FF53007AD9
+113: CA9B79F403412F71FBC10E094B35088576EB3F7F8B5D08757D89F45B
+114: CF60CC5B1822E4A12EEB3E1E5F4AA79E345D8C8FCC546D57DCC7C784
+115: 807D65C33E74DA0E2D5E3788084C61AE3E8771FDFE643D1269A7901A
+116: A5418DBCA94A1F9692FFDB3F7AEED75806CD9FD47171A6B67921C0A8
+117: C2B880C9E9D78B0C397D72C8B6684276E8C22A7F4D6821DB7C998775
+118: EA447EA731673E5DEAB57012CC9E0D3A7B2443165B665822963FD6B5
+119: 0F6D50C04357DF9240802977779D7F2214FBDBAE95B6D8F59B414964
+120: A3B24B29B29BBF32A01F21FFF13F44FCAA5FED50718803AC3BAAC548
+121: E31E36C38A7F2525ECADECA047533830A9C46D609E297142AB3DACAA
+122: 592FF0C399A6CC1606FA3F404DA4BF8618A4DF159CBB7E05DCD30BEB
+123: EEDD6A5902091ADB8EF491F820613740DA73A160D825121912613DDB
+124: 3A2FCBFCB007F45CB0EEDBDD5A765EA0CB7A142CE3C024114D6D61DC
+125: 5D29E1732898854AF468BBFA5B87065BB811AF8F55C91E82E888E842
+126: FD1F646D021EF31F634EF5FB0506620686B9F7D9B5C672734CA10FDF
+127: 5E43945BA9DE62C364E34CC1361FFFEE9BE8974D7CF5D2E06428916B
+128: 0FF4DA564729A0E9984E15BC69B00FA2E54711573BEE3AD608F511B5
+
+HMAC-sha256
+  0: D38B42096D80F45F826B44A9D5607DE72496A415D3F4A1A8C88E3BB9DA8DC1CB
+  1: 12B06C3218C858558CAD1DA6FE409898C31014D66CBE4ECD47C910EC975E104D
+  2: EDBEF6AA747C951F25AB6AAA0D874648CF18FFECC4C9159F8FC71E971FAC6D21
+  3: 03436338A166E9051599AB268CD74867C6159378069A9FF46FC07CAE375EDA68
+  4: 634758DF0774A587F3AC6AD7988D0965524DE24EBE4DFF07EF622BCB8DA71ACD
+  5: 0C08E52C7CFF8B5F70781197069DC8F209552D241687BA0D24661CCCC28D3937
+  6: 749F473E0D934694AB9917569A61591CA50BEF18CABDED51666DF243DE879D53
+  7: B1E12CFE0273F5D27192D1A4B70EEC4DDC714B66C8BB1921C63381F78CEC5219
+  8: 1C60F13A1C539788E989BAC2EBD4F8E126EE6ED82C2E25817C63B2B633FABD33
+  9: 5643F445B2C0656A49BB3DB5088C9E2E4B2082C2B611BBA0DAE5791F2FAA5D43
+ 10: C467F47251DAD4694C9C7A6758E54CEBD68FC933C7C57458020774A2A2B4288B
+ 11: 85C90CF2719BEBF40EF8D501FDA20C342BC406E728551BC0275ADA1747BD981F
+ 12: 06B72DAC895B008DA249B7B1D8A5133F09D86BF82DE2C4251BFA6C3D8C4CF03F
+ 13: 49EDB6714A556DF324E41A3CE5B57006E38FD7CA8B90FEEA2ACAB429204747BE
+ 14: 7411921D759DA0B491D6D4CC372DB79CC163F146C345B4A73D93EEB4C262A1DF
+ 15: 5C37FFBD1F0512AF443265B2F3E8B6D01AD9B45FF6F373D2CD0A7C6E48D03E26
+ 16: 773165FD16D51E51CD8A958E548902B47BBD0A6E156C31B6FEA036F6D8C4A90C
+ 17: 5B4BE909754EBC8ECBBB8B5DA6298B8341B35D92E17CE7281909EBA1EF568347
+ 18: C6EEF2D12F54815561EEED3426D7AA7E671E26D42384B9478D91FC6B14CC76F8
+ 19: 4C9FA0575CD96BB1DEF6EA79F5EC7A1F0478E86352812F690C2C2BDB70028BCC
+ 20: 7F87BA45FC41EC30E76F61E4EADEC013CE2B4C49CA6FE6D2FA525F6BBD45E103
+ 21: 9B8CA1D70339A0894E16CE4E76F6655ADDD3EEB598F3DD80FECC5EEEF3F638C3
+ 22: E4608AEA430A638799991B748BB858C91AF58F56B226E1901D28336B30498279
+ 23: AF4F9C52079B28546FBB44EEBA20C7AF0BF493D34EF6967B07CA32FC4DE25ADB
+ 24: FE51F3A9313EEDAAA991350AB4D1D7045D42AACF3AC7155DA3AD9A2F1DE3A73E
+ 25: C1F5AED9D77F85404A4B308A139D33F351B20C91A738E698BD8182F124D96C82
+ 26: 3CAC12A252B93B7D724AF9119FD3C18E85E88401F93BFF42AA05711B9833B1F6
+ 27: E61D4E94C212324A64B1A0C04B2237A9A1C5CC003D83EA80BCEB45452DCB42F2
+ 28: D01BA47DABCE4704B6820EC0ECDBEF137B9C4ACB80DC99B7C9220CFD9F9CE363
+ 29: AED502C53A8B2C76F671376CDDBD0596376B3664B917CD9C9ADBC489543D4721
+ 30: 3405AFD96584C5E5963362948D112A70155877BE3B5EFD479F226B73351ABAF0
+ 31: 5FA0290DC68B72B1FA27DBAF157923C706B3F52CDE9C4EE38CDA31D376B0BC0D
+ 32: C1391C694C985CCBA707A8C78AD05E2180AF6B4DA5BB877AAC5E2AB33B4890E2
+ 33: B018E7B15F92DBEC58F767633BCA3BD0D84B6D5B9443784DC1757166D7AA1C16
+ 34: 8D9E2C84967004E3957DF59D502BC11CF8C8959368117EC5DB56AC958A3E791B
+ 35: B0EAF9C0E869D7A304DDB30061A73C580B0A6F9D49E15442ECFBB3B5A851855B
+ 36: 0B48B0D8C3ACF7B4F9ECF8E46563C921B1B6720B6C650D72DD1126B6763CD595
+ 37: 8879D239EDB09F6606957D96A1F4BF37EAC0F3419881EEA79E8BF1364FB3FF6D
+ 38: CC663E436DE42E32EA110F9D90EB990D9151C9F06D51243D2076B0CC45361736
+ 39: 732DC3B1F809E55C498C53FC75A23966CAEA16BE984F795CB1BC94D026FAB30E
+ 40: F1F0EEC77D97A0234D0F19B2FB12A96B6E2FF8626F79A74D4AF26CDE1344D838
+ 41: 75C9D8C7344668C478D8AE6D9E2C41E336E7A2504CDD43B73CCBF78B4C05EEB1
+ 42: 4B149BCA6429408B242E76C52C4D3A0A5F5437EC0AB6D24D71EB1AC5496D75BA
+ 43: EDB65EBEBC0411B4FDAF186033E306AD500711CCB80E770E99523BB2672A237A
+ 44: D1BBFF5A48346A0DFD5CFFAA7A2AF08C27F3FC2908D7A5D2F575E07CA9E72474
+ 45: E8EFB6373DD3457610E57750738358A50026D2C6704A98148CDD69BFF7B70551
+ 46: 8E3733B729CEB97444BCCA405044B98F45FC59BBA86444A3FC0F4DF4854B5C4D
+ 47: 868F3EE8F4D4DFEDC3FFAEEE1FA069F5FBB2CB818E63C28151C1566634189234
+ 48: 3F5396115DC7F17AAB19A3A9779CFFCCA57DE7A7C1A42F748FEC49B7D8C2B82D
+ 49: DC2A5E3E176A693AD8CAE551A505729B78FBDE778B526E28953BC1A56B54840E
+ 50: DC91FD745E9A7A9D0B41C79B3B3939B84BDF78BEB007F9AAF8FF82084759223A
+ 51: E73DCF5413F17D4ECCEC813DC060EF907C2E952AF92DD247A0AE2BE798E6A40B
+ 52: 696B5EE4C1E1D8B60B0015EEA2389C9A35088022FFF10034D0D09FA722A2A3E6
+ 53: F86C07265389512B2CE240A89EA29D61C6C79C2738FACA157B0DE43294485682
+ 54: DB31CBBFD28D6F8564219911EFB748A5663E482DBA26E38634E8E27E3CF65707
+ 55: 2F9675313AAB7A940AE77CA906D0342A448FDBA3F7589D14B1344D586EA157DE
+ 56: 7D829FD994258EF2AFDEF22C8CD5CC1D29A9A55B62847B3B6F5DB630421CF999
+ 57: A6CDB9BC9AF75EA4680E895E8EDDCE76F536F7CCA571D62781A06DDB3424FA50
+ 58: 1B4186A34EB07F5B3127F2BE0F3943610679DB0F6BABC7DA03B416FA577D36E2
+ 59: 7B5DFF3459DC10B9B7AA2B2829094F97706DB5B2F133B8BF9F48D90253D68359
+ 60: 2ABB68160300028BBF3B5A414970D11DF4FD6F4B4A35029DEF8492ADFB19A480
+ 61: B1B13ABF9D20C42E755D63EC63C016126259C8A6C3F9AB3F0F6AC5D0BD44ECA2
+ 62: 9ADDD17E5CF407CDBB12E5E52A50CE134F1B48A2A2AF90D7308344FB5A70485F
+ 63: 6A4C06DF40BA515C56476471D4A94F87A2B91EAFF6C66510892F2F20A342B736
+ 64: 555D424206C003BAD0B08BEEA76DFC81B307C79BBB6E4F15325B2ECD37E04423
+ 65: 8A58733E0B990D0D82F93F77DF36E30DCFD03B3181B73C544BB097A3A73B6AC9
+ 66: 6FCCCCA4172E30A281A702E36E7BCA07370D4B57272385077A44D5F7933DD2FC
+ 67: 3B1A91E49AF88B1832F8E91109C7CC5DBEE2847D9ACD2A57404DBB565480AC75
+ 68: 69584075C278763CB0B09D4C9E15E9300A191BF99907049F14EC8DE24D86C121
+ 69: 2EE24340D13E68B10B95C3F77D55027F98BDE6BA5328D0C02CF89965687C062B
+ 70: C04B37F5932F427D40E21EEAB7C9594B16BFCF4F5FE2BF175CD63C62F2CEEAA2
+ 71: 058E1AC8971ADD2617A4BF7D02B46A8B74A4D52B25643DF9729A1E7DF6CCC86F
+ 72: 18001F246ABC760197482E25F3AC64B14A795E55B41B505D6027261BFDE7C52C
+ 73: 4AEAAED524B173E08E54A83E2D9A8B8824E6E2F1B89203D698E9BCE7C3242F8F
+ 74: 7D82CFB1D7427302889CADBA23A99154CBAC0C9ADEC94EAF29EB07DC86B0B7E2
+ 75: 18D42E92BA532A409CEDA8E3A07E751B430800827F5A9F14D93E3ED231BA08AF
+ 76: 8CFBA378D8595372DCE5D9A6E726C23512F84C0C1EC3C66ADF6B6C55DF63936A
+ 77: DE1A6E280A9054C91B826785928F37A16E1D2A9A3CEC831185B26D2B8EDE158C
+ 78: 920C40B4204C7F3D4775176BD245BA0276604C568B3C29943C9AEF1A1C93428A
+ 79: 935BB39E5FBCE5C4A15AC2A854475578CF80308E531CA86818DABE69BED8824A
+ 80: D608E561471CC09EC0865C826242CA26AA1C90BDF1625E1A38B96E3EE0CC5F04
+ 81: EFE2A8D806A1A71596A05A2F5F48D18CFD4A742247B04E8089FAB27291A8DD50
+ 82: 80235BE35DDEA5D49F124D8BE3D143F87CCBA7D0608C7E2CABBAAB01BB95E477
+ 83: E9410E0DC14F3BE36A49A5CA673C12E18CBE4F0817E0C1CBD2069349F8A09BBB
+ 84: B2042A81A36F27B4CB96DBB52A61F701A815869FF5AA0CDCAD0327E1ED1C2F22
+ 85: E9E5A9501B24952DCFBB9D59CF95A9A9E6A27FB7315EB472D1E2B7F523D06D42
+ 86: 99193B4FAFEFFC932B261EF169250B96901ABF877424FF667CC0DA0154C50498
+ 87: 1D9C7F7E681D20E1E0324EFE71C8B6913FE8CA87EE52E443335115AB2C458E7F
+ 88: 7308DB7E2591D2342109C5084B1174F07D289FBE91472FB2D8C06DF39F826B84
+ 89: 90F06ADC29070DC50A23D3F093007E273E783491A70A2F0AD6BA40E34F02518D
+ 90: E676DEEDC972019F10FEC24B4AEAC0A97870E924F7B1D6D3ECF91EF38A2AC544
+ 91: B5DA3B40FBF373795E67A6338F9AC3AD742741F34048930D9336D429D02EE78F
+ 92: 6FDE20988863CE157042EE52065EEDA233BB2E6EC0464B9DCF2AAC1F3A18971F
+ 93: 428D4CFF477F0F0379F634D1E7C15E4CE6DA067ADC45221A860C9C3AC4235753
+ 94: 9EC80B57E921DA3F81D13B65AA851F5971E4074C96E0D8B64E50A7F5089C1FC8
+ 95: 9088151BEF766D0896A48EB6DCC8A09D151C3396FBF3A9FE193C5E7BF9030B01
+ 96: 86D853024A762536666316F363BB867EFE25FBD03BDD28EA7522973A1A1BD95C
+ 97: 007104BD935B532BA4702A78C505D67B41358A61DB8069585B91B1445DC346B5
+ 98: 5C5709F6202948E805FAC25C454ECFADFAC693955864494E511F0CD1FC9CFDCF
+ 99: 0B010F71C5323CC96D3B8DF71170968096E44969EA55B4C3DAC632D30D81D529
+100: 54621EC4F31CC7F6273601D81674612B44726B5CC4A76EAD2BBC3D32DBF62A9D
+101: 28EFE1AB745BE64E5DD7286C97360FF2D287F862ADBE44380F85E1388008079F
+102: 831BFA684C25542676AD52819249A10D9EF9C2505D69CC1397D0D39D08B39E5D
+103: EF7922C40CD96A47C5E7AE4D958B495F1D6954EDC20596E303CFBA43190A9EFA
+104: 3A0262EBC746A7C044C1DB043951F7EAC645C40F554898D3D7B2B7AAC4EBD396
+105: 1F2CFBA7275639A12DA7CD1986F920C47850DE3FE13C931618C0FAC765820ED5
+106: 7AC8913C0975101E187FDADDAC5B5EC467A25869C4E630EADBB42DD2DFE4958A
+107: D386591F326C91D274FE625A667B6F9F6F7D99CF56ACB365A218F1CF8E167A70
+108: 66286CB1B61156B005CBFC94C2CAB1A6694D7F123411B8A123F2ACD821C291F2
+109: 844D1038E710690050DA737D56FD6B17C261C7BE512713E62033384B53C40902
+110: 7EF970C40080F554851277F4E950C6F378B0A3DA3CD1BE250D976162F8A4EE79
+111: 9BC20A2B67566688BCAC77FCF30259F11D9B2FD2277D033E6AAE19E36058A353
+112: 796C72D95BBA1A4341C6B0397E165DD21CFBEF55555B35C717CE33B6C6ADE490
+113: 1E6A9C1F78AFF266EF8FB25C32C1FDFB4A0F64AFFD046D257470BF6DAEF61D6D
+114: 0E1AD927AD658C5E0321333AF8AE4ED69903B4F22C5DFF90AC93268507A7C86B
+115: 07B7A778E2931704E7FECA284FF3B14071E255A2B824AD0A2272D21448579CEE
+116: A8D810DF06368A0E825D6DB4394916E43E217BEE9303AD4096A8E1CAD37B8703
+117: 6A9C7D302CCA1EE170366F355D8F40AE3A20D28BFCB2BA163DCB68E08DACB748
+118: 40C3A8B08FF9F767491E4243D1808572FDAF1D8CD21AB47115849531513D0750
+119: F26EA6760AA80360398371855783815BCD34431E0CCEC58A34A67997ACE43CEF
+120: EEA78D68A509988ED6D7E3F27FC22F3EBCD570EF0FE242A0251457EAC4C3C1F4
+121: AF977819B87F2E63C0E131DFA2A31C555AD831ADCA6DE0FC1BE48D21A1E7E666
+122: 846A75DF3691B2BF224FB0E66E360A2E8BB1DA32422190F2B319B73E6900AD42
+123: FFA997FCFABC9FCAD4B58B0EF848890FB23B974CD57FA07223037450C371B116
+124: 0028C776965A0AE5E9E70D9B833BF328BDBCD06C5A12A2F1C510911E60AA304A
+125: 7FA234C59957C214A7BE8D1B909C540B48E54414EE5FD1081B4C339FD2204515
+126: A840BEEBF2C2E80AF2E4830BB26F71AEE48A9C65DE4A9425DA9F98FA3A37DD84
+127: A95332415EA29A8CA6FDB0F771E3F2262C6907DC45B0AC8BC229F6009323C3A9
+128: 8B185702392BC1E061414539546904553A62510BC2E9E045892D64DAA6B32A76
+
+HMAC-sha384
+  0: 44BE81C415D283AB7A62A45188E5DAFBCB97DA606BD5B16C92C1FC36F198C0B3A714921848D5E03DF1C4849BB8310C66
+  1: C1E1E68D864F758941B87E30C262348B373F167CE4629E4117FBA208773CCC2E6C7797AE5D6BBE2ABE6BAD4DE2E1052E
+  2: BB27A0F06A1BAED5AC4FC2267C36EAB663E11EC5F0FCC0BDC09B9B0E803B0ACAA2F39D2AC73DE489FC7C9AD6DE3FC9C5
+  3: 70A273A2E9E5092EF8D4C58E99734A911B7CADD48954FD518305313B0B682CFCE192018D4847375D7E311470D05D97D9
+  4: B4FAF12B325B486B67E38A855D18B45D1BF6CC60E4D00AAA6E58268F524CC1121AD3EDB64D6E0FA524F11C0F139D0BBD
+  5: B509A325F561CDDC539A3A4680380759747709D428B77E69C4CFE926F65B147D92D2C83692F526EBB5CF606AD162559E
+  6: 9A1E678A743BA285CE154ADBB555CFD097F5839EEB2DE4147986464C1BF032BA0D80473293467ED0A0AC59BEAE736598
+  7: 1DF214529464666002C1AF094BB36F0FB14A4923031B108C21825E8C55BF6A0BB34C9AD7D5030B2FC7C83A2CD4C79C1A
+  8: 86D8BEE44CAC35CD3946321796599F20F3A41BE28F161FDA062E4440CCC16E88BC7FFC714D525A6420CDBEBDF6AE9E12
+  9: 92417595F9974B44BB11EB9200B7560FEA3382CDCB8BA4C2CC5CFDD019C2B5956D3E78D5B186633ACB765E822B3D4E90
+ 10: 2E87CF886036B7A66AE6581BA0DBB9AC2A39E1C7C7594319184FF3B612A165DC02B3A7133E3AB3D29634B1CD5305A46C
+ 11: A5CEDD2B54657832F946BFBA14ED5106E8EB5937EAC6C5405BE5CBE7C58053514E784E3F6668C20466A242D25A44462D
+ 12: 74475D913659C2C304BA49DD2B39B0C7AD7D537BB2240D8611876CF5955B347694525396C43CA73951E711DA38C6976A
+ 13: B0AEE82D70411F1A79DD7012421BAC1202D7C3BAFFA15B4D8B868A3E6F92B513F6B026E2E8FEE45DB2AE70C15E11D19F
+ 14: 7D06EA64FF5B9139662FCF9318589E8FF1F783754A9116E090B0B7A981A9EF1D4C1BF582C8EF5E71A49DEA2834447287
+ 15: 8F52BB9B0A2B1066AB67603C552C17E983D15114C3B9776C548D747F7E24AC782253812802EC456914444DD67C0CDD46
+ 16: 9DE6587211FE4A232F01D6D20554102D24D98EC140A05303C1893F232BAA2C07C81A10C25A95A50B38E87898900BBE1F
+ 17: E0175EB9DB2649801EC2EEA9DE2C1E950C129CA249C14326614E0BB8C32AEE67DF1DFC6320439DAE4FCDB4B037A53868
+ 18: 0606A848086DDA50D031A585103478EED0259A9167959657050F8D7DD21B4D6B62B93AEB0009B1E878EDADEFAE9B2ADB
+ 19: D4A45DD1A6B613E3D2D72B35E6030E1531D75AF7C3F100934CF27EE9D0E0F0C236581EC8EE74FF759D7A19C5AA6DA9E9
+ 20: 3E0FD11AE4933665EF30E10035B0E686DCA837F6D6FE2D5A10B4EC30F183EDDF3558309905F028DB93323D09A3A2F3E9
+ 21: DA2A204C7908FD27A29415CAE3BD16A0488FA1D42CCFA2E2F5A1EFD6F99583EC6B3B36762060F547C629B9A332585355
+ 22: FFE8FFED47933CC941A8E9233C037080B9465B4F9C25DBAC790825C013545D2344930E953187C77466437BE226962F80
+ 23: 69FE734D5C69F34366E5CA6B095DE91CD4DEA29AD70BEF06AFE9BB232162E6BBB1349263087212AE3AE5D74A3B060F50
+ 24: EFCF1B825AF87FA5199FB3C76783CCD1769E7DC77BCF145DB76FDC622BFA2425CFFAA40E6376086B2DBF6F5D9D97A534
+ 25: 98C3DC50FC08D2A87ABE3FC16871ECB820D530B453C41F83FD304D51660FD29BEC6A7D1C63E3E12B6E80E8C58CB129CC
+ 26: 945047CD723EF4F25AAAC4A19FDEED463EB04CCB78EA318989143298DFA70D793391BB7FCEA6BE0D79187543426AADFC
+ 27: 2718D89F835037C94CD6378A3806614B85365A888B48FFD08C09F0B93360C04E43B7E7A19C79BCDC5DB9F5944579AB79
+ 28: F714F16238075796DD43960E17AE0EDF9990132D690F44957C3DE9EEC2773683172FDCC44ED2104320726BAA7DBDA1A7
+ 29: A87A96ED8FF0E7FD1F235F070CB5F14B41B2C4438A6D7A0A39D038C74008FE9C52497CC506498414835AEA1192439379
+ 30: 31B029DFA85DF545B752506E80675E617549A6725A658CA8123D8C837FB71D8C9961BBC2460D7CCE0CABBDEDACB56C37
+ 31: 0B1A9DD308E5E6E65E4C60861D42B628FBDB2C2280370EFFAB736A77A8004C5ACD5269D090B652B1D8F146C1D518D288
+ 32: 2A160E0B2EC7BC927FFF813A2B56AE61301AA14933C659B3398C7A0B3CA506DD00FA6F1DE9C6D47AB0FB2BF2E7B4B83F
+ 33: 6893C0205F3F4ACE906F2FACC97E2B1624D40997370419E5981E6041D5CF34C77EF5ABDB1AA0D3C8C3740100C2711555
+ 34: 95BC8C72DC8C70ADB7CD38311292ADEB9D7BDEC6A9580EF4E11A18317CB65667D344D8D6603C044454E67F97F4DDFF40
+ 35: 3DD892A4E724376814DD5A4CBE96E4317AA8AF72478D53379247E77C35461BB92CF493851FF1FCF57A6704923099DFEE
+ 36: 3A5DEAF967BFA3EECA3F259307991F7DBFCEC1F354DF385CF0EE8D93291721553EA954E9D6593506E9F3E330E0A02574
+ 37: E00A883DCB5460AAD611603614C7214EC4A566E0580FCAB1CA4ECF1386A42DCDA746D3AE1B0D54E0B9AC1FA336FE787B
+ 38: F437CDEA425E7A70CB4D197C0CA01562532A7C51FFB8462B4796A4FD0A7EC880CB0E5EDDD5F703ADC179374416592256
+ 39: CE69E40F5B5F2F25E0B53281BE76ECB0E5B4558292A1C1A5EC56F2CF11B01BEEB1F0BA01E6A9B3D03BEB69AE0511F320
+ 40: 41AA84D15342CD0675C8C0312C024352E99914C3E01C98F969AD04CB5705E9184F3821CFC6A22D43A77C928F6DB79D8D
+ 41: 74001D972353BB45FF3F7F405FC727CB5D0B00431BC76A57EAF17862BD52949AF884403ED6B2A002D618EA33523DE200
+ 42: 968BC28223799F1EB92F1432B6AAF5CF6953491C3F959977B065BDB800AA438CC8AA7EE1304C18999CB5ED709431CFFE
+ 43: D067EC03F14D2D639C4423A311EC86B3DDC3693A2CF43C259BD0358F8D0D68F41950CB705249A59072A2CE7DF155F5C0
+ 44: F41EB77179934884DDB56DCF83DC90C606D0226DDF94135FF8E1E0AA56C9A90881C4C380CC0AD3BD0DA45A6352BACC05
+ 45: 27BF9A98F9E2732972FE2F35ABC80AE2E5A2BC1D238B9B1D9CE605A89144EE9766987384EBDCD63533E64BEE094E4503
+ 46: 166892E106BBD9D16819D9BDD3601D24C0C11860DB13799F0797F204D07DBE914A7BD286B380EFAC34DFE3C940CDD3BE
+ 47: 2D85DBCFC431A94F8F50132DC8C10B25001EA10AA9DF7C53AEE9E8383EAADFCECC21202EFBCA556BB4E33CC68156B190
+ 48: 086007E2874E779A5EDF0E176AC1A11D241F4AD8D02AA99DF2BC1AE3E5CC4775AAA92ADFE772CEEE89D4FDF1B601D05A
+ 49: 2ECA3144F4F9EA0F37C2CA5943F458590A1D4D19C0ECEA6A55CDCA648C99CD457DC57EAA995042D7FBFAB598B8AFEEDF
+ 50: 9C1F31F5D3A589631D8B7EF89A507011736BFC328071513D64E5432D24B1BCF47EB10139B6410A3103145AF67B5B6C46
+ 51: E0645EDA004D9005399A2C072ED9959E4F8905D15C57992553202A3B53BCFEA0098E6B28BE047A4B29EED7B57602C0E3
+ 52: 6CE5CA92F0B1E84D7578DDB86C96A10924601A3680BAFEE5A0B27D8390B59752205EA483832ED3E9343DE7175601C03A
+ 53: 47F50844C897FD910C5C228DEA1EAF456882C1115AB71DB15E6832D96607CB79C8B7AD1CDDE01966FCDDAA0B0BA9F264
+ 54: C0A7EFA24590833E4788BB117D3AB3CE00C84CB4820AD9FD7F03CF1CE1A8983F9906BDD138E1943D75ECD9B98D5AD8D3
+ 55: D056E9F831B6DBE97FC751453B1C52C8C6C4D18A00050F5AF2427C1123706375A918656D6755A4C950F4E5B5C318CEBC
+ 56: 462650CE3981EDD13D0FD2E5FDEA93A9A18CF8FA74CD6142DF4707E604D1F72745D7EE08AB13AFF3A9F8D166EA90CE3E
+ 57: 2BA5249841412584B161063087AF9F5BAEEFD97989BF8A0455E65C94B0663410F0E1BB22EA6402E59CBC5A23F24ABBFD
+ 58: C3B1E4B05A7593CC315AE15F63CE8D91C4B30E0D846A97B7D8F01FAA1B6BD7C9234EB153372F6CC7799A035E22A77EF6
+ 59: 1E652653B9A3CE862DBBAF2C919E86891C5C03F54ED5970E8028F8D5EFB533B9C111DFD88ACBBDE516F0D4D636F5E821
+ 60: DA773D5AAC336B6266D27A03AFDF3A151FAB302E894CC1D09B6E4ECD07C4AF4BE06A2D28D01669C7557FAE8E513D01D5
+ 61: 8C8FE648A29D4BA78B3E0B944597E392A31E28F98B15280E1EC0A721C9ED5E3639A6A457744CC5AABFB3600501F5054D
+ 62: B443DECF40A5693F67B5BF5580A665DF6EB98FA9F14A661CD50D6635E0F78FB2943731AF363839FE6DFC0B4C49F9E849
+ 63: B22EC4AFEE3EA69364701E5621E453A0C3988C1E2FDA54FDB99353F285327A534F7162BC54D701652744413B9A5D4CBB
+ 64: 40A22B7881AE8139941540540FB37C9AF27BCB164B6D1A3BEC709730BBBB413D1F2FD6BA4A7B7EA747FF45F3ED3336C3
+ 65: 246E426C57E414575DF312223272819B0F49FF94953DCB94665FFF74FEAB049AF15160706AC5F702AF66478CF2BBA5BD
+ 66: 184E6E6D5FB55454EEB6DBE323BF28DB8CE60C271DD0ECC8BD4D3F1C2339B7828C1515F030058FF37BD53568FEA81378
+ 67: 10B23FE1616AD5609F6F6C1D9266F702C1B5E6F7FA0B3A81406B5A766E2179D082854687701318A7B46E21FA67D2404F
+ 68: DFCC1280C5206F99A555E291AA1DE6F0A3AE4B49916FEED4337582B91D7EF094159556B01AC87BF7A8E84F9F53595938
+ 69: 91BA9A641616449084A57221647369E2E69525A30B274EE5403FE95A43D0A7C2B301B61929D89222A3A03303550521B4
+ 70: 94F59A7F5E68B942A5D66D3C642A78685F3BB400F4FF971BA576DECE94A353455277632B70D06EAE38329CC2298ED792
+ 71: 21A9F5C4B1290D95A1F3F051A0158F7DD8A879E7861B61CC757FB5C729FE9A8BD46BC6DCE595D20649092B31AD27433D
+ 72: E4246F7DE67C3A08F18852F6159F5DC9FA4C0129A9F894EB610C10F1FB8B61B1C9947D742A418F03A00A7E11ADF436F3
+ 73: 8D2CE8209B8362311D99D68DC2AAE6BE4CC8E52C03A97D99D0C5C15D8E24F1D3B51738BD27BEB6E773472CD22A1225C6
+ 74: 7EAAB124A3C900F33DE06B84E7831FE327FD638C4E68DC8648EB619E3C7E5736A26BCDCFD3AA6AF34EB137C6A210746A
+ 75: 8B60F61A1AC2C6528C8DB07B6874F19B8D474859F98AF03503B115EEB8082E19D53F63D397647BC2D4278B8C2B741D19
+ 76: A48D92BA646DAFF7D0F8CBCB1D574E9C19D396A30573A7404F6196FBD7E226731C8AB05138F7B1936986DE6C1F1F7B52
+ 77: 2C3ECCA6E7AF0F9587E5A03D462C98F18B8C13C039D02D2D29E06B5309EDC82052EF72C94E0A5EB7FD35827665CA2F92
+ 78: C9B659AFAAEAA8778E9E4E3B725F758768963C55151A54BD9DC191E1302ABA1F1F085D5443C46441793682A8047211E1
+ 79: 9A76E83A301C14AC6AB8CFB29D2CE39E0E86B335F2B20C3C889651B4E0B94C5218E910B1DAD28474251D06D12D47072A
+ 80: A526CFAA2EE981A9A4D0EF12A6FA363F562057BB75A218F4645BC5E9BE7CFE7EADFD87386AAE1C607D812772498ABBF6
+ 81: B747819B54CDFEAA751FB9F5C22FB269151028BFBC6650BC518692944C5F4195D26AEC45C9B4C987ECF4076B3871C5CF
+ 82: D45968D452B5349CA43A0FDEFE4A5379381625825A27259AD9BF5A80C46CB07BF1C919FB3ACC250D73238B11C3A07D90
+ 83: C0B8AB0F8C497ED9562C65091DF1D80C32C57A018B00957BF53C41DF81A2F6371FCFE82624B2E84859114152B36B6AAD
+ 84: 30D2BF3DA80C0F37807F042FE7B878851E0BC4093D987438FC2B993F4CC4AF6F704669938B9E30E59BF8999883639F64
+ 85: BB782ACEE42930922A98F65F319089E9B4F5D2DD2374DD76035E3178DB4468A3C04F5EF878ECF9ED757DF14DD89BDD49
+ 86: 157424F30A10748940BBFAFB6D99B1B06A897E7DAA4F03387E5ED03F02D39AF59F96A20E4E9F3A4C5C07C20A8FADC8D0
+ 87: B9ADED711B1E1537A35AF882F1F868D964B5898E85B07F5677DBF183232F36C14AF4D9959C2108D9313F8BFB14830B02
+ 88: 7C4563BAC3C05444C3682039EAF9F9EC79B96F0CD36245F584647BC444B81734D7ED4380CC1F0A2BA876020E55660BE0
+ 89: 9811A4A45CB28A780C063047EC6CF94328102DEED9971DB99E11C6FBCFC046EE38C1A00F290FF64356B9A304DC0F340F
+ 90: 09A69D3255EB08E9B3CF7CFA73D86944CCC91DEEEFC04214F8982836726CAF006A3FD83F8FB75600CBD060ECD639C388
+ 91: 52D6D0943728CD2EED671736B6B3BE801B811410992E4A3BB50AB4269EB21AB945F6A9F7036DA654A7F2785869335395
+ 92: 8C0E1052EF2B06C0C20F67D92E51DFBADF3655FC6475935426AE1C88F3096628EAB9858E5470FB98A546EB11C7B752DD
+ 93: B21351AF8400B9756F104599BA4BB78C2904959E2B24AC3E15FD0398627E6C8D57A7F9FEED63D8638A206BC1683794A3
+ 94: B9F7CFE97C79568D62B07F1EF887C4391B48CAA669AA8495B71A326B120FA49652F02EC0D53441DABA1E104AF091E0E4
+ 95: 69D2D1773208CE3BF02B38A7F14910187F3476817ADCC7A1D9830C9F25F112E604AEBB95D0237AC8795DCB23ECF52927
+ 96: 57A9FA7CA61FA2FDBF0BC3E3E6463901B3B26E5D9AD79DFC0CC77F79EF3AA1AE3949E7D71CF794E067D2E38E7038EDEC
+ 97: FEE9196A0A1199DA8697D00AC8084D6CA1F867D105EE928FFEE14E5E36BEBEDE5C79509CA5BA05E36C3F0BAFDC9A755B
+ 98: 0E8DAF8BA4ED614B38808B4E468CDF88EC9B148017C6BE3FE593410D37D9B50ADF0913B7844FFDCC2F1917A27A58B352
+ 99: C7FD40463E26D6A21373EAE14BCB7403B127A1E23E4583B2AC727106B07B849F74C0907804AA799C05D9FF324D04B182
+100: 16E899F4850512FF3DB0FCC58FEA960831364E5FB077CD8DA3F5B3F0F50AC626601917E8355E4847A00E0A5166E786D8
+101: AF2DADB17605DB3CC471C00D63C42F75F815594C1B49D9396BCFE7ED4D4FBB1CF15B542675DE8C9FF50EF81B72FF72CE
+102: 1699A1EA2CAC707205A6BFAD8DFDAF09C8D6FCDDF2BC14A9678453463AC80054627F2C39B713861734B0974F442D707D
+103: 186DA71D7E913DA49D8D97101882B1282841D41CA12F514C1B2DD61543E330B751E9F97490E18A4A37FF1853EFDD757E
+104: D82050038E6DF6EAE9D2D4019827025A25BC8CB15812E0ACF4B676C799A3D80ACAE5706C0FB1FF72B2C4851DC9232B7C
+105: 1657C99506EC8B28AFC1684C4A9EE4970F8F426E4BB0C3FC2795CFBA82913B453C87D84AE9B32897A4CE26FF4320CF23
+106: 9834E936482592BAC2373AA64806FE0D5C8FA92143070C61E594004F0D3B8516C2A5B0244F273124E83B20FE9A2CF5D3
+107: 5C4856A82C8E6E49BB81E89C26E355AFB75EF921E579EC4B97868BE2CFB4B1D93195ABA0500D774C5365C2269FF333A7
+108: 67B88FAD5085C8BAB8E194DF73153A5B1D334431227DFC619D5CA5D5605EDC7BC95DE33512B2F5B714F46F54E1E61B0A
+109: 90C6A8F36D42C5F21A89417AA04D822A53110DF1D062E0C1A6FD9AE59C6588CC1C78469B94578B6D7C05EFFAF7FEC26A
+110: 817C0E7ACD548BD3733792F4F8D845D7E4B3CAA0F0EA943B51235EB82DA7C8B77A733D756E86D57EA303F34BD97BA1CE
+111: 7FF397FB43DD909AB80BC381EAA4BD50B7278DBF10F39FE718B421D6C07324F398BA5B1DBAAC64137267DE2C62F19F7F
+112: FAC12B732122E18DFBCF8DC7382AB1B55353134F07E07723608825C907DB05B4FDE40FE550878D971F8B0B0953C88C54
+113: 4DB0FA3C105D64A9CAE84C0B5D7AF0955F6F58717F68366935FF9F478E94D3969B1264B1F37F8F5538BF116DE29438AE
+114: BA6E693A6C3C5B048FB7F232CC5E12CA71662332EBF689AD75F6F2C54715A689CB1F75525313FB8B2713909EC13EE0D3
+115: 00BA656BEA25DBA36861B92B356C3DEE0DB1C86D4503C7FEB0A88A3541A7018EA456C95224EFC46AA31CB625421BC811
+116: 812622078CA3B4F59141569A0E125B36F7CC471F76B7B65FEAA1F1F656BAB6A3CD61A4D2456E2F5109274B2090C1F4CB
+117: DBDAD8926A811DD0295C31D55AE0D41672C7F22B5CAEABFDA2C1505B084AD01440E9B8FFDA4DFCFBE281222AFD547E29
+118: A32EBC13D689B31617D24E6AC03CE6FD7B1AAA2BA78CAE2E24C36A8CA7BC74ED9BD4CF6C74E3C96DEFF048FE3964F0A0
+119: 095D2C8DCF88F69DA4CC49C64B03B2A1D2C6922CE0C6EDA12642480AE0DF35152B4E4A9AB08D6642DDC313C0FA01444C
+120: 578A4BFC0CA83F1B38A0D2EABE2C7D3D67436B559624B92E4FBD9241B2CA8C1AB679B503A754D5029314AAC3AF225F38
+121: 25E321E63E4AC8994FA464B3E2B687150007D83ED8D6E1B217E86B0CA0D163B0B9686E4FA2F26C1839F2D778EDCED86D
+122: C761BA17FAC3CCCAF2CACE92283DC5E5B8A6571958FC59D0070FB21CABC88A80A40DCD56318988F3AEDF38AEFBB84EB2
+123: 5EDF5D71D2CF85E7ADF9C7E964FD628ACF304C4DE3483F672666A583E3D9B1D86E9E096541ADA237D69A140571F5B3B9
+124: 401702CD847ECA2BC9208F52F27D84D07B37A86CCA5C3A877F24366CDB9719DE63670E850F02CD02C6227B7214D5DDA7
+125: 362C899156DF70FA189A66DAB6DBB3CBF80B629D1E90D9ABEB007C3C5010277EA589C4D73009C81F94AFF3FFACBFCB1F
+126: CA43387C71B8245B822D3085CF029004E18CEBDFC9F78C276F3559D962635601957B6D2287089AD43F3179D077F37686
+127: 4CE8504297E21812C901E77C6680529103A017553F095913CFF06AF20E3D6DE7EFE911B636DCB5791B292C60147F6473
+128: 2AC71958C77E39D4DE4DACE92FBB6A093EABD191320A5ADA7114BD201DD026567D2B799EAC78C1F084BA9FAEC2FC8BD4
+129: 87487060C273FE18A2CF1DFF222658E1B50C3BC5A3F1F4575B3A4A6EA2F42238DEB68B3A2EC6A325E3FCA504B2E20E26
+130: 4A79A1C3C798D9F26D54715108279948EAB246086EBFDF0EAC9152216C0BA3A77AADF82A230AA84A7C884063960419AA
+131: DB0BA43960FA6B763202B8BDF3FE4ADA0BAD78EBB3E6E8E57C2D5640D1ED4CFB4AC18ADB1B9770DB49A4252CDD25A369
+132: EECE296E258EA3583FBCAD1CDF2B91F4D2AD1FCC1AA339D8F591F89C7ECB5EA2FA644954006F0A58F2F3BEEA1AEAF7F8
+133: 7AFD95C86517BB6050D04BF3BB1448A0608411B612A7C2A939BB44B984E361C40569E5E57AD7DACB018689C2B8E2B3A7
+134: 7FCE7894C8E8D1FB187CC35CF5758269E286427A63A522F4BC45F814B316C1DAEF981917642C50EC693F3EF4DB8E66E3
+135: F67F56C98221892F64E2AE4325CCB80C2846A43E1629D40BB50845184E9C3B66480B3E9F792389983F2FC48FD2508F09
+136: 1CD915561856936AFCC75530DFF151F49A34D0DD0030766FBC1BE47D611F10502BE86C97B91D0E8767D4F38913EEDC1A
+137: 80D9CC8B1B2B883C4735B3C0C19AEDAB78A0771753EBB4688A7E584BE7366B3C181C8532FB3A8BFC484C9CB0BBC1B4F1
+138: 8ADE2B8527C994EAB0807A89CABD5B075CACFEF42381DA3CC3D702316842E25151C65A22E80885E5CD5FB5870FCE501C
+139: 2B403F2188D086327C92169871FD5A7B432D2EB999FFB0F2369B2B766E799AFDC1463CF4D9941F828FE42591D6B966EE
+140: 4A0C18CECC0641C28C4136D42FABD0BC27FEC27C2587FE8A57CE0D279ADAD70F80C1E812E01B26F2BF3ECDC7673C349B
+141: 8906762B63651DD5948C98DBB1B39BD6095C1438B2E4CA4B5A581D451AD3EF76C8A0FADEC9C0B0036A833D8F5C13F1C3
+142: A363BF2A479F67F949AFC151C36B052062CC2CE840974BE2F5E79C0BFD7BA29008A6BFDB55B46527D17F61531C953081
+143: 4E2AC5D6EE56567902CC1E02F119E33974762C03885EB7DFF7C58ADE22E56BC384FE74BD491EFDB2E6CF4021E3016E81
+144: BDF0AFDF17F7B014A61ECE257F8C7E0B52384EB7DEF60ADE785F273851D645E5D3B4D9534C0E6097A12C3CFF5C11D42A
+145: 0CDC61FF0B3D8510C319020B82C1C5AA12C7B6F257D7D4F118A5EC3CCE03C63FFD38710F8A3C621DD8D66D8BF3790B63
+146: 19E35E1E785C7A41C523F88CDCD919EDC45F63783330D9033768546CF59D10AEBC77F013057C0E41D6FD0FE77DBF914D
+147: 8AFA5DF52F6581794FF014A2E1ABCB05781C7F44AE6F37112B363AB13FF01FE1E8074F14466A365374C29FEB048C5B9E
+148: BC9ECD12706BE5ADBA04DCE84AD53AE1B324F99C1F5937774DFE19C5EB4D6A20982E97B8F8E4E02EED13B25B8B13E64B
+149: 8D02A1E318DA1EBFD1CDDBB7280F3603AF3AFA21B3D4E0727C7CFC576F55640B7A978B179EECDB8FBE896AD38E82F12B
+150: 196929CF0849022CCE9CBE4EB2DAF6E5D8014C5A25E119EFF799A82053035BFDB8B05F6C125B1DBDD4E7B393C684FB5D
+151: 58808D04067FAD72BBEEE4F6A355E80A2FF76EDBB5366CA43FF358A842FBFA2F9E1AF5FF266BD2E2DAB1D286AF5BBF92
+152: 4A548031093ABA730D8D99A2C1C6EC2A986A94167CF8C1EBE83D52B34BC2068A4C95665988FA93F5246D0FBACDF85FE2
+153: ED949965036F16A0B5856EA4CF69CEDA35C653BB56FD0F0B397E73FF4884B3E679ECCB19B07D6A93504E82A1613CB87C
+154: DBA644B20B01E4AC5CD0A325CB063EEF53AD77E5A9E7095C1BE0EB0E6B7CFE60BF25F38CD57F2AC055D327EB6AECC7D6
+155: CEFD6165F70D9019866374AD7AF9C73F3041B932D61A41734E39AE8AA9C7A4FBF1DCBAE9B2A4E979C64352E3CD4E1B95
+156: 732C3B457F78DED89390BC461380760FBEF3CFCB9BF42A6C86ECF120C821CAC79D4D51C71A955309E33724742FE2FA0D
+157: 54803568BAE2DB4F143C78FF53B85E6A9D42EC3894FCFB39BED8EE611B36BBCBED834D366A1F797B626DFF3D83CE963C
+158: 35A1858E567FC8A11B92737E369069B12502ED3F44DB50434506F2E540FE643655CBF806C06F15CF2428FB408A65C04B
+159: D1F9E930418D10043D0E83096CF717B79C1C9234C741C59436F42737AC73BD39B3F4B6D6439375E0D44260131B25FDE9
+160: D5B56A1A70C47A3F88C519668097B54C989E119EE9DD5B8B34F0DBC092FE7108C9D396CFC62C9322563EE72A0E324010
+161: 1578BB76F87DB309A5D3A2229A2B346DE39ADB623836EF0561348ACA7E315C16C6E31328BC70DD0B0D7D9B7ECE076CE6
+162: F8DF4C71F3623ED00EDF8EFC4E0EC154644E21E78B06C9C5ACB980480732E17E92ACFA059BDF299BB6C8351C6CC6AFF2
+163: 090DCE25595D7770753B78C410F10E830140B23D779E0F52FC451582CDE7511A390450F8B65D7BDA77A18CD95EE3DD38
+164: 5D3A56D23BEF1324B1EAE33B8255F904F7DDF131517200A505031D41A2EC3F2AB03912DEFF6BCECBFEDCB8B948CDACA2
+165: EF712AC1E6859F70D0D2CACE7AEE120A666DF9F210512F5C94AA7FB388F1DDD913A12FF92CCD2537675EAEC870203411
+166: A0E6443505B193D89595A51BCBD47A46E1B5AEB239D68B8B18A119E5C9EA1EB8863B373F91B9F22FA944C29365406A79
+167: D97DACBF80BCC76335C187DA29FF33F6D35EA8A8925709322EF3C0F6FE35D128D9D423F911EE31F1C38E1DF36046E507
+168: 67FFCF0A9F88F84B3EE85000B2DE0B7DC12A06160FCBBB57BA291DC04E14B6DBB3CDB81A40C2EE1859956DAD097C1EE1
+169: 7AE82196B46DE3E6948D7FBC7383A6F080903D6BE6E357700A87F82A964581D375006DE35169446B447537B4F11C5702
+170: 502E0A4CF125EC0640DC7E7264D9E47300814B00D4322F2F62BC1D5F1D0D77173B0E7C2874CD59FD8E056B8F38F78D99
+171: 74FDBC4532534DBF24230ED5677A920B12E328E3D073364498D80F0CEAFBEC774EB53F28F0934F787C56AB794B60BE31
+172: 3C9BF5EEC652F40AA0ECB82A834C836E495E841D337E1299AAFC067A2049C540AABE92CAEAE02F099BC4D3A383D541B5
+173: 105AC61F2D4E586E376524C488C33521C4D49D1F95B752D27F49ACD7181E8FBBCA2E0F0B543EFC0CBD32A5EED2CC08A2
+174: 5CA49D8B554D70B3FC467604661DF8FA51D9987F2A77B13DE44D7809FE2956D21485B36F1D17B59F2261B1B40553FBE3
+175: 1DD075C696DB9B07510A0D276F8BAD12225E00515D19E3B85583BF97CF82B5FE3F685502F64D91F4FEEE1848BCD0502B
+176: 11A018C4B213BC67C09370C8A3D0B720428BE71C01C6EE9EF6C9C9DA8B2E1FBAEEE42FA44EE54D0F526DCDCD3C2BB2FD
+177: E188EC519C6E0B8A89DE68A7648DAC6D9F84FDAA678B431794EB4BFE077901C95FAE25CA3D39D48EA0292F3F6C35FF73
+178: FABEE0B0A02BA622931A5EB82CD63656B47A20D3C0E703D5A69AFDB92C0A7EC5CF6944D9D7A141C1255D60FF9532B089
+179: 3C8E0BB55E099CA9F6E436BB3CA39D511AB9CE5674469DF8BEA4A20193084AF8561D5130FDFFBE62193A712D7C2D4B48
+180: 914BE8F0A58082B877AF0DC077ED146CCD8245339A170B4099B146476B0A580749D01F83FB52834A033A3822D12041B9
+181: A1B31ECBF451571437DE10330A6E9AB4484576AADC4DEE0B31D9C3AFE59FC6DE028275126D7882A2C225EDFE491305E4
+182: E4DD2E805A5BDE3DCD329ED9D35CAEC2D5A97082966186118DC46BCA7AEB1EF52E0C6007CA28131790838DD8C00E96FB
+183: 785B81A972DFC6A4982E0BB76F90F26DBB7BCD2D06E872304CCF6AB2D639CAD85FB29124ACE411EA4742468A6663EB2A
+184: EEC3CBB5AA129C7206A32A176482C9BA24FE60E71B46F7C3C11FEF8EB57682A3732680E6541D5878CD6A715A48D75F12
+185: 254E279B7C4F17B911712BF7138E2C6933815BAB18661CB47388FEEBDCCDFFFB6AE8B4B88072B90074704EB7EC567843
+186: 9A8CC3FF0D9637220CF2B4AFC9A8A6CBA4D0ABEA6A0BAEBF151380848E92DFED8C0F0E57B6D05095EEAB0A58DFBAED13
+187: 349966E1D59BC9B32E1BEDB050354177868FC07257A3A1800F0E711AD00AE388746DB1E4591E3ABBAD8F418E1AE627DD
+188: 84ED950BE54768557475E6B1A256C30F444E12340C29485832439BBB9CBD219050D184624D6282728D4AFBB98CE4BCD6
+189: 2A7CA4EF1A9356E853329D336B6E7E033F2CA13677BEA67CA669EB7C78DBDDE67F9E7D9099C68F34E07B96DE4155AFF2
+190: 7C7020B0528F1B3F76BA258836A89BD27429110F0AB730FD741FE9EA2714AF827E71B731AFD53A293328788292ACFE23
+191: 91400ABC089F8888DCB22880B87A380FEFDAF81F237D424F057E5C4C8E3C8EE4E423930C1D3D9E16199ED82996BE4232
+192: 412979E13B3D143270BB41FEBC12196B981E99BFD6687B780812F409C78A5E2DB7AE828994B60D26CA4A1F7A3A44C64B
+193: 02BDD417852D9B03A37338549DFB6D765EC4CFE4C2385002848BA4D46F88053FAD2A39DFF615ECFAE0D41F02E5877251
+194: 77845BA2210971E362DC117B1BB13D7DFBA62F81EEEC7068D3CB9CD093DF535448CC357ADBF0C2394351EFB07C3E7DE7
+195: 0F43AA1739359C14BC5702322F193AF89335887F9175289933B2BB3F00A777D1D1DA74F5D45FC43AA90C9FFBB0CD580E
+196: D1D9A7B995B9BFF09252566D2079121AB12B0A5ED06014994464FA1AA18CB1BD8E7D5E07E1C71E2EED9CF081A537F28B
+197: 67DFFE8A168B7408B7DDBD10BDF14F4F2244FC904DEC5850F5D8302FE35AD1752BAD2DE50449F9C12182A2AAB8FBC9F6
+198: 030B5E833F6D8703BD0C5E36354387AF833F466AC812D4E1FAB6CDCD3146FFE3B0E56722D671FB85EAB22CA5CB0309BB
+199: CB992B3785E51EF3A32DE88073586DB045F356F18A09329E82943E29A12B2D1490B386D8CEBF7D90FB492966989A73BE
+200: A1D337D363A0BD8A0F2342351519C62318A120FAF88F9B90330845DA682261C64627B67D2F533FC48D2BE394DF8F4F61
+201: 319DF6326160C7277A3D3C65995BFB729A69B71B40C149DB1241C0B2376B4205837B5770805C86104677917EE5E5912C
+202: EBABE3BCAD828A9A3D5EE05C5EBA9605A67E1ACE73AE69F20BF435C3A14AC63E43B61021CDF3FC2245A14FC14A7AB32B
+203: 1723D844C0558D58EB3EEE3286C48C133C5F6C1D8CA512F2BAF1FAD7884D4FD5C3000A6756DD1E34E83DD066AD2BEBE2
+204: B048BED188BFFB8FF1B14CAA0BACE82605AEB1C666283FB7A6FDF216742F9F64A89C50B9852B8119B5FAEFE64615C241
+205: 7FC6E8633CB9B16F553ECA3C75C0C0F7B610010853EFC94AC330D36977EA8722B970DC264D5FC4D69F39105E7AA0EE3C
+206: BBC6F0E0158B6DD549C5BADE0FDFE415747F1FA2D2A85CC9DB758F34998FBC8C8D99D573CD948EC768540B363D67C4F0
+207: 5073FA9E162BE773AF5BA1CE5E6FC21F2F0F902C80F09BBC3AECAA6CB1867DAE4DC011D1DB987642949E8095909CB984
+208: A641BB0E1D20D5DB0C5CB33D35B73ED83216F2F5DDD5234A0BAA3B209A39E015B7245C40F9F372E618EC73450487B54C
+209: 948806B7335EDCC7C4BBE751844DF5717457B223C7A3B81B57AB3A949D0A726BAACFBA228BF6C2CF94E942F9B2F1A7AA
+210: 0451CD5EEA206D50A7897F495D648425CA333158C126C4DBA44ADC06447A51D3C7BF2D4D81779535CAE29792C7FE5650
+211: B4227FEE0A32009D60C9C30033C12B7143D4C7A1C25F39F3E4A076BC4943992AD299DEB2C15E27DF867BF948DA27C009
+212: DAAEA18FA433CF3E117F2D43303139D3F1D8C3BB8AE8EFB30B44B9D5D4BD4E553B9B6EB9019CC4E1AE5D0DBB6C23A102
+213: 4434C818BCCFD92189A3A466D2757AE2655BF0D6CD954706C85220A33B95B184EB560FF3CDDCC4DF557E427E60F9FBFC
+214: 6AA3B44FA507B6D704A66B4D7F26CBAAB2B400C6BE0A8B61B50EE617A16C2C09CB36E72FC309C6E4DB24961B1785CE3B
+215: 63AE9C02B96B4BC456FE5CB9BA35366DD69E78DC9CEEC376C6780703883D609333D45CA577A982A177515674B975B658
+216: 3B5DD4CCBE8CDF32009CE29FEE4F6EC7CCB1471A3F8E9BC9A35E8CC37F6C56957B757DA4C3204F9014977B93F9E30DCB
+217: 04A6528CDE6BB9F425132CCD4AEA1EC6CEA482249E5F3782B000FB071A4EB2434597A7FCE2A364A9BC9E0643A8403DDD
+218: 69275CA1F9F102925165A568C1F152D25DF8820A6F34595C4359159070052FED260C55FFFAEA2116AEE7A63DDBAA0160
+219: 584697C23C63904709BEA89F055AC592DF48034F908C9F06C706A51C3F6BE5F0F2A5B953AC2119FBC0855B785326C06D
+220: 04221F0A6C4799F9CEA3C1D9E65B9F77F77C613FD114135DB019D8C497B8899513AA4B499E720CC11AECADD1AC071DBC
+221: C7B878613C2F2ED10C8EA413970B124838F11F0414AEC89A3825DDC588629A8049E82B461A23F25C4F93E5BD11C184AC
+222: 1891E7A51768E05BB1D03A1EC1B844C7C8EF77C433F700175998B2D8E2EEEEC4618F00003793C5873655E093048B674E
+223: ADD2B81466BC727AC85DBE258B566C4DB56F6F7D81D7A4E43F86C125F2AB2E08C648E628B9CFE440F8BC06FD5D861D3C
+224: B3684BEBA86D275745CEAF0922473CA581CEB7371C5747EB87B407468006BA50D69F9BD8BB7F214185CD0D0C548C5432
+225: 0C783882FC826917619C07FD03FFC46DE6CD87BDFA87F1FB872989489C32FE74E8C5660748E1E8E9AE19C68B075B0EBA
+226: DF52553B4F7BD148574BB47F61BF8F7B2FDBE5B6963E29CD559F236BAAFC3DFD6A7EB5EC9968E0C2B3A453F982F16AAC
+227: 45102671440B04027B1F9966C1013AA351CAA3F3CF42C4D98F5B2D030FF37836E9F5865421D7DC8B037644FE53C6B280
+228: 247396BF60C0FBA27B245CFCA061D1F6EC50CB87CEE54E8C4A7186A07745D255E4EF9457C0A329AC9E3FC913DF86A4CA
+229: ACC5998C464A26C1719E9B17E1B8F5E3657FF0364C46FE87154DCD1C95A84734214D2B81CEA8DDBA501975281EF4EA9D
+230: 163F5AE385500C1A6EA212D6925E48CE2189DB1DD47F7F2D2D889272D17449A1C33EB3970A5982EF2FE5F1255367C33E
+231: E8BBFF2C5CDA88CB60BEADB8D04B88795B0CCD89057CEFF1FF588A169363AD453564FE7528D1FB7148845363C3E17824
+232: 5F8671B7C62A5EE9717FF80EC2AA0A03E557A2840C0FD0B59027AFC834C051CC9B7BEFFDEE3478165DB9CA303E2D874C
+233: E0E4DE22993E4A6B4884163C678A23AD6349DCD4C16B9041D01F8B3FAB1E8D8B07DA78BFEB57F8C235C173B2D238C4B7
+234: AD6F58BFA15FD0DF1191171F86F2B4C8729FE407128ADB4FAC3404E15C04752F2A4B5F4BDD488378C56FF8D85A38E583
+235: 90C5A75642A1811D8FC1ECB84AF4904C6D9E613353C1B9ED0FCA37D20974CC2425052E2300738824BECFDB981AFF06FD
+236: EF73A9E6D23CE43508400163CE6F3E8F7076CEFB94E549EB6116C2557F740D66A1727AD51CA645A7F9022912058FD262
+237: 99FA424E413A57DB2B1B851098FAB1B6D3337AC7FA85709121F0BBDAFB3EE291F44092EA7EB28E9BF0EA0691AA531BFC
+238: A1E0A088A279E750CEC429D0AE320B638ECBF9EE387C65C66D2231C884D844DCD438D4D4E052B8D76998A444E0666629
+239: 0657FBA0E7A73F7525505235120C44AAC6D37CE974FF23F52872D6ADA50DA022D417D8DAE40E80336846E8CE211D5AC5
+240: A72ED7917F0F9D0DD888DAB10AF9091A380F518D5DAFC005D1EBF0013F57A7452AEBA98913F509509A02665F332EE255
+241: 74CC959DC6CFB31CFBBE9CE8ABF32D1629E0F578F9199B9A2E90889A2F032919923142AB32E1DEE0A53ADAFAEFE0EBF2
+242: 9E4D463D2E3DC2B98CBA40EF84B022A76D01926D8DE6AC05F995C07C5F07D01742C5410B240240459280D7D278E8BFEC
+243: 0D74C427EE654E4790C7118272998C131337D0D0555B68F488AC7CB8DE3CFB461B0248E78340D74B828C80CA28ADF478
+244: 952F274ECBC66B68EA74CC8534A5D7EDB219B755C91266E5A779EC22F52DD2EFA9C447DD311E71C90E1419B4B2F3DAE0
+245: B845B0A56AFEC2FB399559FA77C4835D2BC4C3F8D62BEB1C45462BAC661D2E553B43D0A86073F0BA5AB85B129ED20B1C
+246: E65B931E25101224A6933FAAE7DFCF22FE84759937F5F3BDAA90D9C8E8ECD0BFA1777B99A77E3232E38917F9432CCBFC
+247: 4F69FE2CB97E9233BC873D153ED9D61B88C20FA333BD4137A532F4F703A323FAC6F8675D8B44EF5FAD2314894F7D60B6
+248: B36F43A6DD2917A1AA0C6B566599C274701BDF03A5B7DC65E5E9F0ACF882786F07989B106A50D0D89629136EA0E26EB1
+249: 8DB7B80635C53DAEF891B777850487E72B67F57576EB05F708786F7665F1FDC2A78F441636569D1E84058A43F0243A1A
+250: 14A43F1882AE0214F56819F4AE9276499D39DB4A4A939275DDDCDDD80CB6B70999E6178C4EF295E69A807EE5FDBF9AFD
+251: E5AA44CEA67F0821D4ECBC981F258837A243FD901653D484BE5C24EB7F08E0BF33525EE3DDF9A89E1263A853485B5A02
+252: 0191F0505CE5512FA08500BDC090570F0C430161595894528FE7AE5DAD8726E110B0676181A228A7A90E21B7B055361A
+253: 76FA1230972E771661485546D6CE556FCDA23B6DC0FFE94DD3BF7FF13FE9B46DCBC8D8FFC617F35687903B972FA7EA43
+254: FE280E1191D21CAE12EA3B53D77E03EA4D96108D35555CBFA9B156253A011ED91B857B82D644BB94BAC8E4FC4E0142B5
+255: BEDDC3C0E168A4B14B023DFC1AE07BE9A418678494C2399695EA9B17843D373077A708F8C82F37657BDC101950FED664
+256: AA5D7EA1126BF16DA2897AE036E94D1F96875AD306B19910EFE3F17B7A98F9A4163E4032EFD17DDBF78FE3321047509C
+
+HMAC-sha512
+  0: D29B9E3F87809686F34109FBC718D6ABBB09C278CF05A206ADF21463E1170362122E58272A31679720B254CBD63A7C6D696BF9283F9C6897E7D792483BB0388C
+  1: 5EC18FCA20788348244720D58E9532B4B699E78D48CF7D7BDD1A4E5C61CD09C075EA7F112DE379FBE953332C6A7D6273B3F6360BC07203A5175FAE618E4A2F55
+  2: 293D275FDD5021716117D2B85E6D38F8D60D4984BC73E2D8D7EF5942CF1287B65C0675E566794786FEA18AED1192A024FC4B3E0505D91E1F91833B210590BFDF
+  3: 8D9E222D6B16C58B3862D6BFA556BDFC2A4A152BB2574C2294D5381F6E38FB681500A6A19D55525B337A467A2FC30DD1684832FFF92AD071EEF05BC4F4399FE9
+  4: 71E7028F8C4CE9C1EAEFE459771528D26993E180E616D68355B9C618153AFF2C0E9620B151C8F733E71180EB87BD773A512B945AA353029A8F807FB2A8FF2264
+  5: 589F462D37095693ED0C1F3E0DCB892BD19086FE033718911931509EF6195AD17C79939A87665889EFA6DC19A69BEC6E7058531552832CCBBC06F1BEC70D1736
+  6: D94FC6BDAB3613271522BA05C998A6D1C57CAF0E6EE929651762F257E7EEBC07F5CC7CD3D4064A2755E408B347939B3927434556B4ED49CA406C21D1024E6D80
+  7: 4D8A886A89E9C60EDA3BF0BC512A295196C3F62018936DDB24BE9F6AEC7AA9511B33CBEC8A22309B6389417F4E7FB0489981CACF03DFECF7D9FE5B91D62BB719
+  8: D0E00955F0FFF98ABE885970EE44F1B5D4C23C205C64B681381FA13C543106B2AB4E762FD71F47008B4C429C39ED3D66B3EAEA946674F08684AC99F957F50416
+  9: 4F623E52B5FA2D556D25754FD00BB8429356FD75FE2EC57EB4BA4E25CE03C5332D3A632179C9FCFFF140E6B443A4285F4A7CE881E6D3EEC4FB0DB26C0E2DCDC1
+ 10: 5196EE8D442E5308F9D8911C87050DD3C4842D0CDCF55AC554412CF096EDA94BE1A251743AD5BC5F8AC902A38B66D7D57C90C29200984572D57C04F64166B803
+ 11: EF77019B0F93B1598E38D3B1B703B52660192547353E7FCD5A7C8525DBB516970D3A6F2A94729D90A5A34CEA255F310C1F46546C2A08975AF477DA2F3689F17E
+ 12: 0A77531D7081095AC0D0ADF2B379D3F820DD20CD89610917E287FF57BCA5DEABA750E1E075DAACA9CC4DDC74732E6F7BCCCD3671B6DD27503CA855EACC63FFB1
+ 13: F1E04B1F7B09DA270A44B62DBAD2FC0160BA1D144D7721010D77ED250A00986932CB6652D95B4A977494F11AF7E7FC82A70DFDACFA11232D653B1A052820185A
+ 14: 7BE1855550A49FF66D6D395DA7DEBDEAF674F1AB192DF82D74F6BAE8088F83EF1471F413CE00A404486213E41B42CF6C4F7FF1BFA17A1E28928B7179F0A966EE
+ 15: DFF2CDE8856D811494F559E9F4159065A50B1E82961628E95F04D595F670249A2B71C2625CC1CC2B1F85829255DA007F0374363EB749E935BB72BDA24B8A3F70
+ 16: D2F7FE57D9583EC1AA733403527DFBB118DFE07B2A60C43039FB238A7205A053E0496AD0F3C1896090AEAB3088283C8FAF272D1D53B5F9F88281E0A53FE7F8DB
+ 17: 963F629ED8F0E7D6D4CA4DC8A8B57C825F726380D0BA9A9857459491BA82F64A929EC4ABFCF79374CA68BA812E3A83A643D05454E146E9F4103D17E20B8350F5
+ 18: 1FDAE69CA4A9FAACDDF30A56B23F14768EB7D5616F6666B6F01FE5E216825CD4201A69CE3D2D1D2C3D03246BA7D32ADCAAA4A7D03B9AE6AF4CFBB474E1717BCA
+ 19: 2532E98B6D91D8D658BC1A1FE41AC719D648D47BACB423C031A8E2E9C25CC6650D3E5DF8046BC3532875F0C8DADB38AA911F216E6741E9FAD700D31269EE5D46
+ 20: C81E6E9F4B75A4EB2B903C4DE28CC437CD87BF789F6BE60EF521491CC7E44AF26E9EFAC55961135F79B3591F5F7B92ECDC9917641BDC34943C6759AAD9437498
+ 21: C0C2B9478F956800B64FA408BB0E077FEF48DE4B146926B3C577C00688829FFA6540AD7C211A807286C546F7D146F95989E77B62F5E14D62FE0C77C85FCB6CC3
+ 22: 980D06C1B27EB2EB15069566BD1BD838FD3DA453751BEC564C05941C9BFB9EE8443EECF84CBF8AA7DECAA294C7D1A3FA4A39C20A4659DF332CAFFCB2863A769B
+ 23: 70FB10E482AD19447CFAF10EB9FCFEE67F9DF7164B2647F19CB220E7D83BF892AB7B5C5ABB73B779522012BFD464D9D1B18C37C3F6CB70EC4106FA94F8CEFECC
+ 24: 7AB19BF67380012D3A53B93AC15E353D477FDD1E2E8851CD5AB5F36EA0C8B128D3193934F837D23D232F44009AC60DDD358AFC8D3A201BED3EAEEF74C03617A0
+ 25: AAFC1227AC42CC27BBF78FE26B3FACBB7B15360891C8EAA8C737AD42C00971D02B3A07CA751774D02F402F7E76BE08E2C1241EB66242DB5E11B342C22AAB9FEB
+ 26: D8CC3BE5B48C7BEE8522BD8872419932907B78392B7F2546788477C858D0C7BD772985C0B0D202AB7E69AB5F4E1A0BC848A512FDD79EC29F19BC4BA6D28DEB07
+ 27: 6133D836D68C82658F6263F794073CAD9029F20CC11D0A6CF589335B023CFD66D708F09136546C6C08769139363AE5CB4CC2CC86EC6911237ACBFD8B0423E377
+ 28: 833DAC9CFFBD62FF0749391A42324E2848670913890754E24ECC29D4738AF00A78134660A20078FE59C66113787F4A3E6C0E783740B2F2B2BC8D36FE4EDE39ED
+ 29: A2F3BC0DF058506805DCF5CC3006CC4FC4085FD846C7A7A7DD3A06CD6DF635359F4FBE90A676DABD7F9AAF42577C8E3B07B63B9CEC8A9AD05B38D16F56214E8F
+ 30: A49C3BB487C561E5AADA4FBA2D9F5B42681486AE2DF56087DD65B3D5E03C625F709299C84C64A68D87C92A4CC90246D608E692D1FFCE2C099348CD0A19407C2B
+ 31: C8D7B7A7FFAEDE88963B09A09ECCCB4CAE77DF9D8D242BA19F6485BC7775308E5D11C78FE9C46E609F3AF070F3DA8ED929C103DA1F25BE7867FD4D3E4F2757C9
+ 32: AD4627AFB02DECFF956E612537F011E82CB0C202A5A11AB7AFF55A201016C02CD21EFB4EB197BC2D13D272C6A830FD77F534E800B0AF1E79FCFB626ED6A0D6B8
+ 33: 8D4E232D9614EA1194E60748496CFD32A4AC249BB8F08E55A7C9DFDA708DE90D067FC433EB9DA2A6833D43BBA8E8DBF31137A3C9B26903060EF9217471E9F945
+ 34: 4CE5E4055F10F1D2182A7892F98206D9A120FBDA3251036B7EFEC835C95B4D1FE0BE3892E2363087D01948AA426AA403ABE1CD79F0AA851E2D1195511C7A85AC
+ 35: ABD65F8E9A2B39BFEF6EFC9A9EDEF6572489AE82034EF3BF2AE5F380026FF4CC40AF093F0408445735C0E6EBEF5D7E7ECC13C98B59807AE01FFE1BAB040FD14D
+ 36: E8C687D7AF785B1E547307875682ACD82FB58A8259551D81F309C923C2B1FBAF5935EE059B89070B8420F71EEE3BE7B1E3B55B196872F06DD1FB890F6FED11CA
+ 37: A344BE73E6585E0CC31525BD6D4EC3345D7780CF180D0D5C2D5FBDEDCBEA050A958FEB13C21924E311F57FD6A498756146AAC58412B98E4D2A3B29D9B77A9F53
+ 38: F0A088CC818F76A1FD6B5D707B114BDE24245CD55E48611ACC6AA497A0CEF93768501B5F280AC518CEE48C15373118BE7B72F8ABB2E9FD3526DD1C18D9CB2545
+ 39: 4D56D5C9222BB78E04DC9346FA9C4ADC27AE08DA3E34F490A13F674264896E58F9E9839715F633C7195B40DF722441275C84AEF162B513E673809F7874E7A124
+ 40: C4B3C9E8140F0D5589E326916462354827E491F3444E0C361512E6E761F5E24AE1873B238B73F32F6BF8F1D1D8FF9437A01DACCB749282E776FF66151A4F7E19
+ 41: 7B4E07BAF338DF6479E169EB6CC64CFF88167958D44C5CB6606964B7F9ECF5F3F1B1F695C63F2BD66354722F81EE4BC90B9FCF5345642E264C66F6950CC8C481
+ 42: 8571A8F76A1D5DAA0900A03E236FE965D085BE6035B7C0601EAD338106BE7DAFAEC82F7C3D8AD346FF749B6DAFC69901A6072CA089B7A5724C75CB0818640F7D
+ 43: DF516D84392E571C3FE39F4A0BA5D16D866553644B4C4627D3513F0A1C60D22FC5AA4276A71CB37BD6D6AD05A12BF812A2D5388A606583B78372B84DC567431E
+ 44: 535AF3C73B479B61B8B70E590E335DC4C1E22DCA656454213E1FDD46D026B6D36133BDD372FBFBB27B6DCA8E487F4A54BDA8C5F67B37C871653C656DDE9524EA
+ 45: DBFA27964DC6A80FF76112FC6CC02C87811DF1ECA3A8620A5030C600561032FC374A6B060FEBE0ED67421D9217D2719F5A55621736FFFC6F4F26DD4C6049FC09
+ 46: 6F69BFD2C60AB1554023A6A2094D30CA78D364501F7813A2CB73DEA94AD4B94A0EDF3A3698D6A30C8A5E764B81F51CD0CAEF0F996B8C685A345AA630CD10570A
+ 47: 2769DDB3AF3DD650BC381D7B10CBC4353699A2A352E57FA5D5CC4FB610E498767F49104ED0F4E06E2BD563F7F8045212F5B9C49CBE050A1662F2262BAC4053CE
+ 48: E50169B15772017CD9FF93D1B46AF273B375A39D174E3B8621EAC8EF968BD967E1448DC3B2C72A667EFAEBF2B90D4E6640698CB866075E95817719E0EE61DF30
+ 49: 4212648E8F9ACBDC16D48CD7B355884E0817A95DB03BD9B8AC5B28BE6371D8AF83546DC82550B8B23DC77F6D06211E3AF3B25528BE686CCA1672C91117DF9762
+ 50: 33C71EECDBE503A6AF72EBA8D2B9AA7AB8FA8DE536C87643ABF1BC3EDA535BBA64A8A7F4BAC90ADB7D8C926DCAB1D7DCE15D356C5074BB3EBC7B17516671EC8F
+ 51: C8EE9E57EFA859DC5553D03402AE80B84B1E0032CE3F2CAC43F8422A80E3EF59126AE7AB4893735F9C948CD9FA8793571E4582908DA19FC723A93C7C36F79F9C
+ 52: 7CABE0F83E90CF9A497DCE45F14F9926DC714DEEF05A1A0603F6436E134FC7C8346A19CB92DCDE69D794B38FB22233577BA3905C94A7020841224DA888B9BE1F
+ 53: FDC20554A15B71BA62F896DDC4F8B354E5D2434B0AF719CCA7DC56FBC9BD280B0F80136C4336D605C7C26208649F38C1DD0004C6E0E787A91FAA6075051FFDCF
+ 54: 87387F89646B4068038E011D7E02C353BD5649F6DA1C4C46CD9F7D69EB3A2F6EE84DD42D25B67BB81666CE8F92A5B1A0F3EA58D4F0B5B6E59EDEC86B43BA0CA6
+ 55: 6D0210417671B66D59B8F28CA0EAFDB493C30A7D7329DF29194C53887F05EDC2C3F35853898ED77394CCC650E8D350F69598E3AEF3DDF540DACCED5BBCBAF6AA
+ 56: F14085036C69398BC7E0CD8A9D4451A10B080E7CEDA5582ED396E5D54441125EB3EF6EDE4534E788DFE6DD3DAAA204814097987981EC8BD8E39E8E8B35AD8FAA
+ 57: BA67FB4D7D137531D3F4CD3D91975255FCF8EABBEB97EF0FC7C21C4E25FD034658C63881B0AEBEECD2B7D15357C14542D26EBA3ACCA944EB4C4D7E44E9899D42
+ 58: 4546585669E343AD40792308AB456DF623A6A23CCBE64B26B953D6C461460BBA7A3FB444481BDB3F7FC8D5E825F2527D2DFF193356CB3171CFBB56C679AD1BB9
+ 59: 210F8AD68FCD10BDB8773194FE57EFF566C7E65BCD82BE6196DECB40BF39774691AC6BA718E4B5FF0DDCF2C0510182B9A114C6F0117A0BB0E1AD585C69D38D0B
+ 60: 29003A048ECAC0613CFAE8EC8757F5E5CF80E9B0BBF538D7460765FE2D6B56D6251ABCFD42B56D64B56D8F219868DEB42B968E88D3F3BE3A161DCB43EA98349A
+ 61: A308F9E2B60D0093A7278B0645A471408F58B45B3683531179F34931D06A15F4A502F2F7E1DF8B47830F65387BB9F102646058AB456045267F2DC403A1D9A6DD
+ 62: AD484DDC270FE74E68620AEC882E86320D0D0753E713D9D5C9C7FEEB894DD3FD5FDF4995DDEF87B1126B36E92618331126F5852AA8C0D44404BF9F77B780595D
+ 63: B4BA7B2F08BC0FC901188B50493FD165F659D3226227E2E9892BD70B02312C12D195A73AED3A4009618E6E74799DB158D9AC27FCCA9BC682B09ECF53BD368C46
+ 64: 0AF65ED93646AE826C79BB6E8CD193D5246BD00B0BABF8425ACE03C845B9AEE428045D5F8267F3EA86C433F1A9DBF4AD1883AF164EAFE02C07CE43079668A248
+ 65: 65F899BE2C5E9879F6A3BF7B60E62591B5DC5398283229E4FADB1EE78FFBF962295C427BA0D50BBCB9E2F1DD9694BD36CA598BAE7C2EF1F4D0700DC95BB66C37
+ 66: FA9ACC46F0841962D6DDCBF5D47BBEC43A0E1E9B2A8F8B7970E2E73C06612FD95044B8BEB58C71B19AF4169B7E6500500445490F80EA4E305B6BB00C7181810D
+ 67: E9AEA6E12F881A7AEC3AAF428BBF0DA3138EBF69C6B8E52621609AD340D6537E4A03E2B099B735FA82A3D300F782606EF58598683D4ACB0870D5130B4B3142FB
+ 68: 3558ADBFD411DB8436A1A8B40420EE9C274FA153AEF891290F79DE5714130A50C70EB87E8A901D540ADCFC37E40EF44592822F6ADBBE8E5CB4EC89909633DD7C
+ 69: AF3852A0B4E846B59A4EAEB7A7A451311B1E8F554042CEB2D253F10FCB3067F9CA927C7DA3E57BC9C99E4E7997856B35DAB0645C194AE9F1FA0A92BC218CC9BC
+ 70: 6BD90F0F8FFA39C2A483E8349D2A29A96AA7F3CB4B4C1325FE5162988C9DEE849B8E56BF1423B6905ED3FC6A82A067F850372414E2A4A7E5CA379AB80F1C4F23
+ 71: 6433885A8A39F2E4CBB36191A038EC3E3227BDDDAEAE24FD396481332A9AD7BECCC4E9BDEA0C8A7F33180ECB1EC1DB49218D17C4325B661967ADCBA25B341649
+ 72: C3235054A1FDFF2C0D218C3B54EE6A58FA5AE99040A64A90B9C8DE601B80A7C130168FE7484CE1FD9FBE22E6E794161826730B63DE794EC4ED1D653E40B27F7A
+ 73: 89F4DF5AC626665D9791A1E1C30D1F206D89C4B0C59916DA295931539B0A607A1261B4EF022CCDA6ECE02E99449E252EAFC8929F5074866C3FF59CC58268E2B8
+ 74: 3F1AC15A90C38AA964518F176016FDC73A85B096EFD1FCDCCF38F3EC692635BD4E610F1B3314E068164D02168F73A307AD549E1E7EF07DD374F9697DB6A17447
+ 75: 4FE16A3BF0534DD2E4DACC43E221179C9B61D7D50DAEDA4DA9C45CCFDC76D6FA96EB3CC1C184DD5DDF7DAAA413D05B2FE518117E2C9A880726148C7AE6052160
+ 76: 1EA870E13B7E59B97045F662682F29DAEC4413566DA341468CC9F5CAB733D1897BBAD8E9520B85C43DE33B9B70880AB774EA636248CD0A1626C9CDFEC3F1835F
+ 77: 37AE3A9828B08A055B2E47A613D25A8D43D5A456BF741E7964C0DF4AEC6D8E5F3EF874F2B20606A38AFCBD307C104DFA5BF40BFBB3078771436276E777F645DF
+ 78: 48CB9B779D37299162D2674CE2C2595B2422071917C28AB48781DED5060E76EDABA56E7C538C3182F9D960DC21928E6B3069D510046608C976D7A113DE54DCEB
+ 79: A565459CED6C996C04A21FF0DA10A7F24B1DE22EEAD7FA7FD2CEEAF522A42E29395F771140573D684C94F61F19C771DF68FF8EA0FF727C55294C70E701C8E426
+ 80: 3A0ADB5479E65BE1F00462E60C8F7F74FF5C996680A2A4CF787B5DF65BB2E82264004E396AD7EAFCF8A201E03AA950D42B9A26EF2D24FD2AD7CF57CBD08AFFAC
+ 81: 6FFC799781B2E9F3F573651EB2DCB0771073DA1875CCC3D2B4C6C06F43161195610617007CA9A943B1F2B001E62518EBABD4542E73CA131E20A167FA6E8CAE44
+ 82: 79C9E349F1216FCB295FFFE5771EF54A024306CED9CA111DA3DC629722DF7FA5F0927152E4401E0358BDC16D9ABFA02C709B1C21F6D86905B0CF0D6EC9FD1952
+ 83: 6876CC513300CC83BAFCAAE5DFE4C4A0CB962079523ED475B19568243A63B208301335BDDE10CEC90CA816960013E08271F02111BD18FD03C1B941543FF4A579
+ 84: FB5392BCB60C1329D3FBEDB4DE1131E7B89326A34F34BB099A7EBEE42B985682F52412D3F0628AA72A8C2C46BA3FEA08D5765264E48DDDBB96CB598C9C0BA93C
+ 85: FAE655D7CC2FDB54349870B199FA54CF47BEF2AD98021FA27B968AD4C3AE477C6B2DFA9A10C75FE275D5A32C5E9FA06B03D4C908184F49FCF15ABC409106E951
+ 86: 9B15DD192392017E2F4DDFCD30B7AE58546AB71EC44DB94EE66CA3419D580AA05B5F10E5D36D9E60465FB8F56665366824B5B6E9A63A13F6E83A026F5A8E0911
+ 87: 1A0EC6F024130D24D9740E8037C78A176D9C5933C4073DE3C6B0536E9F7CD20E0E89705953DAC9CD44C85EA059ADC496A7A0EFC40F187DF676D2BC83F80BE983
+ 88: 5E9683BD68FA16BE904FF617510AE99249ED3477276A0B410B269EB2E03A3505EDF653C725811AD9DCD7FCCF6F2411980784F4BE7407D68C02CF6ACD21FA1B52
+ 89: 47CE3079037E396A5B5A1A3FFFC3C60A138AA2C6BF4FFF26D846C7E1E84E31A26270AAC5C688DA7A29DED589018BC349E3247B073B765FDBA4C8BB271CC6E233
+ 90: 280FE2B5B0B72FEFA48A9B6A1B0A3529CAC9D6338E2083816930B14FEA5B21088B1009DE147D81FC7F29B00BADAB32B57E15322A6180D713411F559658FAC715
+ 91: 527C2E33018CE9895C3F84BA5C072055730AAF767DC82AE236F1F7C5511FBF2CFCBE32AAEEFEADE38EED4C0895290D0EAAB38E3A5CF7B2462675D1E6B26CE814
+ 92: 8C0E22F5BE099CEE31C816A0F5DCF9A548B0EAB55AE7CC127D172AA5243A5C73B5BD3AFD77C89370D51460CB7E84F1DD15774D1B8442C07AD21A3B128688E1E0
+ 93: 6CF00F05A9DD7EBA5F1A755987F5678F80AAAF9B5FC44D6199100C062DB50D2DA89096389DB94A6D68BD8337640BAB60AFC8793E1A909624A4E149AECBE415C5
+ 94: 8452FD4AAEB1AF4ACA8192DD59926E7B0D7B295B8FE18DF4DD21E7C7ABE8F4ADE7391753E533EDA2EFA13CBCD96948ACF26B658F1E72390BBCD7C1BDCE8FD650
+ 95: C4DBE8DC875D00FFAE2AAEB3E0BF1F01529A364454D56D329FD493D327287F3E34DBDF2AD54C5BAC5E6059F5897D18157C7DC846F15F2CDA1B2F0A6EEAAE58D5
+ 96: 6C88BBBAD961E9DD1418E9F8EC69FEB443176108F56FA2B0B686E93B0E5F505E56302994FB190787EBA7CED5EAB69DD24CEC39BD566D18ABE337A31414991735
+ 97: 439ACC720E8CD0C4A119B9C318FBC543CB7B35FF12DA190D82A951970248BB47D0DA2171A7BF850A881E8767FBCD542039E483974F18532FDB57DF23CD18B1D3
+ 98: D71EF6284984442D05E8B6B1AB636E0BA013A8D70029F9F1B9BA7927A582D5AC6899B9C8EB990CA93B49E460AE140564D40467A1368FB4A9EFFED4A467E174CD
+ 99: 8B5AD2DDB4F8C044AFE2B0216B7E7D830EBDD285E4D992CA022CA2F59644806D8B7599CEC51DC73786D98B7B6F7C10C3BB7D4CEE3740FA42DB21BB51A1269611
+100: 28CA7AF155E9E7E1F5EB64F211F254D624C6C42935E27A91745F2AF2EECFDCF1DBD5896F60520A527499432DD3D0F3981F0E5BA72EF113231A0319467BF5271A
+101: 45B69480A77AEE3D83D39A38717EC1CAE1634D2D50D05FD78F70309DDA566DFC160FDA967EA6ADEA8BF45B74557DBCAE4D6187DE1BB82A053CF84B4217F9CCA6
+102: BF46E03CEAE3211FEAED2147B3F2909D406A767005F9C8A5CE6139133D41C2812D3225123B3BF0792288E4BB5C8B5ECE9BDFE0F8FF097DD64FB2CCB964FC9862
+103: 3CA25AE24E0D847D9552FD74E1D6FAAF91736603DEE98E51922A2923630D7CF35917916A1DB23A758E7F067F26A5DE9135871B3DE508CE4ECFEBCBBA1A958C78
+104: 2C4380BB9F29041388A0F8292D97482E1E96429B79162A19F01918DBC2DF0B36244ED9E7D015A20290877ACC4D2FFB14D236CE7FC92ED16C7C57012B0CF6DF70
+105: A0020193ADA7F57DA648C1474731F145E6A8E9E7F9550ECE1A841E2D735B18769738AEA78E7AABB8ABB51EF08A34C187478B4C5AB5BFF4932E97F4E246C60C6A
+106: 60E81090C365DA5E69E2FC12256131F134F561C7A411F51F72B7649727C9D7E99795D18D1AA54D09F6B2DD7FC556512F49D582BA6006D951D474039095F3ED07
+107: B213DA3FB3ABD16B1CF5CA81574D78649382A6CFEBA5A88C0B8DD40B1C6E18520F145968C342DB13A2B4B2659F4F865E8CF50BCF2138A7B09A1FC190676E1895
+108: 6862BF8F73054DEF42EF38C4A362ECC8F13BE7E705573D8E9AC6B347EFE6A218950A5AB5ACAC3607C0C94301E0A085BFAE7DAD5E1863D469C113B790C234A947
+109: 2D7D3040A495F8C089C67FEE236A07C7D3361D35271B4DFEA5F17C7E80B888EA339B936C4475194BBE35DD9AF3BE112201AC21C9F5858E4F4C39A0FCFF0EB31C
+110: 1F995515755C98C5EB95818DAF0C55B51192BD8D752FA35EBBF51176F05ADFDC32E2FA845C1821B6110F7EC1F1D1EA963433194BB978285CA4344A5F989113EF
+111: 3F5855B07A4288497533924165E7EAD3D91A16F5E832FB341F5373C118D5ED7E0EF8D837FEF594C2039F08A7870EC1C2770B7C4E7185246908976B62A416DE5B
+112: 1541B5A9C84B684BBDB543F77CF384473D007992F37498F07709EE68033E41829E29109E7C77E252C241C78AF41C790E40696206D58B2FDEE768E5B321362F4E
+113: 6DA9AC8390F4264064947684F53A1ADB49314E0619509298CFFEA1729A944990BE2D4C0988BD6E8BD1062D574879218ED8FC4801877D637ED3B5383C069A29D9
+114: BA0A194D5078019B21910C37AFB81A890C4FECE7B1F4E722CF855A6F2F8B82E4EAD37B7B58C07ACEF1EA2B76B146811732EBE1BC0F76A146207B8213802DFB28
+115: 20631BF1D6555C7BA761B0581BBCDCA5A7B1BAACA1B3D3E5B4D70D0C9B0A279BAF00DE093AB1334ED5994FC17386D0B2BE9E0FB67AC1038704891769AE530BB6
+116: F31F66E176DF632694A6F7E16ED8F15CE88908EF1D1F0067CC8A5C805370B9CACE0BDC78B1CEF06630012B3A35D129C4E2AA4F7302E1A122C7E53C51DA7F795D
+117: 18B5417DC4CEE4387338C63156C34BBAFF19A2BB962E4248B1A1AFF1FF145BA47D84C6C8570D072BBC57D912C8048E0ED50060CA33408A00722A65C194178387
+118: 2AE09DC52D7BB9E692822A6FB3D582B805E5ECD2C1C4813F94F555BA2210429B615A2301B3EB7C491153D68AE33AD9D28F2FC11B6C61700D79BC7DDB251BD15F
+119: 534390ED2DA55D45402F828D6035819C4528768DBFFAE1039CF0D18F89BEAA867589F78871FBC746E43B59E7886FDF734364DEC4193AABF56E8BEDD801E60D89
+120: 231597B2B71E6BE567C86DFE31ADD7B31332BEDA930C4921C4817B7DEBB0282A12D23B076F4783EA840D890F6C571760E70E143F8565561062877D95BD0FF941
+121: D60A1481686AB8F889EACF2E9F66BC32271E70E3E04B91ACA6CFB90375860E0BFC5AD9A627BA0C763CD7576811CDE2921E9A63C0F0A7A26E763F7EC7902308E7
+122: BA65BE7D1EF697281736B3AFA97FF675CD776C125CB01028EC2894EC2EFB9908835A3882E5E57BD44ACA09DC3B0580145EB2265E1724DA6F01AF5F93022D5774
+123: 0DEE2EBEBAA770891C14346A26834CF40212531EDDD64A21EF9FBD62F4728A16E18C673DC8CE3883156F51854A0ACC341DDEE6A0B71C4CBF797CD5327056AAD9
+124: 0717C9EDCC2FAEE525A684EAAB79653DD83BF46ECB285E6B154DFCB8A0C9F8D4B28FA200A6C224B4620CB0AB5B33B9C8BE77B2B5A04DB1A3EF8A5951EC46607C
+125: BADCAAE4F76006290B9090AC81B807E7251EAC041E6CB10A2C5B58C4F4B2386E065E6D55C46CD888396C86606FACC82DE2F3F88904E15D549101AC7FFBA057D3
+126: 751F6366EFC97218AC2E0675E7F375444C8D82AE7A139E78305E14148E07100F5B7EF93B576DCE546A7BAFCE24FE148B248BE072031F89B6AE7BA9CC559E9C9B
+127: EC0FCB3E124C482CC8D86BA2CDDE931E521F0B6F3E7F333C4388E7448A7F196D95766CEB8A49A90E46B592958BB85BD7495747E71508877975EB1454A4EBD57E
+128: CDEEE6EC4D67DD8698B72C13735657EE9F78BB0E1DD37D0CF06063717DA9DCD617C5F4FF7656AA48CB3F697E36B3904F496136A2B04E19726DEF9D3406F8A84A
+129: 81BB692EAF7F5176B6A0E5F2DFC01A045A917649D0B23B22C180BD78672F37F8E562FD006A00AF2D7AF0AFE15C8D191339AE28FF2797E64A3809400E2E73A785
+130: 04A8456D131499586CF7B9FC45C2EC96859F3F4BB8240ECD93E439EFD5DDE1DE7B67B688B583598D7FD50CB179D318D4C05EDE04F6FA318AA1E9DD7D4E279307
+131: E5C9D55B686DD9D7B1819A6144F6272B1FB5BB3B3034AB9D1BF34391283BA614D57894925C3D589A7FAC0CA1B1E98A12E9DFDDC2BCD85D1E7F2980709EF25719
+132: 2C6EF2E1C179BFA8295197371C474081790A63AFAA194E459CDC27AD4453B3A8C0110F9229BBDD4BBA5D6E80F2CEA71059334A97EA34F96810A2EBFCC3B177B8
+133: AAD54FE02E67080851DC84E20F7661E42ADB610D0B105B3EA6EB6654DAF64458B7E0F756392196AE2B40626CC2B0D82E47D74D3C50A607F4402C6C6A62999324
+134: CF210EE9A800943EAAF4EFE15DB7DEB696233A4DD62206D46BD9C84A7EB13B5EA43FF3CE15ADD8FC4BCFF022196197D1D097B7A893A79C6640135929FCEF10F6
+135: C81761EBF3235F4D56697B19F62B4F7445C8FDCE3D7999F3249493D50C19CA57C5FC84CD35CF794F58DDB6AC86E8BD53350BA9676AB63B88214162C8E11C16AF
+136: 8E56EB131EFA286A92078F5A3667BC6669D6A7FD9746CA5F208EE38D5265CF27076C1624ED0F98D486C55C28A4FB89C7B667AAC505CA1CFE1E841184615B7602
+137: B6CAF44F87688E9E3651C2C98E840264464DE9DFE1F3E4CE5C1BEAD46C7D9D747DFFE282D775E101591A7254112C2DFD543E44B41E72EFEE30B032E5E015150A
+138: 8E7851F56585595ABD2B3EBA5AE713672093A3120798506ADD1ACAA3ADD92D737F9AE155B8A5166C0F047801A93731D4B807DFE15F08D67DEF31A7B808601D6E
+139: B36B6689A5F391688DA3A0756A15AF15E6E66701E2132CF6F06326AE9C91A0BBAA35664B28BC5B936D2BF1E6653848C5DB57654685124A08C79FD03ACC0681D1
+140: 24A23CE3A90C8EC3D10330EBDA47763B1B03035F9E4AAE0AD336169A2F464E067B026D94ED4B9723E969C8AAE7F404F7B4481C48EF7545EAAE4E648525A68751
+141: C7ADE61F21133886EE0E0B14438F070DA398B3A5387CABF98B0802662F3BD3AAA8738D36CCC0D3EA25BBE9DD3B59062BDF4BE2740482BF6D4C21D0E0FD7B0679
+142: 17EEAD5930DB3A1F8E123AD2E72C38209824F977674A52F380843442F0A5C82B55F8A362527BF5324124401648BEF5E9E26E08050B1FE80886E3856F98AC1EF8
+143: 9DE4F43CA8F7E528FFF9F4EF5897652323AEB95DF80049AFBA189C3D142CFF55AE340358A71B01797A8B72F478276E6353421E1C0C22EBDEA0C044EA60865784
+144: E259BE34C467B471C94B612EA6BD99A3F7EDE58E237DABA6A6656F7F7EB5466DAF908B7759027C277BD9234ECBB23C5C62DD2C9D248C1AE52865D66B5C256756
+145: E49099FC970994F8293E71467BFB1D241FE99322075795FCACFDBFAB396392E37BA09E66BF492684642FF2A03F8CF92E0ACF4677C21AC1C236DDCA103F0B5A69
+146: 4338E438D419D8694FC40383EB1045FD9DFEBC6F18A9A03B4914687A8639322E3B050F48E872BB7E2AD9013D374D68BDBBDD0B177024C1185320D04598515ADF
+147: A36238A5C795B23F42D0833A5152770A4B0094BC19DFA72C935D32D02FAF5D136BF55D92B022D01949FF04B78507FB203302833AA7103729771A112E4FD1584F
+148: 47180F9E838B129A7732A8DAD763B8CC5437BAEF77EFD34D3B33C63C09F6314B87B3A1436C6866614C3B3A693BC7926E9AE876C7BDE9D712FB5198D6417FCEF6
+149: A87064FF5DA177F3651488A139E568F6C75722ECF97507316BDAC36393724525291682776843B8563A6B014646F6B19F040B17B62BEE4A0711A7B06A67DF75C3
+150: F358321DC6A376ED500A2DABA60096B817D13B59AA02B56C1F51E2C6804F5D2DE2028409964D5755BFC6424287504994C7605749A5E5D9D802BB42922F444D76
+151: AC4A9999133546B8452047EE31B398F623E01DCACED7BAE4CB0B4DF0DD53B8E4921109308DE53C0924E0006361BC8A480AACF798D6B403F338357E8DB676AFBA
+152: 0E73ABBEB68982F163257C1145FA2E465FD6E720EEAF5E532DDD1ACCC690B37A8FAEFF8D7D41564A9C86C2F185E0FBD0FCE75259D34A5E96B8C514EC83CA1382
+153: 094503A1B90D71960F83C91D76754BA6B05D670EC6A8EEE1D3CDC652DA6E52B196E155F3BCB62A9E4EF8C507F377AC1321C4C0D7A03F7D8A5286C0019C358E92
+154: 12803349F15FCBD53F2FE11B67DABCF3F470B8E3AFE8A855D7A918E611A2D5F4DAE8FE847ED1FAF834BB3678C6253111636100A991A80C1EAD0D35E28DB3AC85
+155: F489665F4D8A4AAA679D5E5A1B7C501DECE2E0B228630AEEAA1F5643FC4BCCB9E2F018FC2D7C44ABC4AC0861EBA8B7700A49B42486DD13263D978F8A7C9CA306
+156: D9DFBC3DBF0E3D247C95E16D376E7098A92EC59A54FAB482C330139EC6E06ED514D5C74F9604D1171A127502811A16D1D3039BD03C4DBED20BB765EFD34C5F0F
+157: BA56A64D01FCF392A6E2F73D791D6C5A57AB40A376E73388CECBFDB910402043B4DB2F2D2B86E3510986CF1DEC3880E3C739175D5C0AA1DCEA18959135E2CF48
+158: F4B07B0A063AB240E5A64F1C494FCD9839276FD9689AA6720A94B83E579EF1044997F6506C1AD82C2CABB9384CEEA0B77D3970C1B7E13F8DE98AFA869F1F4D2A
+159: CB4F232024B2D0C48E415D73193CD83C1A6BB9806CA336AC4F3B8FF7BF992B200504ED5E539CAAE68B1E47D4D8ACFD2E6B4BBC1B518689BBB5BB4311C96FE06A
+160: 1E67E36D2EC5D0591C0171E7426A88919EA5A17470DA305CBA7BAEE90002E23043FAE1F4BE003EDDC2520A404E639B03880E3CCC68243C60E243A0E7A02E2CA0
+161: 40E46A8F257265A1E57A09B43890FEEFA57F56BB47551BAB38BE2BA8D143C176749484ADEB2D833EC9D6B70FBE872FA53618E64CF0AED24D51BA982D29E730C8
+162: F399712E5EFBA3FDF6B7D04600C16F69260179AB79545F44EF5849308E6FA589721CF7E6FE384461D05EF02BE51E50FA93C5FEEE9279A953C57EC07CFBE53E1D
+163: 58DEEE13BF73ADD8B49EBBA90A8EDCE7030C17D6E6C449726D094F90A35A07759A3BEA031EEAF963C4753522EBBED1482789833D15D6EED7F5214E1AB93C174B
+164: 13B2F766E6B796C44429A747CB46D99A9866115C78D2E94DAB52BBC9269B6584D26676CFECC2A9F026AE8E0162B6BB8DCB2242659EDA67CF793BF66963C69021
+165: 992B995865F57633665483C7C3ACD34BD108B5DDF151CED97C0D7AD134A8D9250CA8DC17C5C2A76C1C07989228F8B474814FB116C98D25D8F291D10CE259570E
+166: 1C5D5E9C29DD91877E279DB679ACF0EFD8464B0A58EC9A3036EDB2621E8106FCF2A81719FDD1B89F13FCBD20960387754DD0F12876DAA911E793DF8F1991C043
+167: FE7F98A1D7839BB417CFF65A45E2DE806C74ADF2636385FEB16A34C890B524A75452EC096849EF0F905FFB38A0319D31A886DD840FE2FA66E16AC7C68B0D7FCC
+168: EC67530458F01366BE95049FCFBF65465CEC9AD7D12332CF898DD72ED4D275F9C9EE96AD02603E8032F9B3B12615329CF0FEA564D278B1DC3B47EF304BF901B7
+169: 77BB3F5E58AF174DED0B31627648A1C7B5B8092C829020A6FE4CFD42CB51143E9DE20E3D827FB070DEDDA94D39BD0D330604DCB190E7252B12B03F48072B7E27
+170: CF33E5358E518807B70D6DCFBFB1CBAFBA7B2BDD20931B2A3B08BF8C6755367AB3BBB2FDCAE305F04812460FAD37E9AF70F1905D2F0D3E7628DD1FA453E5AE63
+171: 0739D32112107994BF3E6EC3A107AE3BDB9E2BBDA1D7C10D9AD6AE32952649007F68D28BA0DDD1F1C45F7128C1D3C42EBFDB1975A143A42949C7D97D9F9D3BA1
+172: A4F0B775988038E50429428C8526793AD8B6EC1F0F3AB7F6B33F716C61B7DFC49E254EAA01FFA422A31D30A8268E1BE99D385907479C7E2E0492681B6851DE1B
+173: D2472E93989E1F29BE0DCF991A65BFE0E772CE77850A2F96FC6114EBCD78252DFC17712AF193FC5ECBA371B8FD27B0DAC44AFF6140923885F403904F1664AAD4
+174: 6696E09A153B0077D3586705E4A19FA6B3B2DD8621F5D13D7003017A0C569B7483C8CD9218ED1A252EB160C3620FE96A00E267DA0FA8996B417F64DD4A22153B
+175: 2337E38B460CDDB026CB81B59B99572D45BCA4A43949440AA5C9F2502DBD8906453FEE23AC0AE47AB77214E52E7CF06ACE73DD8565BDD315F49A460996E08DE9
+176: 068CAEDFA329C1FB00BA02C80877E0E2B1CB6127FA2224BD14FAE5AD0AAE6FBAE052A145F5A8340B446F54AC9BB2108CF6582AFA0FADE91CD3568B604F68F470
+177: EBD69C96F4F2DB05350B74A475CA8C1FDC671B018A47072A11A8DC082C418EB20466720AF12E113C2D507F02596CB022D2BECC4EF8486CB54260020EB6C36481
+178: DB0770922005DE66FBC2B05B1F863ADA569B76DA9B8CA433C99C2F2B4AD60BD28B19A5B3820C0D8B6B2E443CF54A942B961E5EF1D53BAC4CA379964D701070D3
+179: D435D7240B8C6A6AABCB026EA53BB8DE58C5DB471EDD8173AE30C81BEFA9CCDE8E30758CBD7DED822410576115C2415D9DA7FD8A83CBEAE337E5908A012AE1E7
+180: 838AFEF97BBCFF7692C731D55442140D58CABFBE81BE76D41652106E215AF4E934691DC20F181C2123CF091B6D7552115F59937E165F1645CE0E14DEDB864B11
+181: 771815708A3D7BBE5E00FD677E4EB76B2B9A03A09412284A236401E7FCB19B340782C81D1A49371609DDCD7E38F9448FA657533D53280B3D6B492984E9C9CBC3
+182: 649EAB3244AEDAA18CF0A1FFF6619D63BBB66955C5D58E3A592E53F537FA74C60616B9E4483BCBB08AD7D1F5B6B91ED3176E89C03C224F94E5D3893FB6D01CFB
+183: B4B6C653D90EDFEC3BEA0FE1FD766D5736DAFA184C360C8B036B7CC842E8C76BECFBAA7046AF087831E322FFC181073C19360A269851FF4DFFB4712E68560C3A
+184: B0C0061EC50BBC67DA4765FEBD4033B8A204260177F9CFD451E97B93F19736D4B0B7478E29FBE76BE17AA6B0DFE9C4CB9C6E4734DCC8AA5EA825F101E5C9B02C
+185: 54EB4D2C9B26B8B17818AD702E065407A19A711E22C8E66163E7311D8ECFA54448453890194C3EE892A599125AAFE1CB230C6EA268ED68ACD86DBBD17432352C
+186: C049743F49D57D9226AFD26B94BFE9165BE5A8CEA9DCCD101F837F29C63A4201B1D4478EB5C4CE9D8F5D6E91BF89D09E6A0D918EE7A6D58CCD0A46D36963BCAB
+187: F11AED8EC2B1C003B8E35F8F2A05861D9DD6B7DED02E28EFA4EDBB0BDA0DAA76EAD810CF1C78F50668D50DBE2AE65009C2E12504DFCE9F9BFA9A14969E1D0622
+188: 1CEB4106BC700F76F4825E6790959CC6EC85AD93D6FBB9783098E367E5C9676AA0D6B8CF9A7DCC67565284E71205551650557D556870B421273772524463245B
+189: 9711275100A787D9678CEB38981A2246112C2FB1F0EEC1F844DF1703DE5B0FAD995FAC983526E7E3336B8CDC9DCE56FD66B73811201A2DA6783309AB6B9C0546
+190: 81E9DC0CBF71797104A44E72841FAF7F9CCF35C18EFEEF873450A25AE56564B0E9DA98598C527D5629EEF7F0571D9AD929BAB87A27539CE9898ABF4C57C9EBB5
+191: 28F4214D1C8C5B9291F2E1F7FCE732C3290A691432A65A01F7EAB1A313B83936DC98A3B39B5F7712DDEEB8968001C93A102C7FCFB8AD7D49B29661C9A9867109
+192: 78C7A025ADB85145CA8C6E417C4E68A9DB83FA78A23D0CC3DF20AD1409B936686FF756EB51BD8901157B1D031DE6848D97DC2E0F137BCA1D49EE3FB2D5A5E83F
+193: E2C25FC61AFC794F65AA57DCCC4111D4B15331842493F93E9500AF01E2017CB226444E208BA9C841DF6D7ED28955B318511335F842AF3C2C0573227AFD790739
+194: 50D768C744CDD318B950986E305BF74B77396FDABCAF63AB786893B5F4104C2525F2F69905955A35234BD6BD85DB17B94AE7008F2E2C368E9639ABE8BAFEE4CA
+195: C4F1BF6C56C494351A880172B9CBB59BB0D1A5955352E10A868D3C33BFEA0484EDF6ADDD009A20C8D7B59B7ABD5115D595B026CCA6442921038D9BE860C44CBE
+196: C782CE6A141EF9E6CAA61853588B8C75B3A39CE191C161F43D7C5F88FB77BD5055B21F37D4A49D65CCDBD0E6BFD98193FC0092A34C21D5ED0CAA5F129D462073
+197: 1B2F68D7DC7563C286612B3D708AA725923FC9A2FEDCD4B1F1E2557CC70F3BF65944A2BAD9705303207B00F6DBCCE245C6E653C38EA0896DEF4150DA118A699E
+198: C1248D0A6B75BEFFFD70EF17F2D0F3CE3628BCFB6A634C93E8F0ED97BBFDB48F6E5608511AD7091D7B062B795EBEDEC67696679EA092F7B84A64C99BB224D387
+199: 20A3D3F3676947173C7FB824B40069A202ED3A5637DB41C97ABFE9E7036D6C009BDDD5BFFF97FE80EBC40355A535D7D3A4B2FDC09B809D3BAE2DC31803413B27
+200: B85500CB777B14592A4562A26B13AF3F08CE74E03372D9622E29C1FB7988A86B8C00DDB2049C1395B43B17CD5C415A5AEDD71E05CC0980EB9520D4CAABBD6FDC
+201: DB553A36A3EAABF7BE6FAF85DB96D3D0F207EA1E5B55DE589A116DB80C21AE5B1826A5FF3BB9D84C26A403A1E5C00BC7D2F6DE3F6A9661899D6D75373ED76B71
+202: 5580422E6393475B7C1F5010FA7F4395B969E190AEA056ECC88783A8B5FAB8ACF130DFF39DC0175E9BA8B63B4FABA7E4A36FC55FA1504468727086B2D26B5818
+203: 1CA3DD194E7BCA2591AD1B95D0CD4CF7938334C95A1EBE2C8C1A9B75E6A85F534C094E652248048923CBAB97CB1581E9A2D1AB8375C506159B724F74447A3201
+204: DC525D0EC1E62EA68C013470D77B61377398EDCA82A91C1C3E4D7E5D910A9D556B3AC810FB1457BDD70A18B063523C39BD806A2227C7E057CC6B018DDABFF73E
+205: 2F0B9523725B27245D2A1B635DB5A3A3800099546ABFDD95C8E86C67C378D91E4711AD1927E90CC9B50A1A7BE3D60414E487E72445936FD0FA2BBF541F1394EC
+206: AB6EB21BC802EB0854F61346F7BFCFFF738EA39829AB2785976D869830DBAC367D59D50C3873B960AC5185F3DBCEABD4E4E594C5C2916A8DC304207E887473C5
+207: 8E1C160A334D41F08918EC084BE12872DE79D00473D1B6ACADABD67E2A6827FB1DDDACAD9BFCF27430AA84F3F7A0D6CF2FFC91E7758F471F2739D51B60125D46
+208: C135532CFE84849FE9F40799E1F2CA05568868C0D44E6832A05C29ED17C5F6D0FB844485CBAE5E50A67F2319C30526DB444F4B45CDAE01A9D0542427731DC175
+209: B1FBEE68843D42FB558D1D9E0B759C168D6F84D07B2E90B646F45F1708B0D6AFF7BA8959EBB6AE4D5DF9A9951D139C81BBE602671CFDC618AA1EB63288DAD72D
+210: DC11C3D993F59473F64F16F87D5F085E834306FC1C40D12CE7D6E44C59C31318C694282B0FE53B4B60E1E5DB546D930AB741A8DAAB8ED67C3D87E8E76B8C025C
+211: 85BFAE07EEA80F939D52CB18C970C8ED9D4035B57391739C44D7973223C51344B9BE28C16EA29B35AF74A2F8F7581C766D61525DE5922A83A1BB600D97F7A3F2
+212: 26E52AFEE0F11DD79061EA3E4F97205729E6B61E50B69CC2894CABB08CFD3A10C41662CA6F6FEC9B5B80ACACBF968C5B75BB8CFA31D06C82D9CFE97F6E1F43FD
+213: 74F18E92D85D9AE79BD62C4B8FFB2116DA8157E17A6927BE2B2D0D79CA101F7CAD6A25CD623C8756D49B9CBB903477B9CAC67734F84F0915ACA9025A9D5C6DD2
+214: A51B45BC09382F85334EA58CF7E7747457B517118042D53D773C66668CD6D5059B9997DB183B1C0F2900AC9949028D8F76DD8B7259149388FBF340834A3BF4FA
+215: 59DC88A518FE44A7FD0F316BC8B5C865D370A8BC82533037C9872B24390F7969ECA530911463520218D00B415409AFA90A63F88EE729A252F1B747C414414091
+216: 146FBF362ACCEB8DF79A761285A0653484C38585817E26A7B8906FBBEAD70031160C7B924D3BD3A9ACE28A5712ED0E6E89CE4E71493B27F87BF73BF592D80600
+217: 74B6738B2F0904FD59F3A680CFBFE4E466FB5094037AA1942DB3A0017260D75AC5916E044CAC6BD0E25D176FDA267542B2C7EA201F7237E18B9D00723E98A239
+218: E821A4033FAF0FEFE525115109D0B836A22C287E3B157EC302768BEF7989AACE853218E5AF7DEE9F6E234AD50ABCC8A9658A0EE4D9FE050235341C94308D7A4D
+219: C3EDD652D2F831B1C783CE1B8BB8CEF9453FC71F519A4800EC2362ECDBE9EC142F768185D55E322A32AF421DC84EF84615F7F3DBE6BC6E702B4BC8625CEB5BF3
+220: 6A3CA0B5A43EF42A1D6526C2F1507785248374C7D2602079A923C841F775A652724C29E788695B52387778CF2E2BBE2213B2FE212D729E3718D946238FF0E57E
+221: C425148335AF813E36D072DC64C7EF6782D7DB981C5142B5D32D6D4338E06AC64363E86E88DF018968FD659DBF50A4B77BE2A02E71B243D65024B36CD71C1796
+222: B796D1F5AB11389EC7EC8DD4D1D5AAF17262C8522A4AACF454B44A7ED71E20F7028169F3164AABEE4C716B38271D72D7ACA3E54B30B9E05616AC51594995F61D
+223: 113A56E96ED6F8613705B5CCA6CC4F2138204D7BC0C8965162597C1FD2F6E8143F57FF1160F4B482F7430536A349D20918064AAD2BB38A9D4403C16977B9616D
+224: 9590A3BD7A0613381159E1E26342C150DD9B0A937855BF78FBF625648448B540158196A2855E7FCB967F22F5AE927D60E97D0C1C17A01E8D07284FF985F54B8A
+225: 74B11968CC7CD925E21037DF011F1C93B2EC34C34A3224AA281ACE7D6F1B10F2A755DD6DDF33F1A4630123BC1CF875894FBD8D8B70AC05F8C3C1076E346A45B6
+226: 85A08D6993B7E5C014C3CA957D6B53EC1B8A5CEADD5060BBCC350915D3278F28E238425DA3A95AEF725A23B1BBD43E5D8832382BF76603F7E2E4FF711D540980
+227: BEFB08F621281473943AF153124256386570261916E5238FAFE44A72801D7C204A974B38696C102748CD1DF65BE3EA8C45A40021C28C7E4BB143800A3F38A93F
+228: AFB97494318F31A4C6813246D125217242247D4EB6CF884B244E59655DF866B2820A8E1A7123DCCDE98ECBDF1F6125EC5B95A0D9F85F05CB09537B3FCFC2CF3D
+229: E8C2E1D342E6503D77328A2C1336F95939B0E8855F75CFC61D4B03F4AF2305AB57C7DB383055A51E61AFB75494C222B01967BC74B4574B8208FC337E09E57075
+230: 0B396D0F15F49E60994DF4FB1E7E526A272A5B41FAB67EB8A41547CA6CE5B7F3FCE404B6A46BE79AAE37B4DF2C2EF68EAB71F39D5908760FB2124C7C83B0AAFA
+231: FE86580438E8EE3459A62E73AF0E14F00F4F0FAD0447921FAEB2B77A0D8786784659B1F6D3044538300C759EBEF7066F9218F9386FF6C8099E6C71B5EC6B721B
+232: C7E45B1737EBCA62C87A8F0C46F661BF7D3FC020C3B4B91988FC36C38BBC8DE05A22D4BF148F96D31115605D7B04D4CC8AB3F8738B652E933D76CD6966604CAE
+233: 2C43F84381FB618512EDA0278FD382AABBA41FCF5546312DA565F4503CACB86B8A704B3B49C0C86B2207E4641F71FB5E72654B0AEE705C52ECB2E8FAF109FDF0
+234: ABC4EED8635DDFFD9900F5DF8C6246CAF12D8CD9333F38647255DCC52A20B6DE8D4109957CBCC2F48F52346579E008091628FD7CAFA092F2568828F424EABF26
+235: 14672F19BEEF8896F751B0BCF40FEED78A8093AA4DCB590D7AA588DDEB3170460381FDEF3CFB608D55F9E8A295A36DD64DE058C9EFF30B1D1F1A3671388B0AB8
+236: DB87424F975B03F925D8B99A1DD0967D2283E408B6B0155851DCFD53C0C00B05A42CFE14B10408E0F5985809813D35D7AA7C70C1A7BC852C7F254F0303103628
+237: 095D34066A6E202C896EF29F3481EFACBBFA622676F58E90FCD5A0591124E489BE3804AFA9BD3E4C92A9653EBE878A88B275BF9B5C8EF8EA0F01C89CF40E5FE0
+238: BB5BC80C718B85BB3C3DCE95D186711D5B90827B2097DE63C647E5B6C14B4766BF8EE8ED395103030F72ADF0C8992AE836086571908DB4A6258616EDB4BDA878
+239: 9A18D6DD0F97B7407DB0F17896DB2A2751B76C69B6F91E821A0DD717DFDEF630EEC1427C2D190C095DDB07601DC0EC8687B7411D735A9A6EF0EEB84A60948BAC
+240: 60A614BC40A7DE580B6ADD05279A68DDCAE79EC3DDDD2C6FFF7B77BE9DD0260DA5241660982B77BA9C4B904075F39612F514BC86DF6F68E189FAE2C84A32CCE7
+241: 5CFCD44DECBE3D74708C620C70DA807C5AD58072F7558D950F519691FC96F98B760B02897C3A85F68EE37B2735931660106670C4DC7FA98EE2E18B6DED532A9F
+242: AFBE6D9871AFFE6D201E2E61435703856424301ADD5152DC745D96D1BAA3ADD4C78F2D7C5057F1AE8B21FB91879562050C84144A2042AB2CD273025FA03839F5
+243: CE9C1B19D0E0FFD3085D28C5B2176A741A3034C1B76C54740AAC3470C1C8C6E77BA765AC4D6D90D4DAB0A89AFB17A8863A2917674F5A189A5CBF721C14F5D637
+244: F2F065927839C22DF56960845E27868BA8F272A464619EFFD9AEBAF1E40A72DDA81CFC67DEE13C351736C407F59DAE8EE6F2BDA17521CF66F10C73566B7DA891
+245: 24CD3AFA2218863437C5518021D1B96E0A80EBD14EBF2FA161A5E7032FD985BF71EA59DC5E35DEDE5EEE3098EAF6A16698F5BD5903C4ED218868D1E96E4B8096
+246: 1C6AC311730640FE427C1F23B60E817C25E1318109643A8AB51DA74995FFC3F156F098AEF97F37CD9746002DAD22FBED1A1F222511B92AB5F39DA9B53BD62AF2
+247: 37609371EB63AEF0CA6EACED8388D187203A88C379F24970434D87950C9B7DF9A68B618E9E83E3EB10376504F8FEE2505830EFE3FFBD23EFBE081325AA171482
+248: F0C06F6A2C7AC3F0EE428D7D1BA893E73D4D2F417999043BEFBB3CED51F95F7EA3CA882B9E8C1C973DD8A7F450CD60BB5A0B30D44A574E43E71D2533EFAEC6B5
+249: 3A9D1BD43CB3B7D3E9364F05987DF4CD99D573C036BF1337988751658EAF2896244DF5E4DD8984DD494709E587A75EA8AFF93681787AD738A95C5E98616115F6
+250: D42E2D57B36095F0CFE8F771A9B198C7B7E0433763341D35033F32D21C638CD948D8DBE75F533391347C440F208D17F20614309DBF1091DCA10801E16F5D03B5
+251: FBB964B7865A889433E99C4B61D3CD069DEB99E44673068771030EB1B8F1FD3B3ECAED1DCE8ADFA44F9A625472CD4D987EC7ED7FDA0DA912C8AFF5B20BED7F04
+252: 13F67CAD96C3304FF3C2E45D71A2D69301695516EA384F6001850A46A7F93CB74C5A4CBC1C56544166ABB6C9BBF90B9559320F5F75ABBBDE34C7B8B45C783BC1
+253: 78A609196BB40EEEBEBC04A8794C840A6F831680864D65FAAB093A499A3CF152EAC96865747ACA28392E9F102962C49247E0EDA424A345C4AC6F4B60CC3D2597
+254: F199515CF806EA25237EB93D658BEDC994E61EF70F5665CC2F230E7A40EADA14BFA00D56C1249F2E5C8920977A6C85017F8663BE9422762CF88487B76EE7EF9B
+255: E8702ADD4B9034BCA0590FF897C10022C56D08FC4EEE0A43BA85E9E9C2086616B1BE7B6F928A3C53755506ED2D9D62DF5BA4A1862FBCDBA20683931A2244AFBE
+256: 6E6A3CDE12F2CB3A42EC8A5D21B435C4DA4DF6CA7E41537D361D8169158287BF1D2241581DE07F88FE92F5AE4E96EB9C489FC3B258EA3842EA2D511CE883883E
+
+HMAC-rmd128
+  0: E9BF401EB338AE9ECE9F2DE9CC104A5C
+  1: 9536B19B029E60F979B3A6B3052685BE
+  2: B52F90B48846959EF56051CB6ED21588
+  3: 0811D2108413D9B64ADFA78B05EDF1C8
+  4: E06414189CCE13B61A2FC3CE9BC11938
+  5: 8BA02647A4914BF4248F6C799055ABA8
+  6: A3D5D44CBE30E23D20643E865F28B7CF
+  7: 459DC8A812BBB840CA10A49E10F240E8
+  8: 26131CE4DEA7D66E5B3E6ECB1DDA4329
+  9: 5EB41B6A8F140E49BB4EBCB76EFAA0A4
+ 10: C5E076890071C872B071E2D068EAD1E3
+ 11: 476474365DEBAFE39DE7830A0BC3ADCE
+ 12: 3E9E0D4B41D740310572562E5F7F0CFF
+ 13: 9BA99B782F7B79C9C19D40EB27033941
+ 14: 8E9931A75435B113C7E17E94E22D0B7C
+ 15: 1977BEFFFBF378633AD22D9E489FFB90
+ 16: 9CA06536713225F3A5F67CB6510FB165
+ 17: F46F54B012982621E33BA13A871F82F8
+ 18: 73F925BD50E603A66B17D8D926CAD1FF
+ 19: AC74EC692DDBEF86570044E1B5F31EF2
+ 20: 4F4F95BC7487A8F07B23C11F700F9C4A
+ 21: 02CE78131B27AB77474CFAE5EEA37055
+ 22: 1D66BAD41487BA6C238BDAFC04E9963F
+ 23: 79058EE7D70C9D19058BE2E1D5383F39
+ 24: 773EB9C677055286C84B39D2344C43FE
+ 25: 414A4816C124BB62DBA3BF65B6276208
+ 26: 350DE5DF46801BAF8B12D4516E82EF43
+ 27: F31C58CD73A3D8AC050BFFA5FDB6200C
+ 28: 5D7489AAD6537DB3DC27D43F698F6E79
+ 29: EEF7FC37DCF2AB96328E62B8097203B6
+ 30: 8FD428368B9B52F25C47E74C0327DA52
+ 31: 923B6ECABD0337E39E6D068CC98F71A8
+ 32: ECF2239FC767105FC69F46FDA5BA37CB
+ 33: EAEEFEDEC3B1E74A029683FC21F03B40
+ 34: 9620C4913123F3A718D61C956673FB23
+ 35: 59283EDEA3804ECD6471EA41EAF89A8E
+ 36: FB5B60685DC1DAF0C6557325DBBB32C4
+ 37: DB71D12AA3B97C421FCBE45F8232F3E7
+ 38: B0849EE5F1F9484514F5512BD928148C
+ 39: C73A777E20CC49AD33DBCBB16DC59A84
+ 40: 600BF6FB779EA2F7108D1F7B8FE89F45
+ 41: 0BD76F07D4C433E5BB9FC98B7FE49A2C
+ 42: 209E2124DAAAB3B5C6D2DD9A79A36E4F
+ 43: 907E4E2540A6794D6526A44FA08CAAC3
+ 44: BA1BCEBA60F32ABD0EED0A1A56748248
+ 45: 31F8527CCDD022CB9439F8B39ED70D11
+ 46: 05F429D6AA9FBB1723D81AB268F95963
+ 47: 7B91D5409357FF13F9B92ED2C6D63B66
+ 48: 30AA88DDC6D49AEF0D4058616EEFD9D9
+ 49: 16C0B4F46936AD501EEB5BEC8C699EB3
+ 50: 782DDC3AA9B3E498767AA310D7C32CDB
+ 51: FABED92C454544588965E4CBBBDCDAC5
+ 52: 7B04EC847F160BE26FB4A7C6B111EF91
+ 53: C20AC6220BD352F8D53F0DEDBCA97862
+ 54: 2EB8A89C854AD2412E5E2DB8638550C1
+ 55: 390DC3D1C6EA4CD7A381BDD9F0B505A5
+ 56: 1D86B9AAE5246182EF76456E9A8F2CC3
+ 57: 1759BE8033CD082D771127CC81435696
+ 58: 4F230D4174BBB11231ABD4AB58D6FB80
+ 59: 9FA21699DE8CDE39FE4C9DF25271A87C
+ 60: 7658883C002D62D33EA21AC43E26C355
+ 61: ED1CD4C63C40453677804FD66BE3E068
+ 62: D715E8E09CF4C5A34793FCFF0A7EF0F9
+ 63: 86C450794C4F920138A8CF2DD9221826
+ 64: 2AE1A808F63CF7AFF39FE9595BE540EC
+ 65: C8E550F520B0662100FF767FC0FC38E4
+ 66: 1A4CA5249BA8BF8E4AF50BD01B89C13C
+ 67: 25A3566CEE5E0921857048F4A54BF745
+ 68: 4D76448CE2C08EBCF6C21FD304973DB1
+ 69: 83BBC6D82633974D76A1B0994DD8891E
+ 70: 9F322885EB927B8C4F93AAC081C7F378
+ 71: 7E0DFB22C9433A0A66A673ABB3E81B4A
+ 72: FD3DE62829CCF2AC389581D9932E1B94
+ 73: CADF66BDE69903E9E3117DFE75EB1C6C
+ 74: 71DD9BF191A5A1A0311BA19BF0568727
+ 75: EEC05781AEED255A8DA730399ABE8929
+ 76: 07E7E6E57A239F659A6B17B695161878
+ 77: 6E7DC67642EB72C295EC12C009902577
+ 78: F6AD3BF571AEC27B2C99AAD4A22B9654
+ 79: 0F38A5596BC9BFA1ABB7318A35E5841A
+ 80: 987BA29276694A84DF6F3448D2FA36B1
+ 81: 3661D8F157DCBA761D1292FC2FB332C5
+ 82: 81834820599DE6624EC116A651FFA2A4
+ 83: 59E556C023829D31F76ECB5D2D5050FC
+ 84: 9389597634228E243808C1CCCC71627D
+ 85: FFD30A17850DB17BBDE7C3EBC8482A95
+ 86: 0297895965B8C96F95A77E6A1BEB5FA5
+ 87: 46185FBA371A282AD8251A8DA93E7A10
+ 88: 34940377228A73C2CDA178635B8A4827
+ 89: 0737C31BEFDE68780EB3A5504F295809
+ 90: 3DEE2B38EAF96BC620785551C926E9AF
+ 91: 719B32410E625DC65AB4E422E24C8663
+ 92: 5B9AEA802EFFE00D19E746E0684993CC
+ 93: EE96F9B8F8FFC084C0EF8C28ED0EEC4C
+ 94: C6575E5F4CDEE50C0C2F41ECC33BC9E0
+ 95: 000DCE0FA82C1422ABF37EF1971B4B1F
+ 96: 83D1C6EBEF52D1B9DFA3F439BF8DCE25
+ 97: 657AFE5CA6D54F9083F02C257CE7E3DB
+ 98: 9E65239503BEAB92716D5B504358352A
+ 99: D8375320E32FAE3BBABD4620B1231315
+100: CC8914472A9B5862287D695AD0A88BE6
+101: B0E0D8EDA1BDBEBCD0A78678AD7D6A64
+102: C8EBE9364129E651BD4FB491FE035433
+103: 2A6DF032E0D615DB3BE890B0B6D3349D
+104: 975F0E184517902F1C239684EBC06314
+105: 5A86E403AD3D0B9EE5CF87C32482C6FA
+106: D3E986B5231A204C88D7C2FD1ECA40C5
+107: 891ABD274D024F8B04143DE588A02AC7
+108: EA619405003DD17F13ED5BFB29587568
+109: EF5CD5EF1164A2E5BBC2D96360E55B87
+110: 07C74397955571A7E4025BB9EC555846
+111: B5F20FB0AC1C1DAA0DEF8EF78A9BDDB5
+112: 88D91C18A4AD272B4C1E2C76BE217BFA
+113: AC548888F0E5E559777568ECE71E2007
+114: 816071E2B807CE6EF526E423BBA252D5
+115: 0585A675BADFDD749ECADE66BFFD0546
+116: 964CA97939664EE55B8B973D044D7695
+117: BB8FAACCE9D3238714C3934E6FEE2386
+118: 2BB26CD61B24CB5CB9E2C5FF40C51A00
+119: F5332DEBA64EB35CE3B5C7134C4C8495
+120: ADE7A5C99757D216D10E1F13E3A91F1F
+121: AE98C3C4FD874CE0B8501FE4C428282A
+122: 04D7625B67AC3F9D117AA45FEF6C6AC1
+123: A05D3C933DC8C8A1CF48290A5D52644E
+124: 078F882264317B0C00383FBA7E079301
+125: 44023F3B109763A53FDEFF1822488855
+126: CA535702BAAB858D5FB5B79895E0E1E0
+127: FE1C2C02B7665895DBD2F4D2C22A7232
+128: 75A182DB4FD99599022F5A03F1427289
+
+HMAC-rmd160
+  0: 33528FDB4FD0640B4C4363CEF1DE795719EBC7EE
+  1: 514DF566C6204373EEE6020054AE7DDE2B0934DB
+  2: CC8A5C8D2EBA02BF4474A4CC05CC2D863F1AA392
+  3: 27D731E218C369A32BE4B2BB29D2F1A0988BA583
+  4: 091245BFADF5C6635298702F233ECB3265E85460
+  5: BD2C07FA2197201DCA309063881F2EAC9D925A21
+  6: 480886856354E6FF34B3AFAF9E63FB794BAC4521
+  7: 258D58532BEB5EAD28E9BCA52AA4C0444CC2467A
+  8: DB7513F824B42A9E1FFC1369F22F61054A3EB7F0
+  9: 3A4A258F23675EE02E1AC1F72197D1A11F32DE21
+ 10: 9315ACAAAA8DC91A9AAF8DDD4CD000AE04F70E1D
+ 11: 57D60D77E1D78D23D3F184740D9DE392FC6C3C40
+ 12: 950395C815A3D1A4A8BB25322333FECA15445BFB
+ 13: F8201A01C30F3B569B7497B5191AE16D1705085D
+ 14: 08DEA1A0CD4BD6C9031C84FD2005F15810FF088B
+ 15: CF41D88EB3921FA137F0203C2CB8BC5200FDE7BE
+ 16: A07100AAACF5253501A6643452D07C7DE2EA824E
+ 17: 19DE22082D1F4535A733F16262A135358D651737
+ 18: D50BD92902AE0127AC8DD85E9A81ADB7EF3F1E64
+ 19: 3FA34A3C02E06DE451794AB87C4FCE6877458CDA
+ 20: 5928329E4D830E8B2F7608A4ED46DCCFD5798425
+ 21: 2825DBD7989A8978904A654E6AF125608B0BEBC1
+ 22: 9C812424417D47ED7C78C7A049D4E6CB906DCF3C
+ 23: 9518A473A902DB6BB56F7A767ABA13C8DF306D37
+ 24: 439C444C7AB4395C4DBA32E4F8CF4F76207E5BB4
+ 25: 9021FCB087269457ABAA8105D4DAD8DF8904A2F6
+ 26: 8B7B686199BC73A175940686BD57F45B2329D895
+ 27: 0F50FB7AA9425975BFBB6AD65CF96284F768BB75
+ 28: BAA1B7749A9CCAD7105E9ADEE499058A7BE4BA70
+ 29: FBD3413CE89DFFE2F0A869036F5C4265D5B14743
+ 30: 7CDB257E051ED0EFB761A5A044ECE5B0C1F12033
+ 31: BB1E5D495074594534AD523987D8438CF1632425
+ 32: CE6D7BEAD1496190F0F0E99B0B0C9BECFB7D9173
+ 33: F8BE617A3256EB1C4BFC04CD386EB7FA46603926
+ 34: D1A1F489434C458344239A75DA4241A3A94BEBA2
+ 35: BEDD951DC98BD5C4138C1F8531D8288BA3C51B87
+ 36: 9C2357E832CE87A227F6919B50A0A9D3A29B7CAF
+ 37: C9FCBB9A1AC48B71B2AA20AC992821531F1141EF
+ 38: 0B58D56923F9620BCD072703FBA71EC2172EEAD2
+ 39: D97480E09FA6473AF9AAFA14FA9589AF65E62328
+ 40: 4D5C56D0EB0BAD64FD0B0FB7F87D05EB551951CE
+ 41: B7EC2D13EDD3603D1BBC8CD29F32B43AEAF6EB4E
+ 42: 9BD5300B02C9432F686842E7900F3D2A085C5008
+ 43: 7E8787C8780C64009216324802958E1D845332FB
+ 44: 1A3BC1AE95380D609571B01D8C3458B2566B74A5
+ 45: 9672BD12EBBB12F398CEFA089BD3282A2D2892FB
+ 46: D5D3CAD705E2B0B6E0CBFBB0E8C22CD8EB1DC4C5
+ 47: 408D84FE0B28A3B3CF16F60D6207A94B36219F81
+ 48: 0B7E3D35C292D295797E3ED1F3D8BD5FD92A71BF
+ 49: 18AC1EA3406D69CD9E9C801F471AEA3A31C69D51
+ 50: 98E40CE293ABE4ACFADE7D81371FA92AFA69248C
+ 51: D95E38F2D0C5ADB478A9BFF9F8E7B10064455C31
+ 52: 6246C69FF502D453950BFEB5DBEF68CE76D70F12
+ 53: 9D788F02EEE675F47AB4498B1337C6D83A37F64A
+ 54: 139387D749674D0E84F3C2BFBAFB3F0CDC4CA273
+ 55: 09406CEDC1C37D275EBFE02CC707229244086CA2
+ 56: BACA138E6EB6E5BEF150083CE0EFC64FB163EBF4
+ 57: 87CF4CC4500A691934C2C6607F3296A0BEC980F6
+ 58: F8E4DB4FE6879870E9F47BA29F0DA843342953CE
+ 59: 52DDF305014F1C68A34ED514B10FAE3B1B91F383
+ 60: 0D568164C300BB14A4571A73493C02E4165383E4
+ 61: E1DD806961D718F8C085CEA11A140900FE8064A4
+ 62: 6470CBC7FE079B684D108550698B7C5D265736D4
+ 63: DAF83273B2F16DCC69FD55DC84835931E75FF5D8
+ 64: 47F4D7724BF49DE885D23D84D582EA3A00E1C2DE
+ 65: DBD6BD40F804E38963EBD2E81CE5196F6E69AC48
+ 66: BD96E9391148957BE64FE6DA89CBDFF45233FBCE
+ 67: 20975680C2E31D61D7F303215A25CFAB4479F646
+ 68: FFC321ED45ECC1A9FCDBC28ABAE0DA1FD27A628A
+ 69: 99F90008F139FA442C152706E522CEB349EABB00
+ 70: 288C57DAD9D1174F4EBA92F7815B93C0916E8157
+ 71: 8380FD083E742776CC32971B9E088B894A6A0071
+ 72: B0F44C66552ECE94502597B6B100CC64561E6F1F
+ 73: AA0465458FA1F285F5A4530035F84F844D545A75
+ 74: C90EE3BAC92FA4986C850DED11D728A78BE85543
+ 75: 3E525BBEB158B246A3F4918B6D634CE8EBE4503A
+ 76: 7B42675AAE1D0DA5A84623E47C618744249384E5
+ 77: F50AC31B43BC93D1BE2A4D9C40FC4D3593F2551C
+ 78: A31AE398E0D6668A52DAFE37D019F7571E0F681B
+ 79: BF10B29B4DC7C848C5192631E59E0EED32B8D81C
+ 80: 77B214EB3617C372C191D1D284FCED04F5AE17BF
+ 81: 1B17DC33F5966621F4BFA93961B1A8FFEE1AC820
+ 82: 5A07D9861EDA6D8698E12FE5250CCAD882628B44
+ 83: 176F46FF2202307828D7F62D39330444D688FDAD
+ 84: 59E94CFA3AC2BE8DC6098840E888306764308DE2
+ 85: 679F243847C647FCC3F4589CF87972558350DC98
+ 86: DB97F5EF492C7380472E16E3B055567DAB630153
+ 87: 359CF9515F6B2192BF0E85EDBBC81D51232210B7
+ 88: 30B59B3CBFFC08DA7D9514AE7627460BBBDED722
+ 89: F31D5E2866D9726051B6E5AC9B846DB36EB705FD
+ 90: 860A58DDB6119261646907E251D60760099CAA07
+ 91: 22EA0278EA053175C2F12BA4ED172FB0B518F3BA
+ 92: EC68297334F421AB3F2EF3518684E8E1B548BF56
+ 93: 5C1405CC33D9025DA265FF4F25942853721489E2
+ 94: 8AEA8E9EAFBF3BA597B65BBCCEE59013C8E6AC8B
+ 95: ABF7CCD01374D5DDAD6EFFB19412EE772E663DE2
+ 96: F7F28E05FAB93A3D089BBFF56D4E462F0BEDA41A
+ 97: B6C4199D504E72793EEB49611E28A82DF5CD7905
+ 98: 0B0916C89F1D9F1134E9106FEBAF4169DC49F752
+ 99: 4F18AA0E88A01ED162D08F35300B1C3FCE1FE8B8
+100: 5D4F3C473D5859C16F70C1566F9800B3DBBBC643
+101: 02C1A5F34232B8900E6C7DF2BED957BCAE529784
+102: CDD46E434331D7869A27EA096CAEBF586D93CC2E
+103: 492C04E69F0204F150B63022C7DBD28116458F97
+104: CDDAB90168E934E69E942B1F1EC0D0AD7BFB5B43
+105: F433642FA8091FB2517F3357DD30308B4A2AEF53
+106: 537B2118792B6A419C438E58CBB6C5BA887AE257
+107: 753728CB39813C27498033A07DEC03D1FA720FE9
+108: 119A6C5BF3EA8F7A78DA9ED2DE7ED9AE3942964A
+109: A501EB611542A2A2CCC68AE754D2EAC17942BD8D
+110: 158FB54E37C7DF54B29928B5DFA53A560DC09A5A
+111: 15F5380252E23B5C37EE7E8D1F5963FBF8788577
+112: 735F2C3CF7680C63F33AE2D4F3569FA8EB45EB93
+113: 67AFC501C6582DF2A9DBD713F206041E5F3E1DEB
+114: 7CAEFEC1C6E8232BCB90E3FE3523EE06496F36A3
+115: CC90ADFCF3F9AE777B30EAA6206A34EF54F74C02
+116: 974E0E85B47CCB870A511810DDEFE81CB85B28D3
+117: 516D6BA01E0186CB7D796FCD9DD169C45B63A93E
+118: A1CE534BDD6591AF4EBF61ED75636C7BFF670658
+119: 1E4B241D6EADD77E046BDCCD25F70AAC969262D3
+120: 7F2F1B4B77C3170A9E015DF4E8C6EDFE736DFFC3
+121: 89A3BF181EF195464DBEF9576873CA2DF7D16268
+122: E1F96A7C9115E3DBF28E10D62F2D6EC89415B6D7
+123: D75C1081B3C2720D030EC5DE13093357A0EE6E51
+124: C11603CDAD8DF271093CACDFB5AA4E113A270EA5
+125: 39A9E659DFFDC2ABC88ADA2B6A7445090C7EFBF7
+126: 4132330C5E3344818AF5C054AD55309FF7B767A2
+127: B107A8B0C7B68581969A0F6DB95DB2F790098F1D
+128: AD090CC9A6B381C0B3D87035274FBC056012A4E6
+
+HMAC-whirlpool
+  0: 5C36BE24B458FD3713761955F28353E433B1B818C8EF90F5B7582E249ED0F8C7C518ECF713410885E3FA2B1987B5DEE0FBAC210A007DA0FE995717F8FEA98995
+  1: 30C66EA7CE95764F4CFCFBBE4C166E80A1F23E8C88D2DB7FAC118BCA9EE28299778610D94CD545C18C114A2A144F9E933CD80238E9F1AC737F7149BA232FB846
+  2: A61FAC4DAAADF3DB746DCDC24CACDD8C2B74429CA812D86091B5E7F8186753B34532047B3263D2E231074CCDFB18188747B657E0B685693901CBBEC524949244
+  3: AC3BBA8D998C234F9BCE9A96643E8EFC342F4772DF5606A812C1C6CFD644E8F2B8F9BD724CBC8D769B74C52669705BD3AD390CA61DBC7EBE4438726A91FB2455
+  4: 59AD4171B4C33E09312A01B97B3BC2B7DA43F8791561E32A9186C9B0C418BBC31DF54D6A9ACA00910C0F3DF5D7C2DD7CF5634B76506646B7D4EE5C60AA7C7950
+  5: EDFD9FB5B7BCB39811D87A890171096AD2237B78862C4921191F8B0B137DE5178BE8DA898B6A895FA6C4F401714D2AAC743F512F8989E39081F02A2A0F9F6137
+  6: 6BBE26824C7582213F89F773C520710AE400F01B99BCE126C5F3ABDE79C8B304139352427A3E25A313A5F753A94B55F1EE9D3A0300E8E987E98004F58707F73F
+  7: EB89DDACA2BA68940C4616B3B1BDFC25D94A78B8C3A533F1231A259BAF6A6706E1B90CBC2F21A76210C0322C7E4286E393B167A2455DB24C6B52B0CEF3EB78A5
+  8: E8AF385440589959D67746FCD40E295026E942E44259169780B3954D20CBFE2586D2A8BBE408AC2D707B0FE539DB43B3E9B29A8D26D09A41FA6F191999A45186
+  9: F6B9CF6E0A337906517DB09EFA31E91D57D6B908ED5116C13B49B8F1F3C3A872EF42DED53F939CC4EA4122FD8580D528AD2DA72BE063251CC89FB52741E2AEB2
+ 10: 274FEF3E5EF7AD7AFB1161A29492F0DF44BA9E1C30E1E88CD708A5D27F2B35C45085A200E9F42F340B0D9B3A1A354B1F5F6D0D1A754D51DFC39CB2EE213112DF
+ 11: E2EF7A0A64A3F384F95823201823BC95060707F273E395F46F3C0627E1CD2BCE97DB2984C0EE7A11B22E617F0CF64A3F44BE9FD6B38C3A07A504DDC1D33C73B4
+ 12: 681D72B9BCA446200BA7578E038A8FC418225BE5F02D8DA3CF085182628B7BE587DCAD4851863CE1CE8653E4916047F8E92E91A6B0D7FFB065F316DA93C4F44A
+ 13: 2CC82F237ECC1B9B0B9FB76E6B9651C56AE57CAA072A0C20B968F2A74FCA6A9749FA264331F4F2612AE0DF32810B0CAE95E5861473F4675766459B7380F7B9A7
+ 14: 1F3818CFB04AA3882442FDF1F5CB0DB2FA9604228D3CCA1F14DA16B35D9B2071B372996A176AF0592F00175EEA4C16A6E0162DE62DE30E8A80FA669FAE9A33CD
+ 15: BFE4BF868A8AFED289DED5F6E7B21E6856107EBEFAEAB5CD644FB5634181D52D8DEAA203C468ABD279E9BE73507A690C0B715869F6E722C4512E815FA4EF641C
+ 16: CCBA3834AC7BF06B16675376ECCD96A0F91E3E3C588C5BEE1711A00C107B35D603B20DA8E5CC5FBA6937A24DA53D8F55C907F3E53F0F255E080396426E7ADF9B
+ 17: B09F6898640E5CF77B6DD3D5A8A4452F4F1D25C90F7AA55A205EFF2C319EC0BE245CEB4190F11D85C2F7234BEB899BDA465C95A1C59568987C4C020B9A7AFC00
+ 18: AA7FEEC56E16AD79990B003AD51626C87C9CCB90EBFD748DC268C0C8C1DEE1BDCA1C8064FE7570A5C624AA0CB6BEC163E63680377A16AD49D1AE166090DC0D80
+ 19: F755304A4694DBBEB0E59B978943F3D4E429F8123B3D6CE27AB400D3C4BD81A13A8C3C0BA0FA7E5F13BCB0B48290933A05DCB49A5907C074039427F0EC9004FC
+ 20: CB8B5804EF0478645400B1655DC6E194C8DC26112EF76C57823A02F39C8ADB42F1225B130FF0D40F580DA8CA95D82C0441E3A82C206D9D8D6DBD63B4BB1BCCE2
+ 21: 4EEA4AF294C458BDBA7F49AC0826BC295BAF5B16D16F40D379F6B7C3456EF4145B5EC7F7CFB85638F641CF4D07FE3904DA891E68288FC11C0C72F54430915024
+ 22: EC52FC8CC0F849E633E3F7339031DCBCEAB69B6634D3E54E7C153CC63DF7D3D3F93B13C8E751E79290ED4845FAA3D5A79A7DE6B100F538E0FFF470A51CD630E4
+ 23: D44419C0A36FBFD0FB441B596E8821D3F543D80FC7EB5A3389037BE0139921027571502B5C53BA30D31D4A053E830E610A394842229E08485A2376CB9766313D
+ 24: 3F4BDBC8A4C86B3F646CC445E2CD54B4C786BAEDEE9FD91A879640B4085D46FEBEECECC95E819ECF6AA9085C2309E79DE1A988C6B68930ABCB9BBAB90F1C2F85
+ 25: E5EBC015269E0E61BBD1717618C15D44953AB6F854D962A04FE88865626DCDDEC5F094AAEDCB708D947A9547A985F0B287CA0FBBE3FF2ECCC4C0C4FEE4FE74CB
+ 26: 010C622DF84E677805108A2C5FB1E8BF5922D35CFAC2408F2AE174D353AF169A40169709C39BFE90E51B095C8C0D2886B4F10B37BEFF805D384E29CECE89C4C8
+ 27: 3E9C7BE96E03C48DEA773204E1EC3721EE817ED2403E3C8F950A4C447949438037E2AF0A030CDB983D3FBE5B82226F510FD91CF8830F59212F8CF26C2B5E4DFE
+ 28: 8797C9C14CD2DE3CB1D29808DA9F23A5502A7BA579586DE9513B980FC06990DE0E29837ED06E24B15DD0000697666B8D3DDC556D818E87F84D125697D5E2F8FE
+ 29: 93DFA3DEB3258FC7C4F5362D36C2AE21AC0471AF8B895B5AD1C407E8D50DDCD0111AF76EC500D7BE035E6F9CE932190712A3F52FBA4BB0DFCE74400C82D1BD8F
+ 30: 5587EF7A31353C0E9C346C837EA645770BC5F5C541B72886844B4B0789FF1D95134F558B29385B35960AFDFEA7E3AA40562C12683CB7DD9A410873565CA10880
+ 31: 052CB0FAABB263A49516E39525023E2A02DCDB2D5FC78948E042E59F89363FAAF1869D42EC9D7AFB0DADB7D4E99544BEDA92E3270544900A5641F059571B6238
+ 32: 2FAEBF049CC4C9C2770E859739B1774EB6E6AC2EAF1AF7D3EB55774C03ADC4C865A65C82E795959CBC4BF00A64AFD2AE0CCA16D58AEB874E253FB9FB9A266790
+ 33: 82FBFD2A46F2102AC27089B6889024FA9172FA691C1E3BA9B44A394D52EBF5A7A8BB2321708ED9AF2776D8BAEA13A5F2E9EA4AAF420A24B6F59E2F583D54A797
+ 34: B306D18161C766DBDC734FCEB08D14248EBCC63FCBB5B9CC0AE9D690E20E7152D771B3D623D7ECA1CBD305A31EE10C220FCDDC2CE76B578E2F15DE4741E9C9AE
+ 35: F527D57F0A5F13D7FC6A30A84BF414712044B56FB8F6C1E1375A09783968A851DBD495D51C693590E7A8BB570A7F1C0C9ADAADB74EF8EC71A0093D8D1A4285EE
+ 36: 0D9F9DB43A0FB4BDF70487002943A6CD3BF200518500B6934BA518B3B0958095930EF59BAC48C84C1E1ADB815A6569FBBE7E61F039BFD8C2F727EF4636542A5D
+ 37: 614CFB257400128FBBB7B56550E86198155A5647FC11111FB4D36073BB57AE4D9C0A54BCF0DCDB8B54ADE4FF8AE5645821CF9C83F7FA9468FC2CCB552E30BEDF
+ 38: 7032724503FA5B0765D610D3FA4609F4537F6EAB75D7CC4E2A15D2B1421293D9411C9E8F38999F7D64D607EFE95224331E47FAD4F9BDB6AC19CD3ADE47C17E7D
+ 39: A8E4316126475B429E72432073CBF26E94DA450DB553D46667D597F0AACB99325C9EDDB94F8CE33551857827AF3935F2DFFE1EE69A20884D58E095390C04B925
+ 40: E7E90B19E76017EE80E4979FE56A488AAEEA011DE9DC068DBE53AF06ED44DA4CA3BF662358F191FE2842B083BC5DF2D4183668F4E7FA9E2750869DECA7302202
+ 41: 818D734A02A0AE76A0012D7BFE983B17CACE37D4890214C7C53A81CA9F42EF0A472101D609BE5D3DF4F0A55DAF154C20A1A97D53112E22D136C03004FE09149C
+ 42: 0B9F5B2D4BC3DF781F55ECEE149470F3BF68FC51D121D021DF0CB8D4A5EDA42EA6840DD735ADF8DED72B325662BCEECC6195AE831D169A891F6663F8D7C6E0D3
+ 43: 7A5AE42C635B250598C536E531FDAA1746DE2EC7984DC1BE488DE4766D0CD544AB51AB1E62A8A170D120999A61CC6920DB96935F295817851A4CE285D2755112
+ 44: 95093085CFE52D746C54DDF8D2FBE33EC00D71C39BE0865B896C331C7E5682FBC0DD84ED15B3F790166D537A9A68EEE5FEEC63FC761EB854018CEB68245CCB90
+ 45: 8BA177C495E9832CA8EB55E67E5D7F34C59C4C59D56D50BF6982B36AC341CBFDFBF5A98BBEBC26A9509FBDFB239312DF3B3D5BCE70386EF0E593E17A621F41F5
+ 46: 6DD39D94235D012C89FD030341392AE42BE7702C4D8E725C4229940BC273EBB8EDA7A6893B4FF86D1EF84DFA119058BC6C8CA47675492A0D37C859E6D9BD5471
+ 47: 13A2FBE3DBAEFCAC5AB8BBAF91BAFDEF5FE38B7F2EBA8BFF0F44B4BBB236613B8BB122BECAD9852BF7638E48F0FC656F9C432D9A66C1188DF3FD1D2A88161139
+ 48: 33B9B7EF63B302C1C79E0A43D77487C55D38C53F29C800B4CC287A99A440435121C7ED78BE7406349E65AAF991EA0EF19D06C1AFBB814FE4E0BD68613AF0C760
+ 49: 720E1005ACE28903D9C2B6EDE02A52F89860788AFB35208B4B7C147E43BAB3D06445DA138606F334624C606DFF288B0C70B487679685D1DDD26F1DA0A5F6839F
+ 50: 2A742F1E8CE6CDB501E8AD9BD256786A42E7F1888D9803AA8D5750817B3EA101331D7266298962FA28AF2232BF956FAC7C1C0B1C3DE4C5B3FDDF8E63BEB02185
+ 51: 05CF6361A4A238091A1FD011336F7F53B9ACF78BA1B96997EE49B99FE36F0F1163E04B446EEFC117B377593EE078B85BB9588918C76612E2A6F9515E0CA244B2
+ 52: F510C877546FD2D022051364A09F2051523F8E7FDCD3E9D2AC5158205FB36CF25A9E0FC394ED2FACA7CB4F0639B33B706FD4D072D62F6EB229E4D7879DFB45CD
+ 53: 2664476D94776DB52BAAF3B2DE05A36D3E35EF44ABB6F09670F37EEE00C2C54B38F70D06359B20F7E40E22B42901863864EF89EA473A1F3C834D22176E87E617
+ 54: 62620CBDA92EC8241DD3A6A0EFB28254B0CEBF3E2351B10CF93029244A6A3D1DCE10D9A895EB6E8A33108DDBAA897DFF2703757DA3706209A7871F4274901E3F
+ 55: 51282A90B63998F7AE7ADE4787D957992A81D3009D6AC5BF824DD1507B53F6918E9AB6AA1F36373D5E5D3EF8D01AF9D05FBC224781C62C1DCB4A2089BFF5496F
+ 56: FE1C4394AE26E4B85752045DB14E0AD378726BC1C985C8805222B614C62721E40B2A0D21983FF40AACE8E5F9CD57BA62C37C8F0968EE12FAE14267D6AE906A7A
+ 57: E570E1183CC6AD7A2C73D7D0E96D3AE0605039603B6F6467FA5CA62E4C1424BC14B17E9614F0ACACCAFC2B1B39D8C081B05DFE2B9796F32C0C742FB09DC7B8DD
+ 58: E690D667A94344E267A6EA7F3F7A6A5385C961BB6139800CD5257BFD6C4A672DB576B52335D22160A372987D652741EC3AA9439B35D8975AEA49698F8D5528E8
+ 59: 59FE977EC1D9927FB09389E3D31272E625F089AA75401D1B541DDCE8C6983A363622CA4F2AA9741F0D1484195CA31D6D315DF6B66E74888D111FEFD249FA0174
+ 60: 2CAA990D06814CA73ACEFE0D9A815589958398999707BD52C3773F61B2DC2F20EE7AB7F66D643BD9686C4C460AF45D58BE9F8DFC1B5CFE3A5C2DC2C93D9491A3
+ 61: F198E9238E9592A97DDFE1B0B56DE5DC05D358940672D84F15E1CE71ECFD3854CDD38762DF11E1871EE615EB6080E329495B37B23710DCA9F4179F5F95F3E2A3
+ 62: 3D7C45603510C6916226B192C81B90EC213D30C11AA21C8520437CA5639D00EAB529A4C443C9A39C5E40DFEEA0F685B3D0E1277BEBDDBF80C3D5F9C8326765D9
+ 63: BA081CA12FFBE3CA8F1E2703C96587634F8EB3BA140F93D997B6D0FAD1C1915ECF7D77CC0421E639B083451EDA605571D68DE81E7A4BFC183D7A53A07122168E
+ 64: CEFE2203F6428D267CD2E284C3B8C31E1946558A56A33291508093DCBF64FD5FA4D33FB723ED49CBA02D97743312138FA77AE960EDF5910E3ADBD02B1203FD97
+ 65: DE0379336B1C7421AB4A7F5708BAA3D4E15CE75CEEB8C7349265E71942A963216559FD628C52F71356134AC328D0315ACB63A06382D4251A28127380CCEB08FA
+ 66: 95FD3399270415A80C2F295957C0BD8E33E35C679C31B2118DFABD542EF02F6E2E432559ED4066954AFBF90C982F60D73DA8BCC94DD48BEDBB00A8E458CCB6B8
+ 67: DE49AD8262EACF733B567D8F7752711ECB5D0FF5CB18E5A99C6C35442E652643149A51C820E6D4481AFE63F5B6955105F8173DA57DEFA392E43F7285799A32B9
+ 68: BED41AF0733EED85BB26E8A06949AFA1CBCA9BA87C085BDE29FD38F94709F4AC20360F7C7958457D2C49BC5A38FBA06D6A6AF77ACC883783B357032FBA9F93CD
+ 69: CE72D475D983EB5E528C4D71EEE48EF337E1723DEFDF142598E4CEB3B2978B1B4E36A69EAB6CEE8F3DB2EB353CBD27BF7D41F73FB184CC8785DDCE8EC22E9741
+ 70: 24A8A7C759F59CD3DE2E3BA953EA975B60079D9B331AEC4D1F4586FFAD190EF53C2EC6BAB566660EB5D652D7D54265B8584C6BBF986537F54F9D8E4068C01F67
+ 71: A7CBE72C99EEEACB387D4532BDB651EB46B8D30A9D5DB8095C9B3422D9D5C9480AA820CFAFE4047AA0546C03DBF07424FCF7B812274B3CDFDC76B9FBBBF08190
+ 72: 16D536D1D673F74D9E298B16AE65C65E467131FDE5B4356FE16E3FC36624E19FA7B55727240C51C20491F3122A1AB073B98E095A24F4B3260EBE5211EA2DCB0F
+ 73: 692189C1FF6DA5862657623BC862F5041D63A2A1EC8986139CCBCAB114427B1A2500B152CC611C5D5599E9792F014A640FBF7C6D944EDA811CD92374326B2C52
+ 74: 273E18F4B94E624988C47CC45820E4552DCC53BB40A9A24F744A14E56FB1DADD3EA4087A785AEDB5400A65971709DA1AAB9C18EF534087EA73A1FC8FDC865170
+ 75: 8F048230B202743FF1DEBAFEF8CC93244687A58A8E5E3E6F7D85237ADBC724641431783E63FC8EF2FBEF9DE9CD50C9FB294341654706DBEFE6B05CA8588E1A3C
+ 76: 7AEF7701439F9DB556AD3B166B0B25A51795638A83E0EE25E5244BBE9D2E8CB6A8242D81E78E4906AC9CA0AD4FECD1006D89C5A8582D1BF51C278EE7A357232D
+ 77: 55CE718F7686A0692B3727BB5C24B16FCB87D8E8EC943A80236CF3E9B37A4A20194243E461B453CF03AD846A0B3287A2005D6603D5E080D700ED2FA25F0FCA87
+ 78: 3378B07E0563CA7BCB91F29C8ECA876AD748760748AD07DE0208BAC227E0EED4A4834B8879F3DFE51FFA27B70AAD1F3E9FE1586B1D6B2B9757D545D9CC5DFBB2
+ 79: 040E1EC767CDD85FEED2AC6767F0B3C17CE4579FD9525213A682A9B49ED03979144CCE2B94026AAF7D401355B90B25259954163E0C9739CB9E756177ABA053CE
+ 80: D1CAE0E4FB245C1AC27659C2EE86BADCE26228CF8EA24AA62B69995FF02F9A59B1ACC1C959EF91A7B6EC90EA9D57F49CD0E7621D09E4016676953A3F9B9D40E9
+ 81: B41EAC0850797959C62DA2750F2BCAECCDFBAB843D56C034E4E0DC15C961FA611C50F22BBC135E5D99DC4E4B7634A8DF4B0262829593A8A86EF6C265DB9AE907
+ 82: 66BE82FD1582736D0DE7861D9DF74715658CF3CD2BCED12868EC4D92F4B015B7BACBB331ACA8D58386AE6B0642C3740BF5F3CB26E76551541AD57E1C303D4527
+ 83: C38BC2639AFEC1964C89CB92DE5ECB78E0B2994EF37F839D0A61EA688CCEB068B1A590D6CCC929EFF1145F5A5925A17BF2FC0AD352801CB92651F08352A992D5
+ 84: B699ADFC29C54F178B3EFFBF8FE8BFBCD722F2997AC30754A8FC5CC6D51352AFFF7F31D7F71FD9D136E78D1C1E040B05E25CCB75C7AEEF714018F51663C7AD91
+ 85: FDC4207E97D12B7A8D05F5073D47EF32BA32961568599ED34CA160F2EDC87726C53087711A63F6BB7E840F305477B931D1CBC1939A8B80205565D453675FCFD7
+ 86: 07E1DDE64790A279B69873C6887FBFCA69B87C97BC25B969E2B16040CDD2051BCF43637F490EF1B051CD882B64E22DA55C253A5E796528526EC62A305FB05621
+ 87: 3ABE353A4291A3A0ECF204994D49443C1FCC60C80BF6096026551048533E02C475B905046C7708F4852645168C88125221504E174A8B7E67AE424C0077163E0D
+ 88: 33793697140180A04DA72C0F74E1F845139937CD6F05AF74E3F3C5031D1D2DE571BD72916CBE67859FE501C0E56354C1360E3EBC36EBC11D11C1EE08D158247C
+ 89: 9E5A386AA9C4C5A2419B902D239E49ED84E542A6F949895C88129DFC2844FC77FB132592C7C1474E619C55FC2835F0810F227799984777CE99D586C158C8F9ED
+ 90: 6E0D9841C04BB47DEE30F6AB430E53FA1637421E460BBBD7BC8EA167B9A341DDC5E933B6983A025226B1FB3CC663EDC3477F8F0C8FA109A8B97B4B17AF3C2774
+ 91: AA0218FD54533314F62390B8C02219D26801C249D394E33981E3B853C5735E331826FA02697DF54C9268B891592DBD876E25C8D985DE8752ADAA0CBE55AE7FFB
+ 92: 23905B9273CA17D80D9C877DD78150B5382744896B073DC636618C540876B9BA51EC60F5E45DD53BE210B6076554238A3B5EA95DCE3481F0FCF2825B852BDE3E
+ 93: 1815D1AA4018626EAFF051AFBB92E91F6D6D136F58E8DB160C9E85BEC027B6CC92F0F0760DFD722BE12A97F7D29EEC341BD309F230B55B81D146B409EAEEB7D0
+ 94: A2358789A04795BB20D2EDBF95D5DA28A1FBAB329F99DFD0B103304F868CE5AA2DC1F52FE98CC84EB095B9C5ACBD6DC05FD03CFBB3F1D26675D0A8F652D38236
+ 95: 2C4DEF028098A0680DF15DEBFE6A7FA42C7A7D75CF410340ADD5257037F0B2F98FB5A068361DF33010FD48A4B41E0E40A2730FF2148C45FA568FAA182589A543
+ 96: 360F3B6819EAFD9B3D6BC469F4272F9458C0791759EC1136FAD500F3FCB4FA0598204669E865D7D5F8C289043A2A1CCB47F55CEEFAEAD98C7FDEF38FB22D3A29
+ 97: 1CB2E98EE8795761EDB7579583EF86E7223A2109267E5234663BCAAF9FBF28EAE35FE362AE9AD075023C1D36672002E08CB36189A603C174D73BB9489E13355F
+ 98: 9B3F2D2B2E3D0401229F11E6DED451A1289C631122684BB32B8C0450043ED2267AAEA20E950F52B44EA5941C507F38D23CA76E212593B65BAB347841179BED1D
+ 99: 2E27C53324017626F7EE7EE26BB0C88450B3D882C2D8823647ECA7650CADDFF3E4201D7DFA2A07A51B9372FCB04C1A79A264DCD3D260DE135D08DBABD2C5869A
+100: 0B3D7FFC5DC1CB18B867D995E3D02FB2FBA0DE27BCC85E49A3B01C5581EB3B14C19254C87D92D2EEF952C98E4E6F51C9662CDB982BC95B88C11CB2EECF032576
+101: 85C0B9C8AB8C670C01E179F495DE26F818EE772AAF6FCE4ECBDB4FFADEB1CFD8EA86E42020B47894301920B86082DE52A7E7CDC6DB4904F8F0D383D9CDA312E7
+102: 0C6637D399CFE2734AF7B63F81B7493158B7842E3C5B72E6CEA4388A5C6DB7222D46727B92FB82D88551A227703B8BB6A1AAF47247661E074CF6AE4277D586DB
+103: DC54B4ABBB7942C502BF3275E37570947FF7162B6831AA430566E69AA80658C6E792B78EA081611256C64552A9E15A66000632116AC83769B7C58B809FD96021
+104: 532372848D0F525884E5ACED9A727E96A8D92B484DC2D4089206B001CF9EC52902E49E6FD9FDE634941BDF5AA2B45B0787D0B183B895470BF1E79B57DC976EE0
+105: 4B6CEB5AA2174E6486ECB185044629BE6C280807F102CE52D2CE2DCCCFE96E5586A6888DF7500614896C9FE70CF7BC83FE755E88170B3D39EF9B218BE809E495
+106: 6D506B4BD3F079EF4818FCFDA519E7E2AB6A03293525711142C3CDC5236A7CD82A880D9CEDCBC089F7A3D5D3E48BD75DCCA7ADC53B13A2FC9CAC80C037F2CE5D
+107: B8ABE308840CC901C6C5FD908E2680886AAA0BDF7085C1A6ABC257186AFC52C522528BD7BF4E82553D9E64CBEE09B9318995E13715AB1F7809EF185E8473D70E
+108: 9790A198DA7616F4D8ACDE68DE19635A555874EAE77AD4ECFEF7207DC305D475FD250F308F466B189425AB6A9722D744AEF14541FEB83698943E87E8A39DF838
+109: 816678F1D7484660F4701CE77F4C5E13E5DFADEE6622411BE86DBA4EB71A110DD1087AF7D3F37B8ECB1B9C44A3BD5EA73901C21AAB51E569E61EFF25B5E955F9
+110: 51881FF4B150EDC3542CA12CE6554A40415AFFAA1197FE7CA4B8B065A4FB1DC3B924A444CA31776CED52514C525261269895EBD8584C29747F8D527213534E49
+111: 6D8902F285029EE683CE1803B2D9C6BF6E4B7B59C0ADBFBCED3346782A35652DE3F304ABBDE9F22E4960DF6049431139EC6AA023EE2B013A426DB9A816D92699
+112: 06E5847A060BBC4FCE1375DCC15AEAFBF514EE1ADCDF42AFF932AA277DC09EF614651255E35C499D6BA1BB875EA3E80F80AABF8B7710AA5696B058BE91B99B01
+113: CB1859580DCA13556FAB791572E523C2E888115C18C043B0E33F2268DD0056F9A60EDBB65DD9C8B552CE2299E847ED4617BEF3A453ED2AC3B5366B4D9A651B61
+114: 39778F80D346E53D1B0E60FF7B36A92639D9E7F11548C9326A59D9311D57BF09F33BFD6AC5352F2F041BD07A6D26A181419F5FCD1D5FF8AD38E485DA7DBD5419
+115: E508C9A77F53E36F76F0E477DFF076DE810F9F1599A16A3EFF1840332B26D6C7CC40E03CA8CC212FDA776F4DF968FCF92CE492AEBAABD65F069D1AEBECD11B7B
+116: 4659D0E1F9E5318D7B92FCF7700C467429B63F27188C0BA168F0D5696DC764FBFE2C5EFFCF6DF11EA77A17B0565CADC04F95FFB0485CE6900161B82608B1647B
+117: B3DB7FF2F08F57F0CBF2195BB9600E9AE5D86A15921EB164A98D25D559BAF5FD740D68430653DE73F3277425DD77CC3FB0CB44ACC5FDE693D59D5FA6DED84597
+118: CA4559843946A7583F944D51E31FDF32BBDBBFC049724454C090A6DB9C356739F2B7E254CF9746521D965593FBBCFB26092069FBFB0D17A1593416D69681B687
+119: 27CB8A2143D1073AC17009C31B28DB95DC195E20AD7D245D8AD880789898F043F0565FE41485EDC239C7129E4B7FB693D9044B2C3D34C5648E4FD8447E85FD71
+120: 99811490C7FC83A10AAD197E95D3618ABF5018E9AF7EA0AA2CC0C771FC11FCEF9FD6070A0962A563D260E8CCFDB77B48745C8C27018F9140870F146F124FF14B
+121: A1537FDAD7E18F732181CD9EC9BFD3993FAF5F994A8809A106B59D13BB70FD8D7D4E6A4BEDFA806A9D434AAB0368DE840FD64395B4A9A874DB39405707AE3AE3
+122: FB0D6D962055B47D3A72371BDAF77BE7BF965EA7D53018CAE086E3536804AC748E706E89772DB60896EB8FE2ED8F580866BAF3108CA0C97938B69830FFBC14E3
+123: 3C947F4136D9E780A7572CA4D5D7998DD82D3890CC3F1BCB59A7FE230E31DE322DBA7CF7C1DACB33A3EB1F7E75297C056570D2846EDF756D36C1AE92F8DF6954
+124: BC1BDEFFC6AB779A7ACFE53A3F9DD588CD3C77C740F944C69E331C38F162607E0D4A0CA874AC3D1D74965468843133AA9F961FBFCBF59B58818577132B863181
+125: 51143DA8F5D6E68EC97CE22A4961EF43B3AB658711280587D9ACEE701CA65CAE90D34B66DB52D779A8E2BB6204FFCBCA945C6B98B2C17C8375551FAAFE4C8A44
+126: 2550FCF54872616ED31C60FB3FD97B9AEC7A27B3CEC07D774FCE694ED9D60C43A968251C5F3C5B50E6214426B00C55D7DB1DB31CFC4BC07F6ACEA222052AB796
+127: 1D8B2525E519A3FF8BDAAF31E80EE695F5914B78E7DAB801729B5D84C3A7A2B36A33803F5E0723981CF8A9586EC1BEABC58154EFD919AFF08935FBD756327AAB
+128: 4AABF1C3F24C20FFAA61D6106E32EF1BB7CDEB607354BD4B6251893941730054244E198EECD4943C77082CC9B406A2E12271BCA455DF15D3613336615C36B22E
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/ocb_tv.txt	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,331 @@
+OCB Test Vectors.  Uses the 00010203...NN-1 pattern for nonce/plaintext/key.  The outputs
+are of the form ciphertext,tag for a given NN.  The key for step N>1 is the tag of the previous
+step repeated sufficiently.  The nonce is fixed throughout.
+
+OCB-aes (16 byte key)
+  0: , 04ADA45E947BC5B6E00F4C8B8053902D
+  1: 07, 987354C062CD6251CAA6D93280EFE9BE
+  2: 1CB7, B9F1620EA8374E1C2D05110878D93069
+  3: B98C59, 3793FB737C2DFB29E73DD1AD8B8F71C7
+  4: 8978F240, 5E25316ED13D3300F2EC12D718A0BA8E
+  5: CB4D261594, EDA252A1A5C7D0A4AB4620F771446DD3
+  6: 30D6B6688D59, 684037DE07832C6FC38CA42BDF2A7D53
+  7: D0583F9741BFA4, 3DF53DFF73431C0245982F4EEEAD432F
+  8: EE3B9596CBEFF520, D283D1B9D990739EA05F4BAE2E96BE4E
+  9: 6570FC25E6103AC125, 90D3F1FA6595B775749FAE7B00A8E5B1
+ 10: F56750C98C370DFDC4A0, 19389A6875FAB432B72D64BCDD6BD26C
+ 11: 3344AE6D9528603CC1E4E1, 87AB6FBC7F919125A7DB0D17D19056B8
+ 12: F3D9D816A727D3E67330C779, 07AC0F3841DFCFEC58A5AAC22270538C
+ 13: 976651E63ABC3B276799BC1FE4, EE603A8C66099AD6FF8667B3F34ABF29
+ 14: A48E3ABC31336C6B717A96170A9B, A9D1B973D84D3125F5F9D7923BA0A8FF
+ 15: F60E9B2A911FAFB0080FAA3ECDEE42, 4902F8AEB7685F7B255ECC45B5B7D3D4
+ 16: 0855DE488940144AF18C65A9966DDB66, A66B3E7A75D394273AC196FFD062F9DD
+ 17: 172DC1740F75AB2A27B2B80895961A69AB, D6986BB95F7E4137430CAC67F773623B
+ 18: A414234DCCC61B65A79B7C618A6B91ACA410, 6CE32E55E158BC3E51E94116A615F3A2
+ 19: 16A1B16BC0F63D63179901F1CBC772D612C102, 54007EF9822E0E4A4F953838577C76FA
+ 20: 539788EBF85C15B3A638017B4054D71315BFF25F, 9B2511322E16CECD53E3241F3D51EB97
+ 21: 7E74595A3DCFE1EA2C91B67738765463D50A22924A, AC9C9B526251C16F112E769F9FBE74E4
+ 22: A2B61792102B2E44F1DC0E48B40472CE883730504FEB, 76452A49C2524404C8A4B098D6390F98
+ 23: F58174BC06A022AB7D81991E9346F5E4B0AEC535D93473, 47F96374BC094BB2C1A5D1D291806912
+ 24: A3A7713895D178A85D9092EA6138323DC2FF9090D7F01AC5, 3814208FA7009A2934F9A172D029667D
+ 25: 385525DAF9949DCDEB22F7518AF96438E40F7D94933706A9F2, 1249F3DF50084A6D1A76AA350FD85B0B
+ 26: 6838E207D98A5BF8D8E41454CF51663D8F8B76FD26092D45D1D9, 301723D0F49BF8CF37828340B894689C
+ 27: 736413C025A549CB2550E93139DFD5DC3CE241C296C9FE641FF520, BE07259963F251743A85DF51EB1B47FB
+ 28: 7F2CD26367A885BD9E2B515D4E871272AC1BEA1C650B530E5616B2D3, EEB37E8451597E5A53CB49072EDA9346
+ 29: 68F23DCDEF223B60B46E3D724A93BEEF8B110D4394C990AC3D0E34E1B6, 9A60344982F852EFE02CBE9CBBAB60F1
+ 30: 66C5DE3EB27139983D48BED81D0E5FCE6BA1AB402C357062FE989D31C69C, BAFA0A7997A529039F0CE8528E670415
+ 31: D3B9009C1A930EE288C61B0B15C7E92CB73484C345594DC5A3F377147981DB, 1EDAACF7F1F3AC7EA613F94DA4DEF930
+ 32: F7818DF15FE6FBC42A28FDE1D55A2C07EC8D82AA0E7A680DBD3CF26C13448F9B, 67FEB344108008A88067E92B210766D5
+
+OCB-blowfish (8 byte key)
+  0: , 07B7752047F9E0AE
+  1: CE, 7D69017C42B06204
+  2: 1D6F, 4DFD4BD58439062F
+  3: 30A011, DB49D988798F8842
+  4: B71C8951, AA3261584B0C20FD
+  5: 06F89957DA, 88BFA80D36427F64
+  6: 45BC4CE5FABD, 4CAF71136ED166A7
+  7: A7405F124D0296, 5D8993CE64FFF0E7
+  8: ECABEFD9E6574E4D, B69349673CF86E41
+  9: F7D26A7E82A34ACC71, AFFDEE843ABEA68A
+ 10: E225C5F0FA1D649F81A3, 03AC1D5DF1323EF8
+ 11: 58722FBFB86C2697061217, CE731D80E6355710
+ 12: E577EB8FA70225C5A18D31DC, 2F08B140F0D3A255
+ 13: 92154A94CD7D42EBADB6CFEE14, DC949170E84D3CA2
+ 14: 5A3C08744FD85CA262D51AC6CD25, E83CE45547403BAD
+ 15: 8B2E4980ABA10A20573A402D89AD12, E3D978611DD831D0
+ 16: 3EDC4A0FA95BD8F944BCE4F252B6470C, 87B54BBEA86A5B5C
+
+OCB-xtea (16 byte key)
+  0: , 56722ECFE6ED1300
+  1: CA, DF53479333DB86AA
+  2: 9529, D0B5A859106FCC9B
+  3: DDBAB2, 3B31FFDA57CF51C8
+  4: 22EB7DD4, 2BB34D04FFF810CB
+  5: 108693761A, 7AFF6F52574A019A
+  6: 391FB7C61E76, 616C5E66297F2CCE
+  7: 3E22E4A4A0BD13, E84C385ABE25C8D8
+  8: 94FA11D5243EE34F, 8F017DE96049D0F9
+  9: DADB6B5D27049240A7, CA69E14047C6BBA7
+ 10: F79C8EA83C69DE914DAC, 1EF042DA68106C64
+ 11: C5B6E04AB8B9491E6A99F8, 143515779A55C972
+ 12: 33F493AB7AE62DADA38C5B24, 531BF7799A778620
+ 13: 6DAA66BF02E66DF8C0B6C1CC24, 6CDF72786C5EC761
+ 14: 4940E22F083A0F3EC01B3D468928, 185EE9CD2D7521AB
+ 15: 5D100BF55708147A9537C7DB6E42A6, 78984C682124E904
+ 16: 744033532DDB372BA4AFADEA1959251E, 438EB9F6B939844C
+
+OCB-rc5 (8 byte key)
+  0: , E7462C3C0C95A73E
+  1: C5, 83CB00E780937259
+  2: 1533, 022FF70566E0BA87
+  3: 57543B, AC4EF15FC83BDF2D
+  4: 01E4474B, BD817C06AC2141E0
+  5: 4CD7E850EE, 7BB6B3BDA5373422
+  6: 489C0CD1502A, 23DD4406F87EB164
+  7: 0CBAAE08E07EFF, 92569C958B722413
+  8: 073612F283F8A6E4, 1DD978D01CE8D1DF
+  9: CDE676B1A3AC98B00E, C033F099E2620668
+ 10: AD3BC88EEEDA40A83685, 36DA44E13C0C8A4D
+ 11: CA60E8B918F73E99986021, 45634CA0E43E4B13
+ 12: 3B3CF82157ECEACAD8658EF5, E681F57616146CC7
+ 13: EBC1A7068346EC1B7EB815A7DC, 2C806D2A909CCAF1
+ 14: 97CDB3EF8276F1E7D6B6677DA2DB, 53F00B9A2E43DE08
+ 15: 44169B3EDAD9506C51A6DA055EF9C2, 5BB6DD996130896B
+ 16: 35EC29065B1FC640015B0F779E7A358A, 867EBD0E86823F09
+
+OCB-rc6 (16 byte key)
+  0: , 27B9E3F544B8F567EEBF98ED5FD55C76
+  1: 92, 219FD2D74D7E3F21AA6C2A507C0A546B
+  2: BECF, 96A656A16FB3C4579E6955D592AECAE1
+  3: 4DDE09, 7D1882879B5D6FD8C151502BD8AB220A
+  4: 0D6B4FCC, E01FBD1ECA2A6A8DC6697A06AB12BDB0
+  5: E5E19C973B, E5A86AADF2F333D5DEDCE410688CC6A4
+  6: 90BA7D2A6965, 80523A2CAB2A7BB2E90B121DE80F46A9
+  7: 6FE258148EC8D0, B7254B11276A77C5F99FE5EC91D81F57
+  8: D887080095DF8817, F3FB938068A01EF89DE0F1226C544362
+  9: D9823313289D597614, A547764EF20BD4B4B303882B64FAF2C5
+ 10: FF68942112CF01701E86, 94F3860D4438428EE296CEACB3EB67F5
+ 11: FFD390D3E0B64F64D3192F, 99D2E424C67EBACCD4E2EB9A0CDB8CDD
+ 12: 3162235748BDDECC84FC8C94, BDD400A58AF59100A731DD5B4386444E
+ 13: D2A0EC8B1F20672289F7236C56, B245CF42644BDAC5F077143AF2A57BA7
+ 14: 830929B2850E22F6C1BA2027248C, B6B522F7D6BA3CFFA92D093B383542FE
+ 15: 2A5FCCCCF43F845AA77750D3BC6B1E, 53A0A0882C7844636900509921661FCA
+ 16: 8480234796F9EAC313140CE014B0265C, 0656CA8D851B53FD5C1AAC303B264E43
+ 17: F011A67C22F16A42CEA5E493CB766964AA, 830B8158B7A96224A53FB7F3A08CD128
+ 18: F76274A730A608C2AB37497A049C3699882E, 4DC4DD4DF39D0E68D6169F9DC7F4A6D5
+ 19: 7B38DD237DE552A72E4369A81C30AFEA5E5063, 01A62CBD30153702A5B29FB2A1683899
+ 20: 58EB866F1FCB060ACC821D776AAC4AD9E87C326A, 25AFB8FC48605E1396EA8471F55C1294
+ 21: A25F2C0FAD66B3580627498EC66C994B49C5445911, 0182A951D9A3DA53675612DE8EED1FB9
+ 22: 8813977F092F07F251A1497C898967F3F98F5CB878CB, 80BC353E310880A83DD4DE4FE96AB6F0
+ 23: 52DC8B76F5A6F78D51FB7DB51048E2663563335EC876A5, DC3689AA079C04C19D83646B272F9DEC
+ 24: 965437D3FDF91784B63C73C8CD001BD9372167963DF36B89, 9FF84E2845E3C1E3E6711D1646B18F21
+ 25: ADD40F674BD56FFC8F9B4047FAAD2471F0A48F4544C894F806, 9D684F74F9734F1C497E33D96A27E00C
+ 26: 7B049B688839BC62785082397DEC7AA94B837D094AECA4B14571, EE711DF1C15B5C9E36B6E38B6F7152D2
+ 27: DD4681F9C498A3CF69A9AC876E02BD9CDC4FB1F6798F772013B62D, C5A50676EFAA2A56CBDBE55CFED3050D
+ 28: 471B5E89A1337E75E88AFBAACA1C011790F1657425483229E55C34EE, 20F73F2AC452FFEA423BE2EBDF33CFA1
+ 29: 71812C83DE34DB329C8DCD98890AFB1F7719E890DAE5CEB7AC9668CAD0, 6FAA03E10C6FB67D425C683C6D85FD76
+ 30: 4BC2DB33786CFD29B5CA5B804454169906138E90E29E7BE9197971027AF7, 75053C433EF5572A70C58EEC96F56C53
+ 31: 5E3A0AB41264AB65365458ED3B7E6A25827E50075A9E347F1622ED0723E229, C8F1ECD19AD5FC970CF0D31BF46B0F2B
+ 32: 2E48DEE4B379CD59F5367D17DC397C1BFD53B8C4CE46A8202518614076174EB6, EFCE758ECCB6BE875D16B7E03A498D31
+
+OCB-safer+ (16 byte key)
+  0: , 88618DEF98FE588E23107E9A5D89C26B
+  1: 39, 2B01B202E751F957E331ECD1CEDE3456
+  2: 13CB, 17071E5AFD5D8CE953A73F49412BE8C4
+  3: DC4428, 4B0B1881C2540FF92E7DE63C479A7750
+  4: 120382B0, 0BB11D57B5BD9D846CF31033CD4CCB92
+  5: 97F332F95B, 335E0424D0A820F60DBB968B8B5AA057
+  6: 3C7AAE72037B, C8034C2C76C1CCD7C1B3F36DD8907E1D
+  7: 8A99E4A1B89B6D, 06A8165DFADF1EA5ABD89E574422DF7F
+  8: 676587065F0342B8, 93ADE63994DF2189079234DC204BF92B
+  9: 8EC394CBC6877B245A, 1A89F0AB0B44BC708EBD9DE489E2EEB8
+ 10: 5FB5366E5CAE4DB72411, 5CA5881A5805D53ACA4904A5EEC01550
+ 11: 72A1994028F09ED6A4E45C, 0FFC0052996CE45DF4A28F7A6E9CFEA6
+ 12: 1D5EF20F52A9B72386D1A601, A697DF1179628DE1120D5E8D9F39DA6E
+ 13: 79BD002AA59D74F125AD9E32DE, 2F02CB6F70BF57BBA0DF100DE503F633
+ 14: 442C6F9016DF4C090056258756A9, 58C6FD3180B9B74459D70B5684BE3F4C
+ 15: 4FC5543D9A892B44ED04EE8B25E232, B8B858B3D3EB4B26E867E429F88A56B4
+ 16: F06E7503167C2210AB332259BAFD6AB4, 73CE2589D1DF34CA3DC2B14CC9FA6276
+ 17: BCCC260BD4823B64090FB33E6816F9C330, 81ABBDC83B2544907840FEB5AF4479EC
+ 18: 450C1105B76F960D1A5F33D7F9D37DAE20C3, C41DDC8980E88E3986D9C84857BBE1E7
+ 19: C9F36EF3A990E0554EDB59E6788F8E9BF1DBC7, 90DD543E148D9A0B79A8B376C5509E09
+ 20: 3666FEEA98A4FC434EDB7517E7FCEE2320C69BCB, 99F11B360DDB3A15C42110831CCBF21C
+ 21: 126F39C19D1E0B87F1180F6589A75712B66209E2CE, B4D268FB8EF5C048CA9A35337D57828A
+ 22: C1B6D14EE8B6D0A653BFCC295D5F94E6BCA09E181D8A, 4B4883B614D5CC412B53ED4203EA93B7
+ 23: D1F2A10F1A9DAB738C61CD0EF66FE5F6D1DA95DC671128, 3F1EFDA55EFEF1A0B24708E132BC4D25
+ 24: 9D457216C584F43DBA1DD55C54822A8B6A86D22DBFFA14D4, 53402970B128E98A5F0D62476A38F959
+ 25: 012828614B5D67C9A1EE24A1EBCD322FE9C8BE0C3F20A53714, 2BFF288D90DBDC638084F80F3F7AADF3
+ 26: B1904AECF599F6C74557475E409E75E646271DEDEC7A830260DB, BF119BDBDA27773E038B7067D2B0EECD
+ 27: ED831771C4346FC19435354AE29F7A9436D6E8D4D42CFF26207DBD, C3F029FC8AE690E84FBD0EF806B801F3
+ 28: E051B958601223FECEADF932A277BCF18C25025AE4DA791155B85035, EB75E56BE7856F1B5ED3D125C092D38A
+ 29: AB3449537C5E22125BC32D483F74C3A3DBDBD5232839A85D300F65B4FD, 851B0FBABD080F783BDE4F47ADCD6D76
+ 30: 4E68550837130652795A8C9D68530717D2B0AA5A17F3AEF92FFB502E46AC, 10E222706527A64E757EDE4B9EFC09DD
+ 31: C2D7033DA7A1857D79497EA6C64779EB969046CCEE6C74E6592FEE6E7C94C4, 2015674ECA80AC9B67AE854E18A7D56E
+ 32: 2F3F0374DDC24AE21F02D4DA74D46C71F0CD2269A68F32F7FAA0BAB64AA8E9BC, 737C8BA1677A8CE97D42FBB07530EE99
+
+OCB-twofish (16 byte key)
+  0: , 2CD8EF22E5457C7FE4016B0FB82FD204
+  1: 64, EB7BB60E4932C0E97A7A5906BD044ACF
+  2: 3A59, E3D2024241666369BB542ED096F20C71
+  3: 67C038, 7E6F1EB3F2088F6416BB675DCAC0D484
+  4: BB36BF02, BDEEEF07EBB7A50A5201C8A2D72C0036
+  5: 6F06C0E293, C63557681D84ACCFFBFEE87D82EF1D3C
+  6: 2015F94CC5AA, EF1DEAD4134D2A1A47A20F26FAA3554D
+  7: A5F8CDD07964B0, 672B74D88C8AA7567C6AC4A896E0F6D1
+  8: 5EFC9D8C3B9E7F3F, DB9160C53AD429D4C22BC0E2E6C509C5
+  9: B62CB80F75594BC54F, 20020A798FF59F0472E750C796B5CC94
+ 10: 970983B0F889760EEEF0, 360AE43CEBCC27755548D4984CEEA10C
+ 11: 75C3A8CCB30A94CD57D1F8, 79820F3B1625E216B5BC1D1A22B198F9
+ 12: 033DA41CCBFE3C6897230FCE, CFE3EDD11627270CD63916508B058B7A
+ 13: 15358032F30043A66F49D3F76A, 98B8056A7991D5EF498E7C09DAC7B25D
+ 14: 71FBA7D6C2C8DC4A0E2773766F26, 22BA0ECEF19532554335D8F1A1C7DEFC
+ 15: BD761CD92C6F9FB651B38555CDFDC7, 8E3C7E1D8C4702B85C6FCD04184739E4
+ 16: EB6D310E2B7F84C24872EC48BFAA6BD7, 12DE548D982A122716CEDF5B5D2176D9
+ 17: 8DDF6CE25A67B409D3FB42A25C3AA7A842, 3E9FA2C6C65341A8E1101C15E1BBD936
+ 18: 5563DFC29B750FBC647E427C5480B65846DB, 90881C6820901BD41F7B3C2DF529B8A9
+ 19: 93343C1E9624321C2A0A155BA8B4E66FD92BE2, 71A641DDCD49825E10880D54BEF30E91
+ 20: C256BCA0CF0ACCEEC1AA4B9372AF27D2C3C65AFC, 91D45C4DA49BBAD1809A11F4041C7D09
+ 21: 3DE69FDB72C93518A3E317F7B26C425EE3DD42DA7E, 85E37B3E8EC3AF476DB7819D739D07D5
+ 22: 676AC7885C7C8FBE9862242FCCC46C181440EE49AE59, BCDB42B53AC4FDDF9C3BF8849AB96EEC
+ 23: D71B98B88F46CC47D90BB931564CDF0157F0ABCB5E6954, 289CD5799D9E49F36D70F67726A59610
+ 24: 669C16DB9DC175200C08476832155DAA52F1F8969DF3B79A, 835B210EBBE5C9D34C2E052E1843C1F8
+ 25: 2F39346E14A34BBED0491929CD9F1FB3CEC412C25AB703372A, DC4B42E8BA676BA100B87BEE328C5229
+ 26: 1FD0F8BD0AC95E91881635EB0CF0E4FB099CBB214CE556422E2D, 898CEB3CA8FCA565CE5B01EF932FD391
+ 27: 7FBD32B3D88B7E002BA6055585B5D0E1CC648315A81CFECA363CC8, 804820B1E3813D244164F778B9C2A8C8
+ 28: 877A5F336A1D33AB94751A33E285C21666F0D8F103AC1187FC205372, AF9F0AC165EAFCEE8C2A831608F166B4
+ 29: ECCA297705B0395E71B9E4263343D486B29207DA188C2F1BA626EDBF46, A05DC873406B236E4DDBC038DC4D2627
+ 30: FF3BD8D4E1108E98FBAE2E28BC12819CD7956BC491C0B3A291FBEE739599, 68DFE58473BA2818A23095D1D6EC065C
+ 31: F175230606040ADACEBAFE4D58BBD140B2D45E8BF7E5C904510B58E4B53D3F, DAF579E1A12481D39F4DCFB7C28794B1
+ 32: 261388D491EF1CB92C261FD9B91CAD5B95440DE0A747144EB8697699F600801D, 749056EBEAF4F20CD8746AA8C8846C47
+
+OCB-rc2 (8 byte key)
+  0: , 1A073F25FF5690BE
+  1: F4, 3D3221E92E40F634
+  2: 2C76, C22C20B7231A0DB9
+  3: C647CB, 3E6348D996399629
+  4: 2021891A, 8EF76B24E9D55FDA
+  5: 1966CBCBBF, 310D24024D573E8D
+  6: 42C15AC9AAF0, 217E83C0CDE4F077
+  7: AB70F3F73DF0B6, 16AB2679D96A591B
+  8: B7C7DD845D7E76DD, F33065EA531545CA
+  9: 468CC16A37CF63EA73, 88879733F70AE3D3
+ 10: 4F769E25A7346E22A932, 26E1A92FEDEE0597
+ 11: 304A8B53B1CD24C6C27C17, 48B46E9F091B0B2E
+ 12: 4E3DF867FEFF0B8E06D5FA70, 53BB48BFB8AB4750
+ 13: 2BAB3F0A8C38A3BD3C49DBBA5A, 52303CADCBB6D312
+ 14: 3D04A29924589AAEF93A29003EE7, 120EF9364B83748F
+ 15: 486127A80E4EC599C461451CF1D79B, 2245D51599CAD629
+ 16: AF8FB3FD2DB343F1AFF564FCBEA58785, 805BF441E660B0B0
+
+OCB-des (8 byte key)
+  0: , 8A65BD7DE54082AD
+  1: A8, 3A83897CC8EC7CF6
+  2: 9256, DC66C39C7DD87D93
+  3: C145A0, 45967F3764F62F48
+  4: CD314BAB, EF38B0213259C3D4
+  5: 7074014741, 6748F4BAF06DD7BD
+  6: 9A874CAE01F1, E382DB7235624104
+  7: DFA0D86DC4CA84, 627ABB432E50455E
+  8: 685C2B2CBDD8D144, D166082E085063BA
+  9: 53515DAAC7F7B8CE1D, 6680B6C26E1B0994
+ 10: 2B3967812BF4155A8D36, AFED7F38AFEFC543
+ 11: F4E5AC3CC5913B8A7F35FB, 6181DD3C46A6C24F
+ 12: F3EC89AD4235287D53715A81, 12CC354833FE5BD8
+ 13: 66D554AC2CA85C079F051B8459, 097F31088CFBA239
+ 14: 8746061C26D72771A7586949A3E4, 6CEF3565D0E45C6B
+ 15: FB3BCC650B29F418930A467EA4FB73, 64D12723E100F08B
+ 16: DE1C27E9B3C391AF5DF403291F2C084A, 6BADE4638AE46BE2
+
+OCB-3des (24 byte key)
+  0: , 9CB7074F93CD37DD
+  1: 4D, 51541A838A154E0B
+  2: 5C77, 60E86F2F1F4C6F96
+  3: B3D2F0, 7D74A9E6A061457D
+  4: B3556075, EAF7A89A07453460
+  5: 1B61CE7230, F90D18620E1AB877
+  6: 3987FEC8D0D7, B5EF04DEE2E528F9
+  7: EBD0A7EBEEFF3B, A72CA24DD77A5DDA
+  8: 429FB38DDABF76D4, D0578484C37227C8
+  9: F8DF28BF5C4CD28B1B, 5E7C4DC8E694E3B4
+ 10: 2BF436BBE063F7E830C2, 8D919637C973C71B
+ 11: ED21656C8878319F1B7D29, 8813280C1277DF26
+ 12: F45F90980D38EDF5D0FEC926, F9619341E273A31F
+ 13: 52F2D3CACC294B141B35D73BBF, 7BBC3F1A0D38F61F
+ 14: 2E6DA0FB55962F79B8E890E8DD8D, 8060799DCAB802E4
+ 15: D6F9A6B2420174C499F9FE91178784, D3AAF969ED2F7215
+ 16: 4F1CF285B8748C4F8F4D201C06B343CA, 203A2692C077F1B5
+
+OCB-cast5 (8 byte key)
+  0: , 77E8002236021687
+  1: 52, D57DF1037B6A799D
+  2: 31C9, 7E781759B057D695
+  3: 5C8324, 56965D6CB2C97C0C
+  4: 17D99099, 7C52B5D09475F5D3
+  5: 400082C475, 3CA5CDB9B4A0FAE9
+  6: 4DF0E4000C24, DCFEE2C3384F9731
+  7: 10004C3CE32255, 0A6832F985F61658
+  8: FFA6EA76B346893C, 6202693B153254D6
+  9: E96378C94D246AB51C, 5B259FEB715B9159
+ 10: A9BED2D59A92D3D9418A, 1E7E066C098A023D
+ 11: 4EF144B7D4622BAD4DC840, 5DAB2C1D0DF56B08
+ 12: 6DBCDF56E57CE47DD3D0CF44, 2A24F2A224368F55
+ 13: 43241A0AD933635D7C8EAD47DC, 86B4B5AC22177F19
+ 14: 920D6BDBE073F3C75052420C883D, 10943DBB23BD894D
+ 15: B2C75DF024269833B039CAB19EC865, 84B7DBB425E45855
+ 16: 6A9424B6A873BB7155C01DC87E23EC52, 82C5047655952B01
+
+OCB-noekeon (16 byte key)
+  0: , 72751E743D0B7A07EFB23444F1492DDC
+  1: 61, 41BDE9478A47B2B612A23752B5A42915
+  2: F4EB, 90EF542D89F867CDFB1A0807F8AA3CC6
+  3: F5A59B, 1BED873B613096546D4C201347CC3858
+  4: F454610B, FB4035F28AA75221F599668ABBE21782
+  5: 382FC932F1, B40270E2084E8DCEB14C6603D080D7C2
+  6: 18F921441119, 47F1F889B307298150750E81E94AB360
+  7: EF01C70C9D1810, AE0439DBB3825F27CF846B43E4C3AA80
+  8: 89863EDCAD471C3A, F4E8AF73BFC4CB79AECBBB3774DAF8C2
+  9: A6F494092E066A70F6, F73D3B04752B7D913420C17E656C7F86
+ 10: 342459682E0A8D53AF4F, 61E7CF14E9878E0726C64B1E8CA08BFF
+ 11: 65E520D5A99825DE2441D1, 7A2AA740D786EB7015C61B31959E55D9
+ 12: 2F96D0BB72E37DA202410302, 1A313242527FB522289094B9AFDB5F7B
+ 13: 3E8F8A1FCEE3F866EC29128BA0, B8065DA2DABF04129E5AE28ECC11A15B
+ 14: C2C15976D3C2499ACB9454878131, 372CAD486E104098EB1AA78A2922A1BE
+ 15: 1F12CADABAEE80E448B7EDCB42F8FE, 86A38DE5363787F55B16462C684E08DC
+ 16: 3B9ABB3304E75BF5B63E7F5B5A3F3980, 1FBD6B93E457B9779E2D12D78301EFA9
+ 17: DC0CD805E43675A4317452E378AD48AC4C, 40AE4AFA4B3E580EFDB4AD0AF5BC4E4A
+ 18: E9DD52EA7264C6C7BBA39B761B6E87B65687, 4061DD65D5E7FFFE8D3D4261494D4F8C
+ 19: 80A9735CA1175072823828123413CCE772D521, D3378A12E79C49A37378DF527A460AB2
+ 20: 09AD495AFFBF7CB8841262E7E5E8952878D4391A, C25D7A98C6F260B5FBCA3B8B5F7F33C1
+ 21: 3925615707CC40C351D4A49794778545BC1F683175, 97622437A7208383A4A8D276D5551876
+ 22: 5BB0D41ECD7BD2CF0B12A933255D95A3FE35E4C896BB, 4B8AD84EEA3156765A46AC19C68B6F88
+ 23: 1EE71FE23CBFD5683AB1B391FC12B4E5952E4E6AA3D189, B0FD75996F28E071EB6C86BD7102BAA5
+ 24: 0AA3D8C98AADEEE1867B13B017DD263BD16E960DA64FD071, 5204780963A62C2F4F7B3555BFF73836
+ 25: 3A88B6F2AE321B226DA90B98E04A6A1589411BEDBE994632D5, 5638AF04EACF1EB986AC0702B4373A22
+ 26: C2731661AC634A4DC0345F040DA7AEE507A3B9D019B5958543BA, 4C67D3FE37ABEE928B3BB812E7346823
+ 27: D3E7651AA6DA035D05D599EFB806E8FD45177224593B5974758419, 5814E84258E1B9BD56A188AAE6F25138
+ 28: 17818E7102B8C123230C5D64F18BE94C3159B85C8F7B64A7D4712CDA, FAA905B587A93DCF600BA8589A985432
+ 29: BCA4335C6C29D978032C216114D39C01C6F161BF69D5A1CE55FBA8C575, BE24424A162E43A19755E2EFD274DBED
+ 30: 24C33CEE022F8A633DE9DFD009F535B52BCF64F390D2375E5BED65B70D08, 138F21D54B6B7E34628397DCDE0D33BF
+ 31: 838FE950C8165ADBBD6B61E9732F9A727CA7AE74376981382F0C531C331915, 0742E769CCBA2D1CAC7CAD4E0F012810
+ 32: 57CD778DAD477271794FBF763662D97F8A10B17D70A69FDCB974FFE67E558519, 942C7D1C200C3845748F8131DF71AE26
+
+OCB-skipjack (10 byte key)
+  0: , 90EAAB5131AEB43B
+  1: 2F, 6274B82063314006
+  2: DAF6, 6A6BCCE84FD4EF02
+  3: 5C2A88, C83D54C562A62852
+  4: B6E8FB5E, C44459EF41C8F296
+  5: 6C0888C119, 269DD7657BD0225F
+  6: 1FD9AD7ECCC3, 3CA090F46B107839
+  7: 1EDBFF8AE458A3, 440380BF9745132B
+  8: 04DBECC1F31F9F96, 2653620A4877B0E6
+  9: 908AE5648AF988A896, 00180FF33C1DD249
+ 10: 53E63E0C297C1FC7859B, 36616209504C4230
+ 11: 407BE16144187B4BEBD3A3, 4754B7DD4DB2927B
+ 12: 9961D87CFEDDF9CC22F2C806, 5947FC41E6B9CEC9
+ 13: 9F5254962E4D210ED8AC301252, 97A392BEAF9B3B04
+ 14: 379FDA76ECCFDAAC10F67FBF624C, 1D895ABD932BD5EC
+ 15: 1D5A7AD556FF3078284BB21A536DAA, 01FAE2F4936ED9D2
+ 16: 4B8B71396924880CB33EA6EC6593F969, A0F4B1BE3B9B4CCE
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/omac_tv.txt	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,331 @@
+OMAC Tests.  In these tests messages of N bytes long (00,01,02,...,NN-1) are OMAC'ed.  The initial key is
+of the same format (length specified per cipher).  The OMAC key in step N+1 is the OMAC output of
+step N (repeated as required to fill the array).
+
+OMAC-aes (16 byte key)
+  0: 97DD6E5A882CBD564C39AE7D1C5A31AA
+  1: F69346EEB9A76553172FC20E9DB18C63
+  2: 996B17202E2EDEBD63F414DD5E84F3AF
+  3: D00D7DA967A2873589A7496503B3DBAB
+  4: B43C24C0A82DAA12D328395C2ABD7CAE
+  5: 9B902B6663B5FEDC6F9DCE74B35B91F2
+  6: 06A9678C65D7CE225E082ECA31788335
+  7: 7D67866CDB313DF65DED113DB02D6362
+  8: 259E28CF3E578AC47A21A77BA9EA8261
+  9: 32F23C8F93EA301C6D3FE0840CA8DB4B
+ 10: C2B06388AD6F8C43D19FE4F6A8ED21AE
+ 11: FA8622485DB2F62F84FF46E532A1A141
+ 12: F312D9B2E6272578F406B66C79F30A0E
+ 13: 7A5DE06B2BFB75ADA665E96F680AC098
+ 14: C3B00380F0BD8E2F5C9DD9945E0F36EE
+ 15: DDD87974A5FB2E7A4514241E94526B5B
+ 16: AD24FC47A0FEA84C54696DE997A94F4B
+ 17: 7538713D8AA2AE3726307EFF087BBF5E
+ 18: 7619A52B4C34A98440812F5F28F8DC4F
+ 19: 7E797B8846554888622CC5E400B2FA44
+ 20: 61E8DD3E09145F5657DB4B8F7BD2D7D8
+ 21: FDAE2A3FE60DDF1871C2613A293AB6F1
+ 22: A186D6EFD10DFFD2C088480B0A784185
+ 23: 3119D337865618CDA55C06FB992427CF
+ 24: 413E3EAD7E3F169A37C49F9CA92E235E
+ 25: 37A55AF22373B9A1E2F8368B2FB992CA
+ 26: 4941F604C40EEEE1A16CFE073C12D1FE
+ 27: 3E8F4A0876BF12A2DCA87157F15DC884
+ 28: 5DFAE292D8EEB13D8FE5725E5D169742
+ 29: 59160455E0C0B35D950BA67C77F9FB05
+ 30: 5AC0D736A06A7DD146B137ADEE78EE06
+ 31: 0CA1178F28B953045EE76E2E760036CA
+ 32: 025616215F870D1EF838AD1D2AE0C649
+
+OMAC-blowfish (8 byte key)
+  0: 2CFB5DE451FFE8CC
+  1: A5AC339DB44D020C
+  2: A3CE0CF62249444D
+  3: 3076B7129CE3F6A1
+  4: 9E091A637DDF70E3
+  5: 275199AB20A5F09C
+  6: CDEDA8D16A401E62
+  7: FC980516CF5C9E30
+  8: 659D0B31D21B622B
+  9: 8306847B5E72E018
+ 10: 7AD029BBF1D2919F
+ 11: 133181425C6808C9
+ 12: FC5AC60E367F413A
+ 13: E0DF8BCCF0AD01D9
+ 14: AC5015398FA64A85
+ 15: 1F068F22AFFECEE1
+ 16: 8E6831D5370678EF
+
+OMAC-xtea (16 byte key)
+  0: 4A0B6160602E6C69
+  1: 1B797D5E14237F21
+  2: 938300C83B99D0AC
+  3: F989B99B3DE563C6
+  4: F65DEA2A6AD45D1E
+  5: 1DB329F0239E162E
+  6: C0C148C4EE8B4E1F
+  7: D82B387D5DFFE1FB
+  8: 1D027A4493898DF2
+  9: 196369F6B0AF971A
+ 10: 2A37A2655191D10A
+ 11: BD514BE32718EB4A
+ 12: B4DBC978F8EE74ED
+ 13: 8ACCAD35C3D436AE
+ 14: 73ABDC1956630C9B
+ 15: 73410D3D169373CE
+ 16: 23D797B3C7919374
+
+OMAC-rc5 (8 byte key)
+  0: E374E40562C3CB23
+  1: B46D83F69233E236
+  2: 7CB72B1D335F04B0
+  3: 94457CBC97B31328
+  4: 543D0EDFCDCD7C76
+  5: 5164EFA8412EAA5D
+  6: 13CA0717EF95F9A7
+  7: 2AA49A7AA7719700
+  8: C9E7C56125C3D90F
+  9: 2BE3E15FE58648AA
+ 10: 77D0B90372D6D0FD
+ 11: 17408F62ECD62F57
+ 12: 7864EFFA59DC059B
+ 13: 3212E76E25E5DEA8
+ 14: E2424C083CDE5A6A
+ 15: DE86FFDBDA65D138
+ 16: 85482C24D61B8950
+
+OMAC-rc6 (16 byte key)
+  0: E103BD8BA47B7C1C010E1561712E6722
+  1: E51AEECFED3AF40443B3A1C011407736
+  2: FA6506C5ABE03381B045D28D1D828966
+  3: FAC4237FFE7772E2299D3D983BB130DD
+  4: 3A7E24D41121A5D4F96FCECF0C2A4A10
+  5: AA44291E5500C1C8E1A14CB56E4F979A
+  6: 4B8FDA6DA6B3266E39111F403C31754E
+  7: 4DF5F1A1C8EBC7F56D0D12EEB63FF585
+  8: 46A6DDE419355EDE14D31045FCA1BA35
+  9: 71756D4D3DF59578B7F93FD4B5C08187
+ 10: ADA292A19F8636A03A8BC58C26D65B0D
+ 11: 703190DAF17F8D08A67A11FDF0C2A622
+ 12: D2B94CAD1AFC5CD012575964D1425BE6
+ 13: 45FD0069FCA6F72E23E4DB41AA543091
+ 14: 36F652600F5C9F226721400A7199E2BA
+ 15: E8CC6389ECF8EF1DBB90A0FD051B7570
+ 16: 8125446B975DBDA742A903340D6B96C7
+ 17: 00B55E4399EB930E592F507F896BF3DC
+ 18: 33E58F42A47C9543A851D6CA9324FEE0
+ 19: 9F28FDEA3EC7F515128F5D0C0EB684C5
+ 20: AC1DAF6C01AA28BCC0A819189FA949D7
+ 21: D0532B5F54A179444D052A4D2AD6E4F9
+ 22: 58B80A66549404C7B9F64D5AE3F798AB
+ 23: D0D6D586477F92311DDF667E0749D338
+ 24: 0DFC0FAA67FF114398CE94D0688AE146
+ 25: E163B8C00CF5CC9FA23ACACD62B53D64
+ 26: ACE9270456AF9BD388BA72E98825CFE8
+ 27: 4302EED9BAA19C7A296585E23A066A44
+ 28: B3EEABEFAB25C7478419265564715387
+ 29: 9F0630ADE9C74AB2981D63F3B69E85BF
+ 30: 1215A9446A275CCE2714F94F3C213BB7
+ 31: AF43D7F748DE0E3458DB970BAC37E98D
+ 32: BF871AC9E892CE0DCD7C8C7ADDD854C6
+
+OMAC-safer+ (16 byte key)
+  0: A2C8C7FEA5529D01C3FF4E9359EF74F4
+  1: EAB87021118FF24FE79B69ABCCB14A8F
+  2: 789566F467BAA68F4CC3C4B61901D6D4
+  3: 369F41EEAF7D628F9E0D77BE43BFC1D2
+  4: DC46A20E1F36F45006ED5B43BEC20DA6
+  5: 8F150CE34F57BBA2E6CE3431B78E4ACD
+  6: 61CD154478BE20F33B26CD8FC58091A5
+  7: 4E6DAA575CF28F1F48B256262B7D558C
+  8: D21FA4F1859571DB91E92767C5487AA2
+  9: E3D009DC7E71FBBB030B8FF0B544A2C9
+ 10: 094C236EA48ABF7DBAE5A88AA3DE07D7
+ 11: 00C401996F8224359566660AC1CEDAA1
+ 12: D580EC60F712558D875F01643D96653F
+ 13: 8482298027C7B4D5969787A1DB1B1F2F
+ 14: AB726AE3DA95CB242E63EF876A4BC446
+ 15: D668ED4919003F5E45590663FAED41DA
+ 16: E4CFFD7E0E7B176867C386001849FD6F
+ 17: 37B3C6DEFC5573879006D15F982A397C
+ 18: 0AB8847EE6A41A0E960080EF0D1BF1C5
+ 19: 2C94FCA2A685F276A65ED286AE12FD9F
+ 20: 23383032032D7B5165A31ECA156DBD23
+ 21: E1EECFB3D671DF694FFB05AE4305AD4C
+ 22: A0F6CA99B96CD1EDD04C52828C8A4D74
+ 23: 12D6B7053417AF3E407EFD6EE1CC38FE
+ 24: A566D1C39AE7A1A0A77D5A1F56C5FAAB
+ 25: 81C9FAECEAEA326140AFCD569668F669
+ 26: 6A00BF1D0DC893868378E4347CB4A1B9
+ 27: 98842956DBE7AFB1BF49C46497BD54C7
+ 28: 88EFCD5A1644B75BB0B3F5DD338849CE
+ 29: 77EC62C278C61163B1BEC595A11F047A
+ 30: 147424E817DC69413CC657E0CB292F7F
+ 31: A2946CBB910743EF62D8A3C7391B9B9B
+ 32: 00EEDA55520B8A5B88B76487E80EB6E1
+
+OMAC-twofish (16 byte key)
+  0: 0158EB365FCCFDD94EBA6BE42B6659C4
+  1: 17DA580917D147D10CB73DB6800B0E59
+  2: 3F185CC15EF3328D3E075665308C07C8
+  3: 5712A97ACC9D08FE9D2087D0CA16B0AD
+  4: 90425A8CC1C026DDD896FC2131AF654B
+  5: 30A43D4FEAE71F5396308C16DA081B4A
+  6: 6839FEF605704D49F1A379A9E9595E6F
+  7: 56A8F06DFEE543971B351B07430E2026
+  8: 36DD0E4B55C5314F9F2753D7EB6F0849
+  9: 8E319249A3CD456460F410F518F8CEDB
+ 10: 463978BE2A063C22E71DC71520723517
+ 11: 1B735E45FD3DF636E0A6104D4A2E9CB8
+ 12: 628A82213148AD9791153D5AAFBDDFDC
+ 13: 21AFDF08A36ADB6659B656C8EA0800E5
+ 14: E5C3E58803DDBE174E0D4C2B8171AEF0
+ 15: FC6981F2B4359BA05988D61822C0FA88
+ 16: 7B03498FAFB04A6542248852225F9DAE
+ 17: 9B173E91E59A940186E57BB867B8307B
+ 18: 470BF2EE614C8423AA3FDF323F1C103E
+ 19: 6E664AFDFD8306547BBEDA036D267B79
+ 20: F61AEC1144C3DD646169E16073700AC6
+ 21: AE503B139707AFA494F7F2DE933EE81A
+ 22: A0A8BDD4ED0DCAE4A8E1DCEE56368FF0
+ 23: 460B8207930DA434AE6AFECC305D9A26
+ 24: 7F03F8C7BA5365CC65F7864A42693BC8
+ 25: 31448849D6190484192F29A221700011
+ 26: BDA941019C75551D858F70FB1362EB23
+ 27: 2880CB3E62447AE8EACA76C17971BB18
+ 28: FC8D710FA3990B56357E61C2A302EB84
+ 29: 793CD15348D7DFF301C47BC6E6235E22
+ 30: 6FB0CE69A15A3B6A933324A480077D35
+ 31: C24FCA5DD4AE0DF2BFF17364D17D6743
+ 32: DC6738080478AF9AF7CA833295031E06
+
+OMAC-rc2 (8 byte key)
+  0: F001FE9BBC3A97B0
+  1: 8F8DC9C952897FBD
+  2: EC82EAD195AAC38C
+  3: 53DD52269B19E9A4
+  4: 9B86F64BF72A0647
+  5: 664A88A29F2898C6
+  6: AFEC3F71C1415666
+  7: 9BA1F2C1A2E765F9
+  8: 402A12120908B436
+  9: 03ECCD4C6AF44144
+ 10: E8CA3529B5D9D6FC
+ 11: 951EE10779CC585D
+ 12: B9083CA88E7E819B
+ 13: AFFB9E884DACC5B7
+ 14: E942E8BC241343D6
+ 15: 9B190489091344FB
+ 16: 9330A9E05554A15A
+
+OMAC-des (8 byte key)
+  0: C9085E99D74DF01D
+  1: FAC84F0EFBEF8630
+  2: C37C5FECE671CF16
+  3: 45B2CBEE8701A5B1
+  4: 53665E1F024EB001
+  5: 357123CEDFC9FF61
+  6: BD2CFD33FB1F832B
+  7: 1AAA9D8C9120BDBF
+  8: EB9F589AE9D4E78F
+  9: C8F9D2ACE691922D
+ 10: 81ED6F3611DDC0FD
+ 11: 2965ABEAC46839EE
+ 12: 2208B1E095F7AE2E
+ 13: C0414FE41800113E
+ 14: 653A24119CF43D97
+ 15: 7FB7CE0862958B37
+ 16: 55097816B10C549B
+
+OMAC-3des (24 byte key)
+  0: 7F07A9EA8ECEDF9E
+  1: 4E2A652EB5FBF5F8
+  2: 4F84E3779ACCB9F5
+  3: 7134AB3463115DC6
+  4: 82327BE8EA2D7E0B
+  5: 24950B9C14D87CD9
+  6: B25A097BB7E0E18A
+  7: ED51BAE55ED925E7
+  8: 56B79E7644556975
+  9: A65BD98E4D4E31E2
+ 10: 11145BB51514482D
+ 11: 397486787E676BA6
+ 12: BD1F6DEBAF6D9AEF
+ 13: 5CC3921F7DB815CF
+ 14: B0C0E60DA5F727F3
+ 15: F8637AEEFF10F470
+ 16: 0EA19531D42706EA
+
+OMAC-cast5 (8 byte key)
+  0: 7413DCDB9F0C3100
+  1: 423799EDF1472B79
+  2: 03856F0CB4F11606
+  3: F152AE6360813DE0
+  4: 853998BD980AD146
+  5: AE6C3D667DB8B414
+  6: B5A4986A34BDE20F
+  7: E5ABE5B979798942
+  8: BEE8DFED4555F405
+  9: 6B5339E952AF61BE
+ 10: 5E867CF34D9C1149
+ 11: F9C55CB3BC655E08
+ 12: EA09A2929AC7D915
+ 13: CE8EB0E4370E1933
+ 14: 749A424B2AA91B98
+ 15: 8DDA93C2B814D5D1
+ 16: E8B0B219D4CB699B
+
+OMAC-noekeon (16 byte key)
+  0: EC61647B281C47C1B43F9815064BF953
+  1: B100B1B6CD96DCED8F47A77E70670A92
+  2: A96CDE3C48831A6B0A5ADFECA6399BDB
+  3: 14E75E7CAD840208834918B29A5D4430
+  4: 9577083713AE6E44EEC987C77C93C072
+  5: 2A738C02841E461238C02F5CFC8E66A6
+  6: A901327E451BE0D2D9DEC83DEEA9A022
+  7: 5ED7EE1BE04A64A689D15F6970A821A6
+  8: BA053E24FCFD02C731A8CFCA19EE66A0
+  9: 57139CA8C91072555B29F85A19E2C84D
+ 10: 4585EAC7EFB84869FD96EE7A5FDD350B
+ 11: 62AF6C415CA73E54E82EA306254C1BDE
+ 12: 75304F9724BD364F84371EE154F5210E
+ 13: 7FE5DBCEE826760434745D417453182B
+ 14: EC98DA2A580E9131218D1CDE835423D4
+ 15: 631BD9EAFD1AE445F2C1C35E2B4416ED
+ 16: CA2D902A1D83388FE35BAB7C29F359BA
+ 17: 0DBF0AF7FCBEEE21FB6159C0A2FFCD4C
+ 18: BD7CD2C49241032DA33B1975EE2EE982
+ 19: B30B090EE8626D77D310EDB957552D46
+ 20: 64F608AC5707C381AC6878AA38345144
+ 21: 28513CA7795B23A02B37DC3732413D23
+ 22: 9F440700094517847E9E013C8915C433
+ 23: 8CA483F313D20BFE7E0C089DAA4145BD
+ 24: FA44872743E20E5E0A069B3C4578DB50
+ 25: F6DE8FFBECD52CC1F213CD9E406DF3BC
+ 26: B9702B7E846735A3DCC0724255F88FEC
+ 27: A1DDAFED2B1732C7BA89C2F194AF039E
+ 28: 2549C5F0E30F8F4002431D2C098805B8
+ 29: 52E3836181BF5C9B09A507D5330CD14F
+ 30: 01C55DCBCCFD9D7A4D27BDE2A89AA8EF
+ 31: 3CF721A0CF006702CDA91F2FF3E4D5E3
+ 32: 6D264B9065BE98C170E68E9D2A4DE86E
+
+OMAC-skipjack (10 byte key)
+  0: 84EDFA769040603C
+  1: 7DA58A4CBD642627
+  2: 118F60115CFC8229
+  3: A7F7346D34DB2F0E
+  4: 35615CCD526CD57F
+  5: DE471601A3660844
+  6: 15FCCE6D6D883D1F
+  7: C6F694861233151B
+  8: 3B762B397F16E807
+  9: 976C6AB59FB3AB12
+ 10: 6810791F2C595961
+ 11: 7FA3478286917F17
+ 12: 73DEE44A51C6B610
+ 13: 89EE8B253B1ACE81
+ 14: CDF2586A56C8A0B5
+ 15: ED91F98DA98F42C4
+ 16: D8D0FA5CE96B08BF
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/pmac_tv.txt	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,331 @@
+PMAC Tests.  In these tests messages of N bytes long (00,01,02,...,NN-1) are OMAC'ed.  The initial key is
+of the same format (length specified per cipher).  The OMAC key in step N+1 is the OMAC output of
+step N (repeated as required to fill the array).
+
+PMAC-aes (16 byte key)
+  0: 4399572CD6EA5341B8D35876A7098AF7
+  1: 580F7AA4AA45857C79BA2FB892228893
+  2: 24D2D1DBABDB25F9F2D391BB61F4204A
+  3: 083BF95E310B42A89751BC8E65ABA8B5
+  4: 69BEB9268CD7FD3D7AB820BD7E226955
+  5: FD71B0E647ADB4BB3F587E82B8B3401A
+  6: 07EA46271081840737CEB1AC9E5E22E3
+  7: FFA12AD9A9FDB5EE126084F82B381B10
+  8: 8A11AF301AAFEAC8A75984ED16BB3292
+  9: 368BDC3F4220E89B54C5F9D09FFB8F34
+ 10: 8B6DBFF776FD526147D1C4655626374F
+ 11: C538C09FC10DF38217CD8E799D8D1DC9
+ 12: FC1264A2051DEF73339432EA39443CFD
+ 13: 8AF37ED2FB2E8E30E9C4B75C1F1363E1
+ 14: 4295541FC62F6774068B8194CC9D9A46
+ 15: CFAF4D8EA09BB342F07131344DB0AA52
+ 16: B6CBD6E95959B2A8E22DE07E38B64D8D
+ 17: 3124E42DE3273B0F4806FB72A50F3E54
+ 18: 252D49403509B618AB3A6A1D99F9E9FA
+ 19: 9CDA75594CB696EB19C022DDA7324C10
+ 20: 33BB8AE43B7BC179E85F157FA19607D0
+ 21: 12FE91BCF2F2875379DC671C6F1B403E
+ 22: 416A3E519D1E406C92F8BB0DDBBBB6BF
+ 23: 6F98DCCD5A8D60DEAF612ACCEDD7E465
+ 24: FFCE7604609B2C3C050921854C638B7E
+ 25: DD2BB10AA07A5EC8D326BB7BF8D407F4
+ 26: 468BFE669FCDF354E4F9768FE1EAF8F6
+ 27: 01724D2F2C61EB4F380852218212E892
+ 28: 2D90EC658F57138505598C659C539A3E
+ 29: 6301EAA0E1500FFEB86752744EFFF23D
+ 30: 3CCB177486377616056D835F6F857F7C
+ 31: BFB3C7755C1F4543B516EB8610CB219F
+ 32: D5C505847D7CFFD8CED848F6CB613105
+
+PMAC-blowfish (8 byte key)
+  0: 3B7E4EFE92FA46AF
+  1: 746840017C38C892
+  2: 3B6A92C731465B64
+  3: D89D3B05143B6704
+  4: 43F70D54B808B7CE
+  5: 84E4063AB32F046C
+  6: A7E78CD5CCD23805
+  7: A78FB083475FEF10
+  8: D4F6C26B5386BA25
+  9: 184768A079853C90
+ 10: 0702E6C8140C5D3B
+ 11: 786D94565AA0DF4B
+ 12: F6D36D3A2F4FB2C1
+ 13: 7BB3A0592E02B391
+ 14: 5B575C77A470946B
+ 15: 686DAD633B5A8CC3
+ 16: BDFE0C7F0254BAD5
+
+PMAC-xtea (16 byte key)
+  0: A7EF6BB667216DDA
+  1: B039E53812C4ABDC
+  2: 87D2F8EA5FB6864D
+  3: F85E3F4C1D9F5EFC
+  4: 4EB749D982FB5FE2
+  5: 0BFA0F172027441A
+  6: FF82D01F36A6EC91
+  7: 3BC2AA2028EBBD7A
+  8: 15AA03A97A971E2A
+  9: C974691F5D66B835
+ 10: 4FC7AA8F399A79ED
+ 11: 2633DA9E94673BAE
+ 12: 82A9FD48C5B60902
+ 13: 31BF6DA9EE0CE7E4
+ 14: 26B2538601B7620E
+ 15: D103F3C0B4579BE5
+ 16: 031346BA20CD87BC
+
+PMAC-rc5 (8 byte key)
+  0: C6B48F8DEC631F7C
+  1: F7AA62C39972C358
+  2: 0E26EC105D99F417
+  3: 7D3C942798F20B8C
+  4: 415CDA53E1DE3888
+  5: A314BA5BCA9A67AC
+  6: 02A5D00A3E371326
+  7: E210F0A597A639E5
+  8: D4A15EED872B78A2
+  9: AC5F99886123F7DC
+ 10: 69AEB2478B58FFDF
+ 11: 8AB167DFC9EF7854
+ 12: 945786A136B98E07
+ 13: F3822AB46627CAB5
+ 14: 23833793C3A83DA9
+ 15: 70E6AB9E6734E5A6
+ 16: 0705C312A4BB6EDE
+
+PMAC-rc6 (16 byte key)
+  0: C7715A17012401DE248DC944DEEBD551
+  1: 5B804C6CCDF97BB28811C9ED24FE6157
+  2: 7528378C052F4346253CB0DFA3D251C7
+  3: 6DA86EE0B28606861B1A954D7429A93C
+  4: B4DFF84C25937FB50EE79D4037323160
+  5: A60FD9BE5E1FF67EC9734776C8781096
+  6: 81D3F8EDC0A197DD3739EAE648F38580
+  7: 8BAF47F02120E898916D678DBD0C1641
+  8: 7A9EEC96F10B7CF557B61EF35BB55B08
+  9: B88C11221014F8AE048E56C427DF4A46
+ 10: 4BBA8EED89F357861A265006816D9B04
+ 11: 8497C1D55010A65ED8C3688B75A7CABF
+ 12: 95E1720C06A373CAD1A22F432F26BCCA
+ 13: A175FB732692831E96AFB587BC49E18C
+ 14: 54EBC04FCFD90302907BF77C4D8AC77C
+ 15: EA9F13EE5548CDF771C354527CDDA09B
+ 16: 4EDBCFD0E2E6B321530EB31B3E8C2FE4
+ 17: F412304C1A5B9005CC3B7900A597DFB5
+ 18: 3B9247C12BB25DF048BF5541E91E1A78
+ 19: 39626488635D0A6224CD23C13B25AE8E
+ 20: 40305F5C2FCEF34E764E33EF635A3DC5
+ 21: F84499804086033E85633A1EF9908617
+ 22: C4D263CDC7E0969B8AC6FA9AD9D65CB8
+ 23: 6137DC840E61EA6A288D017EFB9646FC
+ 24: 8619960428EB29B1D5390F40173C152F
+ 25: F0464509D0FBDBECEC9DFC57A820016D
+ 26: 630EED23E87059051E564194831BAEF6
+ 27: 4B792B412458DC9411F281D5DD3A8DF6
+ 28: F2349FA4418BC89853706B35A9F887BA
+ 29: FEAC41D48AEAB0955745DC2BE1E024D5
+ 30: A67A135B4E6043CB7C9CAFBFA25D1828
+ 31: EC12C9574BDE5B0001EE3895B53716E2
+ 32: 44903C5737EE6B08FD7D7A3937CC840D
+
+PMAC-safer+ (16 byte key)
+  0: E8603C78F9324E9D294DA13C1C6E6E9B
+  1: 3F1178DFC2A10567D4BCC817D35D1E16
+  2: 27FE01F90E09237B4B888746199908EE
+  3: 4F5172E3D8A58CD775CD480D85E70835
+  4: 74BED75EFAAB3E8AA0027D6730318521
+  5: 54B003AB0BE29B7C69F7C7494E4E9623
+  6: 8A2DAD967747AEA24670141B52494E2F
+  7: 69EB054A24EE814E1FB7E78395339781
+  8: E59C2D16B76B700DC62093F0A7F716CC
+  9: AB227D6303007FD2001D0B6A9E2BFEB7
+ 10: AE107117D9457A1166C6DFD27A819B44
+ 11: F84DE551B480CED350458851BAE20541
+ 12: B0EB5103E7559B967D06A081665421E0
+ 13: CDB14F3AD1170CE8C6091947BE89DE7B
+ 14: 24FA2F476407094152D528FCF124E438
+ 15: 440144B31EC09BD8791BFE02E24EA170
+ 16: 697D268A46E8B33CEC0BAB8CAF43F52D
+ 17: 587CBDE7608449BD162184020FBFCC8D
+ 18: 3EA999C2169CC65735737F50FCD7956B
+ 19: C6D692698CD8BEEBF2387C6A35A261B0
+ 20: 46DAB3AD3C4E2EF712FAC38F846C63E1
+ 21: 7261E68B530D10DDC9AD4C9AB5D95693
+ 22: 4D0BA5773E988C2B7B2302BBA0A9D368
+ 23: 8617154626362736698613151D1FD03A
+ 24: 23CF25F68B281E21777DC409FE3B774A
+ 25: CA626956C97DC4207D968A8CC85940B8
+ 26: 24C39BE160BDBB753513F949C238014E
+ 27: 83CD65C010FB69A77EEDEA022A650530
+ 28: 1A72DC8438B927464125C0DFEACDE75D
+ 29: 546054936A2CB5BFBB5E25FFD07C9B51
+ 30: 0EB81A268F1BB91997CB9809D7F9F2AD
+ 31: 7D08B4DE960CADC483D55745BB4B2C17
+ 32: FD45061D378A31D0186598B088F6261B
+
+PMAC-twofish (16 byte key)
+  0: D2D40F078CEDC1A330279CB71B0FF12B
+  1: D1C1E80FD5F38212C3527DA3797DA71D
+  2: 071118A5A87F637D627E27CB581AD58C
+  3: C8CFA166A9B300F720590382CE503B94
+  4: 3965342C5A6AC5F7B0A40DC3B89ED4EB
+  5: 6830AB8969796682C3705E368B2BDF74
+  6: FF4DCC4D16B71AFEEA405D0097AD6B89
+  7: ADB77760B079C010889F79AA02190D70
+  8: 5F2FCD6AA2A22CEECAA4671EE0403B88
+  9: 70DD6D396330904A0A03E19046F4C0BF
+ 10: 8A2C9D88FA0303123275C704445A7F47
+ 11: BA0B2F6D029DCD72566821AB884A8427
+ 12: C8DF45FF13D7A2E4CFE1546279172300
+ 13: 512659AD40DC2B9D31D299A1B00B3DAD
+ 14: A8A0E99D2E231180949FC4DFB4B79ED4
+ 15: CA161AFB2BC7D891AAE268D167897EF2
+ 16: D6C19BBDFFC5822663B604B1F836D8BD
+ 17: 4BF115F409A41A26E89C8D758BBF5F68
+ 18: 02E3196D888D5A8DE818DBCBAD6E6DC7
+ 19: 995C9DD698EC711A73BD41CAAE8EB633
+ 20: A031857FADC8C8AFEABF14EF663A712D
+ 21: 124695C9A8132618B10E9800A4EFACC5
+ 22: 997E5E41798648B8CE0C398EF9135A2C
+ 23: 42C92154B71FB4E133F8F5B2A2007AB2
+ 24: 945DC568188D036AC91051A11AC92BBF
+ 25: D5A860CC4C3087E9F4988B25D1F7FAAE
+ 26: 6CD6ABF8EDF3102659AFFBE476E2CBE8
+ 27: 45ECD0C37091414E28153AA5AFA3E0B2
+ 28: CBA6FE296DDE36FE689C65667F67A038
+ 29: C4022281633F2FC438625540B2EE4EB8
+ 30: 864E27045F9CC79B5377FDF80A6199CF
+ 31: 0D06F2FAEC5AA404A4087AAEBC4DBB36
+ 32: 0F396FE9E3D9D74D17EB7A0BF603AB51
+
+PMAC-rc2 (8 byte key)
+  0: E5AF80FAC4580444
+  1: 6A15D6211EB4FF99
+  2: DDB95E9486C4B034
+  3: 9764761DC2AAD5C0
+  4: 1B1CD2E799D44B4F
+  5: 4F80FE32256CF2EC
+  6: 7B70CF31C81CD384
+  7: 9BC10DD9332CF3BB
+  8: 628189801879FDD8
+  9: 5FC17C555E2AE28B
+ 10: E20E68327ABEAC32
+ 11: 5D375CA59E7E2A7C
+ 12: A9F4CFC684113161
+ 13: 3A0E069940DDD13C
+ 14: EAC25B6351941674
+ 15: CB8B5CF885D838CF
+ 16: DCBCDDFC06D3DB9A
+
+PMAC-des (8 byte key)
+  0: 086A2A7CFC08E28E
+  1: F66A1FB75AF18EC9
+  2: B58561DE2BEB96DF
+  3: 9C50856F571B3167
+  4: 6CC645BF3FB00754
+  5: 0E4BEE62B2972C5A
+  6: D2215E451649F11F
+  7: E83DDC61D12F3995
+  8: 155B20BDA899D2CF
+  9: 2567071973052B1D
+ 10: DB9C20237A2D8575
+ 11: DAF4041E5674A48C
+ 12: 552DB7A627E8ECC4
+ 13: 1E8B7F823488DEC0
+ 14: 84AA15713793B25D
+ 15: FCE22E6CAD528B49
+ 16: 993884FB9B3FB620
+
+PMAC-3des (24 byte key)
+  0: E42CCBC9C9457DF6
+  1: FE766F7930557708
+  2: B9011E8AF7CD1E16
+  3: 5AE38B037BEA850B
+  4: A6B2C586E1875116
+  5: BF8BA4F1D53A4473
+  6: 3EB4A079E4E39AD5
+  7: 80293018AC36EDBF
+  8: CC3F5F62C2CEE93C
+  9: EE6AA24CE39BE821
+ 10: 487A6EAF915966EA
+ 11: D94AD6393DF44F00
+ 12: F4BFCCC818B4E20D
+ 13: 2BE9BC57412591AA
+ 14: 7F7CC8D87F2CDAB7
+ 15: B13BFD07E7A202CB
+ 16: 58A6931335B4B2C2
+
+PMAC-cast5 (8 byte key)
+  0: 0654F2F4BC1F7470
+  1: 3F725B162A1C8E6B
+  2: BCFBDC680A20F379
+  3: 027922705BCACDEE
+  4: 44E2F4BE59774BA4
+  5: 3ABD1AFC8EE291F7
+  6: D96347E717921E96
+  7: 96257299FCE55BC6
+  8: C2C1DA176EE98170
+  9: FD415C122E604589
+ 10: DCBCA228D45AEDA4
+ 11: 7801FBCFAAB9DF75
+ 12: D38CB38574474B7F
+ 13: F5C5A23FF3E80F37
+ 14: 83FA4DAD55D092F5
+ 15: BDC0A27EE0CB1657
+ 16: 87D907CACA80A138
+
+PMAC-noekeon (16 byte key)
+  0: A1E4C84B5958726557DF0855B37AA551
+  1: 5DE20299CA919D3365B493D3D4895F92
+  2: AF7E70C336571A857F62A18649EDB197
+  3: C5F55CFE1AA119C352B64252AD246CBD
+  4: FEF68A0CE08E8BA315B73B62F861824F
+  5: 8321C2958DE4903DC12C42A8845ECC20
+  6: 370466D1324AECF1F5B42E0E01381613
+  7: 5CB900190F5CACBACFE5EAB0CC289D87
+  8: A13C043E6CAAA1E34601A93C497446A4
+  9: 865E11622A4CC8A9E1408E00F56C4543
+ 10: 9DC42C26868374649BD17D69D025CA1B
+ 11: 37D33C11B433C91DA09925CA9E86757A
+ 12: 1373D769C270E7137C953AC0F8F37941
+ 13: 7E81DEC583348B1E2F6267ECF82CB994
+ 14: 505B6329338556518FF364CAA730F5E8
+ 15: 0C085AEEB315968B0BDE904E8BBC6FD0
+ 16: 5FED63259364BE7E5133FF0507DD2D4C
+ 17: F7EE5C80A99AAEADB49E7CC69BFFF679
+ 18: 4388FA5E763A641130940EB705BEFD08
+ 19: 1BC31CA79EBE1674CEBE01BC9988267B
+ 20: BE88961637EFFE2D6905D104FEDD51A4
+ 21: 9C341004FB22AFCC496094E3207CA761
+ 22: B9DAA3620E38FFC7C5D5E7D2D8FE3DE4
+ 23: A38D2E571F037061B4400F1131FDBDEA
+ 24: 61DB71AE77A6EB47F2E9E14E8CBF2F4B
+ 25: 9903A072274CC048EF2C51493266D9ED
+ 26: 1EBEA421DD08859C17DDF39B20A82102
+ 27: F425858618E1A86F4912E4714EFB9E75
+ 28: 3B3D4EA07F7FE6DDFDD02D624ACDFC9F
+ 29: CEEE256591D701514EB17DF73B08A970
+ 30: 5CC56D5D46120C530A23B6C511C685FC
+ 31: 68E484CE18BE28EADD0BBF23291B8237
+ 32: ABD58A9CDF8AA68168A1A402074CF520
+
+PMAC-skipjack (10 byte key)
+  0: 9CD94B75BC43B647
+  1: B069ACB82B12BC7B
+  2: 6DD40E71EB03E311
+  3: 74CBED61D77DBA7D
+  4: DD1B7E0D181537FE
+  5: ACB5B96FA0AD1786
+  6: B34E01EB2567D381
+  7: 9623DAADE57B9549
+  8: 8BA384BABB798344
+  9: B147AA9D5C5C67CF
+ 10: 0033C520F4C67523
+ 11: 42DAC184BEABC3E5
+ 12: 428029311004AEBB
+ 13: AC2BB1C0F0ED649B
+ 14: F7CAA9A3BF749C1A
+ 15: 2C5BD475AAC44C77
+ 16: FEB892DA66D31A84
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/tech0001.txt	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,73 @@
+Tech Note 0001
+How to Gather Entropy on Embedded Systems
+Tom St Denis
+
+Introduction
+------------
+
+This tech note explains a relatively simple way to gather entropy for a PRNG (Yarrow in this case) in embedded systems
+where there are few sources of entropy or physical sources.
+
+When trying to setup a secure random number generator a fresh source of random data (entropy) is required to ensure the
+deterministic state of the PRNG is not known or predetermined with respect to an attacker.
+
+At the very least the system requires one timer and one source of un-timed interrupts.  by "un-timed" I mean interrupts
+that do not occur at regular intervals [e.g. joypad/keypad input, network packets, etc...].
+
+First we shall begin by taking an overview of how the Yarrow PRNG works within libtomcrypt.  At the heart of all
+PRNGs is the "prng_state" data type.  This is a union of structures that hold the PRNG state for the various prngs.  The 
+first thing we require is a state... 
+
+   prng_state myPrng;
+
+Next we must initialize the state once to get the ball rolling
+
+   if (yarrow_start(&myPrng) != CRYPT_OK) {
+      // error should never happen!
+   }
+
+At this point the PRNG is ready to accept fresh entropy which is added with
+
+   int yarrow_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
+
+This function is **NOT** thread safe which will come under consideration later.  To add entropy to our PRNG we must 
+call this function with fresh data as its sampled.  Lets say we have a timer counter called "uTimer" which is a 32-bit 
+long and say a 32-bit joyPad state called "uPad".  An example interrupt handler would look like
+
+   void joypad_interrupt(...) {
+       unsigned char buf[8];
+
+       STORE32L(uTimer, buf);
+       STORE32L(uPad, buf+4)
+       if (yarrow_add_entropy(buf, 8, &myPrng) != CRYPT_OK) {
+          // this should never occur either unless you didn't call yarrow_start
+       }
+ 
+       // handle interrupt
+   }
+
+In this snippet the timer count and state of the joypad are added together into the entropy pool.  The timer is important
+because with respect to the joypad it is a good source of entropy (on its own its not).  For example, the probability of
+the user pushing the up arrow is fairly high, but at a specific time is not.
+
+This method doesn't gather alot of entropy and has to be used to for quite a while.  One way to speed it up is to tap
+multiple sources.  If you have a network adapter and other sources of events (keyboard, mouse, etc...) trapping their
+data is ideal as well.  Its important to gather the timer along with the event data.
+
+As mentioned the "yarrow_add_entropy()" function is not thread safe.  If your system allows interrupt handlers to be 
+interrupted themselves then you could have trouble.  One simple way is to detect when an interrupt is in progress and
+simply not add entropy during the call (jump over the yarrow_add_entropy() call)
+
+Once you feel that there has been enough entropy added to the pool then within a single thread you can call
+
+    int yarrow_ready(prng_state *prng)
+
+Now the PRNG is ready to read via the 
+
+    unsigned long yarrow_read(unsigned char *buf, unsigned long len, prng_state *prng)
+
+It is a very good idea that once you call the yarrow_ready() function that you stop harvesting entropy in your interrupt
+functions.  This will free up alot of CPU time.  Also one more final note.  The yarrow_read() function is not thread
+safe either.  This means if you have multiple threads or processes that read from it you will have to add your own semaphores
+around calls to it.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/tech0002.txt	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,52 @@
+Tech Note 0002
+How to avoid non-intrusive timing attacks with online computations
+Tom St Denis
+
+Introduction
+------------
+
+A timing attack is when an attacker can observe a side channel of the device (in this case time).  In this tech note
+we consider only non-intrusive timing attacks with respect to online computations.  That is an attacker can
+determine when a computation (such as a public key encryption) begins and ends but cannot observe the device 
+directly.  This is specifically important for applications which transmit data via a public network.
+
+Consider a Diffie-Hellman encryption which requires the sender to make up a public key "y = g^x mod p".  Libtomcrypt
+uses the MPI bignum library to perform the operation.  The time it takes to compute y is controlled by the number
+of 1 bits in the exponent 'x'.  To a large extent there will be the same number of squaring operations.  "1" bits in
+the exponent require the sender to perform a multiplication.  This means to a certain extent an attacker can 
+determine not only the magnitude of 'x' but the number of one bits.  With this information the attacker cannot directly
+learn the key used.  However, good cryptography mandates the close scrutiny of any practical side channel.
+
+Similar logic applies to the other various routines.  Fortunately for this case there is a simple solution.  First, 
+determine the maximum time the particular operation can require.  For instance, on an Athlon 1.53Ghz XP processor a
+DH-768 encryption requires roughly 50 milliseconds.  Take that time and round it up.  Now place a delay after the call.
+
+For example, 
+
+void demo(void) {
+   clock_t t1;
+
+   // get initial clock
+   t1 = clock();
+   
+   // some PK function
+   
+   // now delay 
+   while (clock() < (t1 + 100));
+   
+   // transmit data...
+   
+}
+
+This code has the effect of taking at least 100 ms always.  In effect someone analyzing the traffic will see that the
+operations always take a fixed amount of time.  Since no two platforms are the same this type of fix has not been 
+incorporated into libtomcrypt (nor is it desired for many platforms).  This requires on the developers part to profile
+the code to determine the delays required.
+
+Note that this "quick" fix has no effect against an intrusive attacker.  For example, power consumption will drop
+significantly in the loop after the operation.  However, this type of fix is more important to secure the user of the 
+application/device.  For example, a user placing an order online won't try to cheat themselves by cracking open their
+device and performing side-channel cryptanalysis.  An attacker over a network might try to use the timing information
+against the user.
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/tech0003.txt	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,52 @@
+Tech Note 0003
+Minimizing Memory Usage
+Tom St Denis
+
+Introduction
+------------
+
+For the most part the library can get by with around 20KB of stack and about 32KB of heap even if you use the
+public key functions.  If all you plan on using are the hashes and ciphers than only about 1KB of stack is required
+and no heap.
+
+To save space all of the symmetric key scheduled keys are stored in a union called "symmetric_key".  This means the 
+size of a symmetric_key is the size of the largest scheduled key.  By removing the ciphers you don't use from
+the build you can minimize the size of this structure.  For instance, by removing both Twofish and Blowfish the
+size reduces to 768 bytes from the 4,256 bytes it would have been (on a 32-bit platform).  Or if you remove
+Blowfish and use Twofish with TWOFISH_SMALL defined its still 768 bytes.  Even at its largest the structure is only 
+4KB which is normally not a problem for any platform.  
+
+
+Cipher Name | Size of scheduled key (bytes) |
+------------+-------------------------------|
+Twofish     | 4,256                         |
+Blowfish    | 4,168                         |
+3DES        | 768                           |
+SAFER+      | 532                           |
+Serpent     | 528                           |
+Rijndael    | 516                           |
+XTEA        | 256                           |
+RC2         | 256                           |
+DES         | 256                           |
+SAFER [#]   | 217                           |
+RC5         | 204                           |
+Twofish [*] | 193                           |
+RC6         | 176                           |
+CAST5       | 132                           |
+Noekeon     | 32                            |
+Skipjack    | 10                            |
+------------+-------------------------------/
+Memory used per cipher on a 32-bit platform.
+
+[*] For Twofish with TWOFISH_SMALL defined
+[#] For all 64-bit SAFER ciphers.
+
+Noekeon is a fairly fast cipher and uses very little memory.  Ideally in low-ram platforms all other ciphers should be
+left undefined and Noekeon should remain.  While Noekeon is generally considered a secure block cipher (it is insecure
+as a hash) CAST5 is perhaps a "runner-up" choice.  CAST5 has been around longer (it is also known as CAST-128) and is 
+fairly fast as well.
+
+You can easily accomplish this via the "config.pl" script. Simply answer "n" to all of the ciphers except the one you want
+and then rebuild the library.  [or you can hand edit mycrypt_custom.h]
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ocb_decrypt.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,58 @@
+/* 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
+ */
+
+/* OCB Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef OCB_MODE
+
+int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt)
+{
+   unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE];
+   int err, x;
+
+   _ARGCHK(ocb != NULL);
+   _ARGCHK(pt  != NULL);
+   _ARGCHK(ct  != NULL);
+   if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
+      return err;
+   }
+   if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* Get Z[i] value */
+   ocb_shift_xor(ocb, Z);
+
+   /* xor ct in, encrypt, xor Z out */
+   for (x = 0; x < ocb->block_len; x++) {
+       tmp[x] = ct[x] ^ Z[x];
+   }
+   cipher_descriptor[ocb->cipher].ecb_decrypt(tmp, pt, &ocb->key);
+   for (x = 0; x < ocb->block_len; x++) {
+       pt[x] ^= Z[x];
+   }
+
+   /* compute checksum */
+   for (x = 0; x < ocb->block_len; x++) {
+       ocb->checksum[x] ^= pt[x];
+   }
+
+
+#ifdef CLEAN_STACK
+   zeromem(Z, sizeof(Z));
+   zeromem(tmp, sizeof(tmp));
+#endif
+   return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ocb_decrypt_verify_memory.c	Mon May 31 18:25:41 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
+ */
+
+/* OCB Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef OCB_MODE
+
+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)
+{
+   int err;
+   ocb_state ocb;
+
+
+   _ARGCHK(key    != NULL);
+   _ARGCHK(nonce  != NULL);
+   _ARGCHK(pt     != NULL);
+   _ARGCHK(ct     != NULL);
+   _ARGCHK(tag    != NULL);
+   _ARGCHK(res    != NULL);
+
+   if ((err = ocb_init(&ocb, cipher, key, keylen, nonce)) != CRYPT_OK) {
+      return err;
+   }
+
+   while (ctlen > (unsigned long)ocb.block_len) {
+        if ((err = ocb_decrypt(&ocb, ct, pt)) != CRYPT_OK) {
+           return err;
+        }
+        ctlen   -= ocb.block_len;
+        pt      += ocb.block_len;
+        ct      += ocb.block_len;
+   }
+
+   return ocb_done_decrypt(&ocb, ct, ctlen, pt, tag, taglen, res);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ocb_done_decrypt.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,51 @@
+/* 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
+ */
+
+/* OCB Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef OCB_MODE
+
+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)
+{
+   int err;
+   unsigned char tagbuf[MAXBLOCKSIZE];
+   unsigned long tagbuflen;
+
+   _ARGCHK(ocb != NULL);
+   _ARGCHK(pt  != NULL);
+   _ARGCHK(ct  != NULL);
+   _ARGCHK(tag != NULL);
+   _ARGCHK(res != NULL);
+
+   *res = 0;
+
+   tagbuflen = sizeof(tagbuf);
+   if ((err = __ocb_done(ocb, ct, ctlen, pt, tagbuf, &tagbuflen, 1)) != CRYPT_OK) {
+      return err;
+   }
+
+   if (taglen <= tagbuflen && memcmp(tagbuf, tag, taglen) == 0) {
+      *res = 1;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(tagbuf, sizeof(tagbuf));
+#endif
+
+   return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ocb_done_encrypt.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,29 @@
+/* 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
+ */
+
+/* OCB Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef OCB_MODE
+
+int ocb_done_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen,
+                     unsigned char *ct, unsigned char *tag, unsigned long *taglen)
+{
+   _ARGCHK(ocb    != NULL);
+   _ARGCHK(pt     != NULL);
+   _ARGCHK(ct     != NULL);
+   _ARGCHK(tag    != NULL);
+   _ARGCHK(taglen != NULL);
+   return __ocb_done(ocb, pt, ptlen, ct, tag, taglen, 0);
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ocb_encrypt.c	Mon May 31 18:25:41 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
+ */
+
+/* OCB Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef OCB_MODE
+
+int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct)
+{
+   unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE];
+   int err, x;
+
+   _ARGCHK(ocb != NULL);
+   _ARGCHK(pt  != NULL);
+   _ARGCHK(ct  != NULL);
+   if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
+      return err;
+   }
+   if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* compute checksum */
+   for (x = 0; x < ocb->block_len; x++) {
+       ocb->checksum[x] ^= pt[x];
+   }
+
+   /* Get Z[i] value */
+   ocb_shift_xor(ocb, Z);
+
+   /* xor pt in, encrypt, xor Z out */
+   for (x = 0; x < ocb->block_len; x++) {
+       tmp[x] = pt[x] ^ Z[x];
+   }
+   cipher_descriptor[ocb->cipher].ecb_encrypt(tmp, ct, &ocb->key);
+   for (x = 0; x < ocb->block_len; x++) {
+       ct[x] ^= Z[x];
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(Z, sizeof(Z));
+   zeromem(tmp, sizeof(tmp));
+#endif
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ocb_encrypt_authenticate_memory.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,50 @@
+/* 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
+ */
+
+/* OCB Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef OCB_MODE
+
+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)
+{
+   int err;
+   ocb_state ocb;
+
+   _ARGCHK(key    != NULL);
+   _ARGCHK(nonce  != NULL);
+   _ARGCHK(pt     != NULL);
+   _ARGCHK(ct     != NULL);
+   _ARGCHK(tag    != NULL);
+   _ARGCHK(taglen != NULL);
+
+   if ((err = ocb_init(&ocb, cipher, key, keylen, nonce)) != CRYPT_OK) {
+      return err;
+   }
+
+   while (ptlen > (unsigned long)ocb.block_len) {
+        if ((err = ocb_encrypt(&ocb, pt, ct)) != CRYPT_OK) {
+           return err;
+        }
+        ptlen   -= ocb.block_len;
+        pt      += ocb.block_len;
+        ct      += ocb.block_len;
+   }
+
+   return ocb_done_encrypt(&ocb, pt, ptlen, ct, tag, taglen);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ocb_init.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,117 @@
+/* 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
+ */
+
+/* OCB Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef OCB_MODE
+
+static const struct {
+    int           len;
+    unsigned char poly_div[MAXBLOCKSIZE], 
+                  poly_mul[MAXBLOCKSIZE];
+} polys[] = {
+{
+    8,
+    { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B }
+}, {
+    16, 
+    { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 }
+}
+};
+
+int ocb_init(ocb_state *ocb, int cipher, 
+             const unsigned char *key, unsigned long keylen, const unsigned char *nonce)
+{
+   int poly, x, y, m, err;
+
+   _ARGCHK(ocb   != NULL);
+   _ARGCHK(key   != NULL);
+   _ARGCHK(nonce != NULL);
+
+   /* valid cipher? */
+   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* determine which polys to use */
+   ocb->block_len = cipher_descriptor[cipher].block_length;
+   for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) {
+       if (polys[poly].len == ocb->block_len) { 
+          break;
+       }
+   }
+   if (polys[poly].len != ocb->block_len) {
+      return CRYPT_INVALID_ARG;
+   }   
+
+   /* schedule the key */
+   if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) {
+      return err;
+   }
+ 
+   /* find L = E[0] */
+   zeromem(ocb->L, ocb->block_len);
+   cipher_descriptor[cipher].ecb_encrypt(ocb->L, ocb->L, &ocb->key);
+
+   /* find R = E[N xor L] */
+   for (x = 0; x < ocb->block_len; x++) {
+       ocb->R[x] = ocb->L[x] ^ nonce[x];
+   }
+   cipher_descriptor[cipher].ecb_encrypt(ocb->R, ocb->R, &ocb->key);
+
+   /* find Ls[i] = L << i for i == 0..31 */
+   memcpy(ocb->Ls[0], ocb->L, ocb->block_len);
+   for (x = 1; x < 32; x++) {
+       m = ocb->Ls[x-1][0] >> 7;
+       for (y = 0; y < ocb->block_len-1; y++) {
+           ocb->Ls[x][y] = ((ocb->Ls[x-1][y] << 1) | (ocb->Ls[x-1][y+1] >> 7)) & 255;
+       }
+       ocb->Ls[x][ocb->block_len-1] = (ocb->Ls[x-1][ocb->block_len-1] << 1) & 255;
+
+       if (m == 1) {
+          for (y = 0; y < ocb->block_len; y++) {
+              ocb->Ls[x][y] ^= polys[poly].poly_mul[y];
+          }
+       }
+    }
+
+    /* find Lr = L / x */
+    m = ocb->L[ocb->block_len-1] & 1;
+
+    /* shift right */
+    for (x = ocb->block_len - 1; x > 0; x--) {
+        ocb->Lr[x] = ((ocb->L[x] >> 1) | (ocb->L[x-1] << 7)) & 255;
+    }
+    ocb->Lr[0] = ocb->L[0] >> 1;
+
+    if (m == 1) {
+       for (x = 0; x < ocb->block_len; x++) {
+           ocb->Lr[x] ^= polys[poly].poly_div[x];
+       }
+    }
+
+    /* set Li, checksum */
+    zeromem(ocb->Li, ocb->block_len);
+    zeromem(ocb->checksum, ocb->block_len);
+
+    /* set other params */
+    ocb->block_index = 1;
+    ocb->cipher      = cipher;
+
+    return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ocb_ntz.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,29 @@
+/* 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
+ */
+
+/* OCB Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef OCB_MODE
+
+int ocb_ntz(unsigned long x)
+{
+   int c;
+   x &= 0xFFFFFFFFUL;
+   c = 0;
+   while ((x & 1) == 0) {
+      ++c;
+      x >>= 1;
+   }
+   return c;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ocb_shift_xor.c	Mon May 31 18:25:41 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 protected], http://libtomcrypt.org
+ */
+
+/* OCB Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef OCB_MODE
+
+void ocb_shift_xor(ocb_state *ocb, unsigned char *Z)
+{
+   int x, y;
+   y = ocb_ntz(ocb->block_index++);
+   for (x = 0; x < ocb->block_len; x++) {
+       ocb->Li[x] ^= ocb->Ls[y][x];
+       Z[x]        = ocb->Li[x] ^ ocb->R[x];
+   }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ocb_test.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,226 @@
+/* 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
+ */
+
+/* OCB Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef OCB_MODE
+
+int ocb_test(void)
+{
+#ifndef LTC_TEST
+   return CRYPT_NOP;
+#else
+   static const struct {
+         int ptlen;
+         unsigned char key[16], nonce[16], pt[34], ct[34], tag[16];
+   } tests[] = {
+
+   /* OCB-AES-128-0B */
+{
+   0,
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* nonce */
+   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+   /* pt */
+   { 0 },
+   /* ct */
+   { 0 },
+   /* tag */
+   { 0x15, 0xd3, 0x7d, 0xd7, 0xc8, 0x90, 0xd5, 0xd6,
+     0xac, 0xab, 0x92, 0x7b, 0xc0, 0xdc, 0x60, 0xee },
+},
+
+
+   /* OCB-AES-128-3B */
+{
+   3, 
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* nonce */
+   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+   /* pt */
+   { 0x00, 0x01, 0x02 },
+   /* ct */
+   { 0xfc, 0xd3, 0x7d },
+   /* tag */
+   { 0x02, 0x25, 0x47, 0x39, 0xa5, 0xe3, 0x56, 0x5a,
+     0xe2, 0xdc, 0xd6, 0x2c, 0x65, 0x97, 0x46, 0xba },
+},
+
+   /* OCB-AES-128-16B */
+{
+   16, 
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* nonce */
+   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+   /* pt */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* ct */
+   { 0x37, 0xdf, 0x8c, 0xe1, 0x5b, 0x48, 0x9b, 0xf3,
+     0x1d, 0x0f, 0xc4, 0x4d, 0xa1, 0xfa, 0xf6, 0xd6 },
+   /* tag */
+   { 0xdf, 0xb7, 0x63, 0xeb, 0xdb, 0x5f, 0x0e, 0x71,
+     0x9c, 0x7b, 0x41, 0x61, 0x80, 0x80, 0x04, 0xdf },
+},
+
+   /* OCB-AES-128-20B  */
+{
+   20, 
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* nonce */
+   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+   /* pt */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 
+     0x10, 0x11, 0x12, 0x13 },
+   /* ct */
+   { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4,
+     0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb,
+     0x70, 0x03, 0xeb, 0x55},
+   /* tag */
+   { 0x75, 0x30, 0x84, 0x14, 0x4e, 0xb6, 0x3b, 0x77,
+     0x0b, 0x06, 0x3c, 0x2e, 0x23, 0xcd, 0xa0, 0xbb },
+},
+
+   /* OCB-AES-128-32B  */
+{
+   32, 
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* nonce */
+   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+   /* pt */
+   { 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 },
+   /* ct */
+   { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4,
+     0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb,
+     0x4a, 0xfc, 0xbb, 0x7f, 0xed, 0xc0, 0x8c, 0xa8,
+     0x65, 0x4c, 0x6d, 0x30, 0x4d, 0x16, 0x12, 0xfa },
+
+   /* tag */
+   { 0xc1, 0x4c, 0xbf, 0x2c, 0x1a, 0x1f, 0x1c, 0x3c,
+     0x13, 0x7e, 0xad, 0xea, 0x1f, 0x2f, 0x2f, 0xcf },
+},
+
+   /* OCB-AES-128-34B  */
+{
+   34, 
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* nonce */
+   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+   /* pt */
+   { 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,
+     0x20, 0x21 },
+   /* ct */
+   { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4,
+     0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb,
+     0xd4, 0x90, 0x3d, 0xd0, 0x02, 0x5b, 0xa4, 0xaa,
+     0x83, 0x7c, 0x74, 0xf1, 0x21, 0xb0, 0x26, 0x0f,
+     0xa9, 0x5d },
+
+   /* tag */
+   { 0xcf, 0x83, 0x41, 0xbb, 0x10, 0x82, 0x0c, 0xcf,
+     0x14, 0xbd, 0xec, 0x56, 0xb8, 0xd7, 0xd6, 0xab },
+},
+
+};
+
+   int err, x, idx, res;
+   unsigned long len;
+   unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE];
+
+    /* AES can be under rijndael or aes... try to find it */ 
+    if ((idx = find_cipher("aes")) == -1) {
+       if ((idx = find_cipher("rijndael")) == -1) {
+          return CRYPT_NOP;
+       }
+    }
+
+    for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+        len = sizeof(outtag);
+        if ((err = ocb_encrypt_authenticate_memory(idx, tests[x].key, 16,
+             tests[x].nonce, tests[x].pt, tests[x].ptlen, outct, outtag, &len)) != CRYPT_OK) {
+           return err;
+        }
+        
+        if (memcmp(outtag, tests[x].tag, len) || memcmp(outct, tests[x].ct, tests[x].ptlen)) {
+#if 0
+           unsigned long y;
+           printf("\n\nFailure: \nCT:\n");
+           for (y = 0; y < (unsigned long)tests[x].ptlen; ) {
+               printf("0x%02x", outct[y]);
+               if (y < (unsigned long)(tests[x].ptlen-1)) printf(", ");
+               if (!(++y % 8)) printf("\n");
+           }
+           printf("\nTAG:\n");
+           for (y = 0; y < len; ) {
+               printf("0x%02x", outtag[y]);
+               if (y < len-1) printf(", ");
+               if (!(++y % 8)) printf("\n");
+           }
+#endif
+           return CRYPT_FAIL_TESTVECTOR;
+        }
+        
+        if ((err = ocb_decrypt_verify_memory(idx, tests[x].key, 16, tests[x].nonce, outct, tests[x].ptlen,
+             outct, tests[x].tag, len, &res)) != CRYPT_OK) {
+           return err;
+        }
+        if ((res != 1) || memcmp(tests[x].pt, outct, tests[x].ptlen)) {
+#if 0
+           unsigned long y;
+           printf("\n\nFailure-decrypt: \nPT:\n");
+           for (y = 0; y < (unsigned long)tests[x].ptlen; ) {
+               printf("0x%02x", outct[y]);
+               if (y < (unsigned long)(tests[x].ptlen-1)) printf(", ");
+               if (!(++y % 8)) printf("\n");
+           }
+           printf("\nres = %d\n\n", res);
+#endif
+        }
+    }
+    return CRYPT_OK;
+#endif /* LTC_TEST */
+}
+
+#endif /* OCB_MODE */
+
+
+/* some comments
+
+   -- it's hard to seek
+   -- hard to stream [you can't emit ciphertext until full block]
+   -- The setup is somewhat complicated...
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ofb_decrypt.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,26 @@
+/* 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 OFB
+
+int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb)
+{
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(ofb != NULL);
+   return ofb_encrypt(ct, pt, len, ofb);
+}
+
+
+#endif
+
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ofb_encrypt.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,41 @@
+/* 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 OFB
+
+int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb)
+{
+   int err;
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(ofb != NULL);
+   if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) {
+       return err;
+   }
+   
+   /* is blocklen/padlen valid? */
+   if (ofb->blocklen < 0 || ofb->blocklen > (int)sizeof(ofb->IV) ||
+       ofb->padlen   < 0 || ofb->padlen   > (int)sizeof(ofb->IV)) {
+      return CRYPT_INVALID_ARG;
+   }
+   
+   while (len-- > 0) {
+       if (ofb->padlen == ofb->blocklen) {
+          cipher_descriptor[ofb->cipher].ecb_encrypt(ofb->IV, ofb->IV, &ofb->key);
+          ofb->padlen = 0;
+       }
+       *ct++ = *pt++ ^ ofb->IV[ofb->padlen++];
+   }
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ofb_start.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,40 @@
+/* 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 OFB
+
+int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, 
+              int keylen, int num_rounds, symmetric_OFB *ofb)
+{
+   int x, err;
+
+   _ARGCHK(IV != NULL);
+   _ARGCHK(key != NULL);
+   _ARGCHK(ofb != NULL);
+
+   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* copy details */
+   ofb->cipher = cipher;
+   ofb->blocklen = cipher_descriptor[cipher].block_length;
+   for (x = 0; x < ofb->blocklen; x++) {
+       ofb->IV[x] = IV[x];
+   }
+
+   /* init the cipher */
+   ofb->padlen = ofb->blocklen;
+   return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ofb->key);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omac_done.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,66 @@
+/* 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
+ */
+/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */
+#include "mycrypt.h"
+
+#ifdef OMAC
+
+int omac_done(omac_state *state, unsigned char *out, unsigned long *outlen)
+{
+   int err, mode, x;
+
+   _ARGCHK(state != NULL);
+   _ARGCHK(out   != NULL);
+   if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) ||
+       (state->blklen > (int)sizeof(state->block)) || (state->buflen > state->blklen)) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* figure out mode */
+   if (state->buflen != state->blklen) {
+      /* add the 0x80 byte */
+      state->block[state->buflen++] = 0x80;
+
+      /* pad with 0x00 */
+      while (state->buflen < state->blklen) {
+         state->block[state->buflen++] = 0x00;
+      }
+      mode = 1;
+   } else {
+      mode = 0;
+   }
+
+   /* now xor prev + Lu[mode] */
+   for (x = 0; x < state->blklen; x++) {
+       state->block[x] ^= state->prev[x] ^ state->Lu[mode][x];
+   }
+
+   /* encrypt it */
+   cipher_descriptor[state->cipher_idx].ecb_encrypt(state->block, state->block, &state->key);
+ 
+   /* output it */
+   for (x = 0; x < state->blklen && (unsigned long)x < *outlen; x++) {
+       out[x] = state->block[x];
+   }
+   *outlen = x;
+
+#ifdef CLEAN_STACK
+   zeromem(state, sizeof(*state));
+#endif
+   return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omac_file.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,65 @@
+/* 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
+ */
+/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */
+#include "mycrypt.h"
+
+#ifdef OMAC
+
+int omac_file(int cipher, 
+              const unsigned char *key, unsigned long keylen,
+              const char *filename, 
+                    unsigned char *out, unsigned long *outlen)
+{
+#ifdef NO_FILE
+   return CRYPT_NOP;
+#else
+   int err, x;
+   omac_state omac;
+   FILE *in;
+   unsigned char buf[512];
+
+   _ARGCHK(key      != NULL);
+   _ARGCHK(filename != NULL);
+   _ARGCHK(out      != NULL);
+   _ARGCHK(outlen   != NULL);
+
+   in = fopen(filename, "rb");
+   if (in == NULL) {
+      return CRYPT_FILE_NOTFOUND;
+   }
+
+   if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) {
+      fclose(in);
+      return err;
+   }
+
+   do {
+      x = fread(buf, 1, sizeof(buf), in);
+      if ((err = omac_process(&omac, buf, x)) != CRYPT_OK) {
+         fclose(in);
+         return err;
+      }
+   } while (x == sizeof(buf));
+   fclose(in);
+
+   if ((err = omac_done(&omac, out, outlen)) != CRYPT_OK) {
+      return err;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+
+   return CRYPT_OK;
+#endif
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omac_init.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,76 @@
+/* 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
+ */
+/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */
+#include "mycrypt.h"
+
+#ifdef OMAC
+
+int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen)
+{
+   int err, x, y, mask, msb, len;
+
+   _ARGCHK(omac != NULL);
+   _ARGCHK(key  != NULL);
+
+   /* schedule the key */
+   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* now setup the system */
+   switch (cipher_descriptor[cipher].block_length) {
+       case 8:  mask = 0x1B;
+                len  = 8;
+                break;
+       case 16: mask = 0x87;
+                len  = 16;
+                break;
+       default: return CRYPT_INVALID_ARG;
+   }
+
+   if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &omac->key)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* ok now we need Lu and Lu^2 [calc one from the other] */
+
+   /* first calc L which is Ek(0) */
+   zeromem(omac->Lu[0], cipher_descriptor[cipher].block_length);
+   cipher_descriptor[cipher].ecb_encrypt(omac->Lu[0], omac->Lu[0], &omac->key);
+
+   /* now do the mults, whoopy! */
+   for (x = 0; x < 2; x++) {
+       /* if msb(L * u^(x+1)) = 0 then just shift, otherwise shift and xor constant mask */
+       msb = omac->Lu[x][0] >> 7;
+
+       /* shift left */
+       for (y = 0; y < (len - 1); y++) {
+           omac->Lu[x][y] = ((omac->Lu[x][y] << 1) | (omac->Lu[x][y+1] >> 7)) & 255;
+       }
+       omac->Lu[x][len - 1] = ((omac->Lu[x][len - 1] << 1) ^ (msb ? mask : 0)) & 255;
+ 
+       /* copy up as require */
+       if (x == 0) {
+          memcpy(omac->Lu[1], omac->Lu[0], sizeof(omac->Lu[0]));
+       }
+   }
+
+   /* setup state */
+   omac->cipher_idx = cipher;
+   omac->buflen     = 0;
+   omac->blklen     = len;
+   zeromem(omac->prev,  sizeof(omac->prev));
+   zeromem(omac->block, sizeof(omac->block));
+
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omac_memory.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,42 @@
+/* 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
+ */
+/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */
+#include "mycrypt.h"
+
+#ifdef OMAC
+
+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)
+{
+   int err;
+   omac_state omac;
+
+   _ARGCHK(key != NULL);
+   _ARGCHK(msg != NULL);
+   _ARGCHK(out != NULL);
+   _ARGCHK(outlen != NULL);
+
+   if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = omac_process(&omac, msg, msglen)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = omac_done(&omac, out, outlen)) != CRYPT_OK) {
+      return err;
+   }
+
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omac_process.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,53 @@
+/* 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
+ */
+/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */
+#include "mycrypt.h"
+
+#ifdef OMAC
+
+int omac_process(omac_state *state, const unsigned char *buf, unsigned long len)
+{
+   int err, n, x;
+
+   _ARGCHK(state != NULL);
+   _ARGCHK(buf   != NULL);
+   if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) ||
+       (state->blklen > (int)sizeof(state->block)) || (state->buflen > state->blklen)) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   while (len != 0) { 
+       /* ok if the block is full we xor in prev, encrypt and replace prev */
+       if (state->buflen == state->blklen) {
+          for (x = 0; x < state->blklen; x++) {
+              state->block[x] ^= state->prev[x];
+          }
+          cipher_descriptor[state->cipher_idx].ecb_encrypt(state->block, state->prev, &state->key);
+          state->buflen = 0;
+       }
+
+       /* add bytes */
+       n = MIN(len, (unsigned long)(state->blklen - state->buflen));
+       memcpy(state->block + state->buflen, buf, n);
+       state->buflen += n;
+       len           -= n;
+       buf           += n;
+   }
+
+   return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omac_test.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,95 @@
+/* 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
+ */
+/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */
+#include "mycrypt.h"
+
+#ifdef OMAC
+
+int omac_test(void)
+{
+#if !defined(LTC_TEST)
+    return CRYPT_NOP;
+#else
+    static const struct { 
+        int keylen, msglen;
+        unsigned char key[16], msg[64], tag[16];
+    } tests[] = {
+    { 16, 0,
+      { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 
+        0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+      { 0x00 },
+      { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
+        0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 }
+    },
+    { 16, 16, 
+      { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 
+        0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+      { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+        0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a },
+      { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 
+        0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c }
+    },
+    { 16, 40, 
+      { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 
+        0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+      { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+        0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+        0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 
+        0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+        0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 },
+      { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
+        0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 }
+    },
+    { 16, 64, 
+      { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 
+        0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c },
+      { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+        0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+        0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 
+        0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+        0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+        0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+        0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+        0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
+      { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 
+        0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe }
+    }
+
+    };
+    unsigned char out[16];
+    int x, y, err, idx;
+    unsigned long len;
+
+
+    /* AES can be under rijndael or aes... try to find it */ 
+    if ((idx = find_cipher("aes")) == -1) {
+       if ((idx = find_cipher("rijndael")) == -1) {
+          return CRYPT_NOP;
+       }
+    }
+
+    for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+       len = sizeof(out); 
+       if ((err = omac_memory(idx, tests[x].key, tests[x].keylen, tests[x].msg, tests[x].msglen, out, &len)) != CRYPT_OK) {
+          return err;
+       }
+
+       if (memcmp(out, tests[x].tag, 16) != 0) {
+          printf("\n\nTag: ");
+          for (y = 0; y < 16; y++) printf("%02x", out[y]); printf("\n\n");
+          return CRYPT_FAIL_TESTVECTOR;
+       }
+    }
+    return CRYPT_OK;
+#endif
+}   
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packet_store_header.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,29 @@
+/* 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 PACKET
+
+void packet_store_header(unsigned char *dst, int section, int subsection)
+{
+   _ARGCHK(dst != NULL);
+
+   /* store version number */
+   dst[0] = (unsigned char)(CRYPT&255);
+   dst[1] = (unsigned char)((CRYPT>>8)&255);
+
+   /* store section and subsection */
+   dst[2] = (unsigned char)(section & 255);
+   dst[3] = (unsigned char)(subsection & 255);
+
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packet_valid_header.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,37 @@
+/* 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 PACKET
+
+int packet_valid_header(unsigned char *src, int section, int subsection)
+{
+   unsigned long ver;
+
+   _ARGCHK(src != NULL);
+
+   /* check version */
+   ver = ((unsigned long)src[0]) | ((unsigned long)src[1] << 8U);
+   if (CRYPT < ver) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* check section and subsection */
+   if (section != (int)src[2] || subsection != (int)src[3]) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   return CRYPT_OK;
+}
+
+#endif
+
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkcs_1_i2osp.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,40 @@
+/* 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"
+
+/* Integer to Octet I2OSP -- Tom St Denis */
+
+#ifdef PKCS_1
+
+/* always stores the same # of bytes, pads with leading zero bytes
+   as required
+ */
+int pkcs_1_i2osp(mp_int *n, unsigned long modulus_len, unsigned char *out)
+{
+   int err;
+   unsigned long size;
+
+   size = mp_unsigned_bin_size(n);
+
+   if (size > modulus_len) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* store it */
+   zeromem(out, modulus_len);
+   if ((err = mp_to_unsigned_bin(n, out+(modulus_len-size))) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+   return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkcs_1_mgf1.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,66 @@
+/* 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"
+
+/* The Mask Generation Function (MGF1) for PKCS #1 -- Tom St Denis */
+
+#ifdef PKCS_1
+
+int pkcs_1_mgf1(const unsigned char *seed, unsigned long seedlen,
+                      int            hash_idx,
+                      unsigned char *mask, unsigned long masklen)
+{
+   unsigned long hLen, counter, x;
+   int           err;
+   hash_state    md;
+   unsigned char buf[MAXBLOCKSIZE];
+ 
+   _ARGCHK(seed != NULL);
+   _ARGCHK(mask != NULL);
+
+   /* ensure valid hash */
+   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { 
+      return err;
+   }
+
+   /* get hash output size */
+   hLen = hash_descriptor[hash_idx].hashsize;
+
+   /* start counter */
+   counter = 0;
+
+   while (masklen > 0) {
+       /* handle counter */
+       STORE32H(counter, buf);
+       ++counter;
+
+       /* get hash of seed || counter */
+       hash_descriptor[hash_idx].init(&md);
+       if ((err = hash_descriptor[hash_idx].process(&md, seed, seedlen)) != CRYPT_OK) {
+          return err;
+       }
+       if ((err = hash_descriptor[hash_idx].process(&md, buf, 4)) != CRYPT_OK) {
+          return err;
+       }
+       if ((err = hash_descriptor[hash_idx].done(&md, buf)) != CRYPT_OK) {
+          return err;
+       }
+
+       /* store it */
+       for (x = 0; x < hLen && masklen > 0; x++, masklen--) {
+          *mask++ = buf[x];
+       }
+   }
+
+   return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkcs_1_oaep_decode.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,135 @@
+/* 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"
+
+/* OAEP Padding for PKCS #1 -- Tom St Denis */
+
+#ifdef PKCS_1
+
+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)
+{
+   unsigned char DB[1024], seed[MAXBLOCKSIZE], mask[sizeof(DB)];
+   unsigned long hLen, x, y, modulus_len;
+   int           err;
+
+   _ARGCHK(msg    != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   
+   /* test valid hash */
+   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { 
+      return err;
+   }
+   hLen        = hash_descriptor[hash_idx].hashsize;
+   modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+   /* test message size */
+   if (modulus_len >= sizeof(DB) || msglen != modulus_len) {
+      return CRYPT_PK_INVALID_SIZE;
+   }
+
+   /* ok so it's now in the form
+  
+      0x00  || maskedseed || maskedDB 
+  
+       1    ||   hLen     ||  modulus_len - hLen - 1
+   
+    */
+
+   /* must have leading 0x00 byte */
+   if (msg[0] != 0x00) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* now read the masked seed */
+   for (x = 1, y = 0; y < hLen; y++) {
+      seed[y] = msg[x++];
+   }
+
+   /* now read the masked DB */
+   for (y = 0; y < modulus_len - hLen - 1; y++) {
+      DB[y] = msg[x++];
+   }
+
+   /* compute MGF1 of maskedDB (hLen) */ 
+   if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* XOR against seed */
+   for (y = 0; y < hLen; y++) {
+      seed[y] ^= mask[y];
+   }
+
+   /* compute MGF1 of seed (k - hlen - 1) */
+   if ((err = pkcs_1_mgf1(seed, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* xor against DB */
+   for (y = 0; y < (modulus_len - hLen - 1); y++) {
+       DB[y] ^= mask[y]; 
+   }
+
+   /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
+
+   /* compute lhash and store it in seed [reuse temps!] */
+   x = sizeof(seed);
+   if (lparam != NULL) {
+      if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) {
+         return err;
+      }
+   } else {
+      /* can't pass hash_memory a NULL so use DB with zero length */
+      if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) {
+         return err;
+      }
+   }
+
+   /* compare the lhash'es */
+   if (memcmp(seed, DB, hLen) != 0) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* now zeroes before a 0x01 */
+   for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) {
+      /* step... */
+   }
+
+   /* error out if wasn't 0x01 */
+   if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* rest is the message (and skip 0x01) */
+   if (msglen - ++x > *outlen) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* copy message */
+   *outlen = (modulus_len - hLen - 1) - x;
+   for (y = 0; x != (modulus_len - hLen - 1); ) {
+       out[y++] = DB[x++];
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(DB,   sizeof(DB));
+   zeromem(seed, sizeof(seed));
+   zeromem(mask, sizeof(mask));
+#endif
+
+   return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkcs_1_oaep_encode.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,128 @@
+/* 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"
+
+/* OAEP Padding for PKCS #1 -- Tom St Denis */
+
+#ifdef PKCS_1
+
+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)
+{
+   unsigned char DB[1024], seed[MAXBLOCKSIZE], mask[sizeof(DB)];
+   unsigned long hLen, x, y, modulus_len;
+   int           err;
+
+   _ARGCHK(msg    != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* test valid hash */
+   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { 
+      return err;
+   }
+
+   /* valid prng */
+   if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   hLen        = hash_descriptor[hash_idx].hashsize;
+   modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+   /* test message size */
+   if (modulus_len >= sizeof(DB) || msglen > (modulus_len - 2*hLen - 2)) {
+      return CRYPT_PK_INVALID_SIZE;
+   }
+
+   /* get lhash */
+// DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes
+   x = sizeof(DB);
+   if (lparam != NULL) {
+      if ((err = hash_memory(hash_idx, lparam, lparamlen, DB, &x)) != CRYPT_OK) {
+         return err;
+      }
+   } else {
+      /* can't pass hash_memory a NULL so use DB with zero length */
+      if ((err = hash_memory(hash_idx, DB, 0, DB, &x)) != CRYPT_OK) {
+         return err;
+      }
+   }
+
+   /* append PS then 0x01 (to lhash)  */
+   x = hLen;
+   y = modulus_len - msglen - 2*hLen - 2;
+   while (y--) {
+      DB[x++] = 0x00;
+   }
+   DB[x++] = 0x01;
+
+   /* message */
+   y = msglen;
+   while (y--) {
+     DB[x++] = *msg++;
+   }
+
+   /* now choose a random seed */
+   if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) {
+      return CRYPT_ERROR_READPRNG;
+   }
+
+   /* compute MGF1 of seed (k - hlen - 1) */
+   if ((err = pkcs_1_mgf1(seed, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* xor against DB */
+   for (y = 0; y < (modulus_len - hLen - 1); y++) {
+       DB[y] ^= mask[y]; 
+   }
+
+   /* compute MGF1 of maskedDB (hLen) */ 
+   if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* XOR against seed */
+   for (y = 0; y < hLen; y++) {
+      seed[y] ^= mask[y];
+   }
+
+   /* create string of length modulus_len */
+   if (*outlen < modulus_len) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* start output which is 0x00 || maskedSeed || maskedDB */
+   x = 0;
+   out[x++] = 0x00;
+   for (y = 0; y < hLen; y++) {
+      out[x++] = seed[y];
+   }
+   for (y = 0; y < modulus_len - hLen - 1; y++) {
+      out[x++] = DB[y];
+   }
+   *outlen = x;
+
+#ifdef CLEAN_STACK
+   zeromem(DB,   sizeof(DB));
+   zeromem(seed, sizeof(seed));
+   zeromem(mask, sizeof(mask));
+#endif
+
+   return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkcs_1_os2ip.c	Mon May 31 18:25:41 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 protected], http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+/*  Octet to Integer OS2IP -- Tom St Denis */
+#ifdef PKCS_1
+
+int pkcs_1_os2ip(mp_int *n, unsigned char *in, unsigned long inlen)
+{
+   int err;
+   /* read it */
+   if ((err = mp_read_unsigned_bin(n, in, inlen)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+   return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkcs_1_pss_decode.c	Mon May 31 18:25:41 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
+ */
+#include "mycrypt.h"
+
+/* PKCS #1 PSS Signature Padding -- Tom St Denis */
+
+#ifdef PKCS_1
+
+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)
+{
+   unsigned char DB[1024], mask[sizeof(DB)], salt[sizeof(DB)], hash[sizeof(DB)];
+   unsigned long x, y, hLen, modulus_len;
+   int           err;
+   hash_state    md;
+
+   _ARGCHK(msghash != NULL);
+   _ARGCHK(res     != NULL);
+
+   /* default to invalid */
+   *res = 0;
+
+   /* ensure hash is valid */
+   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   hLen        = hash_descriptor[hash_idx].hashsize;
+   modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+   /* check sizes */
+   if ((saltlen > sizeof(salt)) || (modulus_len > sizeof(DB)) || 
+       (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len)) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* ensure the 0xBC byte */
+   if (sig[siglen-1] != 0xBC) {
+      return CRYPT_OK;
+   }
+
+   /* copy out the DB */
+   for (x = 0; x < modulus_len - hLen - 1; x++) {
+      DB[x] = sig[x];
+   }
+
+   /* copy out the hash */
+   for (y = 0; y < hLen; y++) {
+      hash[y] = sig[x++];
+   }
+
+   /* check the MSB */
+   if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - modulus_bitlen))) != 0) {
+      return CRYPT_OK;
+   }
+
+   /* generate mask of length modulus_len - hLen - 1 from hash */
+   if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* xor against DB */
+   for (y = 0; y < (modulus_len - hLen - 1); y++) {
+      DB[y] ^= mask[y];
+   }
+
+   /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
+
+   /* check for zeroes and 0x01 */
+   for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) {
+       if (DB[x] != 0x00) {
+          return CRYPT_OK;
+       }
+   }
+
+   if (DB[x++] != 0x01) {
+      return CRYPT_OK;
+   }
+
+   /* M = (eight) 0x00 || msghash || salt, mask = H(M) */
+   hash_descriptor[hash_idx].init(&md);
+   zeromem(mask, 8);
+   if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* mask == hash means valid signature */
+   if (memcmp(mask, hash, hLen) == 0) {
+      *res = 1;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(DB,   sizeof(DB));   
+   zeromem(mask, sizeof(mask));   
+   zeromem(salt, sizeof(salt));   
+   zeromem(hash, sizeof(hash));   
+#endif
+
+   return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkcs_1_pss_encode.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,122 @@
+/* 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"
+
+/* PKCS #1 PSS Signature Padding -- Tom St Denis */
+
+#ifdef PKCS_1
+
+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)
+{
+   unsigned char DB[1024], mask[sizeof(DB)], salt[sizeof(DB)], hash[sizeof(DB)];
+   unsigned long x, y, hLen, modulus_len;
+   int           err;
+   hash_state    md;
+
+   _ARGCHK(msghash != NULL);
+   _ARGCHK(out     != NULL);
+   _ARGCHK(outlen  != NULL);
+
+   /* ensure hash and PRNG are valid */
+   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   hLen        = hash_descriptor[hash_idx].hashsize;
+   modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+   /* check sizes */
+   if ((saltlen > sizeof(salt)) || (modulus_len > sizeof(DB)) || (modulus_len < hLen + saltlen + 2)) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* generate random salt */
+   if (saltlen > 0) {
+      if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) {
+         return CRYPT_ERROR_READPRNG;
+      }
+   }
+
+   /* M = (eight) 0x00 || msghash || salt, hash = H(M) */
+   hash_descriptor[hash_idx].init(&md);
+   zeromem(DB, 8);
+   if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
+   for (x = 0; x < (modulus_len - saltlen - hLen - 2); x++) {
+       DB[x] = 0x00;
+   }
+   DB[x++] = 0x01;
+   for (y = 0; y < saltlen; y++) {
+      DB[x++] = salt[y];
+   }
+
+   /* generate mask of length modulus_len - hLen - 1 from hash */
+   if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* xor against DB */
+   for (y = 0; y < (modulus_len - hLen - 1); y++) {
+      DB[y] ^= mask[y];
+   }
+
+   /* output is DB || hash || 0xBC */
+   if (*outlen < modulus_len) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* DB */
+   for (y = x = 0; x < modulus_len - hLen - 1; x++) {
+       out[y++] = DB[x];
+   }
+   /* hash */
+   for (x = 0; x < hLen; x++) {
+       out[y++] = hash[x];
+   }
+   /* 0xBC */
+   out[y] = 0xBC;
+
+   /* now clear the 8*modulus_len - modulus_bitlen most significant bits */
+   out[0] &= 0xFF >> ((modulus_len<<3) - modulus_bitlen);
+
+   /* store output size */
+   *outlen = modulus_len;
+
+#ifdef CLEAN_STACK
+   zeromem(DB,   sizeof(DB));   
+   zeromem(mask, sizeof(mask));   
+   zeromem(salt, sizeof(salt));   
+   zeromem(hash, sizeof(hash));   
+#endif
+
+   return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkcs_5_1.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,63 @@
+/* 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>
+
+/* PKCS #5, Algorithm #1 */
+#ifdef PKCS_5
+
+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)
+{
+   int err;
+   unsigned long x;
+   hash_state md;
+   unsigned char buf[MAXBLOCKSIZE];
+
+   _ARGCHK(password != NULL);
+   _ARGCHK(salt     != NULL);
+   _ARGCHK(out      != NULL);
+   _ARGCHK(outlen   != NULL);
+
+   /* test hash IDX */
+   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* hash initial password + salt */
+   hash_descriptor[hash_idx].init(&md);
+   hash_descriptor[hash_idx].process(&md, password, password_len);
+   hash_descriptor[hash_idx].process(&md, salt, 8);
+   hash_descriptor[hash_idx].done(&md, buf);
+
+   while (--iteration_count) {
+      // code goes here.
+      x = sizeof(buf);
+      if ((err = hash_memory(hash_idx, buf, hash_descriptor[hash_idx].hashsize, buf, &x)) != CRYPT_OK) {
+         return err;
+      }
+   }
+
+   /* copy upto outlen bytes */
+   for (x = 0; x < hash_descriptor[hash_idx].hashsize && x < *outlen; x++) {
+       out[x] = buf[x];
+   }
+   *outlen = x;
+
+#ifdef CLEAN_STACK 
+   zeromem(buf, sizeof(buf));
+#endif
+
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkcs_5_2.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,88 @@
+/* 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>
+
+/* PKCS #5, Algorithm #2 */
+#ifdef PKCS_5
+
+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)
+{
+   int err, itts;
+   unsigned long stored, left, x, y, blkno;
+   unsigned char buf[2][MAXBLOCKSIZE];
+   hmac_state    hmac;
+
+   _ARGCHK(password != NULL);
+   _ARGCHK(salt     != NULL);
+   _ARGCHK(out      != NULL);
+   _ARGCHK(outlen   != NULL);
+
+   /* test hash IDX */
+   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   left   = *outlen;
+   blkno  = 1;
+   stored = 0;
+   while (left != 0) {
+       /* process block number blkno */
+       zeromem(buf, sizeof(buf));
+       
+       /* store current block number and increment for next pass */
+       STORE32H(blkno, buf[1]);
+       ++blkno;
+
+       /* get PRF(P, S||int(blkno)) */
+       if ((err = hmac_init(&hmac, hash_idx, password, password_len)) != CRYPT_OK) { 
+          return err; 
+       }
+       if ((err = hmac_process(&hmac, salt, salt_len)) != CRYPT_OK) {
+          return err;
+       }
+       if ((err = hmac_process(&hmac, buf[1], 4)) != CRYPT_OK) {
+          return err;
+       }
+       x = sizeof(buf[0]);
+       if ((err = hmac_done(&hmac, buf[0], &x)) != CRYPT_OK) {
+          return err;
+       }
+
+       /* now compute repeated and XOR it in buf[1] */
+       memcpy(buf[1], buf[0], x);
+       for (itts = 2; itts < iteration_count; ++itts) {
+           if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) {
+              return err;
+           }
+           for (y = 0; y < x; y++) {
+               buf[1][y] ^= buf[0][y];
+           }
+       }
+
+       /* now emit upto x bytes of buf[1] to output */
+       for (y = 0; y < x && left != 0; ++y) {
+           out[stored++] = buf[1][y];
+           --left;
+       }
+   }
+   *outlen = stored;
+
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+   return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pmac_done.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,64 @@
+/* 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
+ */
+
+/* PMAC implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef PMAC
+
+int pmac_done(pmac_state *state, unsigned char *out, unsigned long *outlen)
+{
+   int err, x;
+
+   _ARGCHK(state != NULL);
+   _ARGCHK(out   != NULL);
+   if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) ||
+       (state->block_len > (int)sizeof(state->block)) || (state->buflen > state->block_len)) {
+      return CRYPT_INVALID_ARG;
+   }
+
+
+   /* handle padding.  If multiple xor in L/x */
+
+   if (state->buflen == state->block_len) {
+      /* xor Lr against the checksum */
+      for (x = 0; x < state->block_len; x++) {
+          state->checksum[x] ^= state->block[x] ^ state->Lr[x];
+      }
+   } else {
+      /* otherwise xor message bytes then the 0x80 byte */
+      for (x = 0; x < state->buflen; x++) {
+          state->checksum[x] ^= state->block[x];
+      }
+      state->checksum[x] ^= 0x80;
+   }
+
+   /* encrypt it */
+   cipher_descriptor[state->cipher_idx].ecb_encrypt(state->checksum, state->checksum, &state->key);
+
+   /* store it */
+   for (x = 0; x < state->block_len && x <= (int)*outlen; x++) {
+       out[x] = state->checksum[x];
+   }
+   *outlen = x;
+
+#ifdef CLEAN_STACK
+   zeromem(state, sizeof(*state));
+#endif
+   return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pmac_file.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,67 @@
+/* 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
+ */
+
+/* PMAC implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef PMAC
+
+int pmac_file(int cipher, 
+              const unsigned char *key, unsigned long keylen,
+              const char *filename, 
+                    unsigned char *out, unsigned long *outlen)
+{
+#ifdef NO_FILE
+   return CRYPT_NOP;
+#else
+   int err, x;
+   pmac_state pmac;
+   FILE *in;
+   unsigned char buf[512];
+
+
+   _ARGCHK(key      != NULL);
+   _ARGCHK(filename != NULL);
+   _ARGCHK(out      != NULL);
+   _ARGCHK(outlen   != NULL);
+
+   in = fopen(filename, "rb");
+   if (in == NULL) {
+      return CRYPT_FILE_NOTFOUND;
+   }
+
+   if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) {
+      fclose(in);
+      return err;
+   }
+
+   do {
+      x = fread(buf, 1, sizeof(buf), in);
+      if ((err = pmac_process(&pmac, buf, x)) != CRYPT_OK) {
+         fclose(in);
+         return err;
+      }
+   } while (x == sizeof(buf));
+   fclose(in);
+
+   if ((err = pmac_done(&pmac, out, outlen)) != CRYPT_OK) {
+      return err;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+
+   return CRYPT_OK;
+#endif
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pmac_init.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,114 @@
+/* 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
+ */
+
+/* PMAC implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef PMAC
+
+static const struct {
+    int           len;
+    unsigned char poly_div[MAXBLOCKSIZE], 
+                  poly_mul[MAXBLOCKSIZE];
+} polys[] = {
+{
+    8,
+    { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B }
+}, {
+    16, 
+    { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 }
+}
+};
+
+int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen)
+{
+   int poly, x, y, m, err;
+   unsigned char L[MAXBLOCKSIZE];
+
+   _ARGCHK(pmac  != NULL);
+   _ARGCHK(key   != NULL);
+
+   /* valid cipher? */
+   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* determine which polys to use */
+   pmac->block_len = cipher_descriptor[cipher].block_length;
+   for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) {
+       if (polys[poly].len == pmac->block_len) { 
+          break;
+       }
+   }
+   if (polys[poly].len != pmac->block_len) {
+      return CRYPT_INVALID_ARG;
+   }   
+
+   /* schedule the key */
+   if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &pmac->key)) != CRYPT_OK) {
+      return err;
+   }
+ 
+   /* find L = E[0] */
+   zeromem(L, pmac->block_len);
+   cipher_descriptor[cipher].ecb_encrypt(L, L, &pmac->key);
+
+   /* find Ls[i] = L << i for i == 0..31 */
+   memcpy(pmac->Ls[0], L, pmac->block_len);
+   for (x = 1; x < 32; x++) {
+       m = pmac->Ls[x-1][0] >> 7;
+       for (y = 0; y < pmac->block_len-1; y++) {
+           pmac->Ls[x][y] = ((pmac->Ls[x-1][y] << 1) | (pmac->Ls[x-1][y+1] >> 7)) & 255;
+       }
+       pmac->Ls[x][pmac->block_len-1] = (pmac->Ls[x-1][pmac->block_len-1] << 1) & 255;
+
+       if (m == 1) {
+          for (y = 0; y < pmac->block_len; y++) {
+              pmac->Ls[x][y] ^= polys[poly].poly_mul[y];
+          }
+       }
+    }
+
+    /* find Lr = L / x */
+    m = L[pmac->block_len-1] & 1;
+
+    /* shift right */
+    for (x = pmac->block_len - 1; x > 0; x--) {
+        pmac->Lr[x] = ((L[x] >> 1) | (L[x-1] << 7)) & 255;
+    }
+    pmac->Lr[0] = L[0] >> 1;
+
+    if (m == 1) {
+       for (x = 0; x < pmac->block_len; x++) {
+           pmac->Lr[x] ^= polys[poly].poly_div[x];
+       }
+    }
+
+    /* zero buffer, counters, etc... */
+    pmac->block_index = 1;
+    pmac->cipher_idx  = cipher;
+    pmac->buflen      = 0;
+    zeromem(pmac->block,    sizeof(pmac->block));
+    zeromem(pmac->Li,       sizeof(pmac->Li));
+    zeromem(pmac->checksum, sizeof(pmac->checksum));
+
+#ifdef CLEAN_STACK
+    zeromem(L, sizeof(L));
+#endif
+
+    return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pmac_memory.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,44 @@
+/* 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
+ */
+
+/* PMAC implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef PMAC
+
+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)
+{
+   int err;
+   pmac_state pmac;
+
+   _ARGCHK(key    != NULL);
+   _ARGCHK(msg    != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+
+   if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = pmac_process(&pmac, msg, msglen)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = pmac_done(&pmac, out, outlen)) != CRYPT_OK) {
+      return err;
+   }
+
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pmac_ntz.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,29 @@
+/* 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
+ */
+
+/* PMAC implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef PMAC
+
+int pmac_ntz(unsigned long x)
+{
+   int c;
+   x &= 0xFFFFFFFFUL;
+   c = 0;
+   while ((x & 1) == 0) {
+      ++c;
+      x >>= 1;
+   }
+   return c;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pmac_process.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,62 @@
+/* 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
+ */
+
+/* PMAC implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef PMAC
+
+int pmac_process(pmac_state *state, const unsigned char *buf, unsigned long len)
+{
+   int err, n, x;
+   unsigned char Z[MAXBLOCKSIZE];
+
+   _ARGCHK(state != NULL);
+   _ARGCHK(buf   != NULL);
+   if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) ||
+       (state->block_len > (int)sizeof(state->block)) || (state->buflen > state->block_len)) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   while (len != 0) { 
+       /* ok if the block is full we xor in prev, encrypt and replace prev */
+       if (state->buflen == state->block_len) {
+          pmac_shift_xor(state);
+          for (x = 0; x < state->block_len; x++) {
+              Z[x] = state->Li[x] ^ state->block[x];
+          }
+          cipher_descriptor[state->cipher_idx].ecb_encrypt(Z, Z, &state->key);
+          for (x = 0; x < state->block_len; x++) {
+              state->checksum[x] ^= Z[x];
+          }
+          state->buflen = 0;
+       }
+
+       /* add bytes */
+       n = MIN(len, (unsigned long)(state->block_len - state->buflen));
+       memcpy(state->block + state->buflen, buf, n);
+       state->buflen += n;
+       len           -= n;
+       buf           += n;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(Z, sizeof(Z));
+#endif
+
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pmac_shift_xor.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,26 @@
+/* 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
+ */
+
+/* PMAC implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef PMAC
+
+void pmac_shift_xor(pmac_state *pmac)
+{
+   int x, y;
+   y = pmac_ntz(pmac->block_index++);
+   for (x = 0; x < pmac->block_len; x++) {
+       pmac->Li[x] ^= pmac->Ls[y][x];
+   }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pmac_test.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,153 @@
+/* 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
+ */
+
+/* PMAC implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef PMAC
+
+int pmac_test(void)
+{
+#if !defined(LTC_TEST)
+    return CRYPT_NOP;
+#else
+    static const struct { 
+        int msglen;
+        unsigned char key[16], msg[34], tag[16];
+    } tests[] = {
+
+   /* PMAC-AES-128-0B */
+{
+   0,
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* msg */
+   { 0x00 },
+   /* tag */
+   { 0x43, 0x99, 0x57, 0x2c, 0xd6, 0xea, 0x53, 0x41,
+     0xb8, 0xd3, 0x58, 0x76, 0xa7, 0x09, 0x8a, 0xf7 }
+},
+
+   /* PMAC-AES-128-3B */
+{
+   3,
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* msg */
+   { 0x00, 0x01, 0x02 },
+   /* tag */
+   { 0x25, 0x6b, 0xa5, 0x19, 0x3c, 0x1b, 0x99, 0x1b,
+     0x4d, 0xf0, 0xc5, 0x1f, 0x38, 0x8a, 0x9e, 0x27 }
+},
+
+   /* PMAC-AES-128-16B */
+{
+   16,
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* msg */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* tag */
+   { 0xeb, 0xbd, 0x82, 0x2f, 0xa4, 0x58, 0xda, 0xf6,
+     0xdf, 0xda, 0xd7, 0xc2, 0x7d, 0xa7, 0x63, 0x38 }
+},
+
+   /* PMAC-AES-128-20B */
+{
+   20,
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* msg */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+     0x10, 0x11, 0x12, 0x13 },
+   /* tag */
+   { 0x04, 0x12, 0xca, 0x15, 0x0b, 0xbf, 0x79, 0x05,
+     0x8d, 0x8c, 0x75, 0xa5, 0x8c, 0x99, 0x3f, 0x55 }
+},
+
+   /* PMAC-AES-128-32B */
+{
+   32,
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* msg */
+   { 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 },
+   /* tag */
+   { 0xe9, 0x7a, 0xc0, 0x4e, 0x9e, 0x5e, 0x33, 0x99,
+     0xce, 0x53, 0x55, 0xcd, 0x74, 0x07, 0xbc, 0x75 }
+},
+
+   /* PMAC-AES-128-34B */
+{
+   34,
+   /* key */
+   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+   /* msg */
+   { 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,
+     0x20, 0x21 },
+   /* tag */
+   { 0x5c, 0xba, 0x7d, 0x5e, 0xb2, 0x4f, 0x7c, 0x86,
+     0xcc, 0xc5, 0x46, 0x04, 0xe5, 0x3d, 0x55, 0x12 }
+}
+
+};
+   int err, x, idx;
+   unsigned long len;
+   unsigned char outtag[MAXBLOCKSIZE];
+
+    /* AES can be under rijndael or aes... try to find it */ 
+    if ((idx = find_cipher("aes")) == -1) {
+       if ((idx = find_cipher("rijndael")) == -1) {
+          return CRYPT_NOP;
+       }
+    }
+
+    for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+        len = sizeof(outtag);
+        if ((err = pmac_memory(idx, tests[x].key, 16, tests[x].msg, tests[x].msglen, outtag, &len)) != CRYPT_OK) {
+           return err;
+        }
+        
+        if (memcmp(outtag, tests[x].tag, len)) {
+#if 0
+           unsigned long y;
+           printf("\nTAG:\n");
+           for (y = 0; y < len; ) {
+               printf("0x%02x", outtag[y]);
+               if (y < len-1) printf(", ");
+               if (!(++y % 8)) printf("\n");
+           }
+#endif
+           return CRYPT_FAIL_TESTVECTOR;
+        }
+     }
+     return CRYPT_OK;
+#endif /* LTC_TEST */
+}
+
+#endif /* PMAC_MODE */
+
+
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rand_prime.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,65 @@
+/* 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 MPI
+
+struct rng_data {
+   prng_state *prng;
+   int         wprng;
+};
+
+static int rand_prime_helper(unsigned char *dst, int len, void *dat)
+{
+   return (int)prng_descriptor[((struct rng_data *)dat)->wprng].read(dst, len, ((struct rng_data *)dat)->prng);
+}
+
+int rand_prime(mp_int *N, long len, prng_state *prng, int wprng)
+{
+   struct rng_data rng;
+   int             type, err;
+
+   _ARGCHK(N != NULL);
+
+   /* allow sizes between 2 and 256 bytes for a prime size */
+   if (len < 16 || len > 4096) { 
+      return CRYPT_INVALID_PRIME_SIZE;
+   }
+   
+   /* valid PRNG? Better be! */
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err; 
+   }
+
+   /* setup our callback data, then world domination! */
+   rng.prng  = prng;
+   rng.wprng = wprng;
+
+   /* get type */
+   if (len < 0) {
+      type = LTM_PRIME_BBS;
+      len = -len;
+   } else {
+      type = 0;
+   }
+
+   /* New prime generation makes the code even more cryptoish-insane.  Do you know what this means!!!
+      -- Gir:  Yeah, oh wait, er, no.
+    */
+   if ((err = mp_prime_random_ex(N, mp_prime_rabin_miller_trials(len), len, type, rand_prime_helper, &rng)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+
+   return CRYPT_OK;
+}
+      
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rc2.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,319 @@
+/* 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
+ */
+/**********************************************************************\
+* To commemorate the 1996 RSA Data Security Conference, the following  *
+* code is released into the public domain by its author.  Prost!       *
+*                                                                      *
+* This cipher uses 16-bit words and little-endian byte ordering.       *
+* I wonder which processor it was optimized for?                       *
+*                                                                      *
+* Thanks to CodeView, SoftIce, and D86 for helping bring this code to  *
+* the public.                                                          *
+\**********************************************************************/
+
+#include <mycrypt.h>
+
+#ifdef RC2
+
+const struct _cipher_descriptor rc2_desc = {
+   "rc2",
+   12, 8, 128, 8, 16,
+   &rc2_setup,
+   &rc2_ecb_encrypt,
+   &rc2_ecb_decrypt,
+   &rc2_test,
+   &rc2_keysize
+};
+
+
+/**********************************************************************\
+* Expand a variable-length user key (between 1 and 128 bytes) to a     *
+* 64-short working rc2 key, of at most "bits" effective key bits.      *
+* The effective key bits parameter looks like an export control hack.  *
+* For normal use, it should always be set to 1024.  For convenience,   *
+* zero is accepted as an alias for 1024.                               *
+\**********************************************************************/
+
+   /* 256-entry permutation table, probably derived somehow from pi */
+    static const unsigned char permute[256] = {
+        217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157,
+        198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162,
+         23,154, 89,245,135,179, 79, 19, 97, 69,109,141,  9,129,125, 50,
+        189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130,
+         84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220,
+         18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38,
+        111,191, 14,218, 70,105,  7, 87, 39,242, 29,155,188,148, 67,  3,
+        248, 17,199,246,144,239, 62,231,  6,195,213, 47,200,102, 30,215,
+          8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42,
+        150, 26,210,113, 90, 21, 73,116, 75,159,208, 94,  4, 24,164,236,
+        194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57,
+        153,124, 58,133, 35,184,180,122,252,  2, 54, 91, 37, 85,151, 49,
+         45, 93,250,152,227,138,146,174,  5,223, 41, 16,103,108,186,201,
+        211,  0,230,207,225,158,168, 44, 99, 22,  1, 63, 88,226,137,169,
+         13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46,
+        197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173
+    };
+
+int rc2_setup(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
+{
+   unsigned *xkey = skey->rc2.xkey;
+   unsigned char tmp[128];
+   unsigned T8, TM;
+   int i, bits;
+
+   _ARGCHK(key  != NULL);
+   _ARGCHK(skey != NULL);
+
+   if (keylen < 8 || keylen > 128) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+
+   if (rounds != 0 && rounds != 16) {
+      return CRYPT_INVALID_ROUNDS;
+   }
+
+   for (i = 0; i < keylen; i++) {
+       tmp[i] = key[i] & 255;
+   }
+
+    /* Phase 1: Expand input key to 128 bytes */
+    if (keylen < 128) {
+        for (i = keylen; i < 128; i++) {
+            tmp[i] = permute[(int)((tmp[i - 1] + tmp[i - keylen]) & 255)];
+        }
+    }
+    
+    /* Phase 2 - reduce effective key size to "bits" */
+    bits = keylen*8;
+    T8   = (unsigned)(bits+7)>>3;
+    TM   = (255 >> (unsigned)(7 & -bits));
+    tmp[128 - T8] = permute[(int)(tmp[128 - T8] & TM)];
+    for (i = 127 - T8; i >= 0; i--) {
+        tmp[i] = permute[(int)(tmp[i + 1] ^ tmp[i + T8])];
+    }
+
+    /* Phase 3 - copy to xkey in little-endian order */
+    i = 63;
+    do {
+        xkey[i] =  (unsigned)tmp[2*i] + ((unsigned)tmp[2*i+1] << 8);
+    } while (i-- > 0);
+
+#ifdef CLEAN_STACK
+    zeromem(tmp, sizeof(tmp));
+#endif
+    
+    return CRYPT_OK;
+}
+
+/**********************************************************************\
+* Encrypt an 8-byte block of plaintext using the given key.            *
+\**********************************************************************/
+#ifdef CLEAN_STACK
+static void _rc2_ecb_encrypt( const unsigned char *plain,
+                            unsigned char *cipher,
+                            symmetric_key *skey)
+#else
+void rc2_ecb_encrypt( const unsigned char *plain,
+                            unsigned char *cipher,
+                            symmetric_key *skey)
+#endif
+{
+    unsigned *xkey;
+    unsigned x76, x54, x32, x10, i;
+
+    _ARGCHK(plain != NULL);
+    _ARGCHK(cipher != NULL);
+    _ARGCHK(skey != NULL);
+
+    xkey = skey->rc2.xkey;
+
+    x76 = ((unsigned)plain[7] << 8) + (unsigned)plain[6];
+    x54 = ((unsigned)plain[5] << 8) + (unsigned)plain[4];
+    x32 = ((unsigned)plain[3] << 8) + (unsigned)plain[2];
+    x10 = ((unsigned)plain[1] << 8) + (unsigned)plain[0];
+
+    for (i = 0; i < 16; i++) {
+        x10 = (x10 + (x32 & ~x76) + (x54 & x76) + xkey[4*i+0]) & 0xFFFF;
+        x10 = ((x10 << 1) | (x10 >> 15)) & 0xFFFF;
+
+        x32 = (x32 + (x54 & ~x10) + (x76 & x10) + xkey[4*i+1]) & 0xFFFF;
+        x32 = ((x32 << 2) | (x32 >> 14)) & 0xFFFF;
+
+        x54 = (x54 + (x76 & ~x32) + (x10 & x32) + xkey[4*i+2]) & 0xFFFF;
+        x54 = ((x54 << 3) | (x54 >> 13)) & 0xFFFF;
+
+        x76 = (x76 + (x10 & ~x54) + (x32 & x54) + xkey[4*i+3]) & 0xFFFF;
+        x76 = ((x76 << 5) | (x76 >> 11)) & 0xFFFF;
+
+        if (i == 4 || i == 10) {
+            x10 = (x10 + xkey[x76 & 63]) & 0xFFFF;
+            x32 = (x32 + xkey[x10 & 63]) & 0xFFFF;
+            x54 = (x54 + xkey[x32 & 63]) & 0xFFFF;
+            x76 = (x76 + xkey[x54 & 63]) & 0xFFFF;
+        }
+    }
+
+    cipher[0] = (unsigned char)x10;
+    cipher[1] = (unsigned char)(x10 >> 8);
+    cipher[2] = (unsigned char)x32;
+    cipher[3] = (unsigned char)(x32 >> 8);
+    cipher[4] = (unsigned char)x54;
+    cipher[5] = (unsigned char)(x54 >> 8);
+    cipher[6] = (unsigned char)x76;
+    cipher[7] = (unsigned char)(x76 >> 8);
+}
+
+#ifdef CLEAN_STACK
+void rc2_ecb_encrypt( const unsigned char *plain,
+                            unsigned char *cipher,
+                            symmetric_key *skey)
+{
+    _rc2_ecb_encrypt(plain, cipher, skey);
+    burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 5);
+}
+#endif
+
+/**********************************************************************\
+* Decrypt an 8-byte block of ciphertext using the given key.           *
+\**********************************************************************/
+
+#ifdef CLEAN_STACK
+static void _rc2_ecb_decrypt( const unsigned char *cipher,
+                            unsigned char *plain,
+                            symmetric_key *skey)
+#else
+void rc2_ecb_decrypt( const unsigned char *cipher,
+                            unsigned char *plain,
+                            symmetric_key *skey)
+#endif
+{
+    unsigned x76, x54, x32, x10;
+    unsigned *xkey;
+    int i;
+
+    _ARGCHK(plain != NULL);
+    _ARGCHK(cipher != NULL);
+    _ARGCHK(skey != NULL);
+
+    xkey = skey->rc2.xkey;
+
+    x76 = ((unsigned)cipher[7] << 8) + (unsigned)cipher[6];
+    x54 = ((unsigned)cipher[5] << 8) + (unsigned)cipher[4];
+    x32 = ((unsigned)cipher[3] << 8) + (unsigned)cipher[2];
+    x10 = ((unsigned)cipher[1] << 8) + (unsigned)cipher[0];
+
+    for (i = 15; i >= 0; i--) {
+        if (i == 4 || i == 10) {
+            x76 = (x76 - xkey[x54 & 63]) & 0xFFFF;
+            x54 = (x54 - xkey[x32 & 63]) & 0xFFFF;
+            x32 = (x32 - xkey[x10 & 63]) & 0xFFFF;
+            x10 = (x10 - xkey[x76 & 63]) & 0xFFFF;
+        }
+
+        x76 = ((x76 << 11) | (x76 >> 5)) & 0xFFFF;
+        x76 = (x76 - ((x10 & ~x54) + (x32 & x54) + xkey[4*i+3])) & 0xFFFF;
+
+        x54 = ((x54 << 13) | (x54 >> 3)) & 0xFFFF;
+        x54 = (x54 - ((x76 & ~x32) + (x10 & x32) + xkey[4*i+2])) & 0xFFFF;
+
+        x32 = ((x32 << 14) | (x32 >> 2)) & 0xFFFF;
+        x32 = (x32 - ((x54 & ~x10) + (x76 & x10) + xkey[4*i+1])) & 0xFFFF;
+
+        x10 = ((x10 << 15) | (x10 >> 1)) & 0xFFFF;
+        x10 = (x10 - ((x32 & ~x76) + (x54 & x76) + xkey[4*i+0])) & 0xFFFF;
+    }
+
+    plain[0] = (unsigned char)x10;
+    plain[1] = (unsigned char)(x10 >> 8);
+    plain[2] = (unsigned char)x32;
+    plain[3] = (unsigned char)(x32 >> 8);
+    plain[4] = (unsigned char)x54;
+    plain[5] = (unsigned char)(x54 >> 8);
+    plain[6] = (unsigned char)x76;
+    plain[7] = (unsigned char)(x76 >> 8);
+}
+
+#ifdef CLEAN_STACK
+void rc2_ecb_decrypt( const unsigned char *cipher,
+                            unsigned char *plain,
+                            symmetric_key *skey)
+{
+    _rc2_ecb_decrypt(cipher, plain, skey);
+    burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 4 + sizeof(int));
+}
+#endif
+
+int rc2_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+   static const struct {
+        int keylen;
+        unsigned char key[16], pt[8], ct[8];
+   } tests[] = {
+
+   { 8,
+     { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+     { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+     { 0x30, 0x64, 0x9e, 0xdf, 0x9b, 0xe7, 0xd2, 0xc2 }
+
+   },
+   { 16,
+     { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f,
+       0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 },
+     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+     { 0x22, 0x69, 0x55, 0x2a, 0xb0, 0xf8, 0x5c, 0xa6 }
+   }
+  };
+    int x, y, err;
+    symmetric_key skey;
+    unsigned char tmp[2][8];
+
+    for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
+        zeromem(tmp, sizeof(tmp));
+        if ((err = rc2_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) {
+           return err;
+        }
+        
+        rc2_ecb_encrypt(tests[x].pt, tmp[0], &skey);
+        rc2_ecb_decrypt(tmp[0], tmp[1], &skey);
+        
+        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++) rc2_ecb_encrypt(tmp[0], tmp[0], &skey);
+      for (y = 0; y < 1000; y++) rc2_ecb_decrypt(tmp[0], tmp[0], &skey);
+      for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+    }
+    return CRYPT_OK;
+   #endif
+}
+
+int rc2_keysize(int *keysize)
+{
+   _ARGCHK(keysize != NULL);
+   if (*keysize < 8) {
+       return CRYPT_INVALID_KEYSIZE;
+   } else if (*keysize > 128) {
+       *keysize = 128;
+   }
+   return CRYPT_OK;
+}
+
+#endif
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rc4.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,107 @@
+/* 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 RC4
+
+const struct _prng_descriptor rc4_desc = 
+{
+   "rc4",
+    &rc4_start,
+    &rc4_add_entropy,
+    &rc4_ready,
+    &rc4_read
+};
+
+int rc4_start(prng_state *prng)
+{
+    _ARGCHK(prng != NULL);
+
+    /* set keysize to zero */
+    prng->rc4.x = 0;
+    
+    return CRYPT_OK;
+}
+
+int rc4_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
+{
+    _ARGCHK(buf != NULL);
+    _ARGCHK(prng != NULL);
+
+    if (prng->rc4.x + len > 256) {
+       return CRYPT_INVALID_KEYSIZE;
+    }
+
+    while (len--) {
+       prng->rc4.buf[prng->rc4.x++] = *buf++;
+    }
+
+    return CRYPT_OK;
+    
+}
+
+int rc4_ready(prng_state *prng)
+{
+    unsigned char key[256], tmp;
+    int keylen, x, y;
+
+    _ARGCHK(prng != NULL);
+
+    /* extract the key */
+    memcpy(key, prng->rc4.buf, 256);
+    keylen = prng->rc4.x;
+
+    /* make RC4 perm and shuffle */
+    for (x = 0; x < 256; x++) {
+        prng->rc4.buf[x] = x;
+    }
+
+    for (x = y = 0; x < 256; x++) {
+        y = (y + prng->rc4.buf[x] + key[x % keylen]) & 255;
+        tmp = prng->rc4.buf[x]; prng->rc4.buf[x] = prng->rc4.buf[y]; prng->rc4.buf[y] = tmp;
+    }
+    prng->rc4.x = x;
+    prng->rc4.y = y;
+
+#ifdef CLEAN_STACK
+    zeromem(key, sizeof(key));
+#endif
+
+    return CRYPT_OK;
+}
+
+unsigned long rc4_read(unsigned char *buf, unsigned long len, prng_state *prng)
+{
+   int x, y; 
+   unsigned char *s, tmp;
+   unsigned long n;
+
+   _ARGCHK(buf != NULL);
+   _ARGCHK(prng != NULL);
+
+   n = len;
+   x = prng->rc4.x;
+   y = prng->rc4.y;
+   s = prng->rc4.buf;
+   while (len--) {
+      x = (x + 1) & 255;
+      y = (y + s[x]) & 255;
+      tmp = s[x]; s[x] = s[y]; s[y] = tmp;
+      tmp = (s[x] + s[y]) & 255;
+      *buf++ ^= s[tmp];
+   }
+   prng->rc4.x = x;
+   prng->rc4.y = y;
+   return n;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rc5.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,269 @@
+/* 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
+ */
+
+/* RC5 code by Tom St Denis */
+
+#include "mycrypt.h"
+
+#ifdef RC5
+
+const struct _cipher_descriptor rc5_desc =
+{
+    "rc5",
+    2,
+    8, 128, 8, 12,
+    &rc5_setup,
+    &rc5_ecb_encrypt,
+    &rc5_ecb_decrypt,
+    &rc5_test,
+    &rc5_keysize
+};
+
+static const ulong32 stab[50] = {
+0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL,
+0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL,
+0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL,
+0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL,
+0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL,
+0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL, 0xe96a3d2fUL, 0x87a1b6e8UL, 0x25d930a1UL, 0xc410aa5aUL,
+0x62482413UL, 0x007f9dccUL
+};
+
+#ifdef CLEAN_STACK
+static int _rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#else
+int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#endif
+{
+    ulong32 L[64], *S, A, B, i, j, v, s, t, l;
+
+    _ARGCHK(skey != NULL);
+    _ARGCHK(key  != NULL);
+    
+    /* test parameters */
+    if (num_rounds == 0) { 
+       num_rounds = rc5_desc.default_rounds;
+    }
+
+    if (num_rounds < 12 || num_rounds > 24) { 
+       return CRYPT_INVALID_ROUNDS;
+    }
+
+    /* key must be between 64 and 1024 bits */
+    if (keylen < 8 || keylen > 128) {
+       return CRYPT_INVALID_KEYSIZE;
+    }
+    
+    skey->rc5.rounds = num_rounds;
+    S = skey->rc5.K;
+
+    /* copy the key into the L array */
+    for (A = i = j = 0; i < (ulong32)keylen; ) { 
+        A = (A << 8) | ((ulong32)(key[i++] & 255));
+        if ((i & 3) == 0) {
+           L[j++] = BSWAP(A);
+           A = 0;
+        }
+    }
+
+    if ((keylen & 3) != 0) { 
+       A <<= (ulong32)((8 * (4 - (keylen&3)))); 
+       L[j++] = BSWAP(A);
+    }
+
+    /* setup the S array */
+    t = (ulong32)(2 * (num_rounds + 1));
+    memcpy(S, stab, t * sizeof(*S));
+
+    /* mix buffer */
+    s = 3 * MAX(t, j);
+    l = j;
+    for (A = B = i = j = v = 0; v < s; v++) { 
+        A = S[i] = ROL(S[i] + A + B, 3);
+        B = L[j] = ROL(L[j] + A + B, (A+B));
+        if (++i == t) { i = 0; }
+        if (++j == l) { j = 0; }
+    }
+    return CRYPT_OK;
+}
+
+#ifdef CLEAN_STACK
+int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+   int x;
+   x = _rc5_setup(key, keylen, num_rounds, skey);
+   burn_stack(sizeof(ulong32) * 122 + sizeof(int));
+   return x;
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#else
+void rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#endif
+{
+   ulong32 A, B, *K;
+   int r;
+   _ARGCHK(key != NULL);
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+
+   LOAD32L(A, &pt[0]);
+   LOAD32L(B, &pt[4]);
+   A += key->rc5.K[0];
+   B += key->rc5.K[1];
+   K  = key->rc5.K + 2;
+   
+   if ((key->rc5.rounds & 1) == 0) {
+      for (r = 0; r < key->rc5.rounds; r += 2) {
+          A = ROL(A ^ B, B) + K[0];
+          B = ROL(B ^ A, A) + K[1];
+          A = ROL(A ^ B, B) + K[2];
+          B = ROL(B ^ A, A) + K[3];
+          K += 4;
+      }
+   } else {
+      for (r = 0; r < key->rc5.rounds; r++) {
+          A = ROL(A ^ B, B) + K[0];
+          B = ROL(B ^ A, A) + K[1];
+          K += 2;
+      }
+   }
+   STORE32L(A, &ct[0]);
+   STORE32L(B, &ct[4]);
+}
+
+#ifdef CLEAN_STACK
+void rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+{
+   _rc5_ecb_encrypt(pt, ct, key);
+   burn_stack(sizeof(ulong32) * 2 + sizeof(int));
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#else
+void rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#endif
+{
+   ulong32 A, B, *K;
+   int r;
+   _ARGCHK(key != NULL);
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+
+   LOAD32L(A, &ct[0]);
+   LOAD32L(B, &ct[4]);
+   K = key->rc5.K + (key->rc5.rounds << 1);
+   
+   if ((key->rc5.rounds & 1) == 0) {
+       K -= 2;
+       for (r = key->rc5.rounds - 1; r >= 0; r -= 2) {
+          B = ROR(B - K[3], A) ^ A;
+          A = ROR(A - K[2], B) ^ B;
+          B = ROR(B - K[1], A) ^ A;
+          A = ROR(A - K[0], B) ^ B;
+          K -= 4;
+        }
+   } else {
+      for (r = key->rc5.rounds - 1; r >= 0; r--) {
+          B = ROR(B - K[1], A) ^ A;
+          A = ROR(A - K[0], B) ^ B;
+          K -= 2;
+      }
+   }
+   A -= key->rc5.K[0];
+   B -= key->rc5.K[1];
+   STORE32L(A, &pt[0]);
+   STORE32L(B, &pt[4]);
+}
+
+#ifdef CLEAN_STACK
+void rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+{
+   _rc5_ecb_decrypt(ct, pt, key);
+   burn_stack(sizeof(ulong32) * 2 + sizeof(int));
+}
+#endif
+
+int rc5_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+   static const struct {
+       unsigned char key[16], pt[8], ct[8];
+   } tests[] = {
+   {
+       { 0x91, 0x5f, 0x46, 0x19, 0xbe, 0x41, 0xb2, 0x51,
+         0x63, 0x55, 0xa5, 0x01, 0x10, 0xa9, 0xce, 0x91 },
+       { 0x21, 0xa5, 0xdb, 0xee, 0x15, 0x4b, 0x8f, 0x6d },
+       { 0xf7, 0xc0, 0x13, 0xac, 0x5b, 0x2b, 0x89, 0x52 }
+   },
+   {
+       { 0x78, 0x33, 0x48, 0xe7, 0x5a, 0xeb, 0x0f, 0x2f,
+         0xd7, 0xb1, 0x69, 0xbb, 0x8d, 0xc1, 0x67, 0x87 },
+       { 0xF7, 0xC0, 0x13, 0xAC, 0x5B, 0x2B, 0x89, 0x52 },
+       { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 }
+   },
+   {
+       { 0xDC, 0x49, 0xdb, 0x13, 0x75, 0xa5, 0x58, 0x4f,
+         0x64, 0x85, 0xb4, 0x13, 0xb5, 0xf1, 0x2b, 0xaf },
+       { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 },
+       { 0x65, 0xc1, 0x78, 0xb2, 0x84, 0xd1, 0x97, 0xcc }
+   }
+   };
+   unsigned char tmp[2][8];
+   int x, y, err;
+   symmetric_key key;
+
+   for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
+      /* setup key */
+      if ((err = rc5_setup(tests[x].key, 16, 12, &key)) != CRYPT_OK) {
+         return err;
+      }
+
+      /* encrypt and decrypt */
+      rc5_ecb_encrypt(tests[x].pt, tmp[0], &key);
+      rc5_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++) rc5_ecb_encrypt(tmp[0], tmp[0], &key);
+      for (y = 0; y < 1000; y++) rc5_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 rc5_keysize(int *desired_keysize)
+{
+   _ARGCHK(desired_keysize != NULL);
+   if (*desired_keysize < 8) {
+      return CRYPT_INVALID_KEYSIZE;
+   } else if (*desired_keysize > 128) {
+      *desired_keysize = 128;
+   }
+   return CRYPT_OK;
+}
+
+#endif
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rc6.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,298 @@
+/* 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
+ */
+
+/* RC6 code by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef RC6
+
+const struct _cipher_descriptor rc6_desc =
+{
+    "rc6",
+    3,
+    8, 128, 16, 20,
+    &rc6_setup,
+    &rc6_ecb_encrypt,
+    &rc6_ecb_decrypt,
+    &rc6_test,
+    &rc6_keysize
+};
+
+static const ulong32 stab[44] = {
+0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL,
+0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL,
+0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL,
+0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL,
+0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL,
+0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL };
+
+#ifdef CLEAN_STACK
+static int _rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#else
+int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#endif
+{
+    ulong32 L[64], S[50], A, B, i, j, v, s, l;
+
+    _ARGCHK(key != NULL);
+    _ARGCHK(skey != NULL);
+
+    /* test parameters */
+    if (num_rounds != 0 && num_rounds != 20) { 
+       return CRYPT_INVALID_ROUNDS;
+    }
+
+    /* key must be between 64 and 1024 bits */
+    if (keylen < 8 || keylen > 128) {
+       return CRYPT_INVALID_KEYSIZE;
+    }
+
+    /* copy the key into the L array */
+    for (A = i = j = 0; i < (ulong32)keylen; ) { 
+        A = (A << 8) | ((ulong32)(key[i++] & 255));
+        if (!(i & 3)) {
+           L[j++] = BSWAP(A);
+           A = 0;
+        }
+    }
+
+    /* handle odd sized keys */
+    if (keylen & 3) { 
+       A <<= (8 * (4 - (keylen&3))); 
+       L[j++] = BSWAP(A); 
+    }
+
+    /* setup the S array */
+    memcpy(S, stab, 44 * sizeof(stab[0]));
+
+    /* mix buffer */
+    s = 3 * MAX(44, j);
+    l = j;
+    for (A = B = i = j = v = 0; v < s; v++) { 
+        A = S[i] = ROL(S[i] + A + B, 3);
+        B = L[j] = ROL(L[j] + A + B, (A+B));
+        if (++i == 44) { i = 0; }
+        if (++j == l)  { j = 0; }
+    }
+    
+    /* copy to key */
+    for (i = 0; i < 44; i++) { 
+        skey->rc6.K[i] = S[i];
+    }
+    return CRYPT_OK;
+}
+
+#ifdef CLEAN_STACK
+int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+   int x;
+   x = _rc6_setup(key, keylen, num_rounds, skey);
+   burn_stack(sizeof(ulong32) * 122);
+   return x;
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#else
+void rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#endif
+{
+   ulong32 a,b,c,d,t,u, *K;
+   int r;
+   
+   _ARGCHK(key != NULL);
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   LOAD32L(a,&pt[0]);LOAD32L(b,&pt[4]);LOAD32L(c,&pt[8]);LOAD32L(d,&pt[12]);
+
+   b += key->rc6.K[0];
+   d += key->rc6.K[1];
+
+#define RND(a,b,c,d) \
+       t = (b * (b + b + 1)); t = ROL(t, 5); \
+       u = (d * (d + d + 1)); u = ROL(u, 5); \
+       a = ROL(a^t,u) + K[0];                \
+       c = ROL(c^u,t) + K[1]; K += 2;   
+    
+   K = key->rc6.K + 2;
+   for (r = 0; r < 20; r += 4) {
+       RND(a,b,c,d);
+       RND(b,c,d,a);
+       RND(c,d,a,b);
+       RND(d,a,b,c);
+   }
+   
+#undef RND
+
+   a += key->rc6.K[42];
+   c += key->rc6.K[43];
+   STORE32L(a,&ct[0]);STORE32L(b,&ct[4]);STORE32L(c,&ct[8]);STORE32L(d,&ct[12]);
+}
+
+#ifdef CLEAN_STACK
+void rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+{
+   _rc6_ecb_encrypt(pt, ct, key);
+   burn_stack(sizeof(ulong32) * 6 + sizeof(int));
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#else
+void rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#endif
+{
+   ulong32 a,b,c,d,t,u, *K;
+   int r;
+
+   _ARGCHK(key != NULL);
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   
+   LOAD32L(a,&ct[0]);LOAD32L(b,&ct[4]);LOAD32L(c,&ct[8]);LOAD32L(d,&ct[12]);
+   a -= key->rc6.K[42];
+   c -= key->rc6.K[43];
+   
+#define RND(a,b,c,d) \
+       t = (b * (b + b + 1)); t = ROL(t, 5); \
+       u = (d * (d + d + 1)); u = ROL(u, 5); \
+       c = ROR(c - K[1], t) ^ u; \
+       a = ROR(a - K[0], u) ^ t; K -= 2;
+   
+   K = key->rc6.K + 40;
+   
+   for (r = 0; r < 20; r += 4) {
+       RND(d,a,b,c);
+       RND(c,d,a,b);
+       RND(b,c,d,a);
+       RND(a,b,c,d);
+   }
+   
+#undef RND
+
+   b -= key->rc6.K[0];
+   d -= key->rc6.K[1];
+   STORE32L(a,&pt[0]);STORE32L(b,&pt[4]);STORE32L(c,&pt[8]);STORE32L(d,&pt[12]);
+}
+
+#ifdef CLEAN_STACK
+void rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+{
+   _rc6_ecb_decrypt(ct, pt, key);
+   burn_stack(sizeof(ulong32) * 6 + sizeof(int));
+}
+#endif
+
+int rc6_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+   static const struct {
+       int keylen;
+       unsigned char key[32], pt[16], ct[16];
+   } tests[] = {
+   {
+       16,
+       { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+         0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+       { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79,
+         0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 },
+       { 0x52, 0x4e, 0x19, 0x2f, 0x47, 0x15, 0xc6, 0x23,
+         0x1f, 0x51, 0xf6, 0x36, 0x7e, 0xa4, 0x3f, 0x18 }
+   },
+   {
+       24,
+       { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+         0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
+         0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+       { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79,
+         0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 },
+       { 0x68, 0x83, 0x29, 0xd0, 0x19, 0xe5, 0x05, 0x04,
+         0x1e, 0x52, 0xe9, 0x2a, 0xf9, 0x52, 0x91, 0xd4 }
+   },
+   {
+       32,
+       { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+         0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
+         0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0,
+         0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe },
+       { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79,
+         0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 },
+       { 0xc8, 0x24, 0x18, 0x16, 0xf0, 0xd7, 0xe4, 0x89,
+         0x20, 0xad, 0x16, 0xa1, 0x67, 0x4e, 0x5d, 0x48 }
+   }
+   };
+   unsigned char tmp[2][16];
+   int x, y, err;
+   symmetric_key key;
+
+   for (x  = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
+      /* setup key */
+      if ((err = rc6_setup(tests[x].key, tests[x].keylen, 0, &key)) != CRYPT_OK) {
+         return err;
+      }
+
+      /* encrypt and decrypt */
+      rc6_ecb_encrypt(tests[x].pt, tmp[0], &key);
+      rc6_ecb_decrypt(tmp[0], tmp[1], &key);
+
+      /* compare */
+      if (memcmp(tmp[0], tests[x].ct, 16) || memcmp(tmp[1], tests[x].pt, 16)) {
+#if 0
+         printf("\n\nFailed test %d\n", x);
+         if (memcmp(tmp[0], tests[x].ct, 16)) {
+            printf("Ciphertext:  ");
+            for (y = 0; y < 16; y++) printf("%02x ", tmp[0][y]);
+            printf("\nExpected  :  ");
+            for (y = 0; y < 16; y++) printf("%02x ", tests[x].ct[y]);
+            printf("\n");
+         }
+         if (memcmp(tmp[1], tests[x].pt, 16)) {
+            printf("Plaintext:  ");
+            for (y = 0; y < 16; y++) printf("%02x ", tmp[0][y]);
+            printf("\nExpected :  ");
+            for (y = 0; y < 16; y++) printf("%02x ", tests[x].pt[y]);
+            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++) rc6_ecb_encrypt(tmp[0], tmp[0], &key);
+      for (y = 0; y < 1000; y++) rc6_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 rc6_keysize(int *desired_keysize)
+{
+   _ARGCHK(desired_keysize != NULL);
+   if (*desired_keysize < 8) {
+      return CRYPT_INVALID_KEYSIZE;
+   } else if (*desired_keysize > 128) {
+      *desired_keysize = 128;
+   }
+   return CRYPT_OK;
+}
+
+#endif /*RC6*/
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rmd128.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,368 @@
+/* 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 RIPEMD-128 based on the source by Antoon Bosselaers, ESAT-COSIC
+ *
+ * This source has been radically overhauled to be portable and work within
+ * the LibTomCrypt API by Tom St Denis
+ */
+#include "mycrypt.h"
+
+#ifdef RIPEMD128
+
+const struct _hash_descriptor rmd128_desc =
+{
+    "rmd128",
+    8,
+    16,
+    64,
+    &rmd128_init,
+    &rmd128_process,
+    &rmd128_done,
+    &rmd128_test
+};
+
+/* the four basic functions F(), G() and H() */
+#define F(x, y, z)        ((x) ^ (y) ^ (z)) 
+#define G(x, y, z)        (((x) & (y)) | (~(x) & (z))) 
+#define H(x, y, z)        (((x) | ~(y)) ^ (z))
+#define I(x, y, z)        (((x) & (z)) | ((y) & ~(z))) 
+  
+/* the eight basic operations FF() through III() */
+#define FF(a, b, c, d, x, s)        \
+      (a) += F((b), (c), (d)) + (x);\
+      (a) = ROL((a), (s));
+
+#define GG(a, b, c, d, x, s)        \
+      (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
+      (a) = ROL((a), (s));
+
+#define HH(a, b, c, d, x, s)        \
+      (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
+      (a) = ROL((a), (s));
+
+#define II(a, b, c, d, x, s)        \
+      (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
+      (a) = ROL((a), (s));
+
+#define FFF(a, b, c, d, x, s)        \
+      (a) += F((b), (c), (d)) + (x);\
+      (a) = ROL((a), (s));
+
+#define GGG(a, b, c, d, x, s)        \
+      (a) += G((b), (c), (d)) + (x) + 0x6d703ef3UL;\
+      (a) = ROL((a), (s));
+
+#define HHH(a, b, c, d, x, s)        \
+      (a) += H((b), (c), (d)) + (x) + 0x5c4dd124UL;\
+      (a) = ROL((a), (s));
+
+#define III(a, b, c, d, x, s)        \
+      (a) += I((b), (c), (d)) + (x) + 0x50a28be6UL;\
+      (a) = ROL((a), (s));
+
+#ifdef CLEAN_STACK
+static void _rmd128_compress(hash_state *md, unsigned char *buf)
+#else
+static void rmd128_compress(hash_state *md, unsigned char *buf)
+#endif
+{
+   ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,X[16];
+   int i;
+   
+   /* load words X */
+   for (i = 0; i < 16; i++){
+      LOAD32L(X[i], buf + (4 * i));
+   }
+
+   /* load state */
+   aa = aaa = md->rmd128.state[0];
+   bb = bbb = md->rmd128.state[1];
+   cc = ccc = md->rmd128.state[2];
+   dd = ddd = md->rmd128.state[3];
+
+   /* round 1 */
+   FF(aa, bb, cc, dd, X[ 0], 11);
+   FF(dd, aa, bb, cc, X[ 1], 14);
+   FF(cc, dd, aa, bb, X[ 2], 15);
+   FF(bb, cc, dd, aa, X[ 3], 12);
+   FF(aa, bb, cc, dd, X[ 4],  5);
+   FF(dd, aa, bb, cc, X[ 5],  8);
+   FF(cc, dd, aa, bb, X[ 6],  7);
+   FF(bb, cc, dd, aa, X[ 7],  9);
+   FF(aa, bb, cc, dd, X[ 8], 11);
+   FF(dd, aa, bb, cc, X[ 9], 13);
+   FF(cc, dd, aa, bb, X[10], 14);
+   FF(bb, cc, dd, aa, X[11], 15);
+   FF(aa, bb, cc, dd, X[12],  6);
+   FF(dd, aa, bb, cc, X[13],  7);
+   FF(cc, dd, aa, bb, X[14],  9);
+   FF(bb, cc, dd, aa, X[15],  8);
+                             
+   /* round 2 */
+   GG(aa, bb, cc, dd, X[ 7],  7);
+   GG(dd, aa, bb, cc, X[ 4],  6);
+   GG(cc, dd, aa, bb, X[13],  8);
+   GG(bb, cc, dd, aa, X[ 1], 13);
+   GG(aa, bb, cc, dd, X[10], 11);
+   GG(dd, aa, bb, cc, X[ 6],  9);
+   GG(cc, dd, aa, bb, X[15],  7);
+   GG(bb, cc, dd, aa, X[ 3], 15);
+   GG(aa, bb, cc, dd, X[12],  7);
+   GG(dd, aa, bb, cc, X[ 0], 12);
+   GG(cc, dd, aa, bb, X[ 9], 15);
+   GG(bb, cc, dd, aa, X[ 5],  9);
+   GG(aa, bb, cc, dd, X[ 2], 11);
+   GG(dd, aa, bb, cc, X[14],  7);
+   GG(cc, dd, aa, bb, X[11], 13);
+   GG(bb, cc, dd, aa, X[ 8], 12);
+
+   /* round 3 */
+   HH(aa, bb, cc, dd, X[ 3], 11);
+   HH(dd, aa, bb, cc, X[10], 13);
+   HH(cc, dd, aa, bb, X[14],  6);
+   HH(bb, cc, dd, aa, X[ 4],  7);
+   HH(aa, bb, cc, dd, X[ 9], 14);
+   HH(dd, aa, bb, cc, X[15],  9);
+   HH(cc, dd, aa, bb, X[ 8], 13);
+   HH(bb, cc, dd, aa, X[ 1], 15);
+   HH(aa, bb, cc, dd, X[ 2], 14);
+   HH(dd, aa, bb, cc, X[ 7],  8);
+   HH(cc, dd, aa, bb, X[ 0], 13);
+   HH(bb, cc, dd, aa, X[ 6],  6);
+   HH(aa, bb, cc, dd, X[13],  5);
+   HH(dd, aa, bb, cc, X[11], 12);
+   HH(cc, dd, aa, bb, X[ 5],  7);
+   HH(bb, cc, dd, aa, X[12],  5);
+
+   /* round 4 */
+   II(aa, bb, cc, dd, X[ 1], 11);
+   II(dd, aa, bb, cc, X[ 9], 12);
+   II(cc, dd, aa, bb, X[11], 14);
+   II(bb, cc, dd, aa, X[10], 15);
+   II(aa, bb, cc, dd, X[ 0], 14);
+   II(dd, aa, bb, cc, X[ 8], 15);
+   II(cc, dd, aa, bb, X[12],  9);
+   II(bb, cc, dd, aa, X[ 4],  8);
+   II(aa, bb, cc, dd, X[13],  9);
+   II(dd, aa, bb, cc, X[ 3], 14);
+   II(cc, dd, aa, bb, X[ 7],  5);
+   II(bb, cc, dd, aa, X[15],  6);
+   II(aa, bb, cc, dd, X[14],  8);
+   II(dd, aa, bb, cc, X[ 5],  6);
+   II(cc, dd, aa, bb, X[ 6],  5);
+   II(bb, cc, dd, aa, X[ 2], 12);
+
+   /* parallel round 1 */
+   III(aaa, bbb, ccc, ddd, X[ 5],  8); 
+   III(ddd, aaa, bbb, ccc, X[14],  9);
+   III(ccc, ddd, aaa, bbb, X[ 7],  9);
+   III(bbb, ccc, ddd, aaa, X[ 0], 11);
+   III(aaa, bbb, ccc, ddd, X[ 9], 13);
+   III(ddd, aaa, bbb, ccc, X[ 2], 15);
+   III(ccc, ddd, aaa, bbb, X[11], 15);
+   III(bbb, ccc, ddd, aaa, X[ 4],  5);
+   III(aaa, bbb, ccc, ddd, X[13],  7);
+   III(ddd, aaa, bbb, ccc, X[ 6],  7);
+   III(ccc, ddd, aaa, bbb, X[15],  8);
+   III(bbb, ccc, ddd, aaa, X[ 8], 11);
+   III(aaa, bbb, ccc, ddd, X[ 1], 14);
+   III(ddd, aaa, bbb, ccc, X[10], 14);
+   III(ccc, ddd, aaa, bbb, X[ 3], 12);
+   III(bbb, ccc, ddd, aaa, X[12],  6);
+
+   /* parallel round 2 */
+   HHH(aaa, bbb, ccc, ddd, X[ 6],  9);
+   HHH(ddd, aaa, bbb, ccc, X[11], 13);
+   HHH(ccc, ddd, aaa, bbb, X[ 3], 15);
+   HHH(bbb, ccc, ddd, aaa, X[ 7],  7);
+   HHH(aaa, bbb, ccc, ddd, X[ 0], 12);
+   HHH(ddd, aaa, bbb, ccc, X[13],  8);
+   HHH(ccc, ddd, aaa, bbb, X[ 5],  9);
+   HHH(bbb, ccc, ddd, aaa, X[10], 11);
+   HHH(aaa, bbb, ccc, ddd, X[14],  7);
+   HHH(ddd, aaa, bbb, ccc, X[15],  7);
+   HHH(ccc, ddd, aaa, bbb, X[ 8], 12);
+   HHH(bbb, ccc, ddd, aaa, X[12],  7);
+   HHH(aaa, bbb, ccc, ddd, X[ 4],  6);
+   HHH(ddd, aaa, bbb, ccc, X[ 9], 15);
+   HHH(ccc, ddd, aaa, bbb, X[ 1], 13);
+   HHH(bbb, ccc, ddd, aaa, X[ 2], 11);
+
+   /* parallel round 3 */   
+   GGG(aaa, bbb, ccc, ddd, X[15],  9);
+   GGG(ddd, aaa, bbb, ccc, X[ 5],  7);
+   GGG(ccc, ddd, aaa, bbb, X[ 1], 15);
+   GGG(bbb, ccc, ddd, aaa, X[ 3], 11);
+   GGG(aaa, bbb, ccc, ddd, X[ 7],  8);
+   GGG(ddd, aaa, bbb, ccc, X[14],  6);
+   GGG(ccc, ddd, aaa, bbb, X[ 6],  6);
+   GGG(bbb, ccc, ddd, aaa, X[ 9], 14);
+   GGG(aaa, bbb, ccc, ddd, X[11], 12);
+   GGG(ddd, aaa, bbb, ccc, X[ 8], 13);
+   GGG(ccc, ddd, aaa, bbb, X[12],  5);
+   GGG(bbb, ccc, ddd, aaa, X[ 2], 14);
+   GGG(aaa, bbb, ccc, ddd, X[10], 13);
+   GGG(ddd, aaa, bbb, ccc, X[ 0], 13);
+   GGG(ccc, ddd, aaa, bbb, X[ 4],  7);
+   GGG(bbb, ccc, ddd, aaa, X[13],  5);
+
+   /* parallel round 4 */
+   FFF(aaa, bbb, ccc, ddd, X[ 8], 15);
+   FFF(ddd, aaa, bbb, ccc, X[ 6],  5);
+   FFF(ccc, ddd, aaa, bbb, X[ 4],  8);
+   FFF(bbb, ccc, ddd, aaa, X[ 1], 11);
+   FFF(aaa, bbb, ccc, ddd, X[ 3], 14);
+   FFF(ddd, aaa, bbb, ccc, X[11], 14);
+   FFF(ccc, ddd, aaa, bbb, X[15],  6);
+   FFF(bbb, ccc, ddd, aaa, X[ 0], 14);
+   FFF(aaa, bbb, ccc, ddd, X[ 5],  6);
+   FFF(ddd, aaa, bbb, ccc, X[12],  9);
+   FFF(ccc, ddd, aaa, bbb, X[ 2], 12);
+   FFF(bbb, ccc, ddd, aaa, X[13],  9);
+   FFF(aaa, bbb, ccc, ddd, X[ 9], 12);
+   FFF(ddd, aaa, bbb, ccc, X[ 7],  5);
+   FFF(ccc, ddd, aaa, bbb, X[10], 15);
+   FFF(bbb, ccc, ddd, aaa, X[14],  8);
+
+   /* combine results */
+   ddd += cc + md->rmd128.state[1];               /* final result for MDbuf[0] */
+   md->rmd128.state[1] = md->rmd128.state[2] + dd + aaa;
+   md->rmd128.state[2] = md->rmd128.state[3] + aa + bbb;
+   md->rmd128.state[3] = md->rmd128.state[0] + bb + ccc;
+   md->rmd128.state[0] = ddd;
+}
+
+#ifdef CLEAN_STACK
+static void rmd128_compress(hash_state *md, unsigned char *buf)
+{
+   _rmd128_compress(md, buf);
+   burn_stack(sizeof(ulong32) * 24 + sizeof(int));
+}
+#endif
+
+void rmd128_init(hash_state * md)
+{
+   _ARGCHK(md != NULL);
+   md->rmd128.state[0] = 0x67452301UL;
+   md->rmd128.state[1] = 0xefcdab89UL;
+   md->rmd128.state[2] = 0x98badcfeUL;
+   md->rmd128.state[3] = 0x10325476UL;
+   md->rmd128.curlen   = 0;
+   md->rmd128.length   = 0;
+}
+
+HASH_PROCESS(rmd128_process, rmd128_compress, rmd128, 64)
+
+int rmd128_done(hash_state * md, unsigned char *hash)
+{
+    int i;
+
+    _ARGCHK(md != NULL);
+    _ARGCHK(hash != NULL);
+
+    if (md->rmd128.curlen >= sizeof(md->rmd128.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+
+    /* increase the length of the message */
+    md->rmd128.length += md->rmd128.curlen * 8;
+
+    /* append the '1' bit */
+    md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0x80;
+
+    /* if the length is currently above 56 bytes we append zeros
+     * then compress.  Then we can fall back to padding zeros and length
+     * encoding like normal.
+     */
+    if (md->rmd128.curlen > 56) {
+        while (md->rmd128.curlen < 64) {
+            md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0;
+        }
+        rmd128_compress(md, md->rmd128.buf);
+        md->rmd128.curlen = 0;
+    }
+
+    /* pad upto 56 bytes of zeroes */
+    while (md->rmd128.curlen < 56) {
+        md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0;
+    }
+
+    /* store length */
+    STORE64L(md->rmd128.length, md->rmd128.buf+56);
+    rmd128_compress(md, md->rmd128.buf);
+
+    /* copy output */
+    for (i = 0; i < 4; i++) {
+        STORE32L(md->rmd128.state[i], hash+(4*i));
+    }
+#ifdef CLEAN_STACK
+    zeromem(md, sizeof(hash_state));
+#endif
+   return CRYPT_OK;  
+}
+
+int rmd128_test(void)
+{
+#ifndef LTC_TEST
+   return CRYPT_NOP;
+#else
+   static const struct {
+        char *msg;
+        unsigned char md[16];
+   } tests[] = {
+   { "",
+     { 0xcd, 0xf2, 0x62, 0x13, 0xa1, 0x50, 0xdc, 0x3e,
+       0xcb, 0x61, 0x0f, 0x18, 0xf6, 0xb3, 0x8b, 0x46 }
+   },
+   { "a",
+     { 0x86, 0xbe, 0x7a, 0xfa, 0x33, 0x9d, 0x0f, 0xc7,
+       0xcf, 0xc7, 0x85, 0xe7, 0x2f, 0x57, 0x8d, 0x33 }
+   },
+   { "abc",
+     { 0xc1, 0x4a, 0x12, 0x19, 0x9c, 0x66, 0xe4, 0xba,
+       0x84, 0x63, 0x6b, 0x0f, 0x69, 0x14, 0x4c, 0x77 }
+   },
+   { "message digest",
+     { 0x9e, 0x32, 0x7b, 0x3d, 0x6e, 0x52, 0x30, 0x62,
+       0xaf, 0xc1, 0x13, 0x2d, 0x7d, 0xf9, 0xd1, 0xb8 }
+   },
+   { "abcdefghijklmnopqrstuvwxyz",
+     { 0xfd, 0x2a, 0xa6, 0x07, 0xf7, 0x1d, 0xc8, 0xf5,
+       0x10, 0x71, 0x49, 0x22, 0xb3, 0x71, 0x83, 0x4e }
+   },
+   { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+     { 0xd1, 0xe9, 0x59, 0xeb, 0x17, 0x9c, 0x91, 0x1f,
+       0xae, 0xa4, 0x62, 0x4c, 0x60, 0xc5, 0xc7, 0x02 }
+   }
+   };
+   int x;
+   unsigned char buf[16];
+   hash_state md;
+
+   for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+       rmd128_init(&md);
+       rmd128_process(&md, (unsigned char *)tests[x].msg, strlen(tests[x].msg));
+       rmd128_done(&md, buf);
+       if (memcmp(buf, tests[x].md, 16) != 0) {
+       #if 0
+          printf("Failed test %d\n", x);
+       #endif
+          return CRYPT_FAIL_TESTVECTOR;
+       }
+   }
+   return CRYPT_OK;
+#endif
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rmd160.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,427 @@
+/* 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 RIPEMD-160 based on the source by Antoon Bosselaers, ESAT-COSIC
+ *
+ * This source has been radically overhauled to be portable and work within
+ * the LibTomCrypt API by Tom St Denis
+ */
+#include "mycrypt.h"
+
+#ifdef RIPEMD160
+
+const struct _hash_descriptor rmd160_desc =
+{
+    "rmd160",
+    9,
+    20,
+    64,
+    &rmd160_init,
+    &rmd160_process,
+    &rmd160_done,
+    &rmd160_test
+};
+
+/* the five basic functions F(), G() and H() */
+#define F(x, y, z)        ((x) ^ (y) ^ (z)) 
+#define G(x, y, z)        (((x) & (y)) | (~(x) & (z))) 
+#define H(x, y, z)        (((x) | ~(y)) ^ (z))
+#define I(x, y, z)        (((x) & (z)) | ((y) & ~(z))) 
+#define J(x, y, z)        ((x) ^ ((y) | ~(z)))
+  
+/* the ten basic operations FF() through III() */
+#define FF(a, b, c, d, e, x, s)        \
+      (a) += F((b), (c), (d)) + (x);\
+      (a) = ROL((a), (s)) + (e);\
+      (c) = ROL((c), 10);
+
+#define GG(a, b, c, d, e, x, s)        \
+      (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
+      (a) = ROL((a), (s)) + (e);\
+      (c) = ROL((c), 10);
+
+#define HH(a, b, c, d, e, x, s)        \
+      (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
+      (a) = ROL((a), (s)) + (e);\
+      (c) = ROL((c), 10);
+
+#define II(a, b, c, d, e, x, s)        \
+      (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
+      (a) = ROL((a), (s)) + (e);\
+      (c) = ROL((c), 10);
+
+#define JJ(a, b, c, d, e, x, s)        \
+      (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\
+      (a) = ROL((a), (s)) + (e);\
+      (c) = ROL((c), 10);
+
+#define FFF(a, b, c, d, e, x, s)        \
+      (a) += F((b), (c), (d)) + (x);\
+      (a) = ROL((a), (s)) + (e);\
+      (c) = ROL((c), 10);
+
+#define GGG(a, b, c, d, e, x, s)        \
+      (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\
+      (a) = ROL((a), (s)) + (e);\
+      (c) = ROL((c), 10);
+
+#define HHH(a, b, c, d, e, x, s)        \
+      (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\
+      (a) = ROL((a), (s)) + (e);\
+      (c) = ROL((c), 10);
+
+#define III(a, b, c, d, e, x, s)        \
+      (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\
+      (a) = ROL((a), (s)) + (e);\
+      (c) = ROL((c), 10);
+
+#define JJJ(a, b, c, d, e, x, s)        \
+      (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\
+      (a) = ROL((a), (s)) + (e);\
+      (c) = ROL((c), 10);
+
+
+#ifdef CLEAN_STACK
+static void _rmd160_compress(hash_state *md, unsigned char *buf)
+#else
+static void rmd160_compress(hash_state *md, unsigned char *buf)
+#endif
+{
+   ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16];
+   int i;
+
+   /* load words X */
+   for (i = 0; i < 16; i++){
+      LOAD32L(X[i], buf + (4 * i));
+   }
+
+   /* load state */
+   aa = aaa = md->rmd160.state[0];
+   bb = bbb = md->rmd160.state[1];
+   cc = ccc = md->rmd160.state[2];
+   dd = ddd = md->rmd160.state[3];
+   ee = eee = md->rmd160.state[4];
+
+   /* round 1 */
+   FF(aa, bb, cc, dd, ee, X[ 0], 11);
+   FF(ee, aa, bb, cc, dd, X[ 1], 14);
+   FF(dd, ee, aa, bb, cc, X[ 2], 15);
+   FF(cc, dd, ee, aa, bb, X[ 3], 12);
+   FF(bb, cc, dd, ee, aa, X[ 4],  5);
+   FF(aa, bb, cc, dd, ee, X[ 5],  8);
+   FF(ee, aa, bb, cc, dd, X[ 6],  7);
+   FF(dd, ee, aa, bb, cc, X[ 7],  9);
+   FF(cc, dd, ee, aa, bb, X[ 8], 11);
+   FF(bb, cc, dd, ee, aa, X[ 9], 13);
+   FF(aa, bb, cc, dd, ee, X[10], 14);
+   FF(ee, aa, bb, cc, dd, X[11], 15);
+   FF(dd, ee, aa, bb, cc, X[12],  6);
+   FF(cc, dd, ee, aa, bb, X[13],  7);
+   FF(bb, cc, dd, ee, aa, X[14],  9);
+   FF(aa, bb, cc, dd, ee, X[15],  8);
+                             
+   /* round 2 */
+   GG(ee, aa, bb, cc, dd, X[ 7],  7);
+   GG(dd, ee, aa, bb, cc, X[ 4],  6);
+   GG(cc, dd, ee, aa, bb, X[13],  8);
+   GG(bb, cc, dd, ee, aa, X[ 1], 13);
+   GG(aa, bb, cc, dd, ee, X[10], 11);
+   GG(ee, aa, bb, cc, dd, X[ 6],  9);
+   GG(dd, ee, aa, bb, cc, X[15],  7);
+   GG(cc, dd, ee, aa, bb, X[ 3], 15);
+   GG(bb, cc, dd, ee, aa, X[12],  7);
+   GG(aa, bb, cc, dd, ee, X[ 0], 12);
+   GG(ee, aa, bb, cc, dd, X[ 9], 15);
+   GG(dd, ee, aa, bb, cc, X[ 5],  9);
+   GG(cc, dd, ee, aa, bb, X[ 2], 11);
+   GG(bb, cc, dd, ee, aa, X[14],  7);
+   GG(aa, bb, cc, dd, ee, X[11], 13);
+   GG(ee, aa, bb, cc, dd, X[ 8], 12);
+
+   /* round 3 */
+   HH(dd, ee, aa, bb, cc, X[ 3], 11);
+   HH(cc, dd, ee, aa, bb, X[10], 13);
+   HH(bb, cc, dd, ee, aa, X[14],  6);
+   HH(aa, bb, cc, dd, ee, X[ 4],  7);
+   HH(ee, aa, bb, cc, dd, X[ 9], 14);
+   HH(dd, ee, aa, bb, cc, X[15],  9);
+   HH(cc, dd, ee, aa, bb, X[ 8], 13);
+   HH(bb, cc, dd, ee, aa, X[ 1], 15);
+   HH(aa, bb, cc, dd, ee, X[ 2], 14);
+   HH(ee, aa, bb, cc, dd, X[ 7],  8);
+   HH(dd, ee, aa, bb, cc, X[ 0], 13);
+   HH(cc, dd, ee, aa, bb, X[ 6],  6);
+   HH(bb, cc, dd, ee, aa, X[13],  5);
+   HH(aa, bb, cc, dd, ee, X[11], 12);
+   HH(ee, aa, bb, cc, dd, X[ 5],  7);
+   HH(dd, ee, aa, bb, cc, X[12],  5);
+
+   /* round 4 */
+   II(cc, dd, ee, aa, bb, X[ 1], 11);
+   II(bb, cc, dd, ee, aa, X[ 9], 12);
+   II(aa, bb, cc, dd, ee, X[11], 14);
+   II(ee, aa, bb, cc, dd, X[10], 15);
+   II(dd, ee, aa, bb, cc, X[ 0], 14);
+   II(cc, dd, ee, aa, bb, X[ 8], 15);
+   II(bb, cc, dd, ee, aa, X[12],  9);
+   II(aa, bb, cc, dd, ee, X[ 4],  8);
+   II(ee, aa, bb, cc, dd, X[13],  9);
+   II(dd, ee, aa, bb, cc, X[ 3], 14);
+   II(cc, dd, ee, aa, bb, X[ 7],  5);
+   II(bb, cc, dd, ee, aa, X[15],  6);
+   II(aa, bb, cc, dd, ee, X[14],  8);
+   II(ee, aa, bb, cc, dd, X[ 5],  6);
+   II(dd, ee, aa, bb, cc, X[ 6],  5);
+   II(cc, dd, ee, aa, bb, X[ 2], 12);
+
+   /* round 5 */
+   JJ(bb, cc, dd, ee, aa, X[ 4],  9);
+   JJ(aa, bb, cc, dd, ee, X[ 0], 15);
+   JJ(ee, aa, bb, cc, dd, X[ 5],  5);
+   JJ(dd, ee, aa, bb, cc, X[ 9], 11);
+   JJ(cc, dd, ee, aa, bb, X[ 7],  6);
+   JJ(bb, cc, dd, ee, aa, X[12],  8);
+   JJ(aa, bb, cc, dd, ee, X[ 2], 13);
+   JJ(ee, aa, bb, cc, dd, X[10], 12);
+   JJ(dd, ee, aa, bb, cc, X[14],  5);
+   JJ(cc, dd, ee, aa, bb, X[ 1], 12);
+   JJ(bb, cc, dd, ee, aa, X[ 3], 13);
+   JJ(aa, bb, cc, dd, ee, X[ 8], 14);
+   JJ(ee, aa, bb, cc, dd, X[11], 11);
+   JJ(dd, ee, aa, bb, cc, X[ 6],  8);
+   JJ(cc, dd, ee, aa, bb, X[15],  5);
+   JJ(bb, cc, dd, ee, aa, X[13],  6);
+
+   /* parallel round 1 */
+   JJJ(aaa, bbb, ccc, ddd, eee, X[ 5],  8);
+   JJJ(eee, aaa, bbb, ccc, ddd, X[14],  9);
+   JJJ(ddd, eee, aaa, bbb, ccc, X[ 7],  9);
+   JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11);
+   JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13);
+   JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15);
+   JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15);
+   JJJ(ddd, eee, aaa, bbb, ccc, X[ 4],  5);
+   JJJ(ccc, ddd, eee, aaa, bbb, X[13],  7);
+   JJJ(bbb, ccc, ddd, eee, aaa, X[ 6],  7);
+   JJJ(aaa, bbb, ccc, ddd, eee, X[15],  8);
+   JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11);
+   JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14);
+   JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14);
+   JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12);
+   JJJ(aaa, bbb, ccc, ddd, eee, X[12],  6);
+
+   /* parallel round 2 */
+   III(eee, aaa, bbb, ccc, ddd, X[ 6],  9); 
+   III(ddd, eee, aaa, bbb, ccc, X[11], 13);
+   III(ccc, ddd, eee, aaa, bbb, X[ 3], 15);
+   III(bbb, ccc, ddd, eee, aaa, X[ 7],  7);
+   III(aaa, bbb, ccc, ddd, eee, X[ 0], 12);
+   III(eee, aaa, bbb, ccc, ddd, X[13],  8);
+   III(ddd, eee, aaa, bbb, ccc, X[ 5],  9);
+   III(ccc, ddd, eee, aaa, bbb, X[10], 11);
+   III(bbb, ccc, ddd, eee, aaa, X[14],  7);
+   III(aaa, bbb, ccc, ddd, eee, X[15],  7);
+   III(eee, aaa, bbb, ccc, ddd, X[ 8], 12);
+   III(ddd, eee, aaa, bbb, ccc, X[12],  7);
+   III(ccc, ddd, eee, aaa, bbb, X[ 4],  6);
+   III(bbb, ccc, ddd, eee, aaa, X[ 9], 15);
+   III(aaa, bbb, ccc, ddd, eee, X[ 1], 13);
+   III(eee, aaa, bbb, ccc, ddd, X[ 2], 11);
+
+   /* parallel round 3 */
+   HHH(ddd, eee, aaa, bbb, ccc, X[15],  9);
+   HHH(ccc, ddd, eee, aaa, bbb, X[ 5],  7);
+   HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15);
+   HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11);
+   HHH(eee, aaa, bbb, ccc, ddd, X[ 7],  8);
+   HHH(ddd, eee, aaa, bbb, ccc, X[14],  6);
+   HHH(ccc, ddd, eee, aaa, bbb, X[ 6],  6);
+   HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14);
+   HHH(aaa, bbb, ccc, ddd, eee, X[11], 12);
+   HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13);
+   HHH(ddd, eee, aaa, bbb, ccc, X[12],  5);
+   HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14);
+   HHH(bbb, ccc, ddd, eee, aaa, X[10], 13);
+   HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13);
+   HHH(eee, aaa, bbb, ccc, ddd, X[ 4],  7);
+   HHH(ddd, eee, aaa, bbb, ccc, X[13],  5);
+
+   /* parallel round 4 */   
+   GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15);
+   GGG(bbb, ccc, ddd, eee, aaa, X[ 6],  5);
+   GGG(aaa, bbb, ccc, ddd, eee, X[ 4],  8);
+   GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11);
+   GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14);
+   GGG(ccc, ddd, eee, aaa, bbb, X[11], 14);
+   GGG(bbb, ccc, ddd, eee, aaa, X[15],  6);
+   GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14);
+   GGG(eee, aaa, bbb, ccc, ddd, X[ 5],  6);
+   GGG(ddd, eee, aaa, bbb, ccc, X[12],  9);
+   GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12);
+   GGG(bbb, ccc, ddd, eee, aaa, X[13],  9);
+   GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12);
+   GGG(eee, aaa, bbb, ccc, ddd, X[ 7],  5);
+   GGG(ddd, eee, aaa, bbb, ccc, X[10], 15);
+   GGG(ccc, ddd, eee, aaa, bbb, X[14],  8);
+
+   /* parallel round 5 */
+   FFF(bbb, ccc, ddd, eee, aaa, X[12] ,  8);
+   FFF(aaa, bbb, ccc, ddd, eee, X[15] ,  5);
+   FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12);
+   FFF(ddd, eee, aaa, bbb, ccc, X[ 4] ,  9);
+   FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12);
+   FFF(bbb, ccc, ddd, eee, aaa, X[ 5] ,  5);
+   FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14);
+   FFF(eee, aaa, bbb, ccc, ddd, X[ 7] ,  6);
+   FFF(ddd, eee, aaa, bbb, ccc, X[ 6] ,  8);
+   FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13);
+   FFF(bbb, ccc, ddd, eee, aaa, X[13] ,  6);
+   FFF(aaa, bbb, ccc, ddd, eee, X[14] ,  5);
+   FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15);
+   FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13);
+   FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11);
+   FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11);
+
+   /* combine results */
+   ddd += cc + md->rmd160.state[1];               /* final result for md->rmd160.state[0] */
+   md->rmd160.state[1] = md->rmd160.state[2] + dd + eee;
+   md->rmd160.state[2] = md->rmd160.state[3] + ee + aaa;
+   md->rmd160.state[3] = md->rmd160.state[4] + aa + bbb;
+   md->rmd160.state[4] = md->rmd160.state[0] + bb + ccc;
+   md->rmd160.state[0] = ddd;
+}
+
+#ifdef CLEAN_STACK
+static void rmd160_compress(hash_state *md, unsigned char *buf)
+{
+   _rmd160_compress(md, buf);
+   burn_stack(sizeof(ulong32) * 26 + sizeof(int));
+}
+#endif
+
+void rmd160_init(hash_state * md)
+{
+   _ARGCHK(md != NULL);
+   md->rmd160.state[0] = 0x67452301UL;
+   md->rmd160.state[1] = 0xefcdab89UL;
+   md->rmd160.state[2] = 0x98badcfeUL;
+   md->rmd160.state[3] = 0x10325476UL;
+   md->rmd160.state[4] = 0xc3d2e1f0UL;
+   md->rmd160.curlen   = 0;
+   md->rmd160.length   = 0;
+}
+
+HASH_PROCESS(rmd160_process, rmd160_compress, rmd160, 64)
+
+int rmd160_done(hash_state * md, unsigned char *hash)
+{
+    int i;
+
+    _ARGCHK(md != NULL);
+    _ARGCHK(hash != NULL);
+
+    if (md->rmd160.curlen >= sizeof(md->rmd160.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+
+    /* increase the length of the message */
+    md->rmd160.length += md->rmd160.curlen * 8;
+
+    /* append the '1' bit */
+    md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0x80;
+
+    /* if the length is currently above 56 bytes we append zeros
+     * then compress.  Then we can fall back to padding zeros and length
+     * encoding like normal.
+     */
+    if (md->rmd160.curlen > 56) {
+        while (md->rmd160.curlen < 64) {
+            md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0;
+        }
+        rmd160_compress(md, md->rmd160.buf);
+        md->rmd160.curlen = 0;
+    }
+
+    /* pad upto 56 bytes of zeroes */
+    while (md->rmd160.curlen < 56) {
+        md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0;
+    }
+
+    /* store length */
+    STORE64L(md->rmd160.length, md->rmd160.buf+56);
+    rmd160_compress(md, md->rmd160.buf);
+
+    /* copy output */
+    for (i = 0; i < 5; i++) {
+        STORE32L(md->rmd160.state[i], hash+(4*i));
+    }
+#ifdef CLEAN_STACK
+    zeromem(md, sizeof(hash_state));
+#endif
+    return CRYPT_OK;
+}
+
+int rmd160_test(void)
+{
+#ifndef LTC_TEST
+   return CRYPT_NOP;
+#else
+   static const struct {
+        char *msg;
+        unsigned char md[20];
+   } tests[] = {
+   { "",
+     { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28,
+       0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }
+   },
+   { "a",
+     { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae,
+       0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }
+   },
+   { "abc",
+     { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04,
+       0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }
+   },
+   { "message digest",
+     { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8,
+       0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }
+   },
+   { "abcdefghijklmnopqrstuvwxyz",
+     { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb,
+       0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }
+   },
+   { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+     { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05,
+       0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }
+   }
+   };
+   int x;
+   unsigned char buf[20];
+   hash_state md;
+
+   for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+       rmd160_init(&md);
+       rmd160_process(&md, (unsigned char *)tests[x].msg, strlen(tests[x].msg));
+       rmd160_done(&md, buf);
+       if (memcmp(buf, tests[x].md, 20) != 0) {
+#if 0
+          printf("Failed test %d\n", x);
+#endif
+          return CRYPT_FAIL_TESTVECTOR;
+       }
+   }
+   return CRYPT_OK;
+#endif
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rng_get_bytes.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,129 @@
+/* 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
+ */
+/* portable way to get secure random bits to feed a PRNG */
+#include "mycrypt.h"
+
+#ifdef DEVRANDOM
+/* on *NIX read /dev/random */
+static unsigned long rng_nix(unsigned char *buf, unsigned long len, 
+                             void (*callback)(void))
+{
+#ifdef NO_FILE
+    return 0;
+#else
+    FILE *f;
+    unsigned long x;
+#ifdef TRY_URANDOM_FIRST
+    f = fopen("/dev/urandom", "rb");
+    if (f == NULL)
+#endif /* TRY_URANDOM_FIRST */
+       f = fopen("/dev/random", "rb");
+
+    if (f == NULL) {
+       return 0;
+    }
+    
+    /* disable buffering */
+    if (setvbuf(f, NULL, _IONBF, 0) != 0) {
+       fclose(f);
+       return 0;
+    }   
+ 
+    x = (unsigned long)fread(buf, 1, (size_t)len, f);
+    fclose(f);
+    return x;
+#endif /* NO_FILE */
+}
+
+#endif /* DEVRANDOM */
+
+/* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */
+#if defined(CLOCKS_PER_SEC)
+
+#define ANSI_RNG
+
+static unsigned long rng_ansic(unsigned char *buf, unsigned long len, 
+                               void (*callback)(void))
+{
+   clock_t t1;
+   int l, acc, bits, a, b;
+
+   if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) {
+      return 0;
+   }
+
+   l = len;
+   bits = 8;
+   acc  = a = b = 0;
+   while (len--) {
+       if (callback != NULL) callback();
+       while (bits--) {
+          do {
+             t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1;
+             t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1;
+          } while (a == b);
+          acc = (acc << 1) | a;
+       }
+       *buf++ = acc; 
+       acc  = 0;
+       bits = 8;
+   }
+   acc = bits = a = b = 0;
+   return l;
+}
+
+#endif 
+
+/* Try the Microsoft CSP */
+#ifdef WIN32
+#define _WIN32_WINNT 0x0400
+#include <windows.h>
+#include <wincrypt.h>
+
+static unsigned long rng_win32(unsigned char *buf, unsigned long len, 
+                               void (*callback)(void))
+{
+   HCRYPTPROV hProv = 0;
+   if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 
+                            (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && 
+       !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 
+                            CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
+      return 0;
+
+   if (CryptGenRandom(hProv, len, buf) == TRUE) {
+      CryptReleaseContext(hProv, 0);
+      return len;
+   } else {
+      CryptReleaseContext(hProv, 0);
+      return 0;
+   }
+}
+
+#endif /* WIN32 */
+
+unsigned long rng_get_bytes(unsigned char *buf, unsigned long len, 
+                            void (*callback)(void))
+{
+   unsigned long x;
+
+   _ARGCHK(buf != NULL);
+
+#if defined(DEVRANDOM)
+   x = rng_nix(buf, len, callback);   if (x != 0) { return x; }
+#endif
+#ifdef WIN32
+   x = rng_win32(buf, len, callback); if (x != 0) { return x; }
+#endif
+#ifdef ANSI_RNG
+   x = rng_ansic(buf, len, callback); if (x != 0) { return x; }
+#endif
+   return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rng_make_prng.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,53 @@
+/* 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
+ */
+/* portable way to get secure random bits to feed a PRNG */
+#include "mycrypt.h"
+
+int rng_make_prng(int bits, int wprng, prng_state *prng, 
+                  void (*callback)(void))
+{
+   unsigned char buf[256];
+   int err;
+   
+   _ARGCHK(prng != NULL);
+
+   /* check parameter */
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err;
+   }
+
+   if (bits < 64 || bits > 1024) {
+      return CRYPT_INVALID_PRNGSIZE;
+   }
+
+   if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) {
+      return err;
+   }
+
+   bits = ((bits/8)+((bits&7)!=0?1:0)) * 2;
+   if (rng_get_bytes(buf, (unsigned long)bits, callback) != (unsigned long)bits) {
+      return CRYPT_ERROR_READPRNG;
+   }
+
+   if ((err = prng_descriptor[wprng].add_entropy(buf, (unsigned long)bits, prng)) != CRYPT_OK) {
+      return err;
+   }
+
+   if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) {
+      return err;
+   }
+
+   #ifdef CLEAN_STACK
+      zeromem(buf, sizeof(buf));
+   #endif
+   return CRYPT_OK;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,273 @@
+/* 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
+ */
+
+/* RSA Code by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+int rsa_signpad(const unsigned char *in,  unsigned long inlen,
+                      unsigned char *out, unsigned long *outlen)
+{
+   unsigned long x, y;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   if (*outlen < (3 * inlen)) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* check inlen */
+   if (inlen > MAX_RSA_SIZE/8) {
+      return CRYPT_PK_INVALID_SIZE;
+   }
+
+   for (y = x = 0; x < inlen; x++)
+       out[y++] = (unsigned char)0xFF;
+   for (x = 0; x < inlen; x++)
+       out[y++] = in[x];
+   for (x = 0; x < inlen; x++)
+       out[y++] = (unsigned char)0xFF;
+   *outlen = 3 * inlen;
+   return CRYPT_OK;
+}
+
+int rsa_pad(const unsigned char *in,  unsigned long inlen,
+                  unsigned char *out, unsigned long *outlen,
+                  int wprng, prng_state *prng)
+{
+   unsigned char buf[3*(MAX_RSA_SIZE/8)];
+   unsigned long x;
+   int err;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* is output big enough? */
+   if (*outlen < (3 * inlen)) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* get random padding required */
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* check inlen */
+   if (inlen > (MAX_RSA_SIZE/8)) {
+      return CRYPT_PK_INVALID_SIZE;
+   }
+
+   if (prng_descriptor[wprng].read(buf, inlen*2-2, prng) != (inlen*2 - 2))  {
+       return CRYPT_ERROR_READPRNG;
+   }
+
+   /* pad it like a sandwhich
+    *
+    * Looks like 0xFF R1 M R2 0xFF
+    *
+    * Where R1/R2 are random and exactly equal to the length of M minus one byte.
+    */
+   for (x = 0; x < inlen-1; x++) {
+       out[x+1] = buf[x];
+   }
+
+   for (x = 0; x < inlen; x++) {
+       out[x+inlen] = in[x];
+   }
+
+   for (x = 0; x < inlen-1; x++) {
+       out[x+inlen+inlen] = buf[x+inlen-1];
+   }
+
+   /* last and first bytes are 0xFF */
+   out[0] = out[inlen+inlen+inlen-1] = (unsigned char)0xFF;
+
+   /* clear up and return */
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+   *outlen = inlen*3;
+   return CRYPT_OK;
+}
+
+int rsa_signdepad(const unsigned char *in,  unsigned long inlen,
+                        unsigned char *out, unsigned long *outlen)
+{
+   unsigned long x;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   if (*outlen < inlen/3) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* check padding bytes */
+   for (x = 0; x < inlen/3; x++) {
+       if (in[x] != (unsigned char)0xFF || in[x+(inlen/3)+(inlen/3)] != (unsigned char)0xFF) {
+          return CRYPT_INVALID_PACKET;
+       }
+   }
+   for (x = 0; x < inlen/3; x++) {
+       out[x] = in[x+(inlen/3)];
+   }
+   *outlen = inlen/3;
+   return CRYPT_OK;
+}
+
+int rsa_depad(const unsigned char *in,  unsigned long inlen,
+                    unsigned char *out, unsigned long *outlen)
+{
+   unsigned long x;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   if (*outlen < inlen/3) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   for (x = 0; x < inlen/3; x++) {
+       out[x] = in[x+(inlen/3)];
+   }
+   *outlen = inlen/3;
+   return CRYPT_OK;
+}
+
+int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key)
+{
+   unsigned long y, z; 
+   int err;
+
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+   
+   /* can we store the static header?  */
+   if (*outlen < (PACKET_SIZE + 1)) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }   
+
+   /* type valid? */
+   if (!(key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) &&
+        (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED)) {
+      return CRYPT_PK_INVALID_TYPE;
+   }
+
+   /* start at offset y=PACKET_SIZE */
+   y = PACKET_SIZE;
+
+   /* output key type */
+   out[y++] = type;
+
+   /* output modulus */
+   OUTPUT_BIGNUM(&key->N, out, y, z);
+
+   /* output public key */
+   OUTPUT_BIGNUM(&key->e, out, y, z);
+
+   if (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED) {
+      OUTPUT_BIGNUM(&key->d, out, y, z);
+   }
+
+   if (type == PK_PRIVATE_OPTIMIZED) {
+      OUTPUT_BIGNUM(&key->dQ, out, y, z);
+      OUTPUT_BIGNUM(&key->dP, out, y, z);
+      OUTPUT_BIGNUM(&key->pQ, out, y, z);
+      OUTPUT_BIGNUM(&key->qP, out, y, z);
+      OUTPUT_BIGNUM(&key->p, out, y, z);
+      OUTPUT_BIGNUM(&key->q, out, y, z);
+   }
+
+   /* store packet header */
+   packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_KEY);
+
+   /* copy to the user buffer */
+   *outlen = y;
+
+   /* clear stack and return */
+   return CRYPT_OK;
+}
+
+int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+   unsigned long x, y;
+   int err;
+
+   _ARGCHK(in  != NULL);
+   _ARGCHK(key != NULL);
+
+   /* check length */
+   if (inlen < (1+PACKET_SIZE)) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* test packet header */
+   if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_KEY)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* init key */
+   if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP,
+                     &key->pQ, &key->p, &key->q, NULL)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+
+   /* get key type */
+   y = PACKET_SIZE;
+   key->type = (int)in[y++];
+
+   /* load the modulus  */
+   INPUT_BIGNUM(&key->N, in, x, y, inlen);
+
+   /* load public exponent */
+   INPUT_BIGNUM(&key->e, in, x, y, inlen);
+
+   /* get private exponent */
+   if (key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) {
+      INPUT_BIGNUM(&key->d, in, x, y, inlen);
+   }
+
+   /* get CRT private data if required */
+   if (key->type == PK_PRIVATE_OPTIMIZED) {
+      INPUT_BIGNUM(&key->dQ, in, x, y, inlen);
+      INPUT_BIGNUM(&key->dP, in, x, y, inlen);
+      INPUT_BIGNUM(&key->pQ, in, x, y, inlen);
+      INPUT_BIGNUM(&key->qP, in, x, y, inlen);
+      INPUT_BIGNUM(&key->p, in, x, y, inlen);
+      INPUT_BIGNUM(&key->q, in, x, y, inlen);
+   }
+
+   /* free up ram not required */
+   if (key->type != PK_PRIVATE_OPTIMIZED) {
+      mp_clear_multi(&key->dQ, &key->dP, &key->pQ, &key->qP, &key->p, &key->q, NULL);
+   }
+   if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
+      mp_clear(&key->d);
+   }
+
+   return CRYPT_OK;
+error:
+   mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,
+                  &key->pQ, &key->qP, &key->p, &key->q, NULL);
+   return err;
+}
+
+#include "rsa_sys.c"
+
+#endif /* RSA */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa_exptmod.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,87 @@
+/* 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
+ */
+
+/* RSA Code by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+int rsa_exptmod(const unsigned char *in,  unsigned long inlen,
+                      unsigned char *out, unsigned long *outlen, int which,
+                      rsa_key *key)
+{
+   mp_int tmp, tmpa, tmpb;
+   unsigned long x;
+   int err;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+
+   if (which == PK_PRIVATE && (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED)) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   /* must be a private or public operation */
+   if (which != PK_PRIVATE && which != PK_PUBLIC) {
+      return CRYPT_PK_INVALID_TYPE;
+   }
+
+   /* init and copy into tmp */
+   if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != MP_OKAY)                     { goto error; }
+   if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen)) != MP_OKAY) { goto error; }
+
+   /* sanity check on the input */
+   if (mp_cmp(&key->N, &tmp) == MP_LT) {
+      err = CRYPT_PK_INVALID_SIZE;
+      goto done;
+   }
+
+   /* are we using the private exponent and is the key optimized? */
+   if (which == PK_PRIVATE && key->type == PK_PRIVATE_OPTIMIZED) {
+      /* tmpa = tmp^dP mod p */
+      if ((err = mp_exptmod(&tmp, &key->dP, &key->p, &tmpa)) != MP_OKAY)    { goto error; }
+
+      /* tmpb = tmp^dQ mod q */
+      if ((err = mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb)) != MP_OKAY)    { goto error; }
+
+      /* tmp = tmpa*qP + tmpb*pQ mod N */
+      if ((err = mp_mul(&tmpa, &key->qP, &tmpa)) != MP_OKAY)                { goto error; }
+      if ((err = mp_mul(&tmpb, &key->pQ, &tmpb)) != MP_OKAY)                { goto error; }
+      if ((err = mp_addmod(&tmpa, &tmpb, &key->N, &tmp)) != MP_OKAY)        { goto error; }
+   } else {
+      /* exptmod it */
+      if ((err = mp_exptmod(&tmp, which==PK_PRIVATE?&key->d:&key->e, &key->N, &tmp)) != MP_OKAY) { goto error; }
+   }
+
+   /* read it back */
+   x = (unsigned long)mp_unsigned_bin_size(&tmp);
+   if (x > *outlen) {
+      err = CRYPT_BUFFER_OVERFLOW;
+      goto done;
+   }
+   *outlen = x;
+
+   /* convert it */
+   if ((err = mp_to_unsigned_bin(&tmp, out)) != MP_OKAY)                    { goto error; }
+
+   /* clean up and return */
+   err = CRYPT_OK;
+   goto done;
+error:
+   err = mpi_to_ltc_error(err);
+done:
+   mp_clear_multi(&tmp, &tmpa, &tmpb, NULL);
+   return err;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa_free.c	Mon May 31 18:25:41 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
+ */
+
+/* RSA Code by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+void rsa_free(rsa_key *key)
+{
+   _ARGCHK(key != NULL);
+   mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP,
+                  &key->qP, &key->pQ, &key->p, &key->q, NULL);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa_make_key.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,113 @@
+/* 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
+ */
+
+/* RSA Code by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
+{
+   mp_int p, q, tmp1, tmp2, tmp3;
+   int err;
+
+   _ARGCHK(key != NULL);
+
+   if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+
+   if ((e < 3) || ((e & 1) == 0)) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err;
+   }
+
+   if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+
+   /* make primes p and q (optimization provided by Wayne Scott) */
+   if ((err = mp_set_int(&tmp3, e)) != MP_OKAY) { goto error; }            /* tmp3 = e */
+
+   /* make prime "p" */
+   do {
+       if ((err = rand_prime(&p, size*4, prng, wprng)) != CRYPT_OK) { goto done; }
+       if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY)               { goto error; }  /* tmp1 = p-1 */
+       if ((err = mp_gcd(&tmp1, &tmp3, &tmp2)) != MP_OKAY)          { goto error; }  /* tmp2 = gcd(p-1, e) */
+   } while (mp_cmp_d(&tmp2, 1) != 0);                                                /* while e divides p-1 */
+
+   /* make prime "q" */
+   do {
+       if ((err = rand_prime(&q, size*4, prng, wprng)) != CRYPT_OK) { goto done; }
+       if ((err = mp_sub_d(&q, 1, &tmp1)) != MP_OKAY)               { goto error; } /* tmp1 = q-1 */
+       if ((err = mp_gcd(&tmp1, &tmp3, &tmp2)) != MP_OKAY)          { goto error; } /* tmp2 = gcd(q-1, e) */
+   } while (mp_cmp_d(&tmp2, 1) != 0);                                               /* while e divides q-1 */
+
+   /* tmp1 = lcm(p-1, q-1) */
+   if ((err = mp_sub_d(&p, 1, &tmp2)) != MP_OKAY)                  { goto error; } /* tmp2 = p-1 */
+                                                                   /* tmp1 = q-1 (previous do/while loop) */
+   if ((err = mp_lcm(&tmp1, &tmp2, &tmp1)) != MP_OKAY)             { goto error; } /* tmp1 = lcm(p-1, q-1) */
+
+   /* make key */
+   if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP,
+                     &key->qP, &key->pQ, &key->p, &key->q, NULL)) != MP_OKAY) {
+      goto error;
+   }
+
+   if ((err = mp_set_int(&key->e, e)) != MP_OKAY)                  { goto error2; } /* key->e =  e */
+   if ((err = mp_invmod(&key->e, &tmp1, &key->d)) != MP_OKAY)      { goto error2; } /* key->d = 1/e mod lcm(p-1,q-1) */
+   if ((err = mp_mul(&p, &q, &key->N)) != MP_OKAY)                 { goto error2; } /* key->N = pq */
+
+/* optimize for CRT now */
+   /* find d mod q-1 and d mod p-1 */
+   if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY)                  { goto error2; } /* tmp1 = q-1 */
+   if ((err = mp_sub_d(&q, 1, &tmp2)) != MP_OKAY)                  { goto error2; } /* tmp2 = p-1 */
+
+   if ((err = mp_mod(&key->d, &tmp1, &key->dP)) != MP_OKAY)        { goto error2; } /* dP = d mod p-1 */
+   if ((err = mp_mod(&key->d, &tmp2, &key->dQ)) != MP_OKAY)        { goto error2; } /* dQ = d mod q-1 */
+
+   if ((err = mp_invmod(&q, &p, &key->qP)) != MP_OKAY)             { goto error2; } /* qP = 1/q mod p */
+   if ((err = mp_mulmod(&key->qP, &q, &key->N, &key->qP)) != MP_OKAY)         { goto error2; } /* qP = q * (1/q mod p) mod N */
+
+   if ((err = mp_invmod(&p, &q, &key->pQ)) != MP_OKAY)             { goto error2; } /* pQ = 1/p mod q */
+   if ((err = mp_mulmod(&key->pQ, &p, &key->N, &key->pQ)) != MP_OKAY)         { goto error2; } /* pQ = p * (1/p mod q) mod N */
+
+   if ((err = mp_copy(&p, &key->p)) != MP_OKAY)                    { goto error2; }
+   if ((err = mp_copy(&q, &key->q)) != MP_OKAY)                    { goto error2; }
+
+   /* shrink ram required  */
+   if ((err = mp_shrink(&key->e)) != MP_OKAY)                      { goto error2; }
+   if ((err = mp_shrink(&key->d)) != MP_OKAY)                      { goto error2; }
+   if ((err = mp_shrink(&key->N)) != MP_OKAY)                      { goto error2; }
+   if ((err = mp_shrink(&key->dQ)) != MP_OKAY)                     { goto error2; }
+   if ((err = mp_shrink(&key->dP)) != MP_OKAY)                     { goto error2; }
+   if ((err = mp_shrink(&key->qP)) != MP_OKAY)                     { goto error2; }
+   if ((err = mp_shrink(&key->pQ)) != MP_OKAY)                     { goto error2; }
+   if ((err = mp_shrink(&key->p)) != MP_OKAY)                      { goto error2; }
+   if ((err = mp_shrink(&key->q)) != MP_OKAY)                      { goto error2; }
+
+   err = CRYPT_OK;
+   key->type = PK_PRIVATE_OPTIMIZED;
+   goto done;
+error2:
+   mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,
+                  &key->qP, &key->pQ, &key->p, &key->q, NULL);
+error:
+   err = mpi_to_ltc_error(err);
+done:
+   mp_clear_multi(&tmp3, &tmp2, &tmp1, &p, &q, NULL);
+   return err;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa_sys.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,274 @@
+/* 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
+ */
+
+/* these are smaller routines written by Clay Culver.  They do the same function as the rsa_encrypt/decrypt 
+ * except that they are used to RSA encrypt/decrypt a single value and not a packet.
+ */
+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)
+{
+   unsigned char rsa_in[RSA_STACK], rsa_out[RSA_STACK];
+   unsigned long x, y, rsa_size;
+   int err;
+
+   _ARGCHK(inkey  != NULL);
+   _ARGCHK(outkey != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+   
+   /* only allow keys from 64 to 256 bits */
+   if (inlen < 8 || inlen > 32) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* are the parameters valid? */
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err; 
+   }
+
+   /* rsa_pad the symmetric key */
+   y = (unsigned long)sizeof(rsa_in); 
+   if ((err = rsa_pad(inkey, inlen, rsa_in, &y, wprng, prng)) != CRYPT_OK) {
+      return CRYPT_ERROR;
+   }
+   
+   /* rsa encrypt it */
+   rsa_size = (unsigned long)sizeof(rsa_out);
+   if ((err = rsa_exptmod(rsa_in, y, rsa_out, &rsa_size, PK_PUBLIC, key)) != CRYPT_OK) {
+      return CRYPT_ERROR;
+   }
+
+   /* check size */
+   if (*outlen < (PACKET_SIZE+4+rsa_size)) { 
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* store header */
+   packet_store_header(outkey, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY);
+
+   /* now lets make the header */
+   y = PACKET_SIZE;
+   
+   /* store the size of the RSA value */
+   STORE32L(rsa_size, (outkey+y));
+   y += 4;
+
+   /* store the rsa value */
+   for (x = 0; x < rsa_size; x++, y++) {
+       outkey[y] = rsa_out[x];
+   }
+
+   *outlen = y;
+#ifdef CLEAN_STACK
+   /* clean up */
+   zeromem(rsa_in, sizeof(rsa_in));
+   zeromem(rsa_out, sizeof(rsa_out));
+#endif
+
+   return CRYPT_OK;
+}
+
+int rsa_decrypt_key(const unsigned char *in, unsigned long inlen,
+                          unsigned char *outkey, unsigned long *keylen, 
+                          rsa_key *key)
+{
+   unsigned char sym_key[MAXBLOCKSIZE], rsa_out[RSA_STACK];
+   unsigned long x, y, z, i, rsa_size;
+   int err;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(outkey != NULL);
+   _ARGCHK(keylen != NULL);
+   _ARGCHK(key    != NULL);
+
+   /* right key type? */
+   if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   if (inlen < PACKET_SIZE+4) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= PACKET_SIZE+4;
+   }
+
+   /* check the header */
+   if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* grab length of the rsa key */
+   y = PACKET_SIZE;
+   LOAD32L(rsa_size, (in+y));
+   if (inlen < rsa_size) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= rsa_size;
+   }
+   y += 4;
+
+   /* decrypt it */
+   x = (unsigned long)sizeof(rsa_out);
+   if ((err = rsa_exptmod(in+y, rsa_size, rsa_out, &x, PK_PRIVATE, key)) != CRYPT_OK) {
+      return err;
+   }
+   y += rsa_size;
+
+   /* depad it */
+   z = (unsigned long)sizeof(sym_key);
+   if ((err = rsa_depad(rsa_out, x, sym_key, &z)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* check size */
+   if (*keylen < z) { 
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   for (i = 0; i < z; i++) {
+     outkey[i] = sym_key[i];
+   }
+   
+#ifdef CLEAN_STACK
+   /* clean up */
+   zeromem(sym_key, sizeof(sym_key));
+   zeromem(rsa_out, sizeof(rsa_out));
+#endif
+   *keylen = z;
+   return CRYPT_OK;
+}
+
+int rsa_sign_hash(const unsigned char *in,  unsigned long inlen, 
+                        unsigned char *out, unsigned long *outlen, 
+                        rsa_key *key)
+{
+   unsigned long rsa_size, x, y;
+   unsigned char rsa_in[RSA_STACK], rsa_out[RSA_STACK];
+   int err;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+   
+   /* reject nonsense sizes */
+   if (inlen > (512/3) || inlen < 16) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* type of key? */
+   if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   /* pad it */
+   x = (unsigned long)sizeof(rsa_out);
+   if ((err = rsa_signpad(in, inlen, rsa_out, &x)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* sign it */
+   rsa_size = (unsigned long)sizeof(rsa_in);
+   if ((err = rsa_exptmod(rsa_out, x, rsa_in, &rsa_size, PK_PRIVATE, key)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* check size */
+   if (*outlen < (PACKET_SIZE+4+rsa_size)) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* now lets output the message */
+   y = PACKET_SIZE;
+
+   /* output the len */
+   STORE32L(rsa_size, (out+y));
+   y += 4;
+
+   /* store the signature */
+   for (x = 0; x < rsa_size; x++, y++) {
+       out[y] = rsa_in[x];
+   }
+
+   /* store header */
+   packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_SIGNED);
+
+#ifdef CLEAN_STACK
+   /* clean up */
+   zeromem(rsa_in, sizeof(rsa_in));
+   zeromem(rsa_out, sizeof(rsa_out));
+#endif
+   *outlen = y;
+   return CRYPT_OK;
+}
+
+int rsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+                    const unsigned char *md, int *stat, rsa_key *key)
+{
+   unsigned long rsa_size, x, y, z;
+   unsigned char rsa_in[RSA_STACK], rsa_out[RSA_STACK];
+   int err;
+
+   _ARGCHK(sig  != NULL);
+   _ARGCHK(md   != NULL);
+   _ARGCHK(stat != NULL);
+   _ARGCHK(key  != NULL);
+
+   /* always be incorrect by default */
+   *stat = 0;
+   
+   if (siglen < PACKET_SIZE+4) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= PACKET_SIZE+4;
+   }
+
+   /* verify header */
+   if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_RSA, PACKET_SUB_SIGNED)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* get the len */
+   y = PACKET_SIZE;
+   LOAD32L(rsa_size, (sig+y));
+   if (siglen < rsa_size) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= rsa_size;
+   }
+   y += 4;
+
+   /* exptmod it */
+   x = (unsigned long)sizeof(rsa_out);
+   if ((err = rsa_exptmod(sig+y, rsa_size, rsa_out, &x, PK_PUBLIC, key)) != CRYPT_OK) {
+      return err;
+   }
+   y += rsa_size;
+
+   /* depad it */
+   z = (unsigned long)sizeof(rsa_in);
+   if ((err = rsa_signdepad(rsa_out, x, rsa_in, &z)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* check? */
+   if (memcmp(rsa_in, md, (size_t)z) == 0) {
+      *stat = 1;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(rsa_in, sizeof(rsa_in));
+   zeromem(rsa_out, sizeof(rsa_out));
+#endif
+   return CRYPT_OK;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/s_ocb_done.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,102 @@
+/* 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
+ */
+
+/* OCB Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef OCB_MODE
+
+/* Since the last block is encrypted in CTR mode the same code can
+ * be used to finish a decrypt or encrypt stream.  The only difference
+ * is we XOR the final ciphertext into the checksum so we have to xor it
+ * before we CTR [decrypt] or after [encrypt]
+ *
+ * the names pt/ptlen/ct really just mean in/inlen/out but this is the way I wrote it... 
+ */
+int __ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen,
+                     unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode)
+
+{
+   unsigned char Z[MAXBLOCKSIZE], Y[MAXBLOCKSIZE], X[MAXBLOCKSIZE];
+   int err, x;
+
+   _ARGCHK(ocb    != NULL);
+   _ARGCHK(pt     != NULL);
+   _ARGCHK(ct     != NULL);
+   _ARGCHK(tag    != NULL);
+   _ARGCHK(taglen != NULL);
+   if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
+      return err;
+   }
+   if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length ||
+       (int)ptlen > ocb->block_len || (int)ptlen < 0) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* compute X[m] = len(pt[m]) XOR Lr XOR Z[m] */
+   ocb_shift_xor(ocb, X); 
+   memcpy(Z, X, ocb->block_len);
+
+   X[ocb->block_len-1] ^= (ptlen*8)&255;
+   X[ocb->block_len-2] ^= ((ptlen*8)>>8)&255;
+   for (x = 0; x < ocb->block_len; x++) {
+       X[x] ^= ocb->Lr[x]; 
+   }
+
+   /* Y[m] = E(X[m])) */
+   cipher_descriptor[ocb->cipher].ecb_encrypt(X, Y, &ocb->key);
+
+   if (mode == 1) {
+      /* decrypt mode, so let's xor it first */
+      /* xor C[m] into checksum */
+      for (x = 0; x < (int)ptlen; x++) {
+         ocb->checksum[x] ^= ct[x];
+      }  
+   }
+
+   /* C[m] = P[m] xor Y[m] */
+   for (x = 0; x < (int)ptlen; x++) {
+       ct[x] = pt[x] ^ Y[x];
+   }
+
+   if (mode == 0) {
+      /* encrypt mode */    
+      /* xor C[m] into checksum */
+      for (x = 0; x < (int)ptlen; x++) {
+          ocb->checksum[x] ^= ct[x];
+      }
+   }
+
+   /* xor Y[m] and Z[m] into checksum */
+   for (x = 0; x < ocb->block_len; x++) {
+       ocb->checksum[x] ^= Y[x] ^ Z[x];
+   }
+   
+   /* encrypt checksum, er... tag!! */
+   cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->checksum, X, &ocb->key);
+
+   /* now store it */
+   for (x = 0; x < ocb->block_len && x < (int)*taglen; x++) {
+       tag[x] = X[x];
+   }
+   *taglen = x;
+
+#ifdef CLEAN_STACK
+   zeromem(X, sizeof(X));
+   zeromem(Y, sizeof(Y));
+   zeromem(Z, sizeof(Z));
+   zeromem(ocb, sizeof(*ocb));
+#endif
+   return CRYPT_OK;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/safer.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,468 @@
+/* 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
+ */
+
+/*******************************************************************************
+*
+* FILE:           safer.c
+*
+* DESCRIPTION:    block-cipher algorithm SAFER (Secure And Fast Encryption
+*                 Routine) in its four versions: SAFER K-64, SAFER K-128,
+*                 SAFER SK-64 and SAFER SK-128.
+*
+* AUTHOR:         Richard De Moliner ([email protected])
+*                 Signal and Information Processing Laboratory
+*                 Swiss Federal Institute of Technology
+*                 CH-8092 Zuerich, Switzerland
+*
+* DATE:           September 9, 1995
+*
+* CHANGE HISTORY:
+*
+*******************************************************************************/
+
+#include <mycrypt.h>
+
+#ifdef SAFER
+
+const struct _cipher_descriptor 
+   safer_k64_desc = {
+   "safer-k64", 
+   8, 8, 8, 8, SAFER_K64_DEFAULT_NOF_ROUNDS,
+   &safer_k64_setup,
+   &safer_ecb_encrypt,
+   &safer_ecb_decrypt,
+   &safer_k64_test,
+   &safer_64_keysize
+   },
+
+   safer_sk64_desc = {
+   "safer-sk64",
+   9, 8, 8, 8, SAFER_SK64_DEFAULT_NOF_ROUNDS,
+   &safer_sk64_setup,
+   &safer_ecb_encrypt,
+   &safer_ecb_decrypt,
+   &safer_sk64_test,
+   &safer_64_keysize
+   },
+
+   safer_k128_desc = {
+   "safer-k128",
+   10, 16, 16, 8, SAFER_K128_DEFAULT_NOF_ROUNDS,
+   &safer_k128_setup,
+   &safer_ecb_encrypt,
+   &safer_ecb_decrypt,
+   &safer_sk128_test,
+   &safer_128_keysize
+   },
+
+   safer_sk128_desc = {
+   "safer-sk128",
+   11, 16, 16, 8, SAFER_SK128_DEFAULT_NOF_ROUNDS,
+   &safer_sk128_setup,
+   &safer_ecb_encrypt,
+   &safer_ecb_decrypt,
+   &safer_sk128_test,
+   &safer_128_keysize
+   };
+
+/******************* Constants ************************************************/
+// #define TAB_LEN      256
+
+/******************* Assertions ***********************************************/
+
+/******************* Macros ***************************************************/
+#define ROL8(x, n)   ((unsigned char)((unsigned int)(x) << (n)\
+                                     |(unsigned int)((x) & 0xFF) >> (8 - (n))))
+#define EXP(x)       safer_ebox[(x) & 0xFF]
+#define LOG(x)       safer_lbox[(x) & 0xFF]
+#define PHT(x, y)    { y += x; x += y; }
+#define IPHT(x, y)   { x -= y; y -= x; }
+
+/******************* Types ****************************************************/
+extern const unsigned char safer_ebox[], safer_lbox[];
+
+#ifdef CLEAN_STACK
+static void _Safer_Expand_Userkey(const unsigned char *userkey_1,
+                                 const unsigned char *userkey_2,
+                                 unsigned int nof_rounds,
+                                 int strengthened,
+                                 safer_key_t key)
+#else
+static void Safer_Expand_Userkey(const unsigned char *userkey_1,
+                                 const unsigned char *userkey_2,
+                                 unsigned int nof_rounds,
+                                 int strengthened,
+                                 safer_key_t key)
+#endif
+{   unsigned int i, j, k;
+    unsigned char ka[SAFER_BLOCK_LEN + 1];
+    unsigned char kb[SAFER_BLOCK_LEN + 1];
+
+    if (SAFER_MAX_NOF_ROUNDS < nof_rounds)
+        nof_rounds = SAFER_MAX_NOF_ROUNDS;
+    *key++ = (unsigned char)nof_rounds;
+    ka[SAFER_BLOCK_LEN] = (unsigned char)0;
+    kb[SAFER_BLOCK_LEN] = (unsigned char)0;
+    k = 0;
+    for (j = 0; j < SAFER_BLOCK_LEN; j++) {
+        ka[j] = ROL8(userkey_1[j], 5);
+        ka[SAFER_BLOCK_LEN] ^= ka[j];
+        kb[j] = *key++ = userkey_2[j];
+        kb[SAFER_BLOCK_LEN] ^= kb[j];
+    }
+    for (i = 1; i <= nof_rounds; i++) {
+        for (j = 0; j < SAFER_BLOCK_LEN + 1; j++) {
+            ka[j] = ROL8(ka[j], 6);
+            kb[j] = ROL8(kb[j], 6);
+        }
+        if (strengthened) {
+           k = 2 * i - 1;
+           while (k >= (SAFER_BLOCK_LEN + 1)) { k -= SAFER_BLOCK_LEN + 1; }
+        }
+        for (j = 0; j < SAFER_BLOCK_LEN; j++) {
+            if (strengthened) {
+                *key++ = (ka[k]
+                                + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF;
+                if (++k == (SAFER_BLOCK_LEN + 1)) { k = 0; }
+            } else {
+                *key++ = (ka[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF;
+            }
+        }
+        if (strengthened) {
+           k = 2 * i;
+           while (k >= (SAFER_BLOCK_LEN + 1)) { k -= SAFER_BLOCK_LEN + 1; }
+        }
+        for (j = 0; j < SAFER_BLOCK_LEN; j++) {
+            if (strengthened) {
+                *key++ = (kb[k]
+                                + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF;
+                if (++k == (SAFER_BLOCK_LEN + 1)) { k = 0; }
+            } else {
+                *key++ = (kb[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF;
+            }
+        }
+    }
+    
+#ifdef CLEAN_STACK
+    zeromem(ka, sizeof(ka));
+    zeromem(kb, sizeof(kb));
+#endif
+}
+
+#ifdef CLEAN_STACK
+static void Safer_Expand_Userkey(const unsigned char *userkey_1,
+                                 const unsigned char *userkey_2,
+                                 unsigned int nof_rounds,
+                                 int strengthened,
+                                 safer_key_t key)
+{
+   _Safer_Expand_Userkey(userkey_1, userkey_2, nof_rounds, strengthened, key);
+   burn_stack(sizeof(unsigned char) * (2 * (SAFER_BLOCK_LEN + 1)) + sizeof(unsigned int)*2);
+}
+#endif
+
+int safer_k64_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
+{
+   _ARGCHK(key != NULL);
+   _ARGCHK(skey != NULL);
+
+   if (numrounds != 0 && (numrounds < 6 || numrounds > SAFER_MAX_NOF_ROUNDS)) {
+      return CRYPT_INVALID_ROUNDS;
+   }
+
+   if (keylen != 8) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+
+   Safer_Expand_Userkey(key, key, (unsigned int)(numrounds != 0 ?numrounds:SAFER_K64_DEFAULT_NOF_ROUNDS), 0, skey->safer.key);
+   return CRYPT_OK;
+}
+   
+int safer_sk64_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
+{
+   _ARGCHK(key != NULL);
+   _ARGCHK(skey != NULL);
+
+   if (numrounds != 0 && (numrounds < 6 || numrounds > SAFER_MAX_NOF_ROUNDS)) {
+      return CRYPT_INVALID_ROUNDS;
+   }
+
+   if (keylen != 8) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+
+   Safer_Expand_Userkey(key, key, (unsigned int)(numrounds != 0 ?numrounds:SAFER_SK64_DEFAULT_NOF_ROUNDS), 1, skey->safer.key);
+   return CRYPT_OK;
+}
+
+int safer_k128_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
+{
+   _ARGCHK(key != NULL);
+   _ARGCHK(skey != NULL);
+
+   if (numrounds != 0 && (numrounds < 6 || numrounds > SAFER_MAX_NOF_ROUNDS)) {
+      return CRYPT_INVALID_ROUNDS;
+   }
+
+   if (keylen != 16) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+
+   Safer_Expand_Userkey(key, key+8, (unsigned int)(numrounds != 0 ?numrounds:SAFER_K128_DEFAULT_NOF_ROUNDS), 0, skey->safer.key);
+   return CRYPT_OK;
+}
+
+int safer_sk128_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
+{
+   _ARGCHK(key != NULL);
+   _ARGCHK(skey != NULL);
+
+   if (numrounds != 0 && (numrounds < 6 || numrounds > SAFER_MAX_NOF_ROUNDS)) {
+      return CRYPT_INVALID_ROUNDS;
+   }
+
+   if (keylen != 16) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+
+   Safer_Expand_Userkey(key, key+8, (unsigned int)(numrounds != 0?numrounds:SAFER_SK128_DEFAULT_NOF_ROUNDS), 1, skey->safer.key);
+   return CRYPT_OK;
+}
+
+#ifdef CLEAN_STACK
+static void _safer_ecb_encrypt(const unsigned char *block_in,
+                             unsigned char *block_out,
+                             symmetric_key *skey)
+#else
+void safer_ecb_encrypt(const unsigned char *block_in,
+                             unsigned char *block_out,
+                             symmetric_key *skey)
+#endif
+{   unsigned char a, b, c, d, e, f, g, h, t;
+    unsigned int round;
+    unsigned char *key;
+
+    _ARGCHK(block_in != NULL);
+    _ARGCHK(block_out != NULL);
+    _ARGCHK(skey != NULL);
+
+    key = skey->safer.key;
+    a = block_in[0]; b = block_in[1]; c = block_in[2]; d = block_in[3];
+    e = block_in[4]; f = block_in[5]; g = block_in[6]; h = block_in[7];
+    if (SAFER_MAX_NOF_ROUNDS < (round = *key)) round = SAFER_MAX_NOF_ROUNDS;
+    while(round-- > 0)
+    {
+        a ^= *++key; b += *++key; c += *++key; d ^= *++key;
+        e ^= *++key; f += *++key; g += *++key; h ^= *++key;
+        a = EXP(a) + *++key; b = LOG(b) ^ *++key;
+        c = LOG(c) ^ *++key; d = EXP(d) + *++key;
+        e = EXP(e) + *++key; f = LOG(f) ^ *++key;
+        g = LOG(g) ^ *++key; h = EXP(h) + *++key;
+        PHT(a, b); PHT(c, d); PHT(e, f); PHT(g, h);
+        PHT(a, c); PHT(e, g); PHT(b, d); PHT(f, h);
+        PHT(a, e); PHT(b, f); PHT(c, g); PHT(d, h);
+        t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t;
+    }
+    a ^= *++key; b += *++key; c += *++key; d ^= *++key;
+    e ^= *++key; f += *++key; g += *++key; h ^= *++key;
+    block_out[0] = a & 0xFF; block_out[1] = b & 0xFF;
+    block_out[2] = c & 0xFF; block_out[3] = d & 0xFF;
+    block_out[4] = e & 0xFF; block_out[5] = f & 0xFF;
+    block_out[6] = g & 0xFF; block_out[7] = h & 0xFF;
+}
+
+#ifdef CLEAN_STACK
+void safer_ecb_encrypt(const unsigned char *block_in,
+                             unsigned char *block_out,
+                             symmetric_key *skey)
+{
+    _safer_ecb_encrypt(block_in, block_out, skey);
+    burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *));
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _safer_ecb_decrypt(const unsigned char *block_in,
+                             unsigned char *block_out,
+                             symmetric_key *skey)
+#else
+void safer_ecb_decrypt(const unsigned char *block_in,
+                             unsigned char *block_out,
+                             symmetric_key *skey)
+#endif
+{   unsigned char a, b, c, d, e, f, g, h, t;
+    unsigned int round;
+    unsigned char *key;
+
+    _ARGCHK(block_in != NULL);
+    _ARGCHK(block_out != NULL);
+    _ARGCHK(skey != NULL);
+
+    key = skey->safer.key;
+    a = block_in[0]; b = block_in[1]; c = block_in[2]; d = block_in[3];
+    e = block_in[4]; f = block_in[5]; g = block_in[6]; h = block_in[7];
+    if (SAFER_MAX_NOF_ROUNDS < (round = *key)) round = SAFER_MAX_NOF_ROUNDS;
+    key += SAFER_BLOCK_LEN * (1 + 2 * round);
+    h ^= *key; g -= *--key; f -= *--key; e ^= *--key;
+    d ^= *--key; c -= *--key; b -= *--key; a ^= *--key;
+    while (round--)
+    {
+        t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t;
+        IPHT(a, e); IPHT(b, f); IPHT(c, g); IPHT(d, h);
+        IPHT(a, c); IPHT(e, g); IPHT(b, d); IPHT(f, h);
+        IPHT(a, b); IPHT(c, d); IPHT(e, f); IPHT(g, h);
+        h -= *--key; g ^= *--key; f ^= *--key; e -= *--key;
+        d -= *--key; c ^= *--key; b ^= *--key; a -= *--key;
+        h = LOG(h) ^ *--key; g = EXP(g) - *--key;
+        f = EXP(f) - *--key; e = LOG(e) ^ *--key;
+        d = LOG(d) ^ *--key; c = EXP(c) - *--key;
+        b = EXP(b) - *--key; a = LOG(a) ^ *--key;
+    }
+    block_out[0] = a & 0xFF; block_out[1] = b & 0xFF;
+    block_out[2] = c & 0xFF; block_out[3] = d & 0xFF;
+    block_out[4] = e & 0xFF; block_out[5] = f & 0xFF;
+    block_out[6] = g & 0xFF; block_out[7] = h & 0xFF;
+}
+
+#ifdef CLEAN_STACK
+void safer_ecb_decrypt(const unsigned char *block_in,
+                             unsigned char *block_out,
+                             symmetric_key *skey)
+{
+    _safer_ecb_decrypt(block_in, block_out, skey);
+    burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *));
+}
+#endif
+
+int safer_64_keysize(int *keysize)
+{
+   _ARGCHK(keysize != NULL);
+   if (*keysize < 8) {
+      return CRYPT_INVALID_KEYSIZE;
+   } else {
+      *keysize = 8;
+      return CRYPT_OK;
+   }
+}
+
+int safer_128_keysize(int *keysize)
+{
+   _ARGCHK(keysize != NULL);
+   if (*keysize < 16) {
+      return CRYPT_INVALID_KEYSIZE;
+   } else {
+      *keysize = 16;
+      return CRYPT_OK;
+   }
+}
+
+int safer_k64_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+   static const unsigned char k64_pt[]  = { 1, 2, 3, 4, 5, 6, 7, 8 },
+                              k64_key[] = { 8, 7, 6, 5, 4, 3, 2, 1 },
+                              k64_ct[]  = { 200, 242, 156, 221, 135, 120, 62, 217 };
+
+   symmetric_key skey;
+   unsigned char buf[2][8];
+   int err;
+
+   /* test K64 */
+   if ((err = safer_k64_setup(k64_key, 8, 6, &skey)) != CRYPT_OK) {
+      return err;
+   }
+   safer_ecb_encrypt(k64_pt, buf[0], &skey);
+   safer_ecb_decrypt(buf[0], buf[1], &skey);
+
+   if (memcmp(buf[0], k64_ct, 8) != 0 || memcmp(buf[1], k64_pt, 8) != 0) {
+      return CRYPT_FAIL_TESTVECTOR;
+   }
+
+   return CRYPT_OK;
+ #endif
+}
+
+
+int safer_sk64_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+   static const unsigned char sk64_pt[]  = { 1, 2, 3, 4, 5, 6, 7, 8 },
+                              sk64_key[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
+                              sk64_ct[]  = { 95, 206, 155, 162, 5, 132, 56, 199 };
+
+   symmetric_key skey;
+   unsigned char buf[2][8];
+   int err, y;
+
+   /* test SK64 */
+   if ((err = safer_sk64_setup(sk64_key, 8, 6, &skey)) != CRYPT_OK) {
+      return err;
+   }
+
+   safer_ecb_encrypt(sk64_pt, buf[0], &skey);
+   safer_ecb_decrypt(buf[0], buf[1], &skey);
+
+   if (memcmp(buf[0], sk64_ct, 8) != 0 || memcmp(buf[1], sk64_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++) buf[0][y] = 0;
+      for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey);
+      for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey);
+      for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+
+   return CRYPT_OK;
+  #endif
+}
+
+int safer_sk128_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+   static const unsigned char sk128_pt[]  = { 1, 2, 3, 4, 5, 6, 7, 8 },
+                              sk128_key[] = { 1, 2, 3, 4, 5, 6, 7, 8,
+                                              0, 0, 0, 0, 0, 0, 0, 0 },
+                              sk128_ct[]  = { 255, 120, 17, 228, 179, 167, 46, 113 };
+
+   symmetric_key skey;
+   unsigned char buf[2][8];
+   int err, y;
+
+   /* test SK128 */
+   if ((err = safer_sk128_setup(sk128_key, 16, 0, &skey)) != CRYPT_OK) {
+      return err;
+   }
+   safer_ecb_encrypt(sk128_pt, buf[0], &skey);
+   safer_ecb_decrypt(buf[0], buf[1], &skey);
+
+   if (memcmp(buf[0], sk128_ct, 8) != 0 || memcmp(buf[1], sk128_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++) buf[0][y] = 0;
+      for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey);
+      for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey);
+      for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+  return CRYPT_OK;
+ #endif
+}
+
+#endif
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/safer_tab.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,59 @@
+/* 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"
+
+#if defined(SAFERP) || defined(SAFER)
+
+/* This is the box defined by ebox[x] = 45^x mod 257.  
+ * Its assumed that the value "256" corresponds to zero. */
+const unsigned char safer_ebox[256] = {
+  1,  45, 226, 147, 190,  69,  21, 174, 120,   3, 135, 164, 184,  56, 207,  63, 
+  8, 103,   9, 148, 235,  38, 168, 107, 189,  24,  52,  27, 187, 191, 114, 247, 
+ 64,  53,  72, 156,  81,  47,  59,  85, 227, 192, 159, 216, 211, 243, 141, 177, 
+255, 167,  62, 220, 134, 119, 215, 166,  17, 251, 244, 186, 146, 145, 100, 131, 
+241,  51, 239, 218,  44, 181, 178,  43, 136, 209, 153, 203, 140, 132,  29,  20, 
+129, 151, 113, 202,  95, 163, 139,  87,  60, 130, 196,  82,  92,  28, 232, 160, 
+  4, 180, 133,  74, 246,  19,  84, 182, 223,  12,  26, 142, 222, 224,  57, 252, 
+ 32, 155,  36,  78, 169, 152, 158, 171, 242,  96, 208, 108, 234, 250, 199, 217, 
+  0, 212,  31, 110,  67, 188, 236,  83, 137, 254, 122,  93,  73, 201,  50, 194, 
+249, 154, 248, 109,  22, 219,  89, 150,  68, 233, 205, 230,  70,  66, 143,  10, 
+193, 204, 185, 101, 176, 210, 198, 172,  30,  65,  98,  41,  46,  14, 116,  80, 
+  2,  90, 195,  37, 123, 138,  42,  91, 240,   6,  13,  71, 111, 112, 157, 126, 
+ 16, 206,  18,  39, 213,  76,  79, 214, 121,  48, 104,  54, 117, 125, 228, 237, 
+128, 106, 144,  55, 162,  94, 118, 170, 197, 127,  61, 175, 165, 229,  25,  97, 
+253,  77, 124, 183,  11, 238, 173,  75,  34, 245, 231, 115,  35,  33, 200,   5, 
+225, 102, 221, 179,  88, 105,  99,  86,  15, 161,  49, 149,  23,   7,  58,  40
+};
+
+/* This is the inverse of ebox or the base 45 logarithm */
+const unsigned char safer_lbox[256] = {
+128,   0, 176,   9,  96, 239, 185, 253,  16,  18, 159, 228, 105, 186, 173, 248,
+192,  56, 194, 101,  79,   6, 148, 252,  25, 222, 106,  27,  93,  78, 168, 130,
+112, 237, 232, 236, 114, 179,  21, 195, 255, 171, 182,  71,  68,   1, 172,  37, 
+201, 250, 142,  65,  26,  33, 203, 211,  13, 110, 254,  38,  88, 218,  50,  15, 
+ 32, 169, 157, 132, 152,   5, 156, 187,  34, 140,  99, 231, 197, 225, 115, 198, 
+175,  36,  91, 135, 102,  39, 247,  87, 244, 150, 177, 183,  92, 139, 213,  84, 
+121, 223, 170, 246,  62, 163, 241,  17, 202, 245, 209,  23, 123, 147, 131, 188, 
+189,  82,  30, 235, 174, 204, 214,  53,   8, 200, 138, 180, 226, 205, 191, 217,
+208,  80,  89,  63,  77,  98,  52,  10,  72, 136, 181,  86,  76,  46, 107, 158, 
+210,  61,  60,   3,  19, 251, 151,  81, 117,  74, 145, 113,  35, 190, 118,  42, 
+ 95, 249, 212,  85,  11, 220,  55,  49,  22, 116, 215, 119, 167, 230,   7, 219,
+164,  47,  70, 243,  97,  69, 103, 227,  12, 162,  59,  28, 133,  24,   4,  29, 
+ 41, 160, 143, 178,  90, 216, 166, 126, 238, 141,  83,  75, 161, 154, 193,  14, 
+122,  73, 165,  44, 129, 196, 199,  54,  43, 127,  67, 149,  51, 242, 108, 104, 
+109, 240,   2,  40, 206, 221, 155, 234,  94, 153, 124,  20, 134, 207, 229,  66, 
+184,  64, 120,  45,  58, 233, 100,  31, 146, 144, 125,  57, 111, 224, 137,  48
+};
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saferp.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,510 @@
+/* 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
+ */
+
+/* SAFER+ Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef SAFERP
+
+const struct _cipher_descriptor saferp_desc =
+{
+    "safer+",
+    4,
+    16, 32, 16, 8,
+    &saferp_setup,
+    &saferp_ecb_encrypt,
+    &saferp_ecb_decrypt,
+    &saferp_test,
+    &saferp_keysize
+};
+
+/* ROUND(b,i) 
+ *
+ * This is one forward key application.  Note the basic form is 
+ * key addition, substitution, key addition.  The safer_ebox and safer_lbox 
+ * are the exponentiation box and logarithm boxes respectively.  
+ * The value of 'i' is the current round number which allows this 
+ * function to be unrolled massively.  Most of SAFER+'s speed 
+ * comes from not having to compute indirect accesses into the 
+ * array of 16 bytes b[0..15] which is the block of data
+*/
+
+extern const unsigned char safer_ebox[], safer_lbox[];
+
+#define ROUND(b, i)                                                                        \
+    b[0]  = (safer_ebox[(b[0] ^ skey->saferp.K[i][0]) & 255] + skey->saferp.K[i+1][0]) & 255;    \
+    b[1]  = safer_lbox[(b[1] + skey->saferp.K[i][1]) & 255] ^ skey->saferp.K[i+1][1];            \
+    b[2]  = safer_lbox[(b[2] + skey->saferp.K[i][2]) & 255] ^ skey->saferp.K[i+1][2];            \
+    b[3]  = (safer_ebox[(b[3] ^ skey->saferp.K[i][3]) & 255] + skey->saferp.K[i+1][3]) & 255;    \
+    b[4]  = (safer_ebox[(b[4] ^ skey->saferp.K[i][4]) & 255] + skey->saferp.K[i+1][4]) & 255;    \
+    b[5]  = safer_lbox[(b[5] + skey->saferp.K[i][5]) & 255] ^ skey->saferp.K[i+1][5];            \
+    b[6]  = safer_lbox[(b[6] + skey->saferp.K[i][6]) & 255] ^ skey->saferp.K[i+1][6];            \
+    b[7]  = (safer_ebox[(b[7] ^ skey->saferp.K[i][7]) & 255] + skey->saferp.K[i+1][7]) & 255;    \
+    b[8]  = (safer_ebox[(b[8] ^ skey->saferp.K[i][8]) & 255] + skey->saferp.K[i+1][8]) & 255;    \
+    b[9]  = safer_lbox[(b[9] + skey->saferp.K[i][9]) & 255] ^ skey->saferp.K[i+1][9];            \
+    b[10] = safer_lbox[(b[10] + skey->saferp.K[i][10]) & 255] ^ skey->saferp.K[i+1][10];         \
+    b[11] = (safer_ebox[(b[11] ^ skey->saferp.K[i][11]) & 255] + skey->saferp.K[i+1][11]) & 255; \
+    b[12] = (safer_ebox[(b[12] ^ skey->saferp.K[i][12]) & 255] + skey->saferp.K[i+1][12]) & 255; \
+    b[13] = safer_lbox[(b[13] + skey->saferp.K[i][13]) & 255] ^ skey->saferp.K[i+1][13];         \
+    b[14] = safer_lbox[(b[14] + skey->saferp.K[i][14]) & 255] ^ skey->saferp.K[i+1][14];         \
+    b[15] = (safer_ebox[(b[15] ^ skey->saferp.K[i][15]) & 255] + skey->saferp.K[i+1][15]) & 255;        
+
+/* This is one inverse key application */
+#define iROUND(b, i)                                                                       \
+    b[0]  = safer_lbox[(b[0] - skey->saferp.K[i+1][0]) & 255] ^ skey->saferp.K[i][0];            \
+    b[1]  = (safer_ebox[(b[1] ^ skey->saferp.K[i+1][1]) & 255] - skey->saferp.K[i][1]) & 255;    \
+    b[2]  = (safer_ebox[(b[2] ^ skey->saferp.K[i+1][2]) & 255] - skey->saferp.K[i][2]) & 255;    \
+    b[3]  = safer_lbox[(b[3] - skey->saferp.K[i+1][3]) & 255] ^ skey->saferp.K[i][3];            \
+    b[4]  = safer_lbox[(b[4] - skey->saferp.K[i+1][4]) & 255] ^ skey->saferp.K[i][4];            \
+    b[5]  = (safer_ebox[(b[5] ^ skey->saferp.K[i+1][5]) & 255] - skey->saferp.K[i][5]) & 255;    \
+    b[6]  = (safer_ebox[(b[6] ^ skey->saferp.K[i+1][6]) & 255] - skey->saferp.K[i][6]) & 255;    \
+    b[7]  = safer_lbox[(b[7] - skey->saferp.K[i+1][7]) & 255] ^ skey->saferp.K[i][7];            \
+    b[8]  = safer_lbox[(b[8] - skey->saferp.K[i+1][8]) & 255] ^ skey->saferp.K[i][8];            \
+    b[9]  = (safer_ebox[(b[9] ^ skey->saferp.K[i+1][9]) & 255] - skey->saferp.K[i][9]) & 255;    \
+    b[10] = (safer_ebox[(b[10] ^ skey->saferp.K[i+1][10]) & 255] - skey->saferp.K[i][10]) & 255; \
+    b[11] = safer_lbox[(b[11] - skey->saferp.K[i+1][11]) & 255] ^ skey->saferp.K[i][11];         \
+    b[12] = safer_lbox[(b[12] - skey->saferp.K[i+1][12]) & 255] ^ skey->saferp.K[i][12];         \
+    b[13] = (safer_ebox[(b[13] ^ skey->saferp.K[i+1][13]) & 255] - skey->saferp.K[i][13]) & 255; \
+    b[14] = (safer_ebox[(b[14] ^ skey->saferp.K[i+1][14]) & 255] - skey->saferp.K[i][14]) & 255; \
+    b[15] = safer_lbox[(b[15] - skey->saferp.K[i+1][15]) & 255] ^ skey->saferp.K[i][15];
+
+/* This is a forward single layer PHT transform.  */
+#define PHT(b)                                               \
+    b[0]  = (b[0] + (b[1] = (b[0] + b[1]) & 255)) & 255;     \
+    b[2]  = (b[2] + (b[3] = (b[3] + b[2]) & 255)) & 255;     \
+    b[4]  = (b[4] + (b[5] = (b[5] + b[4]) & 255)) & 255;     \
+    b[6]  = (b[6] + (b[7] = (b[7] + b[6]) & 255)) & 255;     \
+    b[8]  = (b[8] + (b[9] = (b[9] + b[8]) & 255)) & 255;     \
+    b[10] = (b[10] + (b[11] = (b[11] + b[10]) & 255)) & 255; \
+    b[12] = (b[12] + (b[13] = (b[13] + b[12]) & 255)) & 255; \
+    b[14] = (b[14] + (b[15] = (b[15] + b[14]) & 255)) & 255;    
+
+/* This is an inverse single layer PHT transform */
+#define iPHT(b)                                               \
+    b[15] = (b[15] - (b[14] = (b[14] - b[15]) & 255)) & 255;  \
+    b[13] = (b[13] - (b[12] = (b[12] - b[13]) & 255)) & 255;  \
+    b[11] = (b[11] - (b[10] = (b[10] - b[11]) & 255)) & 255;  \
+    b[9]  = (b[9] - (b[8] = (b[8] - b[9]) & 255)) & 255;      \
+    b[7]  = (b[7] - (b[6] = (b[6] - b[7]) & 255)) & 255;      \
+    b[5]  = (b[5] - (b[4] = (b[4] - b[5]) & 255)) & 255;      \
+    b[3]  = (b[3] - (b[2] = (b[2] - b[3]) & 255)) & 255;      \
+    b[1]  = (b[1] - (b[0] = (b[0] - b[1]) & 255)) & 255;      \
+
+/* This is the "Armenian" Shuffle.  It takes the input from b and stores it in b2 */
+#define SHUF(b, b2)                                              \
+    b2[0] = b[8]; b2[1] = b[11]; b2[2] = b[12]; b2[3] = b[15];   \
+    b2[4] = b[2]; b2[5] = b[1]; b2[6] = b[6]; b2[7] = b[5];      \
+    b2[8] = b[10]; b2[9] = b[9]; b2[10] = b[14]; b2[11] = b[13]; \
+    b2[12] = b[0]; b2[13] = b[7]; b2[14] = b[4]; b2[15] = b[3];
+
+/* This is the inverse shuffle.  It takes from b and gives to b2 */
+#define iSHUF(b, b2)                                               \
+    b2[0] = b[12]; b2[1] = b[5]; b2[2] = b[4]; b2[3] = b[15];      \
+    b2[4] = b[14]; b2[5] = b[7]; b2[6] = b[6]; b2[7] = b[13];      \
+    b2[8] = b[0]; b2[9] = b[9]; b2[10] = b[8]; b2[11] = b[1];      \
+    b2[12] = b[2]; b2[13] = b[11]; b2[14] = b[10]; b2[15] = b[3];
+
+/* The complete forward Linear Transform layer.  
+ * Note that alternating usage of b and b2.  
+ * Each round of LT starts in 'b' and ends in 'b2'.  
+ */
+#define LT(b, b2)             \
+    PHT(b);  SHUF(b, b2);     \
+    PHT(b2); SHUF(b2, b);     \
+    PHT(b);  SHUF(b, b2);     \
+    PHT(b2); 
+
+/* This is the inverse linear transform layer.  */
+#define iLT(b, b2)            \
+    iPHT(b);                  \
+    iSHUF(b, b2); iPHT(b2);   \
+    iSHUF(b2, b); iPHT(b);    \
+    iSHUF(b, b2); iPHT(b2);
+    
+#ifdef SMALL_CODE    
+
+static void _round(unsigned char *b, int i, symmetric_key *skey) 
+{
+   ROUND(b, i);
+}
+
+static void _iround(unsigned char *b, int i, symmetric_key *skey)
+{
+   iROUND(b, i);
+}
+
+static void _lt(unsigned char *b, unsigned char *b2)
+{
+   LT(b, b2);
+}
+
+static void _ilt(unsigned char *b, unsigned char *b2)
+{
+   iLT(b, b2);
+}   
+
+#undef ROUND
+#define ROUND(b, i) _round(b, i, skey)
+
+#undef iROUND
+#define iROUND(b, i) _iround(b, i, skey)
+
+#undef LT
+#define LT(b, b2) _lt(b, b2)
+
+#undef iLT
+#define iLT(b, b2) _ilt(b, b2)
+
+#endif
+
+/* These are the 33, 128-bit bias words for the key schedule */
+static const unsigned char safer_bias[33][16] = {
+{  70, 151, 177, 186, 163, 183,  16,  10, 197,  55, 179, 201,  90,  40, 172, 100},
+{ 236, 171, 170, 198, 103, 149,  88,  13, 248, 154, 246, 110, 102, 220,   5,  61},
+{ 138, 195, 216, 137, 106, 233,  54,  73,  67, 191, 235, 212, 150, 155, 104, 160},
+{  93,  87, 146,  31, 213, 113,  92, 187,  34, 193, 190, 123, 188, 153,  99, 148},
+{  42,  97, 184,  52,  50,  25, 253, 251,  23,  64, 230,  81,  29,  65,  68, 143},
+{ 221,   4, 128, 222, 231,  49, 214, 127,   1, 162, 247,  57, 218, 111,  35, 202},
+{  58, 208,  28, 209,  48,  62,  18, 161, 205,  15, 224, 168, 175, 130,  89,  44},
+{ 125, 173, 178, 239, 194, 135, 206, 117,   6,  19,   2, 144,  79,  46, 114,  51},
+{ 192, 141, 207, 169, 129, 226, 196,  39,  47, 108, 122, 159,  82, 225,  21,  56},
+{ 252,  32,  66, 199,   8, 228,   9,  85,  94, 140,  20, 118,  96, 255, 223, 215},
+{ 250,  11,  33,   0,  26, 249, 166, 185, 232, 158,  98,  76, 217, 145,  80, 210},
+{  24, 180,   7, 132, 234,  91, 164, 200,  14, 203,  72, 105,  75,  78, 156,  53},
+{  69,  77,  84, 229,  37,  60,  12,  74, 139,  63, 204, 167, 219, 107, 174, 244},
+{  45, 243, 124, 109, 157, 181,  38, 116, 242, 147,  83, 176, 240,  17, 237, 131},
+{ 182,   3,  22, 115,  59,  30, 142, 112, 189, 134,  27,  71, 126,  36,  86, 241},
+{ 136,  70, 151, 177, 186, 163, 183,  16,  10, 197,  55, 179, 201,  90,  40, 172},
+{ 220, 134, 119, 215, 166,  17, 251, 244, 186, 146, 145, 100, 131, 241,  51, 239},
+{  44, 181, 178,  43, 136, 209, 153, 203, 140, 132,  29,  20, 129, 151, 113, 202},
+{ 163, 139,  87,  60, 130, 196,  82,  92,  28, 232, 160,   4, 180, 133,  74, 246},
+{  84, 182, 223,  12,  26, 142, 222, 224,  57, 252,  32, 155,  36,  78, 169, 152},
+{ 171, 242,  96, 208, 108, 234, 250, 199, 217,   0, 212,  31, 110,  67, 188, 236},
+{ 137, 254, 122,  93,  73, 201,  50, 194, 249, 154, 248, 109,  22, 219,  89, 150},
+{ 233, 205, 230,  70,  66, 143,  10, 193, 204, 185, 101, 176, 210, 198, 172,  30},
+{  98,  41,  46,  14, 116,  80,   2,  90, 195,  37, 123, 138,  42,  91, 240,   6},
+{  71, 111, 112, 157, 126,  16, 206,  18,  39, 213,  76,  79, 214, 121,  48, 104},
+{ 117, 125, 228, 237, 128, 106, 144,  55, 162,  94, 118, 170, 197, 127,  61, 175},
+{ 229,  25,  97, 253,  77, 124, 183,  11, 238, 173,  75,  34, 245, 231, 115,  35},
+{ 200,   5, 225, 102, 221, 179,  88, 105,  99,  86,  15, 161,  49, 149,  23,   7},
+{  40,   1,  45, 226, 147, 190,  69,  21, 174, 120,   3, 135, 164, 184,  56, 207},
+{   8, 103,   9, 148, 235,  38, 168, 107, 189,  24,  52,  27, 187, 191, 114, 247},
+{  53,  72, 156,  81,  47,  59,  85, 227, 192, 159, 216, 211, 243, 141, 177, 255},
+{  62, 220, 134, 119, 215, 166,  17, 251, 244, 186, 146, 145, 100, 131, 241,  51}};
+
+int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+   unsigned x, y, z;
+   unsigned char t[33];
+   static const int rounds[3] = { 8, 12, 16 };
+
+   _ARGCHK(key  != NULL);
+   _ARGCHK(skey != NULL);
+
+   /* check arguments */
+   if (keylen != 16 && keylen != 24 && keylen != 32) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+
+   /* Is the number of rounds valid?  Either use zero for default or
+    * 8,12,16 rounds for 16,24,32 byte keys 
+    */
+   if (num_rounds != 0 && num_rounds != rounds[(keylen/8)-2]) {
+      return CRYPT_INVALID_ROUNDS;
+   }
+
+   /* 128 bit key version */
+   if (keylen == 16) {
+       /* copy key into t */
+       for (x = y = 0; x < 16; x++) { 
+           t[x] = key[x]; 
+           y ^= key[x]; 
+       }
+       t[16] = y;
+
+       /* make round keys */
+       for (x = 0; x < 16; x++) {
+           skey->saferp.K[0][x] = t[x];
+       }
+
+       /* make the 16 other keys as a transformation of the first key */
+       for (x = 1; x < 17; x++) {
+           /* rotate 3 bits each */
+           for (y = 0; y < 17; y++) {
+               t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
+           }
+
+           /* select and add */
+           z = x;
+           for (y = 0; y < 16; y++) {
+               skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255;
+               if (++z == 17) { z = 0; }
+           }
+       }
+       skey->saferp.rounds = 8;
+   } else if (keylen == 24) {
+       /* copy key into t */
+       for (x = y = 0; x < 24; x++) { 
+           t[x] = key[x]; 
+           y ^= key[x]; 
+       }
+       t[24] = y;
+
+       /* make round keys */
+       for (x = 0; x < 16; x++) {
+           skey->saferp.K[0][x] = t[x];
+       }
+
+       for (x = 1; x < 25; x++) {
+           /* rotate 3 bits each */
+           for (y = 0; y < 25; y++) {
+               t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
+           }
+
+           /* select and add */
+           z = x;
+           for (y = 0; y < 16; y++) { 
+               skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255;
+               if (++z == 25) { z = 0; }
+           }
+       }
+       skey->saferp.rounds = 12;
+   } else {
+       /* copy key into t */
+       for (x = y = 0; x < 32; x++) { 
+           t[x] = key[x]; 
+           y ^= key[x]; 
+       }
+       t[32] = y;
+
+       /* make round keys */
+       for (x = 0; x < 16; x++) { 
+           skey->saferp.K[0][x] = t[x];
+       }
+
+       for (x = 1; x < 33; x++) {
+           /* rotate 3 bits each */
+           for (y = 0; y < 33; y++) {
+               t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
+           }
+           
+           /* select and add */
+           z = x;
+           for (y = 0; y < 16; y++) {
+               skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255;
+               if (++z == 33) { z = 0; }
+           }
+       }
+       skey->saferp.rounds = 16;
+   }
+#ifdef CLEAN_STACK
+   zeromem(t, sizeof(t));
+#endif
+   return CRYPT_OK;
+}
+
+void saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
+{
+   unsigned char b[16];
+   int x;
+
+   _ARGCHK(pt   != NULL);
+   _ARGCHK(ct   != NULL);
+   _ARGCHK(skey != NULL);
+
+   /* do eight rounds */
+   for (x = 0; x < 16; x++) {
+       b[x] = pt[x];
+   }
+   ROUND(b,  0);  LT(b, ct);
+   ROUND(ct, 2);  LT(ct, b);
+   ROUND(b,  4);  LT(b, ct);
+   ROUND(ct, 6);  LT(ct, b);
+   ROUND(b,  8);  LT(b, ct);
+   ROUND(ct, 10); LT(ct, b);
+   ROUND(b,  12); LT(b, ct);
+   ROUND(ct, 14); LT(ct, b);
+   /* 192-bit key? */
+   if (skey->saferp.rounds > 8) {
+      ROUND(b, 16);  LT(b, ct);
+      ROUND(ct, 18); LT(ct, b);
+      ROUND(b, 20);  LT(b, ct);
+      ROUND(ct, 22); LT(ct, b);
+   }
+   /* 256-bit key? */
+   if (skey->saferp.rounds > 12) {
+      ROUND(b, 24);  LT(b, ct);
+      ROUND(ct, 26); LT(ct, b);
+      ROUND(b, 28);  LT(b, ct);
+      ROUND(ct, 30); LT(ct, b);
+   }
+   ct[0] = b[0] ^ skey->saferp.K[skey->saferp.rounds*2][0];
+   ct[1] = (b[1] + skey->saferp.K[skey->saferp.rounds*2][1]) & 255;
+   ct[2] = (b[2] + skey->saferp.K[skey->saferp.rounds*2][2]) & 255;
+   ct[3] = b[3] ^ skey->saferp.K[skey->saferp.rounds*2][3];
+   ct[4] = b[4] ^ skey->saferp.K[skey->saferp.rounds*2][4];
+   ct[5] = (b[5] + skey->saferp.K[skey->saferp.rounds*2][5]) & 255;
+   ct[6] = (b[6] + skey->saferp.K[skey->saferp.rounds*2][6]) & 255;
+   ct[7] = b[7] ^ skey->saferp.K[skey->saferp.rounds*2][7];
+   ct[8] = b[8] ^ skey->saferp.K[skey->saferp.rounds*2][8];
+   ct[9] = (b[9] + skey->saferp.K[skey->saferp.rounds*2][9]) & 255;
+   ct[10] = (b[10] + skey->saferp.K[skey->saferp.rounds*2][10]) & 255;
+   ct[11] = b[11] ^ skey->saferp.K[skey->saferp.rounds*2][11];
+   ct[12] = b[12] ^ skey->saferp.K[skey->saferp.rounds*2][12];
+   ct[13] = (b[13] + skey->saferp.K[skey->saferp.rounds*2][13]) & 255;
+   ct[14] = (b[14] + skey->saferp.K[skey->saferp.rounds*2][14]) & 255;
+   ct[15] = b[15] ^ skey->saferp.K[skey->saferp.rounds*2][15];
+#ifdef CLEAN_STACK
+   zeromem(b, sizeof(b));
+#endif
+}
+
+void saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
+{
+   unsigned char b[16];
+   int x;
+
+   _ARGCHK(pt   != NULL);
+   _ARGCHK(ct   != NULL);
+   _ARGCHK(skey != NULL);
+
+   /* do eight rounds */
+   b[0] = ct[0] ^ skey->saferp.K[skey->saferp.rounds*2][0];
+   b[1] = (ct[1] - skey->saferp.K[skey->saferp.rounds*2][1]) & 255;
+   b[2] = (ct[2] - skey->saferp.K[skey->saferp.rounds*2][2]) & 255;
+   b[3] = ct[3] ^ skey->saferp.K[skey->saferp.rounds*2][3];
+   b[4] = ct[4] ^ skey->saferp.K[skey->saferp.rounds*2][4];
+   b[5] = (ct[5] - skey->saferp.K[skey->saferp.rounds*2][5]) & 255;
+   b[6] = (ct[6] - skey->saferp.K[skey->saferp.rounds*2][6]) & 255;
+   b[7] = ct[7] ^ skey->saferp.K[skey->saferp.rounds*2][7];
+   b[8] = ct[8] ^ skey->saferp.K[skey->saferp.rounds*2][8];
+   b[9] = (ct[9] - skey->saferp.K[skey->saferp.rounds*2][9]) & 255;
+   b[10] = (ct[10] - skey->saferp.K[skey->saferp.rounds*2][10]) & 255;
+   b[11] = ct[11] ^ skey->saferp.K[skey->saferp.rounds*2][11];
+   b[12] = ct[12] ^ skey->saferp.K[skey->saferp.rounds*2][12];
+   b[13] = (ct[13] - skey->saferp.K[skey->saferp.rounds*2][13]) & 255;
+   b[14] = (ct[14] - skey->saferp.K[skey->saferp.rounds*2][14]) & 255;
+   b[15] = ct[15] ^ skey->saferp.K[skey->saferp.rounds*2][15];
+   /* 256-bit key? */
+   if (skey->saferp.rounds > 12) {
+      iLT(b, pt); iROUND(pt, 30);
+      iLT(pt, b); iROUND(b, 28);
+      iLT(b, pt); iROUND(pt, 26);
+      iLT(pt, b); iROUND(b, 24);
+   }
+   /* 192-bit key? */
+   if (skey->saferp.rounds > 8) {
+      iLT(b, pt); iROUND(pt, 22);
+      iLT(pt, b); iROUND(b, 20);
+      iLT(b, pt); iROUND(pt, 18);
+      iLT(pt, b); iROUND(b, 16);
+   }
+   iLT(b, pt); iROUND(pt, 14);
+   iLT(pt, b); iROUND(b, 12);
+   iLT(b, pt); iROUND(pt,10);
+   iLT(pt, b); iROUND(b, 8);
+   iLT(b, pt); iROUND(pt,6);
+   iLT(pt, b); iROUND(b, 4);
+   iLT(b, pt); iROUND(pt,2);
+   iLT(pt, b); iROUND(b, 0);
+   for (x = 0; x < 16; x++) {
+       pt[x] = b[x];
+   }
+#ifdef CLEAN_STACK
+   zeromem(b, sizeof(b));
+#endif
+}
+
+int saferp_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+   static const struct {
+       int keylen;
+       unsigned char key[32], pt[16], ct[16];
+   } tests[] = {
+       {
+           16,
+           { 41, 35, 190, 132, 225, 108, 214, 174, 
+             82, 144, 73, 241, 241, 187, 233, 235 },
+           { 179, 166, 219, 60, 135, 12, 62, 153, 
+             36, 94, 13, 28, 6, 183, 71, 222 },
+           { 224, 31, 182, 10, 12, 255, 84, 70, 
+             127, 13, 89, 249, 9, 57, 165, 220 }
+       }, {
+           24,
+           { 72, 211, 143, 117, 230, 217, 29, 42, 
+             229, 192, 247, 43, 120, 129, 135, 68, 
+             14, 95, 80, 0, 212, 97, 141, 190 },
+           { 123, 5, 21, 7, 59, 51, 130, 31, 
+             24, 112, 146, 218, 100, 84, 206, 177 },
+           { 92, 136, 4, 63, 57, 95, 100, 0, 
+             150, 130, 130, 16, 193, 111, 219, 133 }
+       }, {
+           32,
+           { 243, 168, 141, 254, 190, 242, 235, 113, 
+             255, 160, 208, 59, 117, 6, 140, 126,
+             135, 120, 115, 77, 208, 190, 130, 190, 
+             219, 194, 70, 65, 43, 140, 250, 48 },
+           { 127, 112, 240, 167, 84, 134, 50, 149, 
+             170, 91, 104, 19, 11, 230, 252, 245 },
+           { 88, 11, 25, 36, 172, 229, 202, 213, 
+             170, 65, 105, 153, 220, 104, 153, 138 }
+       }
+    };       
+
+   unsigned char tmp[2][16];
+   symmetric_key skey;
+   int err, i, y;
+
+   for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+      if ((err = saferp_setup(tests[i].key, tests[i].keylen, 0, &skey)) != CRYPT_OK)  {
+         return err;
+      }
+      saferp_ecb_encrypt(tests[i].pt, tmp[0], &skey);
+      saferp_ecb_decrypt(tmp[0], tmp[1], &skey);
+
+      /* compare */
+      if (memcmp(tmp[0], tests[i].ct, 16) || memcmp(tmp[1], tests[i].pt, 16)) { 
+         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++) saferp_ecb_encrypt(tmp[0], tmp[0], &skey);
+      for (y = 0; y < 1000; y++) saferp_ecb_decrypt(tmp[0], tmp[0], &skey);
+      for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+   }
+
+   return CRYPT_OK;
+ #endif
+}
+
+int saferp_keysize(int *desired_keysize)
+{
+   _ARGCHK(desired_keysize != NULL);
+   
+   if (*desired_keysize < 16)
+      return CRYPT_INVALID_KEYSIZE;
+   if (*desired_keysize < 24) {
+      *desired_keysize = 16;
+   } else if (*desired_keysize < 32) {
+      *desired_keysize = 24;
+   } else {
+      *desired_keysize = 32;
+   }
+   return CRYPT_OK;
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sha1.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,223 @@
+/* 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
+ */
+
+/* SHA1 code by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef SHA1
+
+const struct _hash_descriptor sha1_desc =
+{
+    "sha1",
+    2,
+    20,
+    64,
+    &sha1_init,
+    &sha1_process,
+    &sha1_done,
+    &sha1_test
+};
+
+#define F0(x,y,z)  (z ^ (x & (y ^ z)))
+#define F1(x,y,z)  (x ^ y ^ z)
+#define F2(x,y,z)  ((x & y) | (z & (x | y)))
+#define F3(x,y,z)  (x ^ y ^ z)
+
+#ifdef CLEAN_STACK
+static void _sha1_compress(hash_state *md, unsigned char *buf)
+#else
+static void sha1_compress(hash_state *md, unsigned char *buf)
+#endif
+{
+    ulong32 a,b,c,d,e,W[80],i;
+
+    /* copy the state into 512-bits into W[0..15] */
+    for (i = 0; i < 16; i++) {
+        LOAD32H(W[i], buf + (4*i));
+    }
+
+    /* copy state */
+    a = md->sha1.state[0];
+    b = md->sha1.state[1];
+    c = md->sha1.state[2];
+    d = md->sha1.state[3];
+    e = md->sha1.state[4];
+
+    /* expand it */
+    for (i = 16; i < 80; i++) {
+        W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); 
+    }
+
+    /* compress */
+    /* round one */
+    #define FF0(a,b,c,d,e,i) e = (ROL(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROL(b, 30);
+    #define FF1(a,b,c,d,e,i) e = (ROL(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROL(b, 30);
+    #define FF2(a,b,c,d,e,i) e = (ROL(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROL(b, 30);
+    #define FF3(a,b,c,d,e,i) e = (ROL(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROL(b, 30);
+ 
+    for (i = 0; i < 20; ) {
+       FF0(a,b,c,d,e,i++);
+       FF0(e,a,b,c,d,i++);
+       FF0(d,e,a,b,c,i++);
+       FF0(c,d,e,a,b,i++);
+       FF0(b,c,d,e,a,i++);
+    }
+
+    /* round two */
+    for (; i < 40; )  { 
+       FF1(a,b,c,d,e,i++);
+       FF1(e,a,b,c,d,i++);
+       FF1(d,e,a,b,c,i++);
+       FF1(c,d,e,a,b,i++);
+       FF1(b,c,d,e,a,i++);
+    }
+
+    /* round three */
+    for (; i < 60; )  { 
+       FF2(a,b,c,d,e,i++);
+       FF2(e,a,b,c,d,i++);
+       FF2(d,e,a,b,c,i++);
+       FF2(c,d,e,a,b,i++);
+       FF2(b,c,d,e,a,i++);
+    }
+
+    /* round four */
+    for (; i < 80; )  { 
+       FF3(a,b,c,d,e,i++);
+       FF3(e,a,b,c,d,i++);
+       FF3(d,e,a,b,c,i++);
+       FF3(c,d,e,a,b,i++);
+       FF3(b,c,d,e,a,i++);
+    }
+
+    #undef FF0
+    #undef FF1
+    #undef FF2
+    #undef FF3
+
+    /* store */
+    md->sha1.state[0] = md->sha1.state[0] + a;
+    md->sha1.state[1] = md->sha1.state[1] + b;
+    md->sha1.state[2] = md->sha1.state[2] + c;
+    md->sha1.state[3] = md->sha1.state[3] + d;
+    md->sha1.state[4] = md->sha1.state[4] + e;
+}
+
+#ifdef CLEAN_STACK
+static void sha1_compress(hash_state *md, unsigned char *buf)
+{
+   _sha1_compress(md, buf);
+   burn_stack(sizeof(ulong32) * 87);
+}
+#endif
+
+void sha1_init(hash_state * md)
+{
+   _ARGCHK(md != NULL);
+   md->sha1.state[0] = 0x67452301UL;
+   md->sha1.state[1] = 0xefcdab89UL;
+   md->sha1.state[2] = 0x98badcfeUL;
+   md->sha1.state[3] = 0x10325476UL;
+   md->sha1.state[4] = 0xc3d2e1f0UL;
+   md->sha1.curlen = 0;
+   md->sha1.length = 0;
+}
+
+HASH_PROCESS(sha1_process, sha1_compress, sha1, 64)
+
+int sha1_done(hash_state * md, unsigned char *hash)
+{
+    int i;
+
+    _ARGCHK(md != NULL);
+    _ARGCHK(hash != NULL);
+
+    if (md->sha1.curlen >= sizeof(md->sha1.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+    /* increase the length of the message */
+    md->sha1.length += md->sha1.curlen * 8;
+
+    /* append the '1' bit */
+    md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80;
+
+    /* if the length is currently above 56 bytes we append zeros
+     * then compress.  Then we can fall back to padding zeros and length
+     * encoding like normal.
+     */
+    if (md->sha1.curlen > 56) {
+        while (md->sha1.curlen < 64) {
+            md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
+        }
+        sha1_compress(md, md->sha1.buf);
+        md->sha1.curlen = 0;
+    }
+
+    /* pad upto 56 bytes of zeroes */
+    while (md->sha1.curlen < 56) {
+        md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
+    }
+
+    /* store length */
+    STORE64H(md->sha1.length, md->sha1.buf+56);
+    sha1_compress(md, md->sha1.buf);
+
+    /* copy output */
+    for (i = 0; i < 5; i++) {
+        STORE32H(md->sha1.state[i], hash+(4*i));
+    }
+#ifdef CLEAN_STACK
+    zeromem(md, sizeof(hash_state));
+#endif
+    return CRYPT_OK;
+}
+
+int  sha1_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+  static const struct {
+      char *msg;
+      unsigned char hash[20];
+  } tests[] = {
+    { "abc",
+      { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
+        0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
+        0x9c, 0xd0, 0xd8, 0x9d }
+    },
+    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+      { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
+        0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
+        0xE5, 0x46, 0x70, 0xF1 }
+    }
+  };
+
+  int i;
+  unsigned char tmp[20];
+  hash_state md;
+
+  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0]));  i++) {
+      sha1_init(&md);
+      sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
+      sha1_done(&md, tmp);
+      if (memcmp(tmp, tests[i].hash, 20) != 0) {
+         return CRYPT_FAIL_TESTVECTOR;
+      }
+  }
+  return CRYPT_OK;
+  #endif
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sha224.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,93 @@
+/* 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
+ */
+
+/* SHA-224 new NIST standard based off of SHA-256 truncated to 224 bits */
+const struct _hash_descriptor sha224_desc =
+{
+    "sha224",
+    10,
+    28,
+    64,
+    &sha224_init,
+    &sha256_process,
+    &sha224_done,
+    &sha224_test
+};
+
+/* init the sha256 er... sha224 state ;-) */
+void sha224_init(hash_state * md)
+{
+    _ARGCHK(md != NULL);
+
+    md->sha256.curlen = 0;
+    md->sha256.length = 0;
+    md->sha256.state[0] = 0xc1059ed8UL;
+    md->sha256.state[1] = 0x367cd507UL;
+    md->sha256.state[2] = 0x3070dd17UL;
+    md->sha256.state[3] = 0xf70e5939UL;
+    md->sha256.state[4] = 0xffc00b31UL;
+    md->sha256.state[5] = 0x68581511UL;
+    md->sha256.state[6] = 0x64f98fa7UL;
+    md->sha256.state[7] = 0xbefa4fa4UL;
+}
+
+int sha224_done(hash_state * md, unsigned char *hash)
+{
+    unsigned char buf[32];
+    int err;
+
+    err = sha256_done(md, buf);
+    memcpy(hash, buf, 28);
+#ifdef CLEAN_STACK
+    zeromem(buf, sizeof(buf));
+#endif 
+    return err;
+}
+
+int  sha224_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+  static const struct {
+      char *msg;
+      unsigned char hash[28];
+  } tests[] = {
+    { "abc",
+      { 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8,
+        0x22, 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2,
+        0x55, 0xb3, 0x2a, 0xad, 0xbc, 0xe4, 0xbd,
+        0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, 0xa7 }
+    },
+    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+      { 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76,
+        0xcc, 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89,
+        0x01, 0x50, 0xb0, 0xc6, 0x45, 0x5c, 0xb4,
+        0xf5, 0x8b, 0x19, 0x52, 0x52, 0x25, 0x25 }
+    },
+  };
+
+  int i;
+  unsigned char tmp[28];
+  hash_state md;
+
+  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+      sha224_init(&md);
+      sha224_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
+      sha224_done(&md, tmp);
+      if (memcmp(tmp, tests[i].hash, 28) != 0) {
+         return CRYPT_FAIL_TESTVECTOR;
+      }
+  }
+  return CRYPT_OK;
+ #endif
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sha256.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,305 @@
+/* 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
+ */
+
+
+/* SHA256 by Tom St Denis */
+
+#include "mycrypt.h"
+
+#ifdef SHA256 
+
+const struct _hash_descriptor sha256_desc =
+{
+    "sha256",
+    0,
+    32,
+    64,
+    &sha256_init,
+    &sha256_process,
+    &sha256_done,
+    &sha256_test
+};
+
+/* the K array */
+static const unsigned long K[64] = {
+    0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
+    0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
+    0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
+    0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+    0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
+    0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
+    0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
+    0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+    0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
+    0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
+    0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
+    0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+    0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* Various logical functions */
+#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
+#define Maj(x,y,z)      (((x | y) & z) | (x & y)) 
+#define S(x, n)         ROR((x),(n))
+#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
+#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
+#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
+#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
+#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+
+/* compress 512-bits */
+#ifdef CLEAN_STACK
+static void _sha256_compress(hash_state * md, unsigned char *buf)
+#else
+static void sha256_compress(hash_state * md, unsigned char *buf)
+#endif
+{
+    ulong32 S[8], W[64], t0, t1;
+    int i;
+
+    /* copy state into S */
+    for (i = 0; i < 8; i++) {
+        S[i] = md->sha256.state[i];
+    }
+
+    /* copy the state into 512-bits into W[0..15] */
+    for (i = 0; i < 16; i++) {
+        LOAD32H(W[i], buf + (4*i));
+    }
+
+    /* fill W[16..63] */
+    for (i = 16; i < 64; i++) {
+        W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
+    }        
+
+    /* Compress */
+#ifdef SMALL_CODE   
+#define RND(a,b,c,d,e,f,g,h,i)                    \
+     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
+     t1 = Sigma0(a) + Maj(a, b, c);                  \
+     d += t0;                                        \
+     h  = t0 + t1;
+
+     for (i = 0; i < 64; i += 8) {
+         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
+         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
+         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
+         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
+         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
+         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
+         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
+         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
+     }  
+#else 
+#define RND(a,b,c,d,e,f,g,h,i,ki)                    \
+     t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i];   \
+     t1 = Sigma0(a) + Maj(a, b, c);                  \
+     d += t0;                                        \
+     h  = t0 + t1;
+
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);
+
+#undef RND     
+    
+#endif     
+
+    /* feedback */
+    for (i = 0; i < 8; i++) {
+        md->sha256.state[i] = md->sha256.state[i] + S[i];
+    }
+
+}
+
+#ifdef CLEAN_STACK
+static void sha256_compress(hash_state * md, unsigned char *buf)
+{
+    _sha256_compress(md, buf);
+    burn_stack(sizeof(ulong32) * 74);
+}
+#endif
+
+/* init the sha256 state */
+void sha256_init(hash_state * md)
+{
+    _ARGCHK(md != NULL);
+
+    md->sha256.curlen = 0;
+    md->sha256.length = 0;
+    md->sha256.state[0] = 0x6A09E667UL;
+    md->sha256.state[1] = 0xBB67AE85UL;
+    md->sha256.state[2] = 0x3C6EF372UL;
+    md->sha256.state[3] = 0xA54FF53AUL;
+    md->sha256.state[4] = 0x510E527FUL;
+    md->sha256.state[5] = 0x9B05688CUL;
+    md->sha256.state[6] = 0x1F83D9ABUL;
+    md->sha256.state[7] = 0x5BE0CD19UL;
+}
+
+HASH_PROCESS(sha256_process, sha256_compress, sha256, 64)
+
+int sha256_done(hash_state * md, unsigned char *hash)
+{
+    int i;
+
+    _ARGCHK(md != NULL);
+    _ARGCHK(hash != NULL);
+
+    if (md->sha256.curlen >= sizeof(md->sha256.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+
+    /* increase the length of the message */
+    md->sha256.length += md->sha256.curlen * 8;
+
+    /* append the '1' bit */
+    md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80;
+
+    /* if the length is currently above 56 bytes we append zeros
+     * then compress.  Then we can fall back to padding zeros and length
+     * encoding like normal.
+     */
+    if (md->sha256.curlen > 56) {
+        while (md->sha256.curlen < 64) {
+            md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
+        }
+        sha256_compress(md, md->sha256.buf);
+        md->sha256.curlen = 0;
+    }
+
+    /* pad upto 56 bytes of zeroes */
+    while (md->sha256.curlen < 56) {
+        md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
+    }
+
+    /* store length */
+    STORE64H(md->sha256.length, md->sha256.buf+56);
+    sha256_compress(md, md->sha256.buf);
+
+    /* copy output */
+    for (i = 0; i < 8; i++) {
+        STORE32H(md->sha256.state[i], hash+(4*i));
+    }
+#ifdef CLEAN_STACK
+    zeromem(md, sizeof(hash_state));
+#endif
+    return CRYPT_OK;
+}
+
+int  sha256_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+  static const struct {
+      char *msg;
+      unsigned char hash[32];
+  } tests[] = {
+    { "abc",
+      { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
+        0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
+        0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
+        0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }
+    },
+    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+      { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 
+        0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
+        0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 
+        0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }
+    },
+  };
+
+  int i;
+  unsigned char tmp[32];
+  hash_state md;
+
+  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+      sha256_init(&md);
+      sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
+      sha256_done(&md, tmp);
+      if (memcmp(tmp, tests[i].hash, 32) != 0) {
+         return CRYPT_FAIL_TESTVECTOR;
+      }
+  }
+  return CRYPT_OK;
+ #endif
+}
+
+#ifdef SHA224
+#include "sha224.c"
+#endif
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sha384.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,107 @@
+/* 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
+ */
+
+/* included in sha512.c */
+
+const struct _hash_descriptor sha384_desc =
+{
+    "sha384",
+    4,
+    48,
+    128,
+    &sha384_init,
+    &sha512_process,
+    &sha384_done,
+    &sha384_test
+};
+
+void sha384_init(hash_state * md)
+{
+    _ARGCHK(md != NULL);
+
+    md->sha512.curlen = 0;
+    md->sha512.length = 0;
+    md->sha512.state[0] = CONST64(0xcbbb9d5dc1059ed8);
+    md->sha512.state[1] = CONST64(0x629a292a367cd507);
+    md->sha512.state[2] = CONST64(0x9159015a3070dd17);
+    md->sha512.state[3] = CONST64(0x152fecd8f70e5939);
+    md->sha512.state[4] = CONST64(0x67332667ffc00b31);
+    md->sha512.state[5] = CONST64(0x8eb44a8768581511);
+    md->sha512.state[6] = CONST64(0xdb0c2e0d64f98fa7);
+    md->sha512.state[7] = CONST64(0x47b5481dbefa4fa4);
+}
+
+int sha384_done(hash_state * md, unsigned char *hash)
+{
+   unsigned char buf[64];
+
+   _ARGCHK(md != NULL);
+   _ARGCHK(hash != NULL);
+
+    if (md->sha512.curlen >= sizeof(md->sha512.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+   sha512_done(md, buf);
+   memcpy(hash, buf, 48);
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+   return CRYPT_OK;
+}
+
+int  sha384_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+  static const struct {
+      char *msg;
+      unsigned char hash[48];
+  } tests[] = {
+    { "abc",
+      { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
+        0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
+        0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
+        0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
+        0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
+        0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 }
+    },
+    { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+      { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
+        0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
+        0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
+        0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
+        0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
+        0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 }
+    },
+  };
+
+  int i;
+  unsigned char tmp[48];
+  hash_state md;
+
+  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+      sha384_init(&md);
+      sha384_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
+      sha384_done(&md, tmp);
+      if (memcmp(tmp, tests[i].hash, 48) != 0) {
+         return CRYPT_FAIL_TESTVECTOR;
+      }
+  }
+  return CRYPT_OK;
+ #endif
+}
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sha512.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,282 @@
+/* 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
+ */
+
+/* SHA512 by Tom St Denis */
+
+#include "mycrypt.h"
+
+#ifdef SHA512
+
+const struct _hash_descriptor sha512_desc =
+{
+    "sha512",
+    5,
+    64,
+    128,
+    &sha512_init,
+    &sha512_process,
+    &sha512_done,
+    &sha512_test
+};
+
+/* the K array */
+static const ulong64 K[80] = {
+CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd), 
+CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
+CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019), 
+CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
+CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe), 
+CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
+CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1), 
+CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
+CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3), 
+CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
+CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483), 
+CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
+CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210), 
+CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
+CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725), 
+CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
+CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926), 
+CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
+CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8), 
+CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
+CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
+CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
+CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910), 
+CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
+CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53), 
+CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
+CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb), 
+CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
+CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60), 
+CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
+CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9), 
+CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
+CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207), 
+CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
+CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6), 
+CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
+CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493), 
+CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
+CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a), 
+CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
+};
+
+/* Various logical functions */
+#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
+#define Maj(x,y,z)      (((x | y) & z) | (x & y)) 
+#define S(x, n)         ROR64((x),(n))
+#define R(x, n)         (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)n))
+#define Sigma0(x)       (S(x, 28) ^ S(x, 34) ^ S(x, 39))
+#define Sigma1(x)       (S(x, 14) ^ S(x, 18) ^ S(x, 41))
+#define Gamma0(x)       (S(x, 1) ^ S(x, 8) ^ R(x, 7))
+#define Gamma1(x)       (S(x, 19) ^ S(x, 61) ^ R(x, 6))
+
+/* compress 1024-bits */
+#ifdef CLEAN_STACK
+static void _sha512_compress(hash_state * md, unsigned char *buf)
+#else
+static void sha512_compress(hash_state * md, unsigned char *buf)
+#endif
+{
+    ulong64 S[8], W[80], t0, t1;
+    int i;
+
+    /* copy state into S */
+    for (i = 0; i < 8; i++) {
+        S[i] = md->sha512.state[i];
+    }
+
+    /* copy the state into 1024-bits into W[0..15] */
+    for (i = 0; i < 16; i++) {
+        LOAD64H(W[i], buf + (8*i));
+    }
+
+    /* fill W[16..79] */
+    for (i = 16; i < 80; i++) {
+        W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
+    }        
+
+    /* Compress */
+#ifdef SMALL_CODE
+    for (i = 0; i < 80; i++) {
+        t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i];
+        t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]);
+        S[7] = S[6];
+        S[6] = S[5];
+        S[5] = S[4];
+        S[4] = S[3] + t0;
+        S[3] = S[2];
+        S[2] = S[1];
+        S[1] = S[0];
+        S[0] = t0 + t1;
+    }
+#else
+#define RND(a,b,c,d,e,f,g,h,i)                    \
+     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
+     t1 = Sigma0(a) + Maj(a, b, c);                  \
+     d += t0;                                        \
+     h  = t0 + t1;
+
+     for (i = 0; i < 80; i += 8) {
+         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
+         RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
+         RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
+         RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
+         RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
+         RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
+         RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
+         RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
+     }
+#endif     
+
+
+    /* feedback */
+    for (i = 0; i < 8; i++) {
+        md->sha512.state[i] = md->sha512.state[i] + S[i];
+    }
+}
+
+/* compress 1024-bits */
+#ifdef CLEAN_STACK
+static void sha512_compress(hash_state * md, unsigned char *buf)
+{
+    _sha512_compress(md, buf);
+    burn_stack(sizeof(ulong64) * 90 + sizeof(int));
+}
+#endif
+
+/* init the sha512 state */
+void sha512_init(hash_state * md)
+{
+    _ARGCHK(md != NULL);
+
+    md->sha512.curlen = 0;
+    md->sha512.length = 0;
+    md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);
+    md->sha512.state[1] = CONST64(0xbb67ae8584caa73b);
+    md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b);
+    md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1);
+    md->sha512.state[4] = CONST64(0x510e527fade682d1);
+    md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);
+    md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);
+    md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
+}
+
+HASH_PROCESS(sha512_process, sha512_compress, sha512, 128)
+
+int sha512_done(hash_state * md, unsigned char *hash)
+{
+    int i;
+
+    _ARGCHK(md != NULL);
+    _ARGCHK(hash != NULL);
+
+    if (md->sha512.curlen >= sizeof(md->sha512.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+    /* increase the length of the message */
+    md->sha512.length += md->sha512.curlen * CONST64(8);
+
+    /* append the '1' bit */
+    md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80;
+
+    /* if the length is currently above 112 bytes we append zeros
+     * then compress.  Then we can fall back to padding zeros and length
+     * encoding like normal.
+     */
+    if (md->sha512.curlen > 112) {
+        while (md->sha512.curlen < 128) {
+            md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
+        }
+        sha512_compress(md, md->sha512.buf);
+        md->sha512.curlen = 0;
+    }
+
+    /* pad upto 120 bytes of zeroes 
+     * note: that from 112 to 120 is the 64 MSB of the length.  We assume that you won't hash
+     * > 2^64 bits of data... :-)
+     */
+    while (md->sha512.curlen < 120) {
+        md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
+    }
+
+    /* store length */
+    STORE64H(md->sha512.length, md->sha512.buf+120);
+    sha512_compress(md, md->sha512.buf);
+
+    /* copy output */
+    for (i = 0; i < 8; i++) {
+        STORE64H(md->sha512.state[i], hash+(8*i));
+    }
+#ifdef CLEAN_STACK
+    zeromem(md, sizeof(hash_state));
+#endif
+    return CRYPT_OK;
+}
+
+int  sha512_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+  static const struct {
+      char *msg;
+      unsigned char hash[64];
+  } tests[] = {
+    { "abc",
+     { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
+       0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
+       0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
+       0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
+       0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
+       0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
+       0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
+       0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }
+    },
+    { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+     { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
+       0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
+       0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
+       0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
+       0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
+       0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
+       0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
+       0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }
+    },
+  };
+
+  int i;
+  unsigned char tmp[64];
+  hash_state md;
+
+  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+      sha512_init(&md);
+      sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
+      sha512_done(&md, tmp);
+      if (memcmp(tmp, tests[i].hash, 64) != 0) {
+         return CRYPT_FAIL_TESTVECTOR;
+      }
+  }
+  return CRYPT_OK;
+  #endif
+}
+
+#ifdef SHA384
+   #include "sha384.c"
+#endif
+
+#endif
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/skipjack.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,290 @@
+/* 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
+ */
+
+/* Skipjack Implementation by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef SKIPJACK
+
+const struct _cipher_descriptor skipjack_desc =
+{
+    "skipjack",
+    17,
+    10, 10, 8, 32,
+    &skipjack_setup,
+    &skipjack_ecb_encrypt,
+    &skipjack_ecb_decrypt,
+    &skipjack_test,
+    &skipjack_keysize
+};
+
+static const unsigned char sbox[256] = {
+   0xa3,0xd7,0x09,0x83,0xf8,0x48,0xf6,0xf4,0xb3,0x21,0x15,0x78,0x99,0xb1,0xaf,0xf9,
+   0xe7,0x2d,0x4d,0x8a,0xce,0x4c,0xca,0x2e,0x52,0x95,0xd9,0x1e,0x4e,0x38,0x44,0x28,
+   0x0a,0xdf,0x02,0xa0,0x17,0xf1,0x60,0x68,0x12,0xb7,0x7a,0xc3,0xe9,0xfa,0x3d,0x53,
+   0x96,0x84,0x6b,0xba,0xf2,0x63,0x9a,0x19,0x7c,0xae,0xe5,0xf5,0xf7,0x16,0x6a,0xa2,
+   0x39,0xb6,0x7b,0x0f,0xc1,0x93,0x81,0x1b,0xee,0xb4,0x1a,0xea,0xd0,0x91,0x2f,0xb8,
+   0x55,0xb9,0xda,0x85,0x3f,0x41,0xbf,0xe0,0x5a,0x58,0x80,0x5f,0x66,0x0b,0xd8,0x90,
+   0x35,0xd5,0xc0,0xa7,0x33,0x06,0x65,0x69,0x45,0x00,0x94,0x56,0x6d,0x98,0x9b,0x76,
+   0x97,0xfc,0xb2,0xc2,0xb0,0xfe,0xdb,0x20,0xe1,0xeb,0xd6,0xe4,0xdd,0x47,0x4a,0x1d,
+   0x42,0xed,0x9e,0x6e,0x49,0x3c,0xcd,0x43,0x27,0xd2,0x07,0xd4,0xde,0xc7,0x67,0x18,
+   0x89,0xcb,0x30,0x1f,0x8d,0xc6,0x8f,0xaa,0xc8,0x74,0xdc,0xc9,0x5d,0x5c,0x31,0xa4,
+   0x70,0x88,0x61,0x2c,0x9f,0x0d,0x2b,0x87,0x50,0x82,0x54,0x64,0x26,0x7d,0x03,0x40,
+   0x34,0x4b,0x1c,0x73,0xd1,0xc4,0xfd,0x3b,0xcc,0xfb,0x7f,0xab,0xe6,0x3e,0x5b,0xa5,
+   0xad,0x04,0x23,0x9c,0x14,0x51,0x22,0xf0,0x29,0x79,0x71,0x7e,0xff,0x8c,0x0e,0xe2,
+   0x0c,0xef,0xbc,0x72,0x75,0x6f,0x37,0xa1,0xec,0xd3,0x8e,0x62,0x8b,0x86,0x10,0xe8,
+   0x08,0x77,0x11,0xbe,0x92,0x4f,0x24,0xc5,0x32,0x36,0x9d,0xcf,0xf3,0xa6,0xbb,0xac,
+   0x5e,0x6c,0xa9,0x13,0x57,0x25,0xb5,0xe3,0xbd,0xa8,0x3a,0x01,0x05,0x59,0x2a,0x46
+};
+
+/* simple x + 1 (mod 10) in one step. */
+static const int keystep[] =  { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+
+/* simple x - 1 (mod 10) in one step */
+static const int ikeystep[] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8 };
+
+int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+   int x;
+
+   _ARGCHK(key  != NULL);
+   _ARGCHK(skey != NULL);
+
+   if (keylen != 10) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+
+   if (num_rounds != 32 && num_rounds != 0) { 
+      return CRYPT_INVALID_ROUNDS;
+   }
+
+   /* make sure the key is in range for platforms where CHAR_BIT != 8 */
+   for (x = 0; x < 10; x++) {
+       skey->skipjack.key[x] = key[x] & 255;
+   }
+
+   return CRYPT_OK;
+}
+
+#define RULE_A \
+   tmp = g_func(w1, &kp, key->skipjack.key);      \
+   w1  = tmp ^ w4 ^ x;                            \
+   w4  = w3; w3 = w2;                             \
+   w2  = tmp;
+
+#define RULE_B \
+   tmp  = g_func(w1, &kp, key->skipjack.key);     \
+   tmp1 = w4; w4  = w3;                           \
+   w3   = w1 ^ w2 ^ x;                            \
+   w1   = tmp1; w2 = tmp;
+
+#define RULE_A1 \
+   tmp = w1 ^ w2 ^ x;                             \
+   w1  = ig_func(w2, &kp, key->skipjack.key);     \
+   w2  = w3; w3 = w4; w4 = tmp;
+
+#define RULE_B1 \
+   tmp = ig_func(w2, &kp, key->skipjack.key);     \
+   w2  = tmp ^ w3 ^ x;                            \
+   w3  = w4; w4 = w1; w1 = tmp;
+
+static unsigned g_func(unsigned w, int *kp, unsigned char *key)
+{
+   unsigned char g1,g2;
+
+   g1 = (w >> 8) & 255; g2 = w & 255;
+   g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp];
+   g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp];
+   g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp];
+   g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp];
+   return ((unsigned)g1<<8)|(unsigned)g2;
+}
+
+static unsigned ig_func(unsigned w, int *kp, unsigned char *key)
+{
+   unsigned char g1,g2;
+
+   g1 = (w >> 8) & 255; g2 = w & 255;
+   *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]];
+   *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]];
+   *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]];
+   *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]];
+   return ((unsigned)g1<<8)|(unsigned)g2;
+}
+
+#ifdef CLEAN_STACK
+static void _skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#else
+void skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#endif
+{
+   unsigned w1,w2,w3,w4,tmp,tmp1;
+   int x, kp;
+
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(key != NULL);
+
+   /* load block */
+   w1 = ((unsigned)pt[0]<<8)|pt[1];
+   w2 = ((unsigned)pt[2]<<8)|pt[3];
+   w3 = ((unsigned)pt[4]<<8)|pt[5];
+   w4 = ((unsigned)pt[6]<<8)|pt[7];
+
+   /* 8 rounds of RULE A */
+   for (x = 1, kp = 0; x < 9; x++) {
+       RULE_A;
+   }
+
+   /* 8 rounds of RULE B */
+   for (; x < 17; x++) {
+       RULE_B;
+   }
+
+   /* 8 rounds of RULE A */
+   for (; x < 25; x++) {
+       RULE_A;
+   }
+
+   /* 8 rounds of RULE B */
+   for (; x < 33; x++) {
+       RULE_B;
+   }
+
+   /* store block */
+   ct[0] = (w1>>8)&255; ct[1] = w1&255;
+   ct[2] = (w2>>8)&255; ct[3] = w2&255;
+   ct[4] = (w3>>8)&255; ct[5] = w3&255;
+   ct[6] = (w4>>8)&255; ct[7] = w4&255;
+}
+
+#ifdef CLEAN_STACK
+void skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+{
+   _skipjack_ecb_encrypt(pt, ct, key);
+   burn_stack(sizeof(unsigned) * 8 + sizeof(int) * 2);
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#else
+void skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#endif
+{
+   unsigned w1,w2,w3,w4,tmp;
+   int x, kp;
+
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(key != NULL);
+
+   /* load block */
+   w1 = ((unsigned)ct[0]<<8)|ct[1];
+   w2 = ((unsigned)ct[2]<<8)|ct[3];
+   w3 = ((unsigned)ct[4]<<8)|ct[5];
+   w4 = ((unsigned)ct[6]<<8)|ct[7];
+
+   /* 8 rounds of RULE B^-1 
+
+      Note the value "kp = 8" comes from "kp = (32 * 4) mod 10" where 32*4 is 128 which mod 10 is 8
+    */
+   for (x = 32, kp = 8; x > 24; x--) {
+       RULE_B1;
+   }
+
+   /* 8 rounds of RULE A^-1 */
+   for (; x > 16; x--) {
+       RULE_A1;
+   }
+
+
+   /* 8 rounds of RULE B^-1 */
+   for (; x > 8; x--) {
+       RULE_B1;
+   }
+
+   /* 8 rounds of RULE A^-1 */
+   for (; x > 0; x--) {
+       RULE_A1;
+   }
+
+   /* store block */
+   pt[0] = (w1>>8)&255; pt[1] = w1&255;
+   pt[2] = (w2>>8)&255; pt[3] = w2&255;
+   pt[4] = (w3>>8)&255; pt[5] = w3&255;
+   pt[6] = (w4>>8)&255; pt[7] = w4&255;
+}
+
+#ifdef CLEAN_STACK
+void skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+{
+   _skipjack_ecb_decrypt(ct, pt, key);
+   burn_stack(sizeof(unsigned) * 7 + sizeof(int) * 2);
+}
+#endif
+
+int skipjack_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+   static const struct {
+       unsigned char key[10], pt[8], ct[8];
+   } tests[] = {
+   {
+       { 0x00, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 },
+       { 0x33, 0x22, 0x11, 0x00, 0xdd, 0xcc, 0xbb, 0xaa },
+       { 0x25, 0x87, 0xca, 0xe2, 0x7a, 0x12, 0xd3, 0x00 }
+   }
+   };
+   unsigned char buf[2][8];
+   int x, y, err;
+   symmetric_key key;
+
+   for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
+      /* setup key */
+      if ((err = skipjack_setup(tests[x].key, 10, 0, &key)) != CRYPT_OK) {
+         return err;
+      }
+
+      /* encrypt and decrypt */
+      skipjack_ecb_encrypt(tests[x].pt, buf[0], &key);
+      skipjack_ecb_decrypt(buf[0], buf[1], &key);
+
+      /* compare */
+      if (memcmp(buf[0], tests[x].ct, 8) != 0 || memcmp(buf[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++) buf[0][y] = 0;
+      for (y = 0; y < 1000; y++) skipjack_ecb_encrypt(buf[0], buf[0], &key);
+      for (y = 0; y < 1000; y++) skipjack_ecb_decrypt(buf[0], buf[0], &key);
+      for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+   }
+
+   return CRYPT_OK;
+  #endif
+}
+
+int skipjack_keysize(int *desired_keysize)
+{
+   _ARGCHK(desired_keysize != NULL);
+   if (*desired_keysize < 10) {
+      return CRYPT_INVALID_KEYSIZE;
+   } else if (*desired_keysize > 10) {
+      *desired_keysize = 10;
+   }
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sprng.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,53 @@
+/* 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
+ */
+
+/* A secure PRNG using the RNG functions.  Basically this is a
+ * wrapper that allows you to use a secure RNG as a PRNG
+ * in the various other functions.
+ */
+#include "mycrypt.h"
+
+#ifdef SPRNG
+
+const struct _prng_descriptor sprng_desc =
+{
+    "sprng",
+    &sprng_start,
+    &sprng_add_entropy,
+    &sprng_ready,
+    &sprng_read
+};
+
+int sprng_start(prng_state *prng)
+{
+   return CRYPT_OK;  
+}
+
+int sprng_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
+{
+   return CRYPT_OK;
+}
+
+int sprng_ready(prng_state *prng)
+{
+   return CRYPT_OK;
+}
+
+unsigned long sprng_read(unsigned char *buf, unsigned long len, prng_state *prng)
+{
+   _ARGCHK(buf != NULL);
+   return rng_get_bytes(buf, len, NULL);
+}
+
+#endif
+
+
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/strings.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,86 @@
+/* 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
+ */
+
+/* Future releases will make use of this */
+#include "mycrypt.h"
+
+static const char *err_2_str[] =
+{
+   "CRYPT_OK",
+   "CRYPT_ERROR",
+   "Non-fatal 'no-operation' requested.",
+
+   "Invalid keysize for block cipher.",
+   "Invalid number of rounds for block cipher.",
+   "Algorithm failed test vectors.",
+
+   "Buffer overflow.",
+   "Invalid input packet.",
+
+   "Invalid number of bits for a PRNG.",
+   "Error reading the PRNG.",
+
+   "Invalid cipher specified.",
+   "Invalid hash specified.",
+   "Invalid PRNG specified.",
+
+   "Out of memory.",
+
+   "Invalid PK key or key type specified for function.",
+   "A private PK key is required.",
+
+   "Invalid argument provided.",
+   "File Not Found",
+
+   "Invalid PK type.",
+   "Invalid PK system.",
+   "Duplicate PK key found on keyring.",
+   "Key not found in keyring.",
+   "Invalid sized parameter.",
+
+   "Invalid size for prime.",
+
+};
+
+#ifdef MPI
+static const struct {
+    int mpi_code, ltc_code;
+} mpi_to_ltc_codes[] = {
+   { MP_OKAY ,  CRYPT_OK},
+   { MP_MEM  ,  CRYPT_MEM},
+   { MP_VAL  ,  CRYPT_INVALID_ARG},
+};
+#endif
+
+const char *error_to_string(int err)
+{
+   if (err < 0 || err >= (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) {
+      return "Invalid error code.";
+   } else {
+      return err_2_str[err];
+   }   
+}
+
+#ifdef MPI
+/* convert a MPI error to a LTC error (Possibly the most powerful function ever!  Oh wait... no) */
+int mpi_to_ltc_error(int err)
+{
+   int x;
+
+   for (x = 0; x < (int)(sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0])); x++) {
+       if (err == mpi_to_ltc_codes[x].mpi_code) { 
+          return mpi_to_ltc_codes[x].ltc_code;
+       }
+   }
+   return CRYPT_ERROR;
+}
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tiger.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,772 @@
+/* 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 TIGER
+
+const struct _hash_descriptor tiger_desc =
+{
+    "tiger",
+    1,
+    24,
+    64,
+    &tiger_init,
+    &tiger_process,
+    &tiger_done,
+    &tiger_test
+};
+
+#define t1 (table)
+#define t2 (table+256)
+#define t3 (table+256*2)
+#define t4 (table+256*3)
+
+static const ulong64 table[4*256] = {
+    CONST64(0x02AAB17CF7E90C5E) /*    0 */, CONST64(0xAC424B03E243A8EC) /*    1 */,
+    CONST64(0x72CD5BE30DD5FCD3) /*    2 */, CONST64(0x6D019B93F6F97F3A) /*    3 */,
+    CONST64(0xCD9978FFD21F9193) /*    4 */, CONST64(0x7573A1C9708029E2) /*    5 */,
+    CONST64(0xB164326B922A83C3) /*    6 */, CONST64(0x46883EEE04915870) /*    7 */,
+    CONST64(0xEAACE3057103ECE6) /*    8 */, CONST64(0xC54169B808A3535C) /*    9 */,
+    CONST64(0x4CE754918DDEC47C) /*   10 */, CONST64(0x0AA2F4DFDC0DF40C) /*   11 */,
+    CONST64(0x10B76F18A74DBEFA) /*   12 */, CONST64(0xC6CCB6235AD1AB6A) /*   13 */,
+    CONST64(0x13726121572FE2FF) /*   14 */, CONST64(0x1A488C6F199D921E) /*   15 */,
+    CONST64(0x4BC9F9F4DA0007CA) /*   16 */, CONST64(0x26F5E6F6E85241C7) /*   17 */,
+    CONST64(0x859079DBEA5947B6) /*   18 */, CONST64(0x4F1885C5C99E8C92) /*   19 */,
+    CONST64(0xD78E761EA96F864B) /*   20 */, CONST64(0x8E36428C52B5C17D) /*   21 */,
+    CONST64(0x69CF6827373063C1) /*   22 */, CONST64(0xB607C93D9BB4C56E) /*   23 */,
+    CONST64(0x7D820E760E76B5EA) /*   24 */, CONST64(0x645C9CC6F07FDC42) /*   25 */,
+    CONST64(0xBF38A078243342E0) /*   26 */, CONST64(0x5F6B343C9D2E7D04) /*   27 */,
+    CONST64(0xF2C28AEB600B0EC6) /*   28 */, CONST64(0x6C0ED85F7254BCAC) /*   29 */,
+    CONST64(0x71592281A4DB4FE5) /*   30 */, CONST64(0x1967FA69CE0FED9F) /*   31 */,
+    CONST64(0xFD5293F8B96545DB) /*   32 */, CONST64(0xC879E9D7F2A7600B) /*   33 */,
+    CONST64(0x860248920193194E) /*   34 */, CONST64(0xA4F9533B2D9CC0B3) /*   35 */,
+    CONST64(0x9053836C15957613) /*   36 */, CONST64(0xDB6DCF8AFC357BF1) /*   37 */,
+    CONST64(0x18BEEA7A7A370F57) /*   38 */, CONST64(0x037117CA50B99066) /*   39 */,
+    CONST64(0x6AB30A9774424A35) /*   40 */, CONST64(0xF4E92F02E325249B) /*   41 */,
+    CONST64(0x7739DB07061CCAE1) /*   42 */, CONST64(0xD8F3B49CECA42A05) /*   43 */,
+    CONST64(0xBD56BE3F51382F73) /*   44 */, CONST64(0x45FAED5843B0BB28) /*   45 */,
+    CONST64(0x1C813D5C11BF1F83) /*   46 */, CONST64(0x8AF0E4B6D75FA169) /*   47 */,
+    CONST64(0x33EE18A487AD9999) /*   48 */, CONST64(0x3C26E8EAB1C94410) /*   49 */,
+    CONST64(0xB510102BC0A822F9) /*   50 */, CONST64(0x141EEF310CE6123B) /*   51 */,
+    CONST64(0xFC65B90059DDB154) /*   52 */, CONST64(0xE0158640C5E0E607) /*   53 */,
+    CONST64(0x884E079826C3A3CF) /*   54 */, CONST64(0x930D0D9523C535FD) /*   55 */,
+    CONST64(0x35638D754E9A2B00) /*   56 */, CONST64(0x4085FCCF40469DD5) /*   57 */,
+    CONST64(0xC4B17AD28BE23A4C) /*   58 */, CONST64(0xCAB2F0FC6A3E6A2E) /*   59 */,
+    CONST64(0x2860971A6B943FCD) /*   60 */, CONST64(0x3DDE6EE212E30446) /*   61 */,
+    CONST64(0x6222F32AE01765AE) /*   62 */, CONST64(0x5D550BB5478308FE) /*   63 */,
+    CONST64(0xA9EFA98DA0EDA22A) /*   64 */, CONST64(0xC351A71686C40DA7) /*   65 */,
+    CONST64(0x1105586D9C867C84) /*   66 */, CONST64(0xDCFFEE85FDA22853) /*   67 */,
+    CONST64(0xCCFBD0262C5EEF76) /*   68 */, CONST64(0xBAF294CB8990D201) /*   69 */,
+    CONST64(0xE69464F52AFAD975) /*   70 */, CONST64(0x94B013AFDF133E14) /*   71 */,
+    CONST64(0x06A7D1A32823C958) /*   72 */, CONST64(0x6F95FE5130F61119) /*   73 */,
+    CONST64(0xD92AB34E462C06C0) /*   74 */, CONST64(0xED7BDE33887C71D2) /*   75 */,
+    CONST64(0x79746D6E6518393E) /*   76 */, CONST64(0x5BA419385D713329) /*   77 */,
+    CONST64(0x7C1BA6B948A97564) /*   78 */, CONST64(0x31987C197BFDAC67) /*   79 */,
+    CONST64(0xDE6C23C44B053D02) /*   80 */, CONST64(0x581C49FED002D64D) /*   81 */,
+    CONST64(0xDD474D6338261571) /*   82 */, CONST64(0xAA4546C3E473D062) /*   83 */,
+    CONST64(0x928FCE349455F860) /*   84 */, CONST64(0x48161BBACAAB94D9) /*   85 */,
+    CONST64(0x63912430770E6F68) /*   86 */, CONST64(0x6EC8A5E602C6641C) /*   87 */,
+    CONST64(0x87282515337DDD2B) /*   88 */, CONST64(0x2CDA6B42034B701B) /*   89 */,
+    CONST64(0xB03D37C181CB096D) /*   90 */, CONST64(0xE108438266C71C6F) /*   91 */,
+    CONST64(0x2B3180C7EB51B255) /*   92 */, CONST64(0xDF92B82F96C08BBC) /*   93 */,
+    CONST64(0x5C68C8C0A632F3BA) /*   94 */, CONST64(0x5504CC861C3D0556) /*   95 */,
+    CONST64(0xABBFA4E55FB26B8F) /*   96 */, CONST64(0x41848B0AB3BACEB4) /*   97 */,
+    CONST64(0xB334A273AA445D32) /*   98 */, CONST64(0xBCA696F0A85AD881) /*   99 */,
+    CONST64(0x24F6EC65B528D56C) /*  100 */, CONST64(0x0CE1512E90F4524A) /*  101 */,
+    CONST64(0x4E9DD79D5506D35A) /*  102 */, CONST64(0x258905FAC6CE9779) /*  103 */,
+    CONST64(0x2019295B3E109B33) /*  104 */, CONST64(0xF8A9478B73A054CC) /*  105 */,
+    CONST64(0x2924F2F934417EB0) /*  106 */, CONST64(0x3993357D536D1BC4) /*  107 */,
+    CONST64(0x38A81AC21DB6FF8B) /*  108 */, CONST64(0x47C4FBF17D6016BF) /*  109 */,
+    CONST64(0x1E0FAADD7667E3F5) /*  110 */, CONST64(0x7ABCFF62938BEB96) /*  111 */,
+    CONST64(0xA78DAD948FC179C9) /*  112 */, CONST64(0x8F1F98B72911E50D) /*  113 */,
+    CONST64(0x61E48EAE27121A91) /*  114 */, CONST64(0x4D62F7AD31859808) /*  115 */,
+    CONST64(0xECEBA345EF5CEAEB) /*  116 */, CONST64(0xF5CEB25EBC9684CE) /*  117 */,
+    CONST64(0xF633E20CB7F76221) /*  118 */, CONST64(0xA32CDF06AB8293E4) /*  119 */,
+    CONST64(0x985A202CA5EE2CA4) /*  120 */, CONST64(0xCF0B8447CC8A8FB1) /*  121 */,
+    CONST64(0x9F765244979859A3) /*  122 */, CONST64(0xA8D516B1A1240017) /*  123 */,
+    CONST64(0x0BD7BA3EBB5DC726) /*  124 */, CONST64(0xE54BCA55B86ADB39) /*  125 */,
+    CONST64(0x1D7A3AFD6C478063) /*  126 */, CONST64(0x519EC608E7669EDD) /*  127 */,
+    CONST64(0x0E5715A2D149AA23) /*  128 */, CONST64(0x177D4571848FF194) /*  129 */,
+    CONST64(0xEEB55F3241014C22) /*  130 */, CONST64(0x0F5E5CA13A6E2EC2) /*  131 */,
+    CONST64(0x8029927B75F5C361) /*  132 */, CONST64(0xAD139FABC3D6E436) /*  133 */,
+    CONST64(0x0D5DF1A94CCF402F) /*  134 */, CONST64(0x3E8BD948BEA5DFC8) /*  135 */,
+    CONST64(0xA5A0D357BD3FF77E) /*  136 */, CONST64(0xA2D12E251F74F645) /*  137 */,
+    CONST64(0x66FD9E525E81A082) /*  138 */, CONST64(0x2E0C90CE7F687A49) /*  139 */,
+    CONST64(0xC2E8BCBEBA973BC5) /*  140 */, CONST64(0x000001BCE509745F) /*  141 */,
+    CONST64(0x423777BBE6DAB3D6) /*  142 */, CONST64(0xD1661C7EAEF06EB5) /*  143 */,
+    CONST64(0xA1781F354DAACFD8) /*  144 */, CONST64(0x2D11284A2B16AFFC) /*  145 */,
+    CONST64(0xF1FC4F67FA891D1F) /*  146 */, CONST64(0x73ECC25DCB920ADA) /*  147 */,
+    CONST64(0xAE610C22C2A12651) /*  148 */, CONST64(0x96E0A810D356B78A) /*  149 */,
+    CONST64(0x5A9A381F2FE7870F) /*  150 */, CONST64(0xD5AD62EDE94E5530) /*  151 */,
+    CONST64(0xD225E5E8368D1427) /*  152 */, CONST64(0x65977B70C7AF4631) /*  153 */,
+    CONST64(0x99F889B2DE39D74F) /*  154 */, CONST64(0x233F30BF54E1D143) /*  155 */,
+    CONST64(0x9A9675D3D9A63C97) /*  156 */, CONST64(0x5470554FF334F9A8) /*  157 */,
+    CONST64(0x166ACB744A4F5688) /*  158 */, CONST64(0x70C74CAAB2E4AEAD) /*  159 */,
+    CONST64(0xF0D091646F294D12) /*  160 */, CONST64(0x57B82A89684031D1) /*  161 */,
+    CONST64(0xEFD95A5A61BE0B6B) /*  162 */, CONST64(0x2FBD12E969F2F29A) /*  163 */,
+    CONST64(0x9BD37013FEFF9FE8) /*  164 */, CONST64(0x3F9B0404D6085A06) /*  165 */,
+    CONST64(0x4940C1F3166CFE15) /*  166 */, CONST64(0x09542C4DCDF3DEFB) /*  167 */,
+    CONST64(0xB4C5218385CD5CE3) /*  168 */, CONST64(0xC935B7DC4462A641) /*  169 */,
+    CONST64(0x3417F8A68ED3B63F) /*  170 */, CONST64(0xB80959295B215B40) /*  171 */,
+    CONST64(0xF99CDAEF3B8C8572) /*  172 */, CONST64(0x018C0614F8FCB95D) /*  173 */,
+    CONST64(0x1B14ACCD1A3ACDF3) /*  174 */, CONST64(0x84D471F200BB732D) /*  175 */,
+    CONST64(0xC1A3110E95E8DA16) /*  176 */, CONST64(0x430A7220BF1A82B8) /*  177 */,
+    CONST64(0xB77E090D39DF210E) /*  178 */, CONST64(0x5EF4BD9F3CD05E9D) /*  179 */,
+    CONST64(0x9D4FF6DA7E57A444) /*  180 */, CONST64(0xDA1D60E183D4A5F8) /*  181 */,
+    CONST64(0xB287C38417998E47) /*  182 */, CONST64(0xFE3EDC121BB31886) /*  183 */,
+    CONST64(0xC7FE3CCC980CCBEF) /*  184 */, CONST64(0xE46FB590189BFD03) /*  185 */,
+    CONST64(0x3732FD469A4C57DC) /*  186 */, CONST64(0x7EF700A07CF1AD65) /*  187 */,
+    CONST64(0x59C64468A31D8859) /*  188 */, CONST64(0x762FB0B4D45B61F6) /*  189 */,
+    CONST64(0x155BAED099047718) /*  190 */, CONST64(0x68755E4C3D50BAA6) /*  191 */,
+    CONST64(0xE9214E7F22D8B4DF) /*  192 */, CONST64(0x2ADDBF532EAC95F4) /*  193 */,
+    CONST64(0x32AE3909B4BD0109) /*  194 */, CONST64(0x834DF537B08E3450) /*  195 */,
+    CONST64(0xFA209DA84220728D) /*  196 */, CONST64(0x9E691D9B9EFE23F7) /*  197 */,
+    CONST64(0x0446D288C4AE8D7F) /*  198 */, CONST64(0x7B4CC524E169785B) /*  199 */,
+    CONST64(0x21D87F0135CA1385) /*  200 */, CONST64(0xCEBB400F137B8AA5) /*  201 */,
+    CONST64(0x272E2B66580796BE) /*  202 */, CONST64(0x3612264125C2B0DE) /*  203 */,
+    CONST64(0x057702BDAD1EFBB2) /*  204 */, CONST64(0xD4BABB8EACF84BE9) /*  205 */,
+    CONST64(0x91583139641BC67B) /*  206 */, CONST64(0x8BDC2DE08036E024) /*  207 */,
+    CONST64(0x603C8156F49F68ED) /*  208 */, CONST64(0xF7D236F7DBEF5111) /*  209 */,
+    CONST64(0x9727C4598AD21E80) /*  210 */, CONST64(0xA08A0896670A5FD7) /*  211 */,
+    CONST64(0xCB4A8F4309EBA9CB) /*  212 */, CONST64(0x81AF564B0F7036A1) /*  213 */,
+    CONST64(0xC0B99AA778199ABD) /*  214 */, CONST64(0x959F1EC83FC8E952) /*  215 */,
+    CONST64(0x8C505077794A81B9) /*  216 */, CONST64(0x3ACAAF8F056338F0) /*  217 */,
+    CONST64(0x07B43F50627A6778) /*  218 */, CONST64(0x4A44AB49F5ECCC77) /*  219 */,
+    CONST64(0x3BC3D6E4B679EE98) /*  220 */, CONST64(0x9CC0D4D1CF14108C) /*  221 */,
+    CONST64(0x4406C00B206BC8A0) /*  222 */, CONST64(0x82A18854C8D72D89) /*  223 */,
+    CONST64(0x67E366B35C3C432C) /*  224 */, CONST64(0xB923DD61102B37F2) /*  225 */,
+    CONST64(0x56AB2779D884271D) /*  226 */, CONST64(0xBE83E1B0FF1525AF) /*  227 */,
+    CONST64(0xFB7C65D4217E49A9) /*  228 */, CONST64(0x6BDBE0E76D48E7D4) /*  229 */,
+    CONST64(0x08DF828745D9179E) /*  230 */, CONST64(0x22EA6A9ADD53BD34) /*  231 */,
+    CONST64(0xE36E141C5622200A) /*  232 */, CONST64(0x7F805D1B8CB750EE) /*  233 */,
+    CONST64(0xAFE5C7A59F58E837) /*  234 */, CONST64(0xE27F996A4FB1C23C) /*  235 */,
+    CONST64(0xD3867DFB0775F0D0) /*  236 */, CONST64(0xD0E673DE6E88891A) /*  237 */,
+    CONST64(0x123AEB9EAFB86C25) /*  238 */, CONST64(0x30F1D5D5C145B895) /*  239 */,
+    CONST64(0xBB434A2DEE7269E7) /*  240 */, CONST64(0x78CB67ECF931FA38) /*  241 */,
+    CONST64(0xF33B0372323BBF9C) /*  242 */, CONST64(0x52D66336FB279C74) /*  243 */,
+    CONST64(0x505F33AC0AFB4EAA) /*  244 */, CONST64(0xE8A5CD99A2CCE187) /*  245 */,
+    CONST64(0x534974801E2D30BB) /*  246 */, CONST64(0x8D2D5711D5876D90) /*  247 */,
+    CONST64(0x1F1A412891BC038E) /*  248 */, CONST64(0xD6E2E71D82E56648) /*  249 */,
+    CONST64(0x74036C3A497732B7) /*  250 */, CONST64(0x89B67ED96361F5AB) /*  251 */,
+    CONST64(0xFFED95D8F1EA02A2) /*  252 */, CONST64(0xE72B3BD61464D43D) /*  253 */,
+    CONST64(0xA6300F170BDC4820) /*  254 */, CONST64(0xEBC18760ED78A77A) /*  255 */,
+    CONST64(0xE6A6BE5A05A12138) /*  256 */, CONST64(0xB5A122A5B4F87C98) /*  257 */,
+    CONST64(0x563C6089140B6990) /*  258 */, CONST64(0x4C46CB2E391F5DD5) /*  259 */,
+    CONST64(0xD932ADDBC9B79434) /*  260 */, CONST64(0x08EA70E42015AFF5) /*  261 */,
+    CONST64(0xD765A6673E478CF1) /*  262 */, CONST64(0xC4FB757EAB278D99) /*  263 */,
+    CONST64(0xDF11C6862D6E0692) /*  264 */, CONST64(0xDDEB84F10D7F3B16) /*  265 */,
+    CONST64(0x6F2EF604A665EA04) /*  266 */, CONST64(0x4A8E0F0FF0E0DFB3) /*  267 */,
+    CONST64(0xA5EDEEF83DBCBA51) /*  268 */, CONST64(0xFC4F0A2A0EA4371E) /*  269 */,
+    CONST64(0xE83E1DA85CB38429) /*  270 */, CONST64(0xDC8FF882BA1B1CE2) /*  271 */,
+    CONST64(0xCD45505E8353E80D) /*  272 */, CONST64(0x18D19A00D4DB0717) /*  273 */,
+    CONST64(0x34A0CFEDA5F38101) /*  274 */, CONST64(0x0BE77E518887CAF2) /*  275 */,
+    CONST64(0x1E341438B3C45136) /*  276 */, CONST64(0xE05797F49089CCF9) /*  277 */,
+    CONST64(0xFFD23F9DF2591D14) /*  278 */, CONST64(0x543DDA228595C5CD) /*  279 */,
+    CONST64(0x661F81FD99052A33) /*  280 */, CONST64(0x8736E641DB0F7B76) /*  281 */,
+    CONST64(0x15227725418E5307) /*  282 */, CONST64(0xE25F7F46162EB2FA) /*  283 */,
+    CONST64(0x48A8B2126C13D9FE) /*  284 */, CONST64(0xAFDC541792E76EEA) /*  285 */,
+    CONST64(0x03D912BFC6D1898F) /*  286 */, CONST64(0x31B1AAFA1B83F51B) /*  287 */,
+    CONST64(0xF1AC2796E42AB7D9) /*  288 */, CONST64(0x40A3A7D7FCD2EBAC) /*  289 */,
+    CONST64(0x1056136D0AFBBCC5) /*  290 */, CONST64(0x7889E1DD9A6D0C85) /*  291 */,
+    CONST64(0xD33525782A7974AA) /*  292 */, CONST64(0xA7E25D09078AC09B) /*  293 */,
+    CONST64(0xBD4138B3EAC6EDD0) /*  294 */, CONST64(0x920ABFBE71EB9E70) /*  295 */,
+    CONST64(0xA2A5D0F54FC2625C) /*  296 */, CONST64(0xC054E36B0B1290A3) /*  297 */,
+    CONST64(0xF6DD59FF62FE932B) /*  298 */, CONST64(0x3537354511A8AC7D) /*  299 */,
+    CONST64(0xCA845E9172FADCD4) /*  300 */, CONST64(0x84F82B60329D20DC) /*  301 */,
+    CONST64(0x79C62CE1CD672F18) /*  302 */, CONST64(0x8B09A2ADD124642C) /*  303 */,
+    CONST64(0xD0C1E96A19D9E726) /*  304 */, CONST64(0x5A786A9B4BA9500C) /*  305 */,
+    CONST64(0x0E020336634C43F3) /*  306 */, CONST64(0xC17B474AEB66D822) /*  307 */,
+    CONST64(0x6A731AE3EC9BAAC2) /*  308 */, CONST64(0x8226667AE0840258) /*  309 */,
+    CONST64(0x67D4567691CAECA5) /*  310 */, CONST64(0x1D94155C4875ADB5) /*  311 */,
+    CONST64(0x6D00FD985B813FDF) /*  312 */, CONST64(0x51286EFCB774CD06) /*  313 */,
+    CONST64(0x5E8834471FA744AF) /*  314 */, CONST64(0xF72CA0AEE761AE2E) /*  315 */,
+    CONST64(0xBE40E4CDAEE8E09A) /*  316 */, CONST64(0xE9970BBB5118F665) /*  317 */,
+    CONST64(0x726E4BEB33DF1964) /*  318 */, CONST64(0x703B000729199762) /*  319 */,
+    CONST64(0x4631D816F5EF30A7) /*  320 */, CONST64(0xB880B5B51504A6BE) /*  321 */,
+    CONST64(0x641793C37ED84B6C) /*  322 */, CONST64(0x7B21ED77F6E97D96) /*  323 */,
+    CONST64(0x776306312EF96B73) /*  324 */, CONST64(0xAE528948E86FF3F4) /*  325 */,
+    CONST64(0x53DBD7F286A3F8F8) /*  326 */, CONST64(0x16CADCE74CFC1063) /*  327 */,
+    CONST64(0x005C19BDFA52C6DD) /*  328 */, CONST64(0x68868F5D64D46AD3) /*  329 */,
+    CONST64(0x3A9D512CCF1E186A) /*  330 */, CONST64(0x367E62C2385660AE) /*  331 */,
+    CONST64(0xE359E7EA77DCB1D7) /*  332 */, CONST64(0x526C0773749ABE6E) /*  333 */,
+    CONST64(0x735AE5F9D09F734B) /*  334 */, CONST64(0x493FC7CC8A558BA8) /*  335 */,
+    CONST64(0xB0B9C1533041AB45) /*  336 */, CONST64(0x321958BA470A59BD) /*  337 */,
+    CONST64(0x852DB00B5F46C393) /*  338 */, CONST64(0x91209B2BD336B0E5) /*  339 */,
+    CONST64(0x6E604F7D659EF19F) /*  340 */, CONST64(0xB99A8AE2782CCB24) /*  341 */,
+    CONST64(0xCCF52AB6C814C4C7) /*  342 */, CONST64(0x4727D9AFBE11727B) /*  343 */,
+    CONST64(0x7E950D0C0121B34D) /*  344 */, CONST64(0x756F435670AD471F) /*  345 */,
+    CONST64(0xF5ADD442615A6849) /*  346 */, CONST64(0x4E87E09980B9957A) /*  347 */,
+    CONST64(0x2ACFA1DF50AEE355) /*  348 */, CONST64(0xD898263AFD2FD556) /*  349 */,
+    CONST64(0xC8F4924DD80C8FD6) /*  350 */, CONST64(0xCF99CA3D754A173A) /*  351 */,
+    CONST64(0xFE477BACAF91BF3C) /*  352 */, CONST64(0xED5371F6D690C12D) /*  353 */,
+    CONST64(0x831A5C285E687094) /*  354 */, CONST64(0xC5D3C90A3708A0A4) /*  355 */,
+    CONST64(0x0F7F903717D06580) /*  356 */, CONST64(0x19F9BB13B8FDF27F) /*  357 */,
+    CONST64(0xB1BD6F1B4D502843) /*  358 */, CONST64(0x1C761BA38FFF4012) /*  359 */,
+    CONST64(0x0D1530C4E2E21F3B) /*  360 */, CONST64(0x8943CE69A7372C8A) /*  361 */,
+    CONST64(0xE5184E11FEB5CE66) /*  362 */, CONST64(0x618BDB80BD736621) /*  363 */,
+    CONST64(0x7D29BAD68B574D0B) /*  364 */, CONST64(0x81BB613E25E6FE5B) /*  365 */,
+    CONST64(0x071C9C10BC07913F) /*  366 */, CONST64(0xC7BEEB7909AC2D97) /*  367 */,
+    CONST64(0xC3E58D353BC5D757) /*  368 */, CONST64(0xEB017892F38F61E8) /*  369 */,
+    CONST64(0xD4EFFB9C9B1CC21A) /*  370 */, CONST64(0x99727D26F494F7AB) /*  371 */,
+    CONST64(0xA3E063A2956B3E03) /*  372 */, CONST64(0x9D4A8B9A4AA09C30) /*  373 */,
+    CONST64(0x3F6AB7D500090FB4) /*  374 */, CONST64(0x9CC0F2A057268AC0) /*  375 */,
+    CONST64(0x3DEE9D2DEDBF42D1) /*  376 */, CONST64(0x330F49C87960A972) /*  377 */,
+    CONST64(0xC6B2720287421B41) /*  378 */, CONST64(0x0AC59EC07C00369C) /*  379 */,
+    CONST64(0xEF4EAC49CB353425) /*  380 */, CONST64(0xF450244EEF0129D8) /*  381 */,
+    CONST64(0x8ACC46E5CAF4DEB6) /*  382 */, CONST64(0x2FFEAB63989263F7) /*  383 */,
+    CONST64(0x8F7CB9FE5D7A4578) /*  384 */, CONST64(0x5BD8F7644E634635) /*  385 */,
+    CONST64(0x427A7315BF2DC900) /*  386 */, CONST64(0x17D0C4AA2125261C) /*  387 */,
+    CONST64(0x3992486C93518E50) /*  388 */, CONST64(0xB4CBFEE0A2D7D4C3) /*  389 */,
+    CONST64(0x7C75D6202C5DDD8D) /*  390 */, CONST64(0xDBC295D8E35B6C61) /*  391 */,
+    CONST64(0x60B369D302032B19) /*  392 */, CONST64(0xCE42685FDCE44132) /*  393 */,
+    CONST64(0x06F3DDB9DDF65610) /*  394 */, CONST64(0x8EA4D21DB5E148F0) /*  395 */,
+    CONST64(0x20B0FCE62FCD496F) /*  396 */, CONST64(0x2C1B912358B0EE31) /*  397 */,
+    CONST64(0xB28317B818F5A308) /*  398 */, CONST64(0xA89C1E189CA6D2CF) /*  399 */,
+    CONST64(0x0C6B18576AAADBC8) /*  400 */, CONST64(0xB65DEAA91299FAE3) /*  401 */,
+    CONST64(0xFB2B794B7F1027E7) /*  402 */, CONST64(0x04E4317F443B5BEB) /*  403 */,
+    CONST64(0x4B852D325939D0A6) /*  404 */, CONST64(0xD5AE6BEEFB207FFC) /*  405 */,
+    CONST64(0x309682B281C7D374) /*  406 */, CONST64(0xBAE309A194C3B475) /*  407 */,
+    CONST64(0x8CC3F97B13B49F05) /*  408 */, CONST64(0x98A9422FF8293967) /*  409 */,
+    CONST64(0x244B16B01076FF7C) /*  410 */, CONST64(0xF8BF571C663D67EE) /*  411 */,
+    CONST64(0x1F0D6758EEE30DA1) /*  412 */, CONST64(0xC9B611D97ADEB9B7) /*  413 */,
+    CONST64(0xB7AFD5887B6C57A2) /*  414 */, CONST64(0x6290AE846B984FE1) /*  415 */,
+    CONST64(0x94DF4CDEACC1A5FD) /*  416 */, CONST64(0x058A5BD1C5483AFF) /*  417 */,
+    CONST64(0x63166CC142BA3C37) /*  418 */, CONST64(0x8DB8526EB2F76F40) /*  419 */,
+    CONST64(0xE10880036F0D6D4E) /*  420 */, CONST64(0x9E0523C9971D311D) /*  421 */,
+    CONST64(0x45EC2824CC7CD691) /*  422 */, CONST64(0x575B8359E62382C9) /*  423 */,
+    CONST64(0xFA9E400DC4889995) /*  424 */, CONST64(0xD1823ECB45721568) /*  425 */,
+    CONST64(0xDAFD983B8206082F) /*  426 */, CONST64(0xAA7D29082386A8CB) /*  427 */,
+    CONST64(0x269FCD4403B87588) /*  428 */, CONST64(0x1B91F5F728BDD1E0) /*  429 */,
+    CONST64(0xE4669F39040201F6) /*  430 */, CONST64(0x7A1D7C218CF04ADE) /*  431 */,
+    CONST64(0x65623C29D79CE5CE) /*  432 */, CONST64(0x2368449096C00BB1) /*  433 */,
+    CONST64(0xAB9BF1879DA503BA) /*  434 */, CONST64(0xBC23ECB1A458058E) /*  435 */,
+    CONST64(0x9A58DF01BB401ECC) /*  436 */, CONST64(0xA070E868A85F143D) /*  437 */,
+    CONST64(0x4FF188307DF2239E) /*  438 */, CONST64(0x14D565B41A641183) /*  439 */,
+    CONST64(0xEE13337452701602) /*  440 */, CONST64(0x950E3DCF3F285E09) /*  441 */,
+    CONST64(0x59930254B9C80953) /*  442 */, CONST64(0x3BF299408930DA6D) /*  443 */,
+    CONST64(0xA955943F53691387) /*  444 */, CONST64(0xA15EDECAA9CB8784) /*  445 */,
+    CONST64(0x29142127352BE9A0) /*  446 */, CONST64(0x76F0371FFF4E7AFB) /*  447 */,
+    CONST64(0x0239F450274F2228) /*  448 */, CONST64(0xBB073AF01D5E868B) /*  449 */,
+    CONST64(0xBFC80571C10E96C1) /*  450 */, CONST64(0xD267088568222E23) /*  451 */,
+    CONST64(0x9671A3D48E80B5B0) /*  452 */, CONST64(0x55B5D38AE193BB81) /*  453 */,
+    CONST64(0x693AE2D0A18B04B8) /*  454 */, CONST64(0x5C48B4ECADD5335F) /*  455 */,
+    CONST64(0xFD743B194916A1CA) /*  456 */, CONST64(0x2577018134BE98C4) /*  457 */,
+    CONST64(0xE77987E83C54A4AD) /*  458 */, CONST64(0x28E11014DA33E1B9) /*  459 */,
+    CONST64(0x270CC59E226AA213) /*  460 */, CONST64(0x71495F756D1A5F60) /*  461 */,
+    CONST64(0x9BE853FB60AFEF77) /*  462 */, CONST64(0xADC786A7F7443DBF) /*  463 */,
+    CONST64(0x0904456173B29A82) /*  464 */, CONST64(0x58BC7A66C232BD5E) /*  465 */,
+    CONST64(0xF306558C673AC8B2) /*  466 */, CONST64(0x41F639C6B6C9772A) /*  467 */,
+    CONST64(0x216DEFE99FDA35DA) /*  468 */, CONST64(0x11640CC71C7BE615) /*  469 */,
+    CONST64(0x93C43694565C5527) /*  470 */, CONST64(0xEA038E6246777839) /*  471 */,
+    CONST64(0xF9ABF3CE5A3E2469) /*  472 */, CONST64(0x741E768D0FD312D2) /*  473 */,
+    CONST64(0x0144B883CED652C6) /*  474 */, CONST64(0xC20B5A5BA33F8552) /*  475 */,
+    CONST64(0x1AE69633C3435A9D) /*  476 */, CONST64(0x97A28CA4088CFDEC) /*  477 */,
+    CONST64(0x8824A43C1E96F420) /*  478 */, CONST64(0x37612FA66EEEA746) /*  479 */,
+    CONST64(0x6B4CB165F9CF0E5A) /*  480 */, CONST64(0x43AA1C06A0ABFB4A) /*  481 */,
+    CONST64(0x7F4DC26FF162796B) /*  482 */, CONST64(0x6CBACC8E54ED9B0F) /*  483 */,
+    CONST64(0xA6B7FFEFD2BB253E) /*  484 */, CONST64(0x2E25BC95B0A29D4F) /*  485 */,
+    CONST64(0x86D6A58BDEF1388C) /*  486 */, CONST64(0xDED74AC576B6F054) /*  487 */,
+    CONST64(0x8030BDBC2B45805D) /*  488 */, CONST64(0x3C81AF70E94D9289) /*  489 */,
+    CONST64(0x3EFF6DDA9E3100DB) /*  490 */, CONST64(0xB38DC39FDFCC8847) /*  491 */,
+    CONST64(0x123885528D17B87E) /*  492 */, CONST64(0xF2DA0ED240B1B642) /*  493 */,
+    CONST64(0x44CEFADCD54BF9A9) /*  494 */, CONST64(0x1312200E433C7EE6) /*  495 */,
+    CONST64(0x9FFCC84F3A78C748) /*  496 */, CONST64(0xF0CD1F72248576BB) /*  497 */,
+    CONST64(0xEC6974053638CFE4) /*  498 */, CONST64(0x2BA7B67C0CEC4E4C) /*  499 */,
+    CONST64(0xAC2F4DF3E5CE32ED) /*  500 */, CONST64(0xCB33D14326EA4C11) /*  501 */,
+    CONST64(0xA4E9044CC77E58BC) /*  502 */, CONST64(0x5F513293D934FCEF) /*  503 */,
+    CONST64(0x5DC9645506E55444) /*  504 */, CONST64(0x50DE418F317DE40A) /*  505 */,
+    CONST64(0x388CB31A69DDE259) /*  506 */, CONST64(0x2DB4A83455820A86) /*  507 */,
+    CONST64(0x9010A91E84711AE9) /*  508 */, CONST64(0x4DF7F0B7B1498371) /*  509 */,
+    CONST64(0xD62A2EABC0977179) /*  510 */, CONST64(0x22FAC097AA8D5C0E) /*  511 */,
+    CONST64(0xF49FCC2FF1DAF39B) /*  512 */, CONST64(0x487FD5C66FF29281) /*  513 */,
+    CONST64(0xE8A30667FCDCA83F) /*  514 */, CONST64(0x2C9B4BE3D2FCCE63) /*  515 */,
+    CONST64(0xDA3FF74B93FBBBC2) /*  516 */, CONST64(0x2FA165D2FE70BA66) /*  517 */,
+    CONST64(0xA103E279970E93D4) /*  518 */, CONST64(0xBECDEC77B0E45E71) /*  519 */,
+    CONST64(0xCFB41E723985E497) /*  520 */, CONST64(0xB70AAA025EF75017) /*  521 */,
+    CONST64(0xD42309F03840B8E0) /*  522 */, CONST64(0x8EFC1AD035898579) /*  523 */,
+    CONST64(0x96C6920BE2B2ABC5) /*  524 */, CONST64(0x66AF4163375A9172) /*  525 */,
+    CONST64(0x2174ABDCCA7127FB) /*  526 */, CONST64(0xB33CCEA64A72FF41) /*  527 */,
+    CONST64(0xF04A4933083066A5) /*  528 */, CONST64(0x8D970ACDD7289AF5) /*  529 */,
+    CONST64(0x8F96E8E031C8C25E) /*  530 */, CONST64(0xF3FEC02276875D47) /*  531 */,
+    CONST64(0xEC7BF310056190DD) /*  532 */, CONST64(0xF5ADB0AEBB0F1491) /*  533 */,
+    CONST64(0x9B50F8850FD58892) /*  534 */, CONST64(0x4975488358B74DE8) /*  535 */,
+    CONST64(0xA3354FF691531C61) /*  536 */, CONST64(0x0702BBE481D2C6EE) /*  537 */,
+    CONST64(0x89FB24057DEDED98) /*  538 */, CONST64(0xAC3075138596E902) /*  539 */,
+    CONST64(0x1D2D3580172772ED) /*  540 */, CONST64(0xEB738FC28E6BC30D) /*  541 */,
+    CONST64(0x5854EF8F63044326) /*  542 */, CONST64(0x9E5C52325ADD3BBE) /*  543 */,
+    CONST64(0x90AA53CF325C4623) /*  544 */, CONST64(0xC1D24D51349DD067) /*  545 */,
+    CONST64(0x2051CFEEA69EA624) /*  546 */, CONST64(0x13220F0A862E7E4F) /*  547 */,
+    CONST64(0xCE39399404E04864) /*  548 */, CONST64(0xD9C42CA47086FCB7) /*  549 */,
+    CONST64(0x685AD2238A03E7CC) /*  550 */, CONST64(0x066484B2AB2FF1DB) /*  551 */,
+    CONST64(0xFE9D5D70EFBF79EC) /*  552 */, CONST64(0x5B13B9DD9C481854) /*  553 */,
+    CONST64(0x15F0D475ED1509AD) /*  554 */, CONST64(0x0BEBCD060EC79851) /*  555 */,
+    CONST64(0xD58C6791183AB7F8) /*  556 */, CONST64(0xD1187C5052F3EEE4) /*  557 */,
+    CONST64(0xC95D1192E54E82FF) /*  558 */, CONST64(0x86EEA14CB9AC6CA2) /*  559 */,
+    CONST64(0x3485BEB153677D5D) /*  560 */, CONST64(0xDD191D781F8C492A) /*  561 */,
+    CONST64(0xF60866BAA784EBF9) /*  562 */, CONST64(0x518F643BA2D08C74) /*  563 */,
+    CONST64(0x8852E956E1087C22) /*  564 */, CONST64(0xA768CB8DC410AE8D) /*  565 */,
+    CONST64(0x38047726BFEC8E1A) /*  566 */, CONST64(0xA67738B4CD3B45AA) /*  567 */,
+    CONST64(0xAD16691CEC0DDE19) /*  568 */, CONST64(0xC6D4319380462E07) /*  569 */,
+    CONST64(0xC5A5876D0BA61938) /*  570 */, CONST64(0x16B9FA1FA58FD840) /*  571 */,
+    CONST64(0x188AB1173CA74F18) /*  572 */, CONST64(0xABDA2F98C99C021F) /*  573 */,
+    CONST64(0x3E0580AB134AE816) /*  574 */, CONST64(0x5F3B05B773645ABB) /*  575 */,
+    CONST64(0x2501A2BE5575F2F6) /*  576 */, CONST64(0x1B2F74004E7E8BA9) /*  577 */,
+    CONST64(0x1CD7580371E8D953) /*  578 */, CONST64(0x7F6ED89562764E30) /*  579 */,
+    CONST64(0xB15926FF596F003D) /*  580 */, CONST64(0x9F65293DA8C5D6B9) /*  581 */,
+    CONST64(0x6ECEF04DD690F84C) /*  582 */, CONST64(0x4782275FFF33AF88) /*  583 */,
+    CONST64(0xE41433083F820801) /*  584 */, CONST64(0xFD0DFE409A1AF9B5) /*  585 */,
+    CONST64(0x4325A3342CDB396B) /*  586 */, CONST64(0x8AE77E62B301B252) /*  587 */,
+    CONST64(0xC36F9E9F6655615A) /*  588 */, CONST64(0x85455A2D92D32C09) /*  589 */,
+    CONST64(0xF2C7DEA949477485) /*  590 */, CONST64(0x63CFB4C133A39EBA) /*  591 */,
+    CONST64(0x83B040CC6EBC5462) /*  592 */, CONST64(0x3B9454C8FDB326B0) /*  593 */,
+    CONST64(0x56F56A9E87FFD78C) /*  594 */, CONST64(0x2DC2940D99F42BC6) /*  595 */,
+    CONST64(0x98F7DF096B096E2D) /*  596 */, CONST64(0x19A6E01E3AD852BF) /*  597 */,
+    CONST64(0x42A99CCBDBD4B40B) /*  598 */, CONST64(0xA59998AF45E9C559) /*  599 */,
+    CONST64(0x366295E807D93186) /*  600 */, CONST64(0x6B48181BFAA1F773) /*  601 */,
+    CONST64(0x1FEC57E2157A0A1D) /*  602 */, CONST64(0x4667446AF6201AD5) /*  603 */,
+    CONST64(0xE615EBCACFB0F075) /*  604 */, CONST64(0xB8F31F4F68290778) /*  605 */,
+    CONST64(0x22713ED6CE22D11E) /*  606 */, CONST64(0x3057C1A72EC3C93B) /*  607 */,
+    CONST64(0xCB46ACC37C3F1F2F) /*  608 */, CONST64(0xDBB893FD02AAF50E) /*  609 */,
+    CONST64(0x331FD92E600B9FCF) /*  610 */, CONST64(0xA498F96148EA3AD6) /*  611 */,
+    CONST64(0xA8D8426E8B6A83EA) /*  612 */, CONST64(0xA089B274B7735CDC) /*  613 */,
+    CONST64(0x87F6B3731E524A11) /*  614 */, CONST64(0x118808E5CBC96749) /*  615 */,
+    CONST64(0x9906E4C7B19BD394) /*  616 */, CONST64(0xAFED7F7E9B24A20C) /*  617 */,
+    CONST64(0x6509EADEEB3644A7) /*  618 */, CONST64(0x6C1EF1D3E8EF0EDE) /*  619 */,
+    CONST64(0xB9C97D43E9798FB4) /*  620 */, CONST64(0xA2F2D784740C28A3) /*  621 */,
+    CONST64(0x7B8496476197566F) /*  622 */, CONST64(0x7A5BE3E6B65F069D) /*  623 */,
+    CONST64(0xF96330ED78BE6F10) /*  624 */, CONST64(0xEEE60DE77A076A15) /*  625 */,
+    CONST64(0x2B4BEE4AA08B9BD0) /*  626 */, CONST64(0x6A56A63EC7B8894E) /*  627 */,
+    CONST64(0x02121359BA34FEF4) /*  628 */, CONST64(0x4CBF99F8283703FC) /*  629 */,
+    CONST64(0x398071350CAF30C8) /*  630 */, CONST64(0xD0A77A89F017687A) /*  631 */,
+    CONST64(0xF1C1A9EB9E423569) /*  632 */, CONST64(0x8C7976282DEE8199) /*  633 */,
+    CONST64(0x5D1737A5DD1F7ABD) /*  634 */, CONST64(0x4F53433C09A9FA80) /*  635 */,
+    CONST64(0xFA8B0C53DF7CA1D9) /*  636 */, CONST64(0x3FD9DCBC886CCB77) /*  637 */,
+    CONST64(0xC040917CA91B4720) /*  638 */, CONST64(0x7DD00142F9D1DCDF) /*  639 */,
+    CONST64(0x8476FC1D4F387B58) /*  640 */, CONST64(0x23F8E7C5F3316503) /*  641 */,
+    CONST64(0x032A2244E7E37339) /*  642 */, CONST64(0x5C87A5D750F5A74B) /*  643 */,
+    CONST64(0x082B4CC43698992E) /*  644 */, CONST64(0xDF917BECB858F63C) /*  645 */,
+    CONST64(0x3270B8FC5BF86DDA) /*  646 */, CONST64(0x10AE72BB29B5DD76) /*  647 */,
+    CONST64(0x576AC94E7700362B) /*  648 */, CONST64(0x1AD112DAC61EFB8F) /*  649 */,
+    CONST64(0x691BC30EC5FAA427) /*  650 */, CONST64(0xFF246311CC327143) /*  651 */,
+    CONST64(0x3142368E30E53206) /*  652 */, CONST64(0x71380E31E02CA396) /*  653 */,
+    CONST64(0x958D5C960AAD76F1) /*  654 */, CONST64(0xF8D6F430C16DA536) /*  655 */,
+    CONST64(0xC8FFD13F1BE7E1D2) /*  656 */, CONST64(0x7578AE66004DDBE1) /*  657 */,
+    CONST64(0x05833F01067BE646) /*  658 */, CONST64(0xBB34B5AD3BFE586D) /*  659 */,
+    CONST64(0x095F34C9A12B97F0) /*  660 */, CONST64(0x247AB64525D60CA8) /*  661 */,
+    CONST64(0xDCDBC6F3017477D1) /*  662 */, CONST64(0x4A2E14D4DECAD24D) /*  663 */,
+    CONST64(0xBDB5E6D9BE0A1EEB) /*  664 */, CONST64(0x2A7E70F7794301AB) /*  665 */,
+    CONST64(0xDEF42D8A270540FD) /*  666 */, CONST64(0x01078EC0A34C22C1) /*  667 */,
+    CONST64(0xE5DE511AF4C16387) /*  668 */, CONST64(0x7EBB3A52BD9A330A) /*  669 */,
+    CONST64(0x77697857AA7D6435) /*  670 */, CONST64(0x004E831603AE4C32) /*  671 */,
+    CONST64(0xE7A21020AD78E312) /*  672 */, CONST64(0x9D41A70C6AB420F2) /*  673 */,
+    CONST64(0x28E06C18EA1141E6) /*  674 */, CONST64(0xD2B28CBD984F6B28) /*  675 */,
+    CONST64(0x26B75F6C446E9D83) /*  676 */, CONST64(0xBA47568C4D418D7F) /*  677 */,
+    CONST64(0xD80BADBFE6183D8E) /*  678 */, CONST64(0x0E206D7F5F166044) /*  679 */,
+    CONST64(0xE258A43911CBCA3E) /*  680 */, CONST64(0x723A1746B21DC0BC) /*  681 */,
+    CONST64(0xC7CAA854F5D7CDD3) /*  682 */, CONST64(0x7CAC32883D261D9C) /*  683 */,
+    CONST64(0x7690C26423BA942C) /*  684 */, CONST64(0x17E55524478042B8) /*  685 */,
+    CONST64(0xE0BE477656A2389F) /*  686 */, CONST64(0x4D289B5E67AB2DA0) /*  687 */,
+    CONST64(0x44862B9C8FBBFD31) /*  688 */, CONST64(0xB47CC8049D141365) /*  689 */,
+    CONST64(0x822C1B362B91C793) /*  690 */, CONST64(0x4EB14655FB13DFD8) /*  691 */,
+    CONST64(0x1ECBBA0714E2A97B) /*  692 */, CONST64(0x6143459D5CDE5F14) /*  693 */,
+    CONST64(0x53A8FBF1D5F0AC89) /*  694 */, CONST64(0x97EA04D81C5E5B00) /*  695 */,
+    CONST64(0x622181A8D4FDB3F3) /*  696 */, CONST64(0xE9BCD341572A1208) /*  697 */,
+    CONST64(0x1411258643CCE58A) /*  698 */, CONST64(0x9144C5FEA4C6E0A4) /*  699 */,
+    CONST64(0x0D33D06565CF620F) /*  700 */, CONST64(0x54A48D489F219CA1) /*  701 */,
+    CONST64(0xC43E5EAC6D63C821) /*  702 */, CONST64(0xA9728B3A72770DAF) /*  703 */,
+    CONST64(0xD7934E7B20DF87EF) /*  704 */, CONST64(0xE35503B61A3E86E5) /*  705 */,
+    CONST64(0xCAE321FBC819D504) /*  706 */, CONST64(0x129A50B3AC60BFA6) /*  707 */,
+    CONST64(0xCD5E68EA7E9FB6C3) /*  708 */, CONST64(0xB01C90199483B1C7) /*  709 */,
+    CONST64(0x3DE93CD5C295376C) /*  710 */, CONST64(0xAED52EDF2AB9AD13) /*  711 */,
+    CONST64(0x2E60F512C0A07884) /*  712 */, CONST64(0xBC3D86A3E36210C9) /*  713 */,
+    CONST64(0x35269D9B163951CE) /*  714 */, CONST64(0x0C7D6E2AD0CDB5FA) /*  715 */,
+    CONST64(0x59E86297D87F5733) /*  716 */, CONST64(0x298EF221898DB0E7) /*  717 */,
+    CONST64(0x55000029D1A5AA7E) /*  718 */, CONST64(0x8BC08AE1B5061B45) /*  719 */,
+    CONST64(0xC2C31C2B6C92703A) /*  720 */, CONST64(0x94CC596BAF25EF42) /*  721 */,
+    CONST64(0x0A1D73DB22540456) /*  722 */, CONST64(0x04B6A0F9D9C4179A) /*  723 */,
+    CONST64(0xEFFDAFA2AE3D3C60) /*  724 */, CONST64(0xF7C8075BB49496C4) /*  725 */,
+    CONST64(0x9CC5C7141D1CD4E3) /*  726 */, CONST64(0x78BD1638218E5534) /*  727 */,
+    CONST64(0xB2F11568F850246A) /*  728 */, CONST64(0xEDFABCFA9502BC29) /*  729 */,
+    CONST64(0x796CE5F2DA23051B) /*  730 */, CONST64(0xAAE128B0DC93537C) /*  731 */,
+    CONST64(0x3A493DA0EE4B29AE) /*  732 */, CONST64(0xB5DF6B2C416895D7) /*  733 */,
+    CONST64(0xFCABBD25122D7F37) /*  734 */, CONST64(0x70810B58105DC4B1) /*  735 */,
+    CONST64(0xE10FDD37F7882A90) /*  736 */, CONST64(0x524DCAB5518A3F5C) /*  737 */,
+    CONST64(0x3C9E85878451255B) /*  738 */, CONST64(0x4029828119BD34E2) /*  739 */,
+    CONST64(0x74A05B6F5D3CECCB) /*  740 */, CONST64(0xB610021542E13ECA) /*  741 */,
+    CONST64(0x0FF979D12F59E2AC) /*  742 */, CONST64(0x6037DA27E4F9CC50) /*  743 */,
+    CONST64(0x5E92975A0DF1847D) /*  744 */, CONST64(0xD66DE190D3E623FE) /*  745 */,
+    CONST64(0x5032D6B87B568048) /*  746 */, CONST64(0x9A36B7CE8235216E) /*  747 */,
+    CONST64(0x80272A7A24F64B4A) /*  748 */, CONST64(0x93EFED8B8C6916F7) /*  749 */,
+    CONST64(0x37DDBFF44CCE1555) /*  750 */, CONST64(0x4B95DB5D4B99BD25) /*  751 */,
+    CONST64(0x92D3FDA169812FC0) /*  752 */, CONST64(0xFB1A4A9A90660BB6) /*  753 */,
+    CONST64(0x730C196946A4B9B2) /*  754 */, CONST64(0x81E289AA7F49DA68) /*  755 */,
+    CONST64(0x64669A0F83B1A05F) /*  756 */, CONST64(0x27B3FF7D9644F48B) /*  757 */,
+    CONST64(0xCC6B615C8DB675B3) /*  758 */, CONST64(0x674F20B9BCEBBE95) /*  759 */,
+    CONST64(0x6F31238275655982) /*  760 */, CONST64(0x5AE488713E45CF05) /*  761 */,
+    CONST64(0xBF619F9954C21157) /*  762 */, CONST64(0xEABAC46040A8EAE9) /*  763 */,
+    CONST64(0x454C6FE9F2C0C1CD) /*  764 */, CONST64(0x419CF6496412691C) /*  765 */,
+    CONST64(0xD3DC3BEF265B0F70) /*  766 */, CONST64(0x6D0E60F5C3578A9E) /*  767 */,
+    CONST64(0x5B0E608526323C55) /*  768 */, CONST64(0x1A46C1A9FA1B59F5) /*  769 */,
+    CONST64(0xA9E245A17C4C8FFA) /*  770 */, CONST64(0x65CA5159DB2955D7) /*  771 */,
+    CONST64(0x05DB0A76CE35AFC2) /*  772 */, CONST64(0x81EAC77EA9113D45) /*  773 */,
+    CONST64(0x528EF88AB6AC0A0D) /*  774 */, CONST64(0xA09EA253597BE3FF) /*  775 */,
+    CONST64(0x430DDFB3AC48CD56) /*  776 */, CONST64(0xC4B3A67AF45CE46F) /*  777 */,
+    CONST64(0x4ECECFD8FBE2D05E) /*  778 */, CONST64(0x3EF56F10B39935F0) /*  779 */,
+    CONST64(0x0B22D6829CD619C6) /*  780 */, CONST64(0x17FD460A74DF2069) /*  781 */,
+    CONST64(0x6CF8CC8E8510ED40) /*  782 */, CONST64(0xD6C824BF3A6ECAA7) /*  783 */,
+    CONST64(0x61243D581A817049) /*  784 */, CONST64(0x048BACB6BBC163A2) /*  785 */,
+    CONST64(0xD9A38AC27D44CC32) /*  786 */, CONST64(0x7FDDFF5BAAF410AB) /*  787 */,
+    CONST64(0xAD6D495AA804824B) /*  788 */, CONST64(0xE1A6A74F2D8C9F94) /*  789 */,
+    CONST64(0xD4F7851235DEE8E3) /*  790 */, CONST64(0xFD4B7F886540D893) /*  791 */,
+    CONST64(0x247C20042AA4BFDA) /*  792 */, CONST64(0x096EA1C517D1327C) /*  793 */,
+    CONST64(0xD56966B4361A6685) /*  794 */, CONST64(0x277DA5C31221057D) /*  795 */,
+    CONST64(0x94D59893A43ACFF7) /*  796 */, CONST64(0x64F0C51CCDC02281) /*  797 */,
+    CONST64(0x3D33BCC4FF6189DB) /*  798 */, CONST64(0xE005CB184CE66AF1) /*  799 */,
+    CONST64(0xFF5CCD1D1DB99BEA) /*  800 */, CONST64(0xB0B854A7FE42980F) /*  801 */,
+    CONST64(0x7BD46A6A718D4B9F) /*  802 */, CONST64(0xD10FA8CC22A5FD8C) /*  803 */,
+    CONST64(0xD31484952BE4BD31) /*  804 */, CONST64(0xC7FA975FCB243847) /*  805 */,
+    CONST64(0x4886ED1E5846C407) /*  806 */, CONST64(0x28CDDB791EB70B04) /*  807 */,
+    CONST64(0xC2B00BE2F573417F) /*  808 */, CONST64(0x5C9590452180F877) /*  809 */,
+    CONST64(0x7A6BDDFFF370EB00) /*  810 */, CONST64(0xCE509E38D6D9D6A4) /*  811 */,
+    CONST64(0xEBEB0F00647FA702) /*  812 */, CONST64(0x1DCC06CF76606F06) /*  813 */,
+    CONST64(0xE4D9F28BA286FF0A) /*  814 */, CONST64(0xD85A305DC918C262) /*  815 */,
+    CONST64(0x475B1D8732225F54) /*  816 */, CONST64(0x2D4FB51668CCB5FE) /*  817 */,
+    CONST64(0xA679B9D9D72BBA20) /*  818 */, CONST64(0x53841C0D912D43A5) /*  819 */,
+    CONST64(0x3B7EAA48BF12A4E8) /*  820 */, CONST64(0x781E0E47F22F1DDF) /*  821 */,
+    CONST64(0xEFF20CE60AB50973) /*  822 */, CONST64(0x20D261D19DFFB742) /*  823 */,
+    CONST64(0x16A12B03062A2E39) /*  824 */, CONST64(0x1960EB2239650495) /*  825 */,
+    CONST64(0x251C16FED50EB8B8) /*  826 */, CONST64(0x9AC0C330F826016E) /*  827 */,
+    CONST64(0xED152665953E7671) /*  828 */, CONST64(0x02D63194A6369570) /*  829 */,
+    CONST64(0x5074F08394B1C987) /*  830 */, CONST64(0x70BA598C90B25CE1) /*  831 */,
+    CONST64(0x794A15810B9742F6) /*  832 */, CONST64(0x0D5925E9FCAF8C6C) /*  833 */,
+    CONST64(0x3067716CD868744E) /*  834 */, CONST64(0x910AB077E8D7731B) /*  835 */,
+    CONST64(0x6A61BBDB5AC42F61) /*  836 */, CONST64(0x93513EFBF0851567) /*  837 */,
+    CONST64(0xF494724B9E83E9D5) /*  838 */, CONST64(0xE887E1985C09648D) /*  839 */,
+    CONST64(0x34B1D3C675370CFD) /*  840 */, CONST64(0xDC35E433BC0D255D) /*  841 */,
+    CONST64(0xD0AAB84234131BE0) /*  842 */, CONST64(0x08042A50B48B7EAF) /*  843 */,
+    CONST64(0x9997C4EE44A3AB35) /*  844 */, CONST64(0x829A7B49201799D0) /*  845 */,
+    CONST64(0x263B8307B7C54441) /*  846 */, CONST64(0x752F95F4FD6A6CA6) /*  847 */,
+    CONST64(0x927217402C08C6E5) /*  848 */, CONST64(0x2A8AB754A795D9EE) /*  849 */,
+    CONST64(0xA442F7552F72943D) /*  850 */, CONST64(0x2C31334E19781208) /*  851 */,
+    CONST64(0x4FA98D7CEAEE6291) /*  852 */, CONST64(0x55C3862F665DB309) /*  853 */,
+    CONST64(0xBD0610175D53B1F3) /*  854 */, CONST64(0x46FE6CB840413F27) /*  855 */,
+    CONST64(0x3FE03792DF0CFA59) /*  856 */, CONST64(0xCFE700372EB85E8F) /*  857 */,
+    CONST64(0xA7BE29E7ADBCE118) /*  858 */, CONST64(0xE544EE5CDE8431DD) /*  859 */,
+    CONST64(0x8A781B1B41F1873E) /*  860 */, CONST64(0xA5C94C78A0D2F0E7) /*  861 */,
+    CONST64(0x39412E2877B60728) /*  862 */, CONST64(0xA1265EF3AFC9A62C) /*  863 */,
+    CONST64(0xBCC2770C6A2506C5) /*  864 */, CONST64(0x3AB66DD5DCE1CE12) /*  865 */,
+    CONST64(0xE65499D04A675B37) /*  866 */, CONST64(0x7D8F523481BFD216) /*  867 */,
+    CONST64(0x0F6F64FCEC15F389) /*  868 */, CONST64(0x74EFBE618B5B13C8) /*  869 */,
+    CONST64(0xACDC82B714273E1D) /*  870 */, CONST64(0xDD40BFE003199D17) /*  871 */,
+    CONST64(0x37E99257E7E061F8) /*  872 */, CONST64(0xFA52626904775AAA) /*  873 */,
+    CONST64(0x8BBBF63A463D56F9) /*  874 */, CONST64(0xF0013F1543A26E64) /*  875 */,
+    CONST64(0xA8307E9F879EC898) /*  876 */, CONST64(0xCC4C27A4150177CC) /*  877 */,
+    CONST64(0x1B432F2CCA1D3348) /*  878 */, CONST64(0xDE1D1F8F9F6FA013) /*  879 */,
+    CONST64(0x606602A047A7DDD6) /*  880 */, CONST64(0xD237AB64CC1CB2C7) /*  881 */,
+    CONST64(0x9B938E7225FCD1D3) /*  882 */, CONST64(0xEC4E03708E0FF476) /*  883 */,
+    CONST64(0xFEB2FBDA3D03C12D) /*  884 */, CONST64(0xAE0BCED2EE43889A) /*  885 */,
+    CONST64(0x22CB8923EBFB4F43) /*  886 */, CONST64(0x69360D013CF7396D) /*  887 */,
+    CONST64(0x855E3602D2D4E022) /*  888 */, CONST64(0x073805BAD01F784C) /*  889 */,
+    CONST64(0x33E17A133852F546) /*  890 */, CONST64(0xDF4874058AC7B638) /*  891 */,
+    CONST64(0xBA92B29C678AA14A) /*  892 */, CONST64(0x0CE89FC76CFAADCD) /*  893 */,
+    CONST64(0x5F9D4E0908339E34) /*  894 */, CONST64(0xF1AFE9291F5923B9) /*  895 */,
+    CONST64(0x6E3480F60F4A265F) /*  896 */, CONST64(0xEEBF3A2AB29B841C) /*  897 */,
+    CONST64(0xE21938A88F91B4AD) /*  898 */, CONST64(0x57DFEFF845C6D3C3) /*  899 */,
+    CONST64(0x2F006B0BF62CAAF2) /*  900 */, CONST64(0x62F479EF6F75EE78) /*  901 */,
+    CONST64(0x11A55AD41C8916A9) /*  902 */, CONST64(0xF229D29084FED453) /*  903 */,
+    CONST64(0x42F1C27B16B000E6) /*  904 */, CONST64(0x2B1F76749823C074) /*  905 */,
+    CONST64(0x4B76ECA3C2745360) /*  906 */, CONST64(0x8C98F463B91691BD) /*  907 */,
+    CONST64(0x14BCC93CF1ADE66A) /*  908 */, CONST64(0x8885213E6D458397) /*  909 */,
+    CONST64(0x8E177DF0274D4711) /*  910 */, CONST64(0xB49B73B5503F2951) /*  911 */,
+    CONST64(0x10168168C3F96B6B) /*  912 */, CONST64(0x0E3D963B63CAB0AE) /*  913 */,
+    CONST64(0x8DFC4B5655A1DB14) /*  914 */, CONST64(0xF789F1356E14DE5C) /*  915 */,
+    CONST64(0x683E68AF4E51DAC1) /*  916 */, CONST64(0xC9A84F9D8D4B0FD9) /*  917 */,
+    CONST64(0x3691E03F52A0F9D1) /*  918 */, CONST64(0x5ED86E46E1878E80) /*  919 */,
+    CONST64(0x3C711A0E99D07150) /*  920 */, CONST64(0x5A0865B20C4E9310) /*  921 */,
+    CONST64(0x56FBFC1FE4F0682E) /*  922 */, CONST64(0xEA8D5DE3105EDF9B) /*  923 */,
+    CONST64(0x71ABFDB12379187A) /*  924 */, CONST64(0x2EB99DE1BEE77B9C) /*  925 */,
+    CONST64(0x21ECC0EA33CF4523) /*  926 */, CONST64(0x59A4D7521805C7A1) /*  927 */,
+    CONST64(0x3896F5EB56AE7C72) /*  928 */, CONST64(0xAA638F3DB18F75DC) /*  929 */,
+    CONST64(0x9F39358DABE9808E) /*  930 */, CONST64(0xB7DEFA91C00B72AC) /*  931 */,
+    CONST64(0x6B5541FD62492D92) /*  932 */, CONST64(0x6DC6DEE8F92E4D5B) /*  933 */,
+    CONST64(0x353F57ABC4BEEA7E) /*  934 */, CONST64(0x735769D6DA5690CE) /*  935 */,
+    CONST64(0x0A234AA642391484) /*  936 */, CONST64(0xF6F9508028F80D9D) /*  937 */,
+    CONST64(0xB8E319A27AB3F215) /*  938 */, CONST64(0x31AD9C1151341A4D) /*  939 */,
+    CONST64(0x773C22A57BEF5805) /*  940 */, CONST64(0x45C7561A07968633) /*  941 */,
+    CONST64(0xF913DA9E249DBE36) /*  942 */, CONST64(0xDA652D9B78A64C68) /*  943 */,
+    CONST64(0x4C27A97F3BC334EF) /*  944 */, CONST64(0x76621220E66B17F4) /*  945 */,
+    CONST64(0x967743899ACD7D0B) /*  946 */, CONST64(0xF3EE5BCAE0ED6782) /*  947 */,
+    CONST64(0x409F753600C879FC) /*  948 */, CONST64(0x06D09A39B5926DB6) /*  949 */,
+    CONST64(0x6F83AEB0317AC588) /*  950 */, CONST64(0x01E6CA4A86381F21) /*  951 */,
+    CONST64(0x66FF3462D19F3025) /*  952 */, CONST64(0x72207C24DDFD3BFB) /*  953 */,
+    CONST64(0x4AF6B6D3E2ECE2EB) /*  954 */, CONST64(0x9C994DBEC7EA08DE) /*  955 */,
+    CONST64(0x49ACE597B09A8BC4) /*  956 */, CONST64(0xB38C4766CF0797BA) /*  957 */,
+    CONST64(0x131B9373C57C2A75) /*  958 */, CONST64(0xB1822CCE61931E58) /*  959 */,
+    CONST64(0x9D7555B909BA1C0C) /*  960 */, CONST64(0x127FAFDD937D11D2) /*  961 */,
+    CONST64(0x29DA3BADC66D92E4) /*  962 */, CONST64(0xA2C1D57154C2ECBC) /*  963 */,
+    CONST64(0x58C5134D82F6FE24) /*  964 */, CONST64(0x1C3AE3515B62274F) /*  965 */,
+    CONST64(0xE907C82E01CB8126) /*  966 */, CONST64(0xF8ED091913E37FCB) /*  967 */,
+    CONST64(0x3249D8F9C80046C9) /*  968 */, CONST64(0x80CF9BEDE388FB63) /*  969 */,
+    CONST64(0x1881539A116CF19E) /*  970 */, CONST64(0x5103F3F76BD52457) /*  971 */,
+    CONST64(0x15B7E6F5AE47F7A8) /*  972 */, CONST64(0xDBD7C6DED47E9CCF) /*  973 */,
+    CONST64(0x44E55C410228BB1A) /*  974 */, CONST64(0xB647D4255EDB4E99) /*  975 */,
+    CONST64(0x5D11882BB8AAFC30) /*  976 */, CONST64(0xF5098BBB29D3212A) /*  977 */,
+    CONST64(0x8FB5EA14E90296B3) /*  978 */, CONST64(0x677B942157DD025A) /*  979 */,
+    CONST64(0xFB58E7C0A390ACB5) /*  980 */, CONST64(0x89D3674C83BD4A01) /*  981 */,
+    CONST64(0x9E2DA4DF4BF3B93B) /*  982 */, CONST64(0xFCC41E328CAB4829) /*  983 */,
+    CONST64(0x03F38C96BA582C52) /*  984 */, CONST64(0xCAD1BDBD7FD85DB2) /*  985 */,
+    CONST64(0xBBB442C16082AE83) /*  986 */, CONST64(0xB95FE86BA5DA9AB0) /*  987 */,
+    CONST64(0xB22E04673771A93F) /*  988 */, CONST64(0x845358C9493152D8) /*  989 */,
+    CONST64(0xBE2A488697B4541E) /*  990 */, CONST64(0x95A2DC2DD38E6966) /*  991 */,
+    CONST64(0xC02C11AC923C852B) /*  992 */, CONST64(0x2388B1990DF2A87B) /*  993 */,
+    CONST64(0x7C8008FA1B4F37BE) /*  994 */, CONST64(0x1F70D0C84D54E503) /*  995 */,
+    CONST64(0x5490ADEC7ECE57D4) /*  996 */, CONST64(0x002B3C27D9063A3A) /*  997 */,
+    CONST64(0x7EAEA3848030A2BF) /*  998 */, CONST64(0xC602326DED2003C0) /*  999 */,
+    CONST64(0x83A7287D69A94086) /* 1000 */, CONST64(0xC57A5FCB30F57A8A) /* 1001 */,
+    CONST64(0xB56844E479EBE779) /* 1002 */, CONST64(0xA373B40F05DCBCE9) /* 1003 */,
+    CONST64(0xD71A786E88570EE2) /* 1004 */, CONST64(0x879CBACDBDE8F6A0) /* 1005 */,
+    CONST64(0x976AD1BCC164A32F) /* 1006 */, CONST64(0xAB21E25E9666D78B) /* 1007 */,
+    CONST64(0x901063AAE5E5C33C) /* 1008 */, CONST64(0x9818B34448698D90) /* 1009 */,
+    CONST64(0xE36487AE3E1E8ABB) /* 1010 */, CONST64(0xAFBDF931893BDCB4) /* 1011 */,
+    CONST64(0x6345A0DC5FBBD519) /* 1012 */, CONST64(0x8628FE269B9465CA) /* 1013 */,
+    CONST64(0x1E5D01603F9C51EC) /* 1014 */, CONST64(0x4DE44006A15049B7) /* 1015 */,
+    CONST64(0xBF6C70E5F776CBB1) /* 1016 */, CONST64(0x411218F2EF552BED) /* 1017 */,
+    CONST64(0xCB0C0708705A36A3) /* 1018 */, CONST64(0xE74D14754F986044) /* 1019 */,
+    CONST64(0xCD56D9430EA8280E) /* 1020 */, CONST64(0xC12591D7535F5065) /* 1021 */,
+    CONST64(0xC83223F1720AEF96) /* 1022 */, CONST64(0xC3A0396F7363A51F) /* 1023 */};
+
+#ifdef _MSC_VER
+   #define INLINE __inline
+#else
+   #define INLINE 
+#endif   
+
+/* one round of the hash function */
+INLINE static void round(ulong64 *a, ulong64 *b, ulong64 *c, ulong64 x, int mul)
+{
+    ulong64 tmp;
+    tmp = (*c ^= x); 
+           *a -= t1[byte(tmp, 0)] ^ t2[byte(tmp, 2)] ^ t3[byte(tmp, 4)] ^ t4[byte(tmp, 6)];      
+    tmp = (*b += t4[byte(tmp, 1)] ^ t3[byte(tmp, 3)] ^ t2[byte(tmp,5)] ^ t1[byte(tmp,7)]); 
+    switch (mul) {
+        case 5:  *b = (tmp << 2) + tmp; break;
+        case 7:  *b = (tmp << 3) - tmp; break;
+        case 9:  *b = (tmp << 3) + tmp; break;
+    }
+}
+
+/* one complete pass */
+static void pass(ulong64 *a, ulong64 *b, ulong64 *c, ulong64 *x, int mul)
+{
+   round(a,b,c,x[0],mul); 
+   round(b,c,a,x[1],mul); 
+   round(c,a,b,x[2],mul); 
+   round(a,b,c,x[3],mul); 
+   round(b,c,a,x[4],mul); 
+   round(c,a,b,x[5],mul); 
+   round(a,b,c,x[6],mul); 
+   round(b,c,a,x[7],mul);          
+}   
+
+/* The key mixing schedule */
+static void key_schedule(ulong64 *x) 
+{
+    x[0] -= x[7] ^ CONST64(0xA5A5A5A5A5A5A5A5); 
+    x[1] ^= x[0];                               
+    x[2] += x[1];                               
+    x[3] -= x[2] ^ ((~x[1])<<19);               
+    x[4] ^= x[3];                               
+    x[5] += x[4];                               
+    x[6] -= x[5] ^ ((~x[4])>>23);               
+    x[7] ^= x[6];                               
+    x[0] += x[7];                               
+    x[1] -= x[0] ^ ((~x[7])<<19);               
+    x[2] ^= x[1];                               
+    x[3] += x[2];                               
+    x[4] -= x[3] ^ ((~x[2])>>23);               
+    x[5] ^= x[4];                               
+    x[6] += x[5];                               
+    x[7] -= x[6] ^ CONST64(0x0123456789ABCDEF);
+}    
+
+#ifdef CLEAN_STACK
+static void _tiger_compress(hash_state *md, unsigned char *buf)
+#else
+static void tiger_compress(hash_state *md, unsigned char *buf)
+#endif
+{
+    ulong64 a, b, c, x[8];
+    unsigned long i;
+
+    /* load words */
+    for (i = 0; i < 8; i++) {
+        LOAD64L(x[i],&buf[8*i]);
+    }
+    a = md->tiger.state[0];
+    b = md->tiger.state[1];
+    c = md->tiger.state[2];
+
+    pass(&a,&b,&c,x,5);
+    key_schedule(x);
+    pass(&c,&a,&b,x,7);
+    key_schedule(x);
+    pass(&b,&c,&a,x,9);
+
+    /* store state */
+    md->tiger.state[0] = a ^ md->tiger.state[0];
+    md->tiger.state[1] = b - md->tiger.state[1];
+    md->tiger.state[2] = c + md->tiger.state[2];
+}
+
+#ifdef CLEAN_STACK
+static void tiger_compress(hash_state *md, unsigned char *buf)
+{
+   _tiger_compress(md, buf);
+   burn_stack(sizeof(ulong64) * 11 + sizeof(unsigned long));
+}
+#endif
+
+void tiger_init(hash_state *md)
+{
+    _ARGCHK(md != NULL);
+    md->tiger.state[0] = CONST64(0x0123456789ABCDEF);
+    md->tiger.state[1] = CONST64(0xFEDCBA9876543210);
+    md->tiger.state[2] = CONST64(0xF096A5B4C3B2E187);
+    md->tiger.curlen = 0;
+    md->tiger.length = 0;
+}
+
+HASH_PROCESS(tiger_process, tiger_compress, tiger, 64)
+
+int tiger_done(hash_state * md, unsigned char *hash)
+{
+    _ARGCHK(md   != NULL);
+    _ARGCHK(hash != NULL);
+
+    if (md->tiger.curlen >= sizeof(md->tiger.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+    /* increase the length of the message */
+    md->tiger.length += md->tiger.curlen * 8;
+
+    /* append the '1' bit */
+    md->tiger.buf[md->tiger.curlen++] = (unsigned char)0x01;
+
+    /* if the length is currently above 56 bytes we append zeros
+     * then compress.  Then we can fall back to padding zeros and length
+     * encoding like normal. */
+    if (md->tiger.curlen > 56) {
+        while (md->tiger.curlen < 64) {
+            md->tiger.buf[md->tiger.curlen++] = (unsigned char)0;
+        }
+        tiger_compress(md, md->tiger.buf);
+        md->tiger.curlen = 0;
+    }
+
+    /* pad upto 56 bytes of zeroes */
+    while (md->tiger.curlen < 56) {
+        md->tiger.buf[md->tiger.curlen++] = (unsigned char)0; 
+    }
+
+    /* store length */
+    STORE64L(md->tiger.length, md->tiger.buf+56);
+    tiger_compress(md, md->tiger.buf);
+
+    /* copy output */
+    STORE64L(md->tiger.state[0], &hash[0]);
+    STORE64L(md->tiger.state[1], &hash[8]);
+    STORE64L(md->tiger.state[2], &hash[16]);
+#ifdef CLEAN_STACK
+    zeromem(md, sizeof(hash_state));
+#endif
+
+    return CRYPT_OK;
+}
+
+int  tiger_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+  static const struct {
+      char *msg;
+      unsigned char hash[24];
+  } tests[] = {
+    { "",
+     { 0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24,
+       0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16,
+       0x7a, 0x4e, 0x58, 0x49, 0x2d, 0xde, 0x73, 0xf3 }
+    },
+    { "abc",
+     { 0x2a, 0xab, 0x14, 0x84, 0xe8, 0xc1, 0x58, 0xf2,
+       0xbf, 0xb8, 0xc5, 0xff, 0x41, 0xb5, 0x7a, 0x52,
+       0x51, 0x29, 0x13, 0x1c, 0x95, 0x7b, 0x5f, 0x93 }
+    },
+    { "Tiger",
+     { 0xdd, 0x00, 0x23, 0x07, 0x99, 0xf5, 0x00, 0x9f,
+       0xec, 0x6d, 0xeb, 0xc8, 0x38, 0xbb, 0x6a, 0x27,
+       0xdf, 0x2b, 0x9d, 0x6f, 0x11, 0x0c, 0x79, 0x37 }
+    },
+    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+     { 0xf7, 0x1c, 0x85, 0x83, 0x90, 0x2a, 0xfb, 0x87,
+       0x9e, 0xdf, 0xe6, 0x10, 0xf8, 0x2c, 0x0d, 0x47,
+       0x86, 0xa3, 0xa5, 0x34, 0x50, 0x44, 0x86, 0xb5 }
+    },
+    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+     { 0xc5, 0x40, 0x34, 0xe5, 0xb4, 0x3e, 0xb8, 0x00,
+       0x58, 0x48, 0xa7, 0xe0, 0xae, 0x6a, 0xac, 0x76,
+       0xe4, 0xff, 0x59, 0x0a, 0xe7, 0x15, 0xfd, 0x25 }
+    },
+  };
+
+  int i;
+  unsigned char tmp[24];
+  hash_state md;
+
+  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+      tiger_init(&md);
+      tiger_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
+      tiger_done(&md, tmp);
+      if (memcmp(tmp, tests[i].hash, 24) != 0) {
+          return CRYPT_FAIL_TESTVECTOR;
+      }
+  }
+  return CRYPT_OK;
+  #endif
+}
+
+#endif
+
+/*
+Hash of "":
+        24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A
+Hash of "abc":
+        F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951
+Hash of "Tiger":
+        9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF
+Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-":
+        87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386
+Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789":
+        467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197
+Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham":
+        0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303
+Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge.":
+        EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193
+Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.":
+        3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC
+Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-":
+        00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4
+*/
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tommath.h	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,556 @@
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#ifndef BN_H_
+#define BN_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+#undef MIN
+#define MIN(x,y) ((x)<(y)?(x):(y))
+#undef MAX
+#define MAX(x,y) ((x)>(y)?(x):(y))
+
+#ifdef __cplusplus
+extern "C" {
+
+/* C++ compilers don't like assigning void * to mp_digit * */
+#define  OPT_CAST(x)  (x *)
+
+#else
+
+/* C on the other hand doesn't care */
+#define  OPT_CAST(x)
+
+#endif
+
+/* some default configurations.
+ *
+ * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
+ * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
+ *
+ * At the very least a mp_digit must be able to hold 7 bits
+ * [any size beyond that is ok provided it doesn't overflow the data type]
+ */
+#ifdef MP_8BIT
+   typedef unsigned char      mp_digit;
+   typedef unsigned short     mp_word;
+#elif defined(MP_16BIT)
+   typedef unsigned short     mp_digit;
+   typedef unsigned long      mp_word;
+#elif defined(MP_64BIT)
+   /* for GCC only on supported platforms */
+#ifndef CRYPT
+   typedef unsigned long long ulong64;
+   typedef signed long long   long64;
+#endif
+
+   typedef ulong64            mp_digit;
+   typedef unsigned long      mp_word __attribute__ ((mode(TI)));
+
+   #define DIGIT_BIT          60
+#else
+   /* this is the default case, 28-bit digits */
+   
+   /* this is to make porting into LibTomCrypt easier :-) */
+#ifndef CRYPT
+   #if defined(_MSC_VER) || defined(__BORLANDC__) 
+      typedef unsigned __int64   ulong64;
+      typedef signed __int64     long64;
+   #else
+      typedef unsigned long long ulong64;
+      typedef signed long long   long64;
+   #endif
+#endif
+
+   typedef unsigned long      mp_digit;
+   typedef ulong64            mp_word;
+
+#ifdef MP_31BIT   
+   /* this is an extension that uses 31-bit digits */
+   #define DIGIT_BIT          31
+#else
+   /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
+   #define DIGIT_BIT          28
+   #define MP_28BIT
+#endif   
+#endif
+
+/* define heap macros */
+#ifndef CRYPT
+   /* default to libc stuff */
+   #ifndef XMALLOC 
+       #define XMALLOC  malloc
+       #define XFREE    free
+       #define XREALLOC realloc
+       #define XCALLOC  calloc
+   #else
+      /* prototypes for our heap functions */
+      extern void *XMALLOC(size_t n);
+      extern void *REALLOC(void *p, size_t n);
+      extern void *XCALLOC(size_t n, size_t s);
+      extern void XFREE(void *p);
+   #endif
+#endif
+
+
+/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
+#ifndef DIGIT_BIT
+   #define DIGIT_BIT     ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))  /* bits per digit */
+#endif
+
+#define MP_DIGIT_BIT     DIGIT_BIT
+#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+#define MP_DIGIT_MAX     MP_MASK
+
+/* equalities */
+#define MP_LT        -1   /* less than */
+#define MP_EQ         0   /* equal to */
+#define MP_GT         1   /* greater than */
+
+#define MP_ZPOS       0   /* positive integer */
+#define MP_NEG        1   /* negative */
+
+#define MP_OKAY       0   /* ok result */
+#define MP_MEM        -2  /* out of mem */
+#define MP_VAL        -3  /* invalid input */
+#define MP_RANGE      MP_VAL
+
+#define MP_YES        1   /* yes response */
+#define MP_NO         0   /* no response */
+
+/* Primality generation flags */
+#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
+#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
+#define LTM_PRIME_2MSB_OFF 0x0004 /* force 2nd MSB to 0 */
+#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */
+
+typedef int           mp_err;
+
+/* you'll have to tune these... */
+extern int KARATSUBA_MUL_CUTOFF,
+           KARATSUBA_SQR_CUTOFF,
+           TOOM_MUL_CUTOFF,
+           TOOM_SQR_CUTOFF;
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+/* #define MP_LOW_MEM */
+
+/* default precision */
+#ifndef MP_PREC
+   #ifdef MP_LOW_MEM
+      #define MP_PREC                 64     /* default digits of precision */
+   #else
+      #define MP_PREC                 8      /* default digits of precision */
+   #endif   
+#endif
+
+/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
+#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
+
+/* the infamous mp_int structure */
+typedef struct  {
+    int used, alloc, sign;
+    mp_digit *dp;
+} mp_int;
+
+/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
+typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
+
+
+#define USED(m)    ((m)->used)
+#define DIGIT(m,k) ((m)->dp[(k)])
+#define SIGN(m)    ((m)->sign)
+
+/* error code to char* string */
+char *mp_error_to_string(int code);
+
+/* ---> init and deinit bignum functions <--- */
+/* init a bignum */
+int mp_init(mp_int *a);
+
+/* free a bignum */
+void mp_clear(mp_int *a);
+
+/* init a null terminated series of arguments */
+int mp_init_multi(mp_int *mp, ...);
+
+/* clear a null terminated series of arguments */
+void mp_clear_multi(mp_int *mp, ...);
+
+/* exchange two ints */
+void mp_exch(mp_int *a, mp_int *b);
+
+/* shrink ram required for a bignum */
+int mp_shrink(mp_int *a);
+
+/* grow an int to a given size */
+int mp_grow(mp_int *a, int size);
+
+/* init to a given number of digits */
+int mp_init_size(mp_int *a, int size);
+
+/* ---> Basic Manipulations <--- */
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
+#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
+
+/* set to zero */
+void mp_zero(mp_int *a);
+
+/* set to a digit */
+void mp_set(mp_int *a, mp_digit b);
+
+/* set a 32-bit const */
+int mp_set_int(mp_int *a, unsigned long b);
+
+/* get a 32-bit value */
+unsigned long mp_get_int(mp_int * a);
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b);
+
+/* initialize and set 32-bit value */
+int mp_init_set_int (mp_int * a, unsigned long b);
+
+/* copy, b = a */
+int mp_copy(mp_int *a, mp_int *b);
+
+/* inits and copies, a = b */
+int mp_init_copy(mp_int *a, mp_int *b);
+
+/* trim unused digits */
+void mp_clamp(mp_int *a);
+
+/* ---> digit manipulation <--- */
+
+/* right shift by "b" digits */
+void mp_rshd(mp_int *a, int b);
+
+/* left shift by "b" digits */
+int mp_lshd(mp_int *a, int b);
+
+/* c = a / 2**b */
+int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);
+
+/* b = a/2 */
+int mp_div_2(mp_int *a, mp_int *b);
+
+/* c = a * 2**b */
+int mp_mul_2d(mp_int *a, int b, mp_int *c);
+
+/* b = a*2 */
+int mp_mul_2(mp_int *a, mp_int *b);
+
+/* c = a mod 2**d */
+int mp_mod_2d(mp_int *a, int b, mp_int *c);
+
+/* computes a = 2**b */
+int mp_2expt(mp_int *a, int b);
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a);
+
+/* I Love Earth! */
+
+/* makes a pseudo-random int of a given size */
+int mp_rand(mp_int *a, int digits);
+
+/* ---> binary operations <--- */
+/* c = a XOR b  */
+int mp_xor(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a OR b */
+int mp_or(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a AND b */
+int mp_and(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> Basic arithmetic <--- */
+
+/* b = -a */
+int mp_neg(mp_int *a, mp_int *b);
+
+/* b = |a| */
+int mp_abs(mp_int *a, mp_int *b);
+
+/* compare a to b */
+int mp_cmp(mp_int *a, mp_int *b);
+
+/* compare |a| to |b| */
+int mp_cmp_mag(mp_int *a, mp_int *b);
+
+/* c = a + b */
+int mp_add(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a - b */
+int mp_sub(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a * b */
+int mp_mul(mp_int *a, mp_int *b, mp_int *c);
+
+/* b = a*a  */
+int mp_sqr(mp_int *a, mp_int *b);
+
+/* a/b => cb + d == a */
+int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a mod b, 0 <= c < b  */
+int mp_mod(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> single digit functions <--- */
+
+/* compare against a single digit */
+int mp_cmp_d(mp_int *a, mp_digit b);
+
+/* c = a + b */
+int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a - b */
+int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a * b */
+int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* a/b => cb + d == a */
+int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
+
+/* a/3 => 3c + d == a */
+int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);
+
+/* c = a**b */
+int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a mod b, 0 <= c < b  */
+int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
+
+/* ---> number theory <--- */
+
+/* d = a + b (mod c) */
+int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a - b (mod c) */
+int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a * b (mod c) */
+int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a * a (mod b) */
+int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = 1/a (mod b) */
+int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = (a, b) */
+int mp_gcd(mp_int *a, mp_int *b, mp_int *c);
+
+/* produces value such that U1*a + U2*b = U3 */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);
+
+/* c = [a, b] or (a*b)/(a, b) */
+int mp_lcm(mp_int *a, mp_int *b, mp_int *c);
+
+/* finds one of the b'th root of a, such that |c|**b <= |a|
+ *
+ * returns error if a < 0 and b is even
+ */
+int mp_n_root(mp_int *a, mp_digit b, mp_int *c);
+
+/* special sqrt algo */
+int mp_sqrt(mp_int *arg, mp_int *ret);
+
+/* is number a square? */
+int mp_is_square(mp_int *arg, int *ret);
+
+/* computes the jacobi c = (a | n) (or Legendre if b is prime)  */
+int mp_jacobi(mp_int *a, mp_int *n, int *c);
+
+/* used to setup the Barrett reduction for a given modulus b */
+int mp_reduce_setup(mp_int *a, mp_int *b);
+
+/* Barrett Reduction, computes a (mod b) with a precomputed value c
+ *
+ * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
+ * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
+ */
+int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
+
+/* setups the montgomery reduction */
+int mp_montgomery_setup(mp_int *a, mp_digit *mp);
+
+/* computes a = B**n mod b without division or multiplication useful for
+ * normalizing numbers in a Montgomery system.
+ */
+int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
+
+/* computes x/R == x (mod N) via Montgomery Reduction */
+int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+
+/* returns 1 if a is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a);
+
+/* sets the value of "d" required for mp_dr_reduce */
+void mp_dr_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b using the Diminished Radix method */
+int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);
+
+/* returns true if a can be reduced with mp_reduce_2k */
+int mp_reduce_is_2k(mp_int *a);
+
+/* determines k value for 2k reduction */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
+
+/* d = a**b (mod c) */
+int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* ---> Primes <--- */
+
+/* number of primes */
+#ifdef MP_8BIT
+   #define PRIME_SIZE      31
+#else
+   #define PRIME_SIZE      256
+#endif
+
+/* table of first PRIME_SIZE primes */
+extern const mp_digit __prime_tab[];
+
+/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
+int mp_prime_is_divisible(mp_int *a, int *result);
+
+/* performs one Fermat test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
+
+/* performs one Miller-Rabin test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
+
+/* This gives [for a given bit size] the number of trials required
+ * such that Miller-Rabin gives a prob of failure lower than 2^-96 
+ */
+int mp_prime_rabin_miller_trials(int size);
+
+/* performs t rounds of Miller-Rabin on "a" using the first
+ * t prime bases.  Also performs an initial sieve of trial
+ * division.  Determines if "a" is prime with probability
+ * of error no more than (1/4)**t.
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime(mp_int *a, int t, int *result);
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
+
+/* makes a truly random prime of a given size (bytes),
+ * call with bbs = 1 if you want it to be congruent to 3 mod 4 
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ * The prime generated will be larger than 2^(8*size).
+ */
+#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ * 
+ *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
+ *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);
+
+/* ---> radix conversion <--- */
+int mp_count_bits(mp_int *a);
+
+int mp_unsigned_bin_size(mp_int *a);
+int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c);
+int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
+
+int mp_signed_bin_size(mp_int *a);
+int mp_read_signed_bin(mp_int *a, unsigned char *b, int c);
+int mp_to_signed_bin(mp_int *a, unsigned char *b);
+
+int mp_read_radix(mp_int *a, char *str, int radix);
+int mp_toradix(mp_int *a, char *str, int radix);
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
+int mp_radix_size(mp_int *a, int radix, int *size);
+
+int mp_fread(mp_int *a, int radix, FILE *stream);
+int mp_fwrite(mp_int *a, int radix, FILE *stream);
+
+#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
+#define mp_raw_size(mp)           mp_signed_bin_size(mp)
+#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
+#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
+#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
+#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))
+
+#define mp_tobinary(M, S)  mp_toradix((M), (S), 2)
+#define mp_tooctal(M, S)   mp_toradix((M), (S), 8)
+#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
+#define mp_tohex(M, S)     mp_toradix((M), (S), 16)
+
+/* lowlevel functions, do not call! */
+int s_mp_add(mp_int *a, mp_int *b, mp_int *c);
+int s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_sqr(mp_int *a, mp_int *b);
+int s_mp_sqr(mp_int *a, mp_int *b);
+int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_karatsuba_sqr(mp_int *a, mp_int *b);
+int mp_toom_sqr(mp_int *a, mp_int *b);
+int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode);
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y);
+void bn_reverse(unsigned char *s, int len);
+
+extern const char *mp_s_rmap;
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/twofish.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,661 @@
+/* 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 Twofish by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef TWOFISH
+
+/* first TWOFISH_ALL_TABLES must ensure TWOFISH_TABLES is defined */
+#ifdef TWOFISH_ALL_TABLES
+#ifndef TWOFISH_TABLES
+#define TWOFISH_TABLES
+#endif
+#endif
+
+const struct _cipher_descriptor twofish_desc =
+{
+    "twofish",
+    7,
+    16, 32, 16, 16,
+    &twofish_setup,
+    &twofish_ecb_encrypt,
+    &twofish_ecb_decrypt,
+    &twofish_test,
+    &twofish_keysize
+};
+
+/* the two polynomials */
+#define MDS_POLY          0x169
+#define RS_POLY           0x14D
+
+/* The 4x4 MDS Linear Transform */
+static const unsigned char MDS[4][4] = {
+    { 0x01, 0xEF, 0x5B, 0x5B },
+    { 0x5B, 0xEF, 0xEF, 0x01 },
+    { 0xEF, 0x5B, 0x01, 0xEF },
+    { 0xEF, 0x01, 0xEF, 0x5B }
+};
+
+/* The 4x8 RS Linear Transform */
+static const unsigned char RS[4][8] = {
+    { 0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E },
+    { 0xA4, 0x56, 0x82, 0xF3, 0X1E, 0XC6, 0X68, 0XE5 },
+    { 0X02, 0XA1, 0XFC, 0XC1, 0X47, 0XAE, 0X3D, 0X19 },
+    { 0XA4, 0X55, 0X87, 0X5A, 0X58, 0XDB, 0X9E, 0X03 }
+};
+
+/* sbox usage orderings */
+static const unsigned char qord[4][5] = {
+   { 1, 1, 0, 0, 1 },
+   { 0, 1, 1, 0, 0 },
+   { 0, 0, 0, 1, 1 },
+   { 1, 0, 1, 1, 0 }
+};
+
+#ifdef TWOFISH_TABLES
+
+#include "twofish_tab.c"
+
+#define sbox(i, x) ((ulong32)SBOX[i][(x)&255])
+
+#else
+
+/* The Q-box tables */
+static const unsigned char qbox[2][4][16] = {
+{
+   { 0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4 },
+   { 0xE, 0XC, 0XB, 0X8, 0X1, 0X2, 0X3, 0X5, 0XF, 0X4, 0XA, 0X6, 0X7, 0X0, 0X9, 0XD },
+   { 0XB, 0XA, 0X5, 0XE, 0X6, 0XD, 0X9, 0X0, 0XC, 0X8, 0XF, 0X3, 0X2, 0X4, 0X7, 0X1 },
+   { 0XD, 0X7, 0XF, 0X4, 0X1, 0X2, 0X6, 0XE, 0X9, 0XB, 0X3, 0X0, 0X8, 0X5, 0XC, 0XA }
+},
+{
+   { 0X2, 0X8, 0XB, 0XD, 0XF, 0X7, 0X6, 0XE, 0X3, 0X1, 0X9, 0X4, 0X0, 0XA, 0XC, 0X5 },
+   { 0X1, 0XE, 0X2, 0XB, 0X4, 0XC, 0X3, 0X7, 0X6, 0XD, 0XA, 0X5, 0XF, 0X9, 0X0, 0X8 },
+   { 0X4, 0XC, 0X7, 0X5, 0X1, 0X6, 0X9, 0XA, 0X0, 0XE, 0XD, 0X8, 0X2, 0XB, 0X3, 0XF },
+   { 0xB, 0X9, 0X5, 0X1, 0XC, 0X3, 0XD, 0XE, 0X6, 0X4, 0X7, 0XF, 0X2, 0X0, 0X8, 0XA }
+}
+};
+
+/* computes S_i[x] */
+#ifdef CLEAN_STACK
+static ulong32 _sbox(int i, ulong32 x)
+#else
+static ulong32 sbox(int i, ulong32 x)
+#endif
+{
+   unsigned char a0,b0,a1,b1,a2,b2,a3,b3,a4,b4,y;
+
+   /* a0,b0 = [x/16], x mod 16 */
+   a0 = (unsigned char)((x>>4)&15);
+   b0 = (unsigned char)((x)&15);
+
+   /* a1 = a0 ^ b0 */
+   a1 = a0 ^ b0;
+
+   /* b1 = a0 ^ ROR(b0, 1) ^ 8a0 */
+   b1 = (a0 ^ ((b0<<3)|(b0>>1)) ^ (a0<<3)) & 15;
+
+   /* a2,b2 = t0[a1], t1[b1] */
+   a2 = qbox[i][0][(int)a1];
+   b2 = qbox[i][1][(int)b1];
+
+   /* a3 = a2 ^ b2 */
+   a3 = a2 ^ b2;
+
+   /* b3 = a2 ^ ROR(b2, 1) ^ 8a2 */
+   b3 = (a2 ^ ((b2<<3)|(b2>>1)) ^ (a2<<3)) & 15;
+
+   /* a4,b4 = t2[a3], t3[b3] */
+   a4 = qbox[i][2][(int)a3];
+   b4 = qbox[i][3][(int)b3];
+
+   /* y = 16b4 + a4 */
+   y = (b4 << 4) + a4;
+
+   /* return result */
+   return (ulong32)y;
+}
+
+#ifdef CLEAN_STACK
+static ulong32 sbox(int i, ulong32 x)
+{
+   ulong32 y;
+   y = _sbox(i, x);
+   burn_stack(sizeof(unsigned char) * 11);
+   return y;
+}
+#endif /* CLEAN_STACK */
+
+#endif /* TWOFISH_TABLES */
+
+/* computes ab mod p */
+static ulong32 gf_mult(ulong32 a, ulong32 b, ulong32 p)
+{
+   ulong32 result, B[2], P[2];
+
+   P[1] = p;
+   B[1] = b;
+   result = P[0] = B[0] = 0;
+
+   /* unrolled branchless GF multiplier */
+   result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1); 
+   result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1); 
+   result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1); 
+   result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1); 
+   result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1); 
+   result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1); 
+   result ^= B[a&1]; a >>= 1;  B[1] = P[B[1]>>7] ^ (B[1] << 1); 
+   result ^= B[a&1]; 
+
+   return result;
+}
+
+/* computes [y0 y1 y2 y3] = MDS . [x0] */
+#ifndef TWOFISH_TABLES
+static ulong32 mds_column_mult(unsigned char in, int col)
+{
+   ulong32 x01, x5B, xEF;
+
+   x01 = in;
+   x5B = gf_mult(in, 0x5B, MDS_POLY);
+   xEF = gf_mult(in, 0xEF, MDS_POLY);
+
+   switch (col) {
+       case 0:
+          return (x01 << 0 ) |
+                 (x5B << 8 ) |
+                 (xEF << 16) |
+                 (xEF << 24);
+       case 1:
+          return (xEF << 0 ) |
+                 (xEF << 8 ) |
+                 (x5B << 16) |
+                 (x01 << 24);
+       case 2:
+          return (x5B << 0 ) |
+                 (xEF << 8 ) |
+                 (x01 << 16) |
+                 (xEF << 24);
+       case 3:
+          return (x5B << 0 ) |
+                 (x01 << 8 ) |
+                 (xEF << 16) |
+                 (x5B << 24);
+   }
+   /* avoid warnings, we'd never get here normally but just to calm compiler warnings... */
+   return 0;
+}
+
+#else /* !TWOFISH_TABLES */
+
+#define mds_column_mult(x, i) mds_tab[i][x]
+
+#endif /* TWOFISH_TABLES */
+
+/* Computes [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] */
+static void mds_mult(const unsigned char *in, unsigned char *out)
+{
+  int x;
+  ulong32 tmp;
+  for (tmp = x = 0; x < 4; x++) {
+      tmp ^= mds_column_mult(in[x], x);
+  }
+  STORE32L(tmp, out);
+}
+
+#ifdef TWOFISH_ALL_TABLES
+/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */
+static void rs_mult(const unsigned char *in, unsigned char *out)
+{
+   ulong32 tmp;
+   tmp = rs_tab0[in[0]] ^ rs_tab1[in[1]] ^ rs_tab2[in[2]] ^ rs_tab3[in[3]] ^
+         rs_tab4[in[4]] ^ rs_tab5[in[5]] ^ rs_tab6[in[6]] ^ rs_tab7[in[7]];
+   STORE32L(tmp, out);
+}
+
+#else /* !TWOFISH_ALL_TABLES */
+
+/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */
+static void rs_mult(const unsigned char *in, unsigned char *out)
+{
+  int x, y;
+  for (x = 0; x < 4; x++) {
+      out[x] = 0;
+      for (y = 0; y < 8; y++) {
+          out[x] ^= gf_mult(in[y], RS[x][y], RS_POLY);
+      }
+  }
+}
+
+#endif
+
+/* computes h(x) */
+static void h_func(const unsigned char *in, unsigned char *out, unsigned char *M, int k, int offset)
+{
+  int x;
+  unsigned char y[4];
+  for (x = 0; x < 4; x++) {
+      y[x] = in[x];
+ }
+  switch (k) {
+     case 4:
+            y[0] = (unsigned char)(sbox(1, (ulong32)y[0]) ^ M[4 * (6 + offset) + 0]);
+            y[1] = (unsigned char)(sbox(0, (ulong32)y[1]) ^ M[4 * (6 + offset) + 1]);
+            y[2] = (unsigned char)(sbox(0, (ulong32)y[2]) ^ M[4 * (6 + offset) + 2]);
+            y[3] = (unsigned char)(sbox(1, (ulong32)y[3]) ^ M[4 * (6 + offset) + 3]);
+     case 3:
+            y[0] = (unsigned char)(sbox(1, (ulong32)y[0]) ^ M[4 * (4 + offset) + 0]);
+            y[1] = (unsigned char)(sbox(1, (ulong32)y[1]) ^ M[4 * (4 + offset) + 1]);
+            y[2] = (unsigned char)(sbox(0, (ulong32)y[2]) ^ M[4 * (4 + offset) + 2]);
+            y[3] = (unsigned char)(sbox(0, (ulong32)y[3]) ^ M[4 * (4 + offset) + 3]);
+     case 2:
+            y[0] = (unsigned char)(sbox(1, sbox(0, sbox(0, (ulong32)y[0]) ^ M[4 * (2 + offset) + 0]) ^ M[4 * (0 + offset) + 0]));
+            y[1] = (unsigned char)(sbox(0, sbox(0, sbox(1, (ulong32)y[1]) ^ M[4 * (2 + offset) + 1]) ^ M[4 * (0 + offset) + 1]));
+            y[2] = (unsigned char)(sbox(1, sbox(1, sbox(0, (ulong32)y[2]) ^ M[4 * (2 + offset) + 2]) ^ M[4 * (0 + offset) + 2]));
+            y[3] = (unsigned char)(sbox(0, sbox(1, sbox(1, (ulong32)y[3]) ^ M[4 * (2 + offset) + 3]) ^ M[4 * (0 + offset) + 3]));
+  }
+  mds_mult(y, out);
+}
+
+#ifndef TWOFISH_SMALL
+
+/* for GCC we don't use pointer aliases */
+#if defined(__GNUC__)
+    #define S1 key->twofish.S[0]
+    #define S2 key->twofish.S[1]
+    #define S3 key->twofish.S[2]
+    #define S4 key->twofish.S[3]
+#endif
+
+/* the G function */
+#define g_func(x, dum)  (S1[byte(x,0)] ^ S2[byte(x,1)] ^ S3[byte(x,2)] ^ S4[byte(x,3)])
+#define g1_func(x, dum) (S2[byte(x,0)] ^ S3[byte(x,1)] ^ S4[byte(x,2)] ^ S1[byte(x,3)])
+
+#else
+
+#ifdef CLEAN_STACK
+static ulong32 _g_func(ulong32 x, symmetric_key *key)
+#else
+static ulong32 g_func(ulong32 x, symmetric_key *key)
+#endif
+{
+   unsigned char g, i, y, z;
+   ulong32 res;
+
+   res = 0;
+   for (y = 0; y < 4; y++) {
+       z = key->twofish.start;
+
+       /* do unkeyed substitution */
+       g = sbox(qord[y][z++], (x >> (8*y)) & 255);
+
+       /* first subkey */
+       i = 0;
+
+       /* do key mixing+sbox until z==5 */
+       while (z != 5) {
+          g = g ^ key->twofish.S[4*i++ + y];
+          g = sbox(qord[y][z++], g);
+       }
+
+       /* multiply g by a column of the MDS */
+       res ^= mds_column_mult(g, y);
+   }
+   return res;
+}
+
+#define g1_func(x, key) g_func(ROL(x, 8), key)
+
+#ifdef CLEAN_STACK
+static ulong32 g_func(ulong32 x, symmetric_key *key)
+{
+    ulong32 y;
+    y = _g_func(x, key);
+    burn_stack(sizeof(unsigned char) * 4 + sizeof(ulong32));
+    return y;
+}
+#endif /* CLEAN_STACK */
+
+#endif /* TWOFISH_SMALL */
+
+#ifdef CLEAN_STACK
+static int _twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#else
+int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#endif
+{
+#ifndef TWOFISH_SMALL
+   unsigned char S[4*4], tmpx0, tmpx1;
+#endif
+   int k, x, y;
+   unsigned char tmp[4], tmp2[4], M[8*4];
+   ulong32 A, B;
+
+   _ARGCHK(key  != NULL);
+   _ARGCHK(skey != NULL);
+
+   /* invalid arguments? */
+   if (num_rounds != 16 && num_rounds != 0) {
+      return CRYPT_INVALID_ROUNDS;
+   }
+
+   if (keylen != 16 && keylen != 24 && keylen != 32) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+
+   /* k = keysize/64 [but since our keysize is in bytes...] */
+   k = keylen / 8;
+
+   /* copy the key into M */
+   for (x = 0; x < keylen; x++) {
+       M[x] = key[x] & 255;
+   }
+
+   /* create the S[..] words */
+#ifndef TWOFISH_SMALL
+   for (x = 0; x < k; x++) {
+       rs_mult(M+(x*8), S+(x*4));
+   }
+#else
+   for (x = 0; x < k; x++) {
+       rs_mult(M+(x*8), skey->twofish.S+(x*4));
+   }
+#endif
+
+   /* make subkeys */
+   for (x = 0; x < 20; x++) {
+       /* A = h(p * 2x, Me) */
+       for (y = 0; y < 4; y++) {
+           tmp[y] = x+x;
+       }
+       h_func(tmp, tmp2, M, k, 0);
+       LOAD32L(A, tmp2);
+
+       /* B = ROL(h(p * (2x + 1), Mo), 8) */
+       for (y = 0; y < 4; y++) {
+           tmp[y] = (unsigned char)(x+x+1);
+       }
+       h_func(tmp, tmp2, M, k, 1);
+       LOAD32L(B, tmp2);
+       B = ROL(B, 8);
+
+       /* K[2i]   = A + B */
+       skey->twofish.K[x+x] = (A + B) & 0xFFFFFFFFUL;
+
+       /* K[2i+1] = (A + 2B) <<< 9 */
+       skey->twofish.K[x+x+1] = ROL(B + B + A, 9);
+   }
+
+#ifndef TWOFISH_SMALL
+   /* make the sboxes (large ram variant) */
+   if (k == 2) {
+        for (x = 0; x < 256; x++) {
+           tmpx0 = sbox(0, x);
+           tmpx1 = sbox(1, x);
+           skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, tmpx0 ^ S[0]) ^ S[4])),0);
+           skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, tmpx1 ^ S[1]) ^ S[5])),1);
+           skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, tmpx0 ^ S[2]) ^ S[6])),2);
+           skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, tmpx1 ^ S[3]) ^ S[7])),3);
+        }
+   } else if (k == 3) {
+        for (x = 0; x < 256; x++) {
+           tmpx0 = sbox(0, x);
+           tmpx1 = sbox(1, x);
+           skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, tmpx1 ^ S[0]) ^ S[4]) ^ S[8])),0);
+           skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, tmpx1 ^ S[1]) ^ S[5]) ^ S[9])),1);
+           skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10])),2);
+           skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, tmpx0 ^ S[3]) ^ S[7]) ^ S[11])),3);
+        }
+   } else {
+        for (x = 0; x < 256; x++) {
+           tmpx0 = sbox(0, x);
+           tmpx1 = sbox(1, x);
+           skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, sbox(1, tmpx1 ^ S[0]) ^ S[4]) ^ S[8]) ^ S[12])),0);
+           skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, sbox(1, tmpx0 ^ S[1]) ^ S[5]) ^ S[9]) ^ S[13])),1);
+           skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10]) ^ S[14])),2);
+           skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, sbox(0, tmpx1 ^ S[3]) ^ S[7]) ^ S[11]) ^ S[15])),3);
+        }
+   }
+#else
+   /* where to start in the sbox layers */
+   /* small ram variant */
+   switch (k) {
+         case 4 : skey->twofish.start = 0; break;
+         case 3 : skey->twofish.start = 1; break; 
+         default: skey->twofish.start = 2; break;
+   }
+#endif
+   return CRYPT_OK;
+}
+
+#ifdef CLEAN_STACK
+int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+   int x;
+   x = _twofish_setup(key, keylen, num_rounds, skey);
+   burn_stack(sizeof(int) * 7 + sizeof(unsigned char) * 56 + sizeof(ulong32) * 2);
+   return x;
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#else
+void twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+#endif
+{
+    ulong32 a,b,c,d,ta,tb,tc,td,t1,t2, *k;
+    int r;
+#if !defined(TWOFISH_SMALL) && !defined(__GNUC__)
+    ulong32 *S1, *S2, *S3, *S4;
+#endif    
+
+    _ARGCHK(pt  != NULL);
+    _ARGCHK(ct  != NULL);
+    _ARGCHK(key != NULL);
+    
+#if !defined(TWOFISH_SMALL) && !defined(__GNUC__)
+    S1 = key->twofish.S[0];
+    S2 = key->twofish.S[1];
+    S3 = key->twofish.S[2];
+    S4 = key->twofish.S[3];
+#endif    
+
+    LOAD32L(a,&pt[0]); LOAD32L(b,&pt[4]);
+    LOAD32L(c,&pt[8]); LOAD32L(d,&pt[12]);
+    a ^= key->twofish.K[0];
+    b ^= key->twofish.K[1];
+    c ^= key->twofish.K[2];
+    d ^= key->twofish.K[3];
+    
+    k  = key->twofish.K + 8;
+    for (r = 8; r != 0; --r) {
+        t2 = g1_func(b, key);
+        t1 = g_func(a, key) + t2;
+        c  = ROR(c ^ (t1 + k[0]), 1);
+        d  = ROL(d, 1) ^ (t2 + t1 + k[1]);
+        
+        t2 = g1_func(d, key);
+        t1 = g_func(c, key) + t2;
+        a  = ROR(a ^ (t1 + k[2]), 1);
+        b  = ROL(b, 1) ^ (t2 + t1 + k[3]);
+        k += 4;
+   }
+
+    /* output with "undo last swap" */
+    ta = c ^ key->twofish.K[4];
+    tb = d ^ key->twofish.K[5];
+    tc = a ^ key->twofish.K[6];
+    td = b ^ key->twofish.K[7];
+
+    /* store output */
+    STORE32L(ta,&ct[0]); STORE32L(tb,&ct[4]);
+    STORE32L(tc,&ct[8]); STORE32L(td,&ct[12]);
+}
+
+#ifdef CLEAN_STACK
+void twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+{
+   _twofish_ecb_encrypt(pt, ct, key);
+   burn_stack(sizeof(ulong32) * 10 + sizeof(int));
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#else
+void twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+#endif
+{
+    ulong32 a,b,c,d,ta,tb,tc,td,t1,t2, *k;
+    int r;
+#if !defined(TWOFISH_SMALL) && !defined(__GNUC__)
+    ulong32 *S1, *S2, *S3, *S4;
+#endif    
+
+    _ARGCHK(pt != NULL);
+    _ARGCHK(ct != NULL);
+    _ARGCHK(key != NULL);
+    
+#if !defined(TWOFISH_SMALL) && !defined(__GNUC__)
+    S1 = key->twofish.S[0];
+    S2 = key->twofish.S[1];
+    S3 = key->twofish.S[2];
+    S4 = key->twofish.S[3];
+#endif    
+
+    /* load input */
+    LOAD32L(ta,&ct[0]); LOAD32L(tb,&ct[4]);
+    LOAD32L(tc,&ct[8]); LOAD32L(td,&ct[12]);
+
+    /* undo undo final swap */
+    a = tc ^ key->twofish.K[6];
+    b = td ^ key->twofish.K[7];
+    c = ta ^ key->twofish.K[4];
+    d = tb ^ key->twofish.K[5];
+
+    k = key->twofish.K + 36;
+    for (r = 8; r != 0; --r) {
+        t2 = g1_func(d, key);
+        t1 = g_func(c, key) + t2;
+        a = ROL(a, 1) ^ (t1 + k[2]);
+        b = ROR(b ^ (t2 + t1 + k[3]), 1);
+
+        t2 = g1_func(b, key);
+        t1 = g_func(a, key) + t2;
+        c = ROL(c, 1) ^ (t1 + k[0]);
+        d = ROR(d ^ (t2 +  t1 + k[1]), 1);
+        k -= 4;
+    }
+
+    /* pre-white */
+    a ^= key->twofish.K[0];
+    b ^= key->twofish.K[1];
+    c ^= key->twofish.K[2];
+    d ^= key->twofish.K[3];
+    
+    /* store */
+    STORE32L(a, &pt[0]); STORE32L(b, &pt[4]);
+    STORE32L(c, &pt[8]); STORE32L(d, &pt[12]);
+}
+
+#ifdef CLEAN_STACK
+void twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+{
+   _twofish_ecb_decrypt(ct, pt, key);
+   burn_stack(sizeof(ulong32) * 10 + sizeof(int));
+}
+#endif
+
+int twofish_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+ static const struct { 
+     int keylen;
+     unsigned char key[32], pt[16], ct[16];
+ } tests[] = {
+   { 16,
+     { 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32,
+       0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A },
+     { 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E,
+       0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 },
+     { 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85,
+       0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 }
+   }, {
+     24,
+     { 0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36,
+       0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88,
+       0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44 },
+     { 0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5,
+       0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2 },
+     { 0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45,
+       0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65 }
+   }, { 
+     32,
+     { 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46,
+       0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
+       0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B,
+       0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F },
+     { 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F,
+       0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 },
+     { 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97,
+       0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA }
+   }
+};
+
+
+ symmetric_key key;
+ unsigned char tmp[2][16];
+ int err, i, y;
+ 
+ for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+    if ((err = twofish_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
+       return err;
+    }
+    twofish_ecb_encrypt(tests[i].pt, tmp[0], &key);
+    twofish_ecb_decrypt(tmp[0], tmp[1], &key);
+    if (memcmp(tmp[0], tests[i].ct, 16) != 0 || memcmp(tmp[1], tests[i].pt, 16) != 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 < 16; y++) tmp[0][y] = 0;
+      for (y = 0; y < 1000; y++) twofish_ecb_encrypt(tmp[0], tmp[0], &key);
+      for (y = 0; y < 1000; y++) twofish_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 twofish_keysize(int *desired_keysize)
+{
+   _ARGCHK(desired_keysize);
+   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/twofish_tab.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,488 @@
+/* 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
+ */
+
+#ifdef TWOFISH_TABLES
+
+/* pre generated 8x8 tables from the four 4x4s */
+static const unsigned char SBOX[2][256] = {
+{
+ 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 
+ 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, 0x0d, 0xc6, 0x35, 0x98, 
+ 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 
+ 0x94, 0x48, 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 
+ 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, 0x63, 0x01, 
+ 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 
+ 0x16, 0x0c, 0xe3, 0x61, 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 
+ 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1, 
+ 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95,
+ 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, 0xfb, 0xc3, 0x8e, 0xb5, 
+ 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 
+ 0x62, 0x71, 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 
+ 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, 0xa1, 0x1d, 
+ 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 
+ 0x31, 0xc2, 0x27, 0x90, 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c,
+ 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef, 
+ 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 
+ 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, 0x2a, 0xce, 0xcb, 0x2f, 
+ 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 
+ 0xa7, 0x5a, 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 
+ 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, 0x57, 0xc7, 
+ 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 
+ 0x58, 0x07, 0x99, 0x34, 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 
+ 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4, 
+ 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 
+ 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0},
+{
+ 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 
+ 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, 0xd6, 0x32, 0xd8, 0xfd,
+ 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa,
+ 0x06, 0x3f, 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d,
+ 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, 0xa0, 0x84, 
+ 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 
+ 0x92, 0x74, 0x36, 0x51, 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 
+ 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c, 
+ 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 
+ 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, 0xa6, 0x83, 0x20, 0xff,
+ 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 
+ 0x2b, 0xe2, 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 
+ 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, 0x66, 0x94, 
+ 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 
+ 0xef, 0xd1, 0x53, 0x3e, 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 
+ 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9, 
+ 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 
+ 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, 0x4f, 0xf2, 0x65, 0x8e, 
+ 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 
+ 0x05, 0x64, 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 
+ 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, 0x29, 0x2e, 
+ 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 
+ 0x35, 0x6a, 0xcf, 0xdc, 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 
+ 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9, 
+ 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 
+ 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91}
+};
+
+/* the 4x4 MDS in a nicer format */
+static const ulong32 mds_tab[4][256] = {
+{
+0x00000000UL, 0xefef5b01UL, 0xb7b7b602UL, 0x5858ed03UL, 0x07070504UL, 0xe8e85e05UL, 0xb0b0b306UL, 0x5f5fe807UL, 
+0x0e0e0a08UL, 0xe1e15109UL, 0xb9b9bc0aUL, 0x5656e70bUL, 0x09090f0cUL, 0xe6e6540dUL, 0xbebeb90eUL, 0x5151e20fUL, 
+0x1c1c1410UL, 0xf3f34f11UL, 0xababa212UL, 0x4444f913UL, 0x1b1b1114UL, 0xf4f44a15UL, 0xacaca716UL, 0x4343fc17UL, 
+0x12121e18UL, 0xfdfd4519UL, 0xa5a5a81aUL, 0x4a4af31bUL, 0x15151b1cUL, 0xfafa401dUL, 0xa2a2ad1eUL, 0x4d4df61fUL, 
+0x38382820UL, 0xd7d77321UL, 0x8f8f9e22UL, 0x6060c523UL, 0x3f3f2d24UL, 0xd0d07625UL, 0x88889b26UL, 0x6767c027UL, 
+0x36362228UL, 0xd9d97929UL, 0x8181942aUL, 0x6e6ecf2bUL, 0x3131272cUL, 0xdede7c2dUL, 0x8686912eUL, 0x6969ca2fUL, 
+0x24243c30UL, 0xcbcb6731UL, 0x93938a32UL, 0x7c7cd133UL, 0x23233934UL, 0xcccc6235UL, 0x94948f36UL, 0x7b7bd437UL, 
+0x2a2a3638UL, 0xc5c56d39UL, 0x9d9d803aUL, 0x7272db3bUL, 0x2d2d333cUL, 0xc2c2683dUL, 0x9a9a853eUL, 0x7575de3fUL, 
+0x70705040UL, 0x9f9f0b41UL, 0xc7c7e642UL, 0x2828bd43UL, 0x77775544UL, 0x98980e45UL, 0xc0c0e346UL, 0x2f2fb847UL,
+0x7e7e5a48UL, 0x91910149UL, 0xc9c9ec4aUL, 0x2626b74bUL, 0x79795f4cUL, 0x9696044dUL, 0xcecee94eUL, 0x2121b24fUL, 
+0x6c6c4450UL, 0x83831f51UL, 0xdbdbf252UL, 0x3434a953UL, 0x6b6b4154UL, 0x84841a55UL, 0xdcdcf756UL, 0x3333ac57UL, 
+0x62624e58UL, 0x8d8d1559UL, 0xd5d5f85aUL, 0x3a3aa35bUL, 0x65654b5cUL, 0x8a8a105dUL, 0xd2d2fd5eUL, 0x3d3da65fUL, 
+0x48487860UL, 0xa7a72361UL, 0xffffce62UL, 0x10109563UL, 0x4f4f7d64UL, 0xa0a02665UL, 0xf8f8cb66UL, 0x17179067UL, 
+0x46467268UL, 0xa9a92969UL, 0xf1f1c46aUL, 0x1e1e9f6bUL, 0x4141776cUL, 0xaeae2c6dUL, 0xf6f6c16eUL, 0x19199a6fUL,
+0x54546c70UL, 0xbbbb3771UL, 0xe3e3da72UL, 0x0c0c8173UL, 0x53536974UL, 0xbcbc3275UL, 0xe4e4df76UL, 0x0b0b8477UL, 
+0x5a5a6678UL, 0xb5b53d79UL, 0xededd07aUL, 0x02028b7bUL, 0x5d5d637cUL, 0xb2b2387dUL, 0xeaead57eUL, 0x05058e7fUL, 
+0xe0e0a080UL, 0x0f0ffb81UL, 0x57571682UL, 0xb8b84d83UL, 0xe7e7a584UL, 0x0808fe85UL, 0x50501386UL, 0xbfbf4887UL, 
+0xeeeeaa88UL, 0x0101f189UL, 0x59591c8aUL, 0xb6b6478bUL, 0xe9e9af8cUL, 0x0606f48dUL, 0x5e5e198eUL, 0xb1b1428fUL, 
+0xfcfcb490UL, 0x1313ef91UL, 0x4b4b0292UL, 0xa4a45993UL, 0xfbfbb194UL, 0x1414ea95UL, 0x4c4c0796UL, 0xa3a35c97UL, 
+0xf2f2be98UL, 0x1d1de599UL, 0x4545089aUL, 0xaaaa539bUL, 0xf5f5bb9cUL, 0x1a1ae09dUL, 0x42420d9eUL, 0xadad569fUL, 
+0xd8d888a0UL, 0x3737d3a1UL, 0x6f6f3ea2UL, 0x808065a3UL, 0xdfdf8da4UL, 0x3030d6a5UL, 0x68683ba6UL, 0x878760a7UL, 
+0xd6d682a8UL, 0x3939d9a9UL, 0x616134aaUL, 0x8e8e6fabUL, 0xd1d187acUL, 0x3e3edcadUL, 0x666631aeUL, 0x89896aafUL, 
+0xc4c49cb0UL, 0x2b2bc7b1UL, 0x73732ab2UL, 0x9c9c71b3UL, 0xc3c399b4UL, 0x2c2cc2b5UL, 0x74742fb6UL, 0x9b9b74b7UL, 
+0xcaca96b8UL, 0x2525cdb9UL, 0x7d7d20baUL, 0x92927bbbUL, 0xcdcd93bcUL, 0x2222c8bdUL, 0x7a7a25beUL, 0x95957ebfUL, 
+0x9090f0c0UL, 0x7f7fabc1UL, 0x272746c2UL, 0xc8c81dc3UL, 0x9797f5c4UL, 0x7878aec5UL, 0x202043c6UL, 0xcfcf18c7UL, 
+0x9e9efac8UL, 0x7171a1c9UL, 0x29294ccaUL, 0xc6c617cbUL, 0x9999ffccUL, 0x7676a4cdUL, 0x2e2e49ceUL, 0xc1c112cfUL, 
+0x8c8ce4d0UL, 0x6363bfd1UL, 0x3b3b52d2UL, 0xd4d409d3UL, 0x8b8be1d4UL, 0x6464bad5UL, 0x3c3c57d6UL, 0xd3d30cd7UL, 
+0x8282eed8UL, 0x6d6db5d9UL, 0x353558daUL, 0xdada03dbUL, 0x8585ebdcUL, 0x6a6ab0ddUL, 0x32325ddeUL, 0xdddd06dfUL, 
+0xa8a8d8e0UL, 0x474783e1UL, 0x1f1f6ee2UL, 0xf0f035e3UL, 0xafafdde4UL, 0x404086e5UL, 0x18186be6UL, 0xf7f730e7UL,
+0xa6a6d2e8UL, 0x494989e9UL, 0x111164eaUL, 0xfefe3febUL, 0xa1a1d7ecUL, 0x4e4e8cedUL, 0x161661eeUL, 0xf9f93aefUL,
+0xb4b4ccf0UL, 0x5b5b97f1UL, 0x03037af2UL, 0xecec21f3UL, 0xb3b3c9f4UL, 0x5c5c92f5UL, 0x04047ff6UL, 0xebeb24f7UL, 
+0xbabac6f8UL, 0x55559df9UL, 0x0d0d70faUL, 0xe2e22bfbUL, 0xbdbdc3fcUL, 0x525298fdUL, 0x0a0a75feUL, 0xe5e52effUL
+}, 
+{
+0x00000000UL, 0x015befefUL, 0x02b6b7b7UL, 0x03ed5858UL, 0x04050707UL, 0x055ee8e8UL, 0x06b3b0b0UL, 0x07e85f5fUL, 
+0x080a0e0eUL, 0x0951e1e1UL, 0x0abcb9b9UL, 0x0be75656UL, 0x0c0f0909UL, 0x0d54e6e6UL, 0x0eb9bebeUL, 0x0fe25151UL, 
+0x10141c1cUL, 0x114ff3f3UL, 0x12a2ababUL, 0x13f94444UL, 0x14111b1bUL, 0x154af4f4UL, 0x16a7acacUL, 0x17fc4343UL, 
+0x181e1212UL, 0x1945fdfdUL, 0x1aa8a5a5UL, 0x1bf34a4aUL, 0x1c1b1515UL, 0x1d40fafaUL, 0x1eada2a2UL, 0x1ff64d4dUL, 
+0x20283838UL, 0x2173d7d7UL, 0x229e8f8fUL, 0x23c56060UL, 0x242d3f3fUL, 0x2576d0d0UL, 0x269b8888UL, 0x27c06767UL, 
+0x28223636UL, 0x2979d9d9UL, 0x2a948181UL, 0x2bcf6e6eUL, 0x2c273131UL, 0x2d7cdedeUL, 0x2e918686UL, 0x2fca6969UL, 
+0x303c2424UL, 0x3167cbcbUL, 0x328a9393UL, 0x33d17c7cUL, 0x34392323UL, 0x3562ccccUL, 0x368f9494UL, 0x37d47b7bUL, 
+0x38362a2aUL, 0x396dc5c5UL, 0x3a809d9dUL, 0x3bdb7272UL, 0x3c332d2dUL, 0x3d68c2c2UL, 0x3e859a9aUL, 0x3fde7575UL, 
+0x40507070UL, 0x410b9f9fUL, 0x42e6c7c7UL, 0x43bd2828UL, 0x44557777UL, 0x450e9898UL, 0x46e3c0c0UL, 0x47b82f2fUL, 
+0x485a7e7eUL, 0x49019191UL, 0x4aecc9c9UL, 0x4bb72626UL, 0x4c5f7979UL, 0x4d049696UL, 0x4ee9ceceUL, 0x4fb22121UL, 
+0x50446c6cUL, 0x511f8383UL, 0x52f2dbdbUL, 0x53a93434UL, 0x54416b6bUL, 0x551a8484UL, 0x56f7dcdcUL, 0x57ac3333UL, 
+0x584e6262UL, 0x59158d8dUL, 0x5af8d5d5UL, 0x5ba33a3aUL, 0x5c4b6565UL, 0x5d108a8aUL, 0x5efdd2d2UL, 0x5fa63d3dUL,
+0x60784848UL, 0x6123a7a7UL, 0x62ceffffUL, 0x63951010UL, 0x647d4f4fUL, 0x6526a0a0UL, 0x66cbf8f8UL, 0x67901717UL, 
+0x68724646UL, 0x6929a9a9UL, 0x6ac4f1f1UL, 0x6b9f1e1eUL, 0x6c774141UL, 0x6d2caeaeUL, 0x6ec1f6f6UL, 0x6f9a1919UL, 
+0x706c5454UL, 0x7137bbbbUL, 0x72dae3e3UL, 0x73810c0cUL, 0x74695353UL, 0x7532bcbcUL, 0x76dfe4e4UL, 0x77840b0bUL, 
+0x78665a5aUL, 0x793db5b5UL, 0x7ad0ededUL, 0x7b8b0202UL, 0x7c635d5dUL, 0x7d38b2b2UL, 0x7ed5eaeaUL, 0x7f8e0505UL, 
+0x80a0e0e0UL, 0x81fb0f0fUL, 0x82165757UL, 0x834db8b8UL, 0x84a5e7e7UL, 0x85fe0808UL, 0x86135050UL, 0x8748bfbfUL, 
+0x88aaeeeeUL, 0x89f10101UL, 0x8a1c5959UL, 0x8b47b6b6UL, 0x8cafe9e9UL, 0x8df40606UL, 0x8e195e5eUL, 0x8f42b1b1UL, 
+0x90b4fcfcUL, 0x91ef1313UL, 0x92024b4bUL, 0x9359a4a4UL, 0x94b1fbfbUL, 0x95ea1414UL, 0x96074c4cUL, 0x975ca3a3UL, 
+0x98bef2f2UL, 0x99e51d1dUL, 0x9a084545UL, 0x9b53aaaaUL, 0x9cbbf5f5UL, 0x9de01a1aUL, 0x9e0d4242UL, 0x9f56adadUL,
+0xa088d8d8UL, 0xa1d33737UL, 0xa23e6f6fUL, 0xa3658080UL, 0xa48ddfdfUL, 0xa5d63030UL, 0xa63b6868UL, 0xa7608787UL, 
+0xa882d6d6UL, 0xa9d93939UL, 0xaa346161UL, 0xab6f8e8eUL, 0xac87d1d1UL, 0xaddc3e3eUL, 0xae316666UL, 0xaf6a8989UL, 
+0xb09cc4c4UL, 0xb1c72b2bUL, 0xb22a7373UL, 0xb3719c9cUL, 0xb499c3c3UL, 0xb5c22c2cUL, 0xb62f7474UL, 0xb7749b9bUL, 
+0xb896cacaUL, 0xb9cd2525UL, 0xba207d7dUL, 0xbb7b9292UL, 0xbc93cdcdUL, 0xbdc82222UL, 0xbe257a7aUL, 0xbf7e9595UL, 
+0xc0f09090UL, 0xc1ab7f7fUL, 0xc2462727UL, 0xc31dc8c8UL, 0xc4f59797UL, 0xc5ae7878UL, 0xc6432020UL, 0xc718cfcfUL, 
+0xc8fa9e9eUL, 0xc9a17171UL, 0xca4c2929UL, 0xcb17c6c6UL, 0xccff9999UL, 0xcda47676UL, 0xce492e2eUL, 0xcf12c1c1UL, 
+0xd0e48c8cUL, 0xd1bf6363UL, 0xd2523b3bUL, 0xd309d4d4UL, 0xd4e18b8bUL, 0xd5ba6464UL, 0xd6573c3cUL, 0xd70cd3d3UL, 
+0xd8ee8282UL, 0xd9b56d6dUL, 0xda583535UL, 0xdb03dadaUL, 0xdceb8585UL, 0xddb06a6aUL, 0xde5d3232UL, 0xdf06ddddUL, 
+0xe0d8a8a8UL, 0xe1834747UL, 0xe26e1f1fUL, 0xe335f0f0UL, 0xe4ddafafUL, 0xe5864040UL, 0xe66b1818UL, 0xe730f7f7UL, 
+0xe8d2a6a6UL, 0xe9894949UL, 0xea641111UL, 0xeb3ffefeUL, 0xecd7a1a1UL, 0xed8c4e4eUL, 0xee611616UL, 0xef3af9f9UL, 
+0xf0ccb4b4UL, 0xf1975b5bUL, 0xf27a0303UL, 0xf321ececUL, 0xf4c9b3b3UL, 0xf5925c5cUL, 0xf67f0404UL, 0xf724ebebUL, 
+0xf8c6babaUL, 0xf99d5555UL, 0xfa700d0dUL, 0xfb2be2e2UL, 0xfcc3bdbdUL, 0xfd985252UL, 0xfe750a0aUL, 0xff2ee5e5UL
+}, 
+{
+0x00000000UL, 0xef01ef5bUL, 0xb702b7b6UL, 0x580358edUL, 0x07040705UL, 0xe805e85eUL, 0xb006b0b3UL, 0x5f075fe8UL, 
+0x0e080e0aUL, 0xe109e151UL, 0xb90ab9bcUL, 0x560b56e7UL, 0x090c090fUL, 0xe60de654UL, 0xbe0ebeb9UL, 0x510f51e2UL,
+0x1c101c14UL, 0xf311f34fUL, 0xab12aba2UL, 0x441344f9UL, 0x1b141b11UL, 0xf415f44aUL, 0xac16aca7UL, 0x431743fcUL, 
+0x1218121eUL, 0xfd19fd45UL, 0xa51aa5a8UL, 0x4a1b4af3UL, 0x151c151bUL, 0xfa1dfa40UL, 0xa21ea2adUL, 0x4d1f4df6UL, 
+0x38203828UL, 0xd721d773UL, 0x8f228f9eUL, 0x602360c5UL, 0x3f243f2dUL, 0xd025d076UL, 0x8826889bUL, 0x672767c0UL, 
+0x36283622UL, 0xd929d979UL, 0x812a8194UL, 0x6e2b6ecfUL, 0x312c3127UL, 0xde2dde7cUL, 0x862e8691UL, 0x692f69caUL, 
+0x2430243cUL, 0xcb31cb67UL, 0x9332938aUL, 0x7c337cd1UL, 0x23342339UL, 0xcc35cc62UL, 0x9436948fUL, 0x7b377bd4UL, 
+0x2a382a36UL, 0xc539c56dUL, 0x9d3a9d80UL, 0x723b72dbUL, 0x2d3c2d33UL, 0xc23dc268UL, 0x9a3e9a85UL, 0x753f75deUL,
+0x70407050UL, 0x9f419f0bUL, 0xc742c7e6UL, 0x284328bdUL, 0x77447755UL, 0x9845980eUL, 0xc046c0e3UL, 0x2f472fb8UL, 
+0x7e487e5aUL, 0x91499101UL, 0xc94ac9ecUL, 0x264b26b7UL, 0x794c795fUL, 0x964d9604UL, 0xce4ecee9UL, 0x214f21b2UL, 
+0x6c506c44UL, 0x8351831fUL, 0xdb52dbf2UL, 0x345334a9UL, 0x6b546b41UL, 0x8455841aUL, 0xdc56dcf7UL, 0x335733acUL,
+0x6258624eUL, 0x8d598d15UL, 0xd55ad5f8UL, 0x3a5b3aa3UL, 0x655c654bUL, 0x8a5d8a10UL, 0xd25ed2fdUL, 0x3d5f3da6UL, 
+0x48604878UL, 0xa761a723UL, 0xff62ffceUL, 0x10631095UL, 0x4f644f7dUL, 0xa065a026UL, 0xf866f8cbUL, 0x17671790UL, 
+0x46684672UL, 0xa969a929UL, 0xf16af1c4UL, 0x1e6b1e9fUL, 0x416c4177UL, 0xae6dae2cUL, 0xf66ef6c1UL, 0x196f199aUL, 
+0x5470546cUL, 0xbb71bb37UL, 0xe372e3daUL, 0x0c730c81UL, 0x53745369UL, 0xbc75bc32UL, 0xe476e4dfUL, 0x0b770b84UL,
+0x5a785a66UL, 0xb579b53dUL, 0xed7aedd0UL, 0x027b028bUL, 0x5d7c5d63UL, 0xb27db238UL, 0xea7eead5UL, 0x057f058eUL, 
+0xe080e0a0UL, 0x0f810ffbUL, 0x57825716UL, 0xb883b84dUL, 0xe784e7a5UL, 0x088508feUL, 0x50865013UL, 0xbf87bf48UL,
+0xee88eeaaUL, 0x018901f1UL, 0x598a591cUL, 0xb68bb647UL, 0xe98ce9afUL, 0x068d06f4UL, 0x5e8e5e19UL, 0xb18fb142UL,
+0xfc90fcb4UL, 0x139113efUL, 0x4b924b02UL, 0xa493a459UL, 0xfb94fbb1UL, 0x149514eaUL, 0x4c964c07UL, 0xa397a35cUL, 
+0xf298f2beUL, 0x1d991de5UL, 0x459a4508UL, 0xaa9baa53UL, 0xf59cf5bbUL, 0x1a9d1ae0UL, 0x429e420dUL, 0xad9fad56UL, 
+0xd8a0d888UL, 0x37a137d3UL, 0x6fa26f3eUL, 0x80a38065UL, 0xdfa4df8dUL, 0x30a530d6UL, 0x68a6683bUL, 0x87a78760UL, 
+0xd6a8d682UL, 0x39a939d9UL, 0x61aa6134UL, 0x8eab8e6fUL, 0xd1acd187UL, 0x3ead3edcUL, 0x66ae6631UL, 0x89af896aUL, 
+0xc4b0c49cUL, 0x2bb12bc7UL, 0x73b2732aUL, 0x9cb39c71UL, 0xc3b4c399UL, 0x2cb52cc2UL, 0x74b6742fUL, 0x9bb79b74UL, 
+0xcab8ca96UL, 0x25b925cdUL, 0x7dba7d20UL, 0x92bb927bUL, 0xcdbccd93UL, 0x22bd22c8UL, 0x7abe7a25UL, 0x95bf957eUL, 
+0x90c090f0UL, 0x7fc17fabUL, 0x27c22746UL, 0xc8c3c81dUL, 0x97c497f5UL, 0x78c578aeUL, 0x20c62043UL, 0xcfc7cf18UL, 
+0x9ec89efaUL, 0x71c971a1UL, 0x29ca294cUL, 0xc6cbc617UL, 0x99cc99ffUL, 0x76cd76a4UL, 0x2ece2e49UL, 0xc1cfc112UL, 
+0x8cd08ce4UL, 0x63d163bfUL, 0x3bd23b52UL, 0xd4d3d409UL, 0x8bd48be1UL, 0x64d564baUL, 0x3cd63c57UL, 0xd3d7d30cUL, 
+0x82d882eeUL, 0x6dd96db5UL, 0x35da3558UL, 0xdadbda03UL, 0x85dc85ebUL, 0x6add6ab0UL, 0x32de325dUL, 0xdddfdd06UL, 
+0xa8e0a8d8UL, 0x47e14783UL, 0x1fe21f6eUL, 0xf0e3f035UL, 0xafe4afddUL, 0x40e54086UL, 0x18e6186bUL, 0xf7e7f730UL, 
+0xa6e8a6d2UL, 0x49e94989UL, 0x11ea1164UL, 0xfeebfe3fUL, 0xa1eca1d7UL, 0x4eed4e8cUL, 0x16ee1661UL, 0xf9eff93aUL, 
+0xb4f0b4ccUL, 0x5bf15b97UL, 0x03f2037aUL, 0xecf3ec21UL, 0xb3f4b3c9UL, 0x5cf55c92UL, 0x04f6047fUL, 0xebf7eb24UL, 
+0xbaf8bac6UL, 0x55f9559dUL, 0x0dfa0d70UL, 0xe2fbe22bUL, 0xbdfcbdc3UL, 0x52fd5298UL, 0x0afe0a75UL, 0xe5ffe52eUL
+}, 
+{
+0x00000000UL, 0x5bef015bUL, 0xb6b702b6UL, 0xed5803edUL, 0x05070405UL, 0x5ee8055eUL, 0xb3b006b3UL, 0xe85f07e8UL, 
+0x0a0e080aUL, 0x51e10951UL, 0xbcb90abcUL, 0xe7560be7UL, 0x0f090c0fUL, 0x54e60d54UL, 0xb9be0eb9UL, 0xe2510fe2UL, 
+0x141c1014UL, 0x4ff3114fUL, 0xa2ab12a2UL, 0xf94413f9UL, 0x111b1411UL, 0x4af4154aUL, 0xa7ac16a7UL, 0xfc4317fcUL, 
+0x1e12181eUL, 0x45fd1945UL, 0xa8a51aa8UL, 0xf34a1bf3UL, 0x1b151c1bUL, 0x40fa1d40UL, 0xada21eadUL, 0xf64d1ff6UL, 
+0x28382028UL, 0x73d72173UL, 0x9e8f229eUL, 0xc56023c5UL, 0x2d3f242dUL, 0x76d02576UL, 0x9b88269bUL, 0xc06727c0UL, 
+0x22362822UL, 0x79d92979UL, 0x94812a94UL, 0xcf6e2bcfUL, 0x27312c27UL, 0x7cde2d7cUL, 0x91862e91UL, 0xca692fcaUL, 
+0x3c24303cUL, 0x67cb3167UL, 0x8a93328aUL, 0xd17c33d1UL, 0x39233439UL, 0x62cc3562UL, 0x8f94368fUL, 0xd47b37d4UL, 
+0x362a3836UL, 0x6dc5396dUL, 0x809d3a80UL, 0xdb723bdbUL, 0x332d3c33UL, 0x68c23d68UL, 0x859a3e85UL, 0xde753fdeUL,
+0x50704050UL, 0x0b9f410bUL, 0xe6c742e6UL, 0xbd2843bdUL, 0x55774455UL, 0x0e98450eUL, 0xe3c046e3UL, 0xb82f47b8UL, 
+0x5a7e485aUL, 0x01914901UL, 0xecc94aecUL, 0xb7264bb7UL, 0x5f794c5fUL, 0x04964d04UL, 0xe9ce4ee9UL, 0xb2214fb2UL, 
+0x446c5044UL, 0x1f83511fUL, 0xf2db52f2UL, 0xa93453a9UL, 0x416b5441UL, 0x1a84551aUL, 0xf7dc56f7UL, 0xac3357acUL, 
+0x4e62584eUL, 0x158d5915UL, 0xf8d55af8UL, 0xa33a5ba3UL, 0x4b655c4bUL, 0x108a5d10UL, 0xfdd25efdUL, 0xa63d5fa6UL, 
+0x78486078UL, 0x23a76123UL, 0xceff62ceUL, 0x95106395UL, 0x7d4f647dUL, 0x26a06526UL, 0xcbf866cbUL, 0x90176790UL, 
+0x72466872UL, 0x29a96929UL, 0xc4f16ac4UL, 0x9f1e6b9fUL, 0x77416c77UL, 0x2cae6d2cUL, 0xc1f66ec1UL, 0x9a196f9aUL, 
+0x6c54706cUL, 0x37bb7137UL, 0xdae372daUL, 0x810c7381UL, 0x69537469UL, 0x32bc7532UL, 0xdfe476dfUL, 0x840b7784UL, 
+0x665a7866UL, 0x3db5793dUL, 0xd0ed7ad0UL, 0x8b027b8bUL, 0x635d7c63UL, 0x38b27d38UL, 0xd5ea7ed5UL, 0x8e057f8eUL, 
+0xa0e080a0UL, 0xfb0f81fbUL, 0x16578216UL, 0x4db8834dUL, 0xa5e784a5UL, 0xfe0885feUL, 0x13508613UL, 0x48bf8748UL, 
+0xaaee88aaUL, 0xf10189f1UL, 0x1c598a1cUL, 0x47b68b47UL, 0xafe98cafUL, 0xf4068df4UL, 0x195e8e19UL, 0x42b18f42UL,
+0xb4fc90b4UL, 0xef1391efUL, 0x024b9202UL, 0x59a49359UL, 0xb1fb94b1UL, 0xea1495eaUL, 0x074c9607UL, 0x5ca3975cUL, 
+0xbef298beUL, 0xe51d99e5UL, 0x08459a08UL, 0x53aa9b53UL, 0xbbf59cbbUL, 0xe01a9de0UL, 0x0d429e0dUL, 0x56ad9f56UL, 
+0x88d8a088UL, 0xd337a1d3UL, 0x3e6fa23eUL, 0x6580a365UL, 0x8ddfa48dUL, 0xd630a5d6UL, 0x3b68a63bUL, 0x6087a760UL, 
+0x82d6a882UL, 0xd939a9d9UL, 0x3461aa34UL, 0x6f8eab6fUL, 0x87d1ac87UL, 0xdc3eaddcUL, 0x3166ae31UL, 0x6a89af6aUL, 
+0x9cc4b09cUL, 0xc72bb1c7UL, 0x2a73b22aUL, 0x719cb371UL, 0x99c3b499UL, 0xc22cb5c2UL, 0x2f74b62fUL, 0x749bb774UL, 
+0x96cab896UL, 0xcd25b9cdUL, 0x207dba20UL, 0x7b92bb7bUL, 0x93cdbc93UL, 0xc822bdc8UL, 0x257abe25UL, 0x7e95bf7eUL,
+0xf090c0f0UL, 0xab7fc1abUL, 0x4627c246UL, 0x1dc8c31dUL, 0xf597c4f5UL, 0xae78c5aeUL, 0x4320c643UL, 0x18cfc718UL, 
+0xfa9ec8faUL, 0xa171c9a1UL, 0x4c29ca4cUL, 0x17c6cb17UL, 0xff99ccffUL, 0xa476cda4UL, 0x492ece49UL, 0x12c1cf12UL, 
+0xe48cd0e4UL, 0xbf63d1bfUL, 0x523bd252UL, 0x09d4d309UL, 0xe18bd4e1UL, 0xba64d5baUL, 0x573cd657UL, 0x0cd3d70cUL, 
+0xee82d8eeUL, 0xb56dd9b5UL, 0x5835da58UL, 0x03dadb03UL, 0xeb85dcebUL, 0xb06addb0UL, 0x5d32de5dUL, 0x06dddf06UL, 
+0xd8a8e0d8UL, 0x8347e183UL, 0x6e1fe26eUL, 0x35f0e335UL, 0xddafe4ddUL, 0x8640e586UL, 0x6b18e66bUL, 0x30f7e730UL, 
+0xd2a6e8d2UL, 0x8949e989UL, 0x6411ea64UL, 0x3ffeeb3fUL, 0xd7a1ecd7UL, 0x8c4eed8cUL, 0x6116ee61UL, 0x3af9ef3aUL,
+0xccb4f0ccUL, 0x975bf197UL, 0x7a03f27aUL, 0x21ecf321UL, 0xc9b3f4c9UL, 0x925cf592UL, 0x7f04f67fUL, 0x24ebf724UL, 
+0xc6baf8c6UL, 0x9d55f99dUL, 0x700dfa70UL, 0x2be2fb2bUL, 0xc3bdfcc3UL, 0x9852fd98UL, 0x750afe75UL, 0x2ee5ff2eUL
+}};
+
+#ifdef TWOFISH_ALL_TABLES
+
+/* the 4x8 RS transform */
+static const ulong32 rs_tab0[256] = {
+0x00000000LU, 0xa402a401LU, 0x05040502LU, 0xa106a103LU, 0x0a080a04LU, 0xae0aae05LU, 0x0f0c0f06LU, 0xab0eab07LU, 
+0x14101408LU, 0xb012b009LU, 0x1114110aLU, 0xb516b50bLU, 0x1e181e0cLU, 0xba1aba0dLU, 0x1b1c1b0eLU, 0xbf1ebf0fLU, 
+0x28202810LU, 0x8c228c11LU, 0x2d242d12LU, 0x89268913LU, 0x22282214LU, 0x862a8615LU, 0x272c2716LU, 0x832e8317LU, 
+0x3c303c18LU, 0x98329819LU, 0x3934391aLU, 0x9d369d1bLU, 0x3638361cLU, 0x923a921dLU, 0x333c331eLU, 0x973e971fLU, 
+0x50405020LU, 0xf442f421LU, 0x55445522LU, 0xf146f123LU, 0x5a485a24LU, 0xfe4afe25LU, 0x5f4c5f26LU, 0xfb4efb27LU, 
+0x44504428LU, 0xe052e029LU, 0x4154412aLU, 0xe556e52bLU, 0x4e584e2cLU, 0xea5aea2dLU, 0x4b5c4b2eLU, 0xef5eef2fLU, 
+0x78607830LU, 0xdc62dc31LU, 0x7d647d32LU, 0xd966d933LU, 0x72687234LU, 0xd66ad635LU, 0x776c7736LU, 0xd36ed337LU, 
+0x6c706c38LU, 0xc872c839LU, 0x6974693aLU, 0xcd76cd3bLU, 0x6678663cLU, 0xc27ac23dLU, 0x637c633eLU, 0xc77ec73fLU, 
+0xa080a040LU, 0x04820441LU, 0xa584a542LU, 0x01860143LU, 0xaa88aa44LU, 0x0e8a0e45LU, 0xaf8caf46LU, 0x0b8e0b47LU, 
+0xb490b448LU, 0x10921049LU, 0xb194b14aLU, 0x1596154bLU, 0xbe98be4cLU, 0x1a9a1a4dLU, 0xbb9cbb4eLU, 0x1f9e1f4fLU, 
+0x88a08850LU, 0x2ca22c51LU, 0x8da48d52LU, 0x29a62953LU, 0x82a88254LU, 0x26aa2655LU, 0x87ac8756LU, 0x23ae2357LU, 
+0x9cb09c58LU, 0x38b23859LU, 0x99b4995aLU, 0x3db63d5bLU, 0x96b8965cLU, 0x32ba325dLU, 0x93bc935eLU, 0x37be375fLU, 
+0xf0c0f060LU, 0x54c25461LU, 0xf5c4f562LU, 0x51c65163LU, 0xfac8fa64LU, 0x5eca5e65LU, 0xffccff66LU, 0x5bce5b67LU, 
+0xe4d0e468LU, 0x40d24069LU, 0xe1d4e16aLU, 0x45d6456bLU, 0xeed8ee6cLU, 0x4ada4a6dLU, 0xebdceb6eLU, 0x4fde4f6fLU, 
+0xd8e0d870LU, 0x7ce27c71LU, 0xdde4dd72LU, 0x79e67973LU, 0xd2e8d274LU, 0x76ea7675LU, 0xd7ecd776LU, 0x73ee7377LU, 
+0xccf0cc78LU, 0x68f26879LU, 0xc9f4c97aLU, 0x6df66d7bLU, 0xc6f8c67cLU, 0x62fa627dLU, 0xc3fcc37eLU, 0x67fe677fLU, 
+0x0d4d0d80LU, 0xa94fa981LU, 0x08490882LU, 0xac4bac83LU, 0x07450784LU, 0xa347a385LU, 0x02410286LU, 0xa643a687LU, 
+0x195d1988LU, 0xbd5fbd89LU, 0x1c591c8aLU, 0xb85bb88bLU, 0x1355138cLU, 0xb757b78dLU, 0x1651168eLU, 0xb253b28fLU, 
+0x256d2590LU, 0x816f8191LU, 0x20692092LU, 0x846b8493LU, 0x2f652f94LU, 0x8b678b95LU, 0x2a612a96LU, 0x8e638e97LU, 
+0x317d3198LU, 0x957f9599LU, 0x3479349aLU, 0x907b909bLU, 0x3b753b9cLU, 0x9f779f9dLU, 0x3e713e9eLU, 0x9a739a9fLU, 
+0x5d0d5da0LU, 0xf90ff9a1LU, 0x580958a2LU, 0xfc0bfca3LU, 0x570557a4LU, 0xf307f3a5LU, 0x520152a6LU, 0xf603f6a7LU, 
+0x491d49a8LU, 0xed1feda9LU, 0x4c194caaLU, 0xe81be8abLU, 0x431543acLU, 0xe717e7adLU, 0x461146aeLU, 0xe213e2afLU, 
+0x752d75b0LU, 0xd12fd1b1LU, 0x702970b2LU, 0xd42bd4b3LU, 0x7f257fb4LU, 0xdb27dbb5LU, 0x7a217ab6LU, 0xde23deb7LU, 
+0x613d61b8LU, 0xc53fc5b9LU, 0x643964baLU, 0xc03bc0bbLU, 0x6b356bbcLU, 0xcf37cfbdLU, 0x6e316ebeLU, 0xca33cabfLU, 
+0xadcdadc0LU, 0x09cf09c1LU, 0xa8c9a8c2LU, 0x0ccb0cc3LU, 0xa7c5a7c4LU, 0x03c703c5LU, 0xa2c1a2c6LU, 0x06c306c7LU, 
+0xb9ddb9c8LU, 0x1ddf1dc9LU, 0xbcd9bccaLU, 0x18db18cbLU, 0xb3d5b3ccLU, 0x17d717cdLU, 0xb6d1b6ceLU, 0x12d312cfLU, 
+0x85ed85d0LU, 0x21ef21d1LU, 0x80e980d2LU, 0x24eb24d3LU, 0x8fe58fd4LU, 0x2be72bd5LU, 0x8ae18ad6LU, 0x2ee32ed7LU, 
+0x91fd91d8LU, 0x35ff35d9LU, 0x94f994daLU, 0x30fb30dbLU, 0x9bf59bdcLU, 0x3ff73fddLU, 0x9ef19edeLU, 0x3af33adfLU, 
+0xfd8dfde0LU, 0x598f59e1LU, 0xf889f8e2LU, 0x5c8b5ce3LU, 0xf785f7e4LU, 0x538753e5LU, 0xf281f2e6LU, 0x568356e7LU, 
+0xe99de9e8LU, 0x4d9f4de9LU, 0xec99eceaLU, 0x489b48ebLU, 0xe395e3ecLU, 0x479747edLU, 0xe691e6eeLU, 0x429342efLU, 
+0xd5add5f0LU, 0x71af71f1LU, 0xd0a9d0f2LU, 0x74ab74f3LU, 0xdfa5dff4LU, 0x7ba77bf5LU, 0xdaa1daf6LU, 0x7ea37ef7LU, 
+0xc1bdc1f8LU, 0x65bf65f9LU, 0xc4b9c4faLU, 0x60bb60fbLU, 0xcbb5cbfcLU, 0x6fb76ffdLU, 0xceb1cefeLU, 0x6ab36affLU }; 
+
+static const ulong32 rs_tab1[256] = {
+0x00000000LU, 0x55a156a4LU, 0xaa0fac05LU, 0xffaefaa1LU, 0x191e150aLU, 0x4cbf43aeLU, 0xb311b90fLU, 0xe6b0efabLU, 
+0x323c2a14LU, 0x679d7cb0LU, 0x98338611LU, 0xcd92d0b5LU, 0x2b223f1eLU, 0x7e8369baLU, 0x812d931bLU, 0xd48cc5bfLU, 
+0x64785428LU, 0x31d9028cLU, 0xce77f82dLU, 0x9bd6ae89LU, 0x7d664122LU, 0x28c71786LU, 0xd769ed27LU, 0x82c8bb83LU, 
+0x56447e3cLU, 0x03e52898LU, 0xfc4bd239LU, 0xa9ea849dLU, 0x4f5a6b36LU, 0x1afb3d92LU, 0xe555c733LU, 0xb0f49197LU, 
+0xc8f0a850LU, 0x9d51fef4LU, 0x62ff0455LU, 0x375e52f1LU, 0xd1eebd5aLU, 0x844febfeLU, 0x7be1115fLU, 0x2e4047fbLU, 
+0xfacc8244LU, 0xaf6dd4e0LU, 0x50c32e41LU, 0x056278e5LU, 0xe3d2974eLU, 0xb673c1eaLU, 0x49dd3b4bLU, 0x1c7c6defLU, 
+0xac88fc78LU, 0xf929aadcLU, 0x0687507dLU, 0x532606d9LU, 0xb596e972LU, 0xe037bfd6LU, 0x1f994577LU, 0x4a3813d3LU, 
+0x9eb4d66cLU, 0xcb1580c8LU, 0x34bb7a69LU, 0x611a2ccdLU, 0x87aac366LU, 0xd20b95c2LU, 0x2da56f63LU, 0x780439c7LU, 
+0xddad1da0LU, 0x880c4b04LU, 0x77a2b1a5LU, 0x2203e701LU, 0xc4b308aaLU, 0x91125e0eLU, 0x6ebca4afLU, 0x3b1df20bLU, 
+0xef9137b4LU, 0xba306110LU, 0x459e9bb1LU, 0x103fcd15LU, 0xf68f22beLU, 0xa32e741aLU, 0x5c808ebbLU, 0x0921d81fLU, 
+0xb9d54988LU, 0xec741f2cLU, 0x13dae58dLU, 0x467bb329LU, 0xa0cb5c82LU, 0xf56a0a26LU, 0x0ac4f087LU, 0x5f65a623LU, 
+0x8be9639cLU, 0xde483538LU, 0x21e6cf99LU, 0x7447993dLU, 0x92f77696LU, 0xc7562032LU, 0x38f8da93LU, 0x6d598c37LU, 
+0x155db5f0LU, 0x40fce354LU, 0xbf5219f5LU, 0xeaf34f51LU, 0x0c43a0faLU, 0x59e2f65eLU, 0xa64c0cffLU, 0xf3ed5a5bLU, 
+0x27619fe4LU, 0x72c0c940LU, 0x8d6e33e1LU, 0xd8cf6545LU, 0x3e7f8aeeLU, 0x6bdedc4aLU, 0x947026ebLU, 0xc1d1704fLU, 
+0x7125e1d8LU, 0x2484b77cLU, 0xdb2a4dddLU, 0x8e8b1b79LU, 0x683bf4d2LU, 0x3d9aa276LU, 0xc23458d7LU, 0x97950e73LU, 
+0x4319cbccLU, 0x16b89d68LU, 0xe91667c9LU, 0xbcb7316dLU, 0x5a07dec6LU, 0x0fa68862LU, 0xf00872c3LU, 0xa5a92467LU,
+0xf7173a0dLU, 0xa2b66ca9LU, 0x5d189608LU, 0x08b9c0acLU, 0xee092f07LU, 0xbba879a3LU, 0x44068302LU, 0x11a7d5a6LU, 
+0xc52b1019LU, 0x908a46bdLU, 0x6f24bc1cLU, 0x3a85eab8LU, 0xdc350513LU, 0x899453b7LU, 0x763aa916LU, 0x239bffb2LU, 
+0x936f6e25LU, 0xc6ce3881LU, 0x3960c220LU, 0x6cc19484LU, 0x8a717b2fLU, 0xdfd02d8bLU, 0x207ed72aLU, 0x75df818eLU, 
+0xa1534431LU, 0xf4f21295LU, 0x0b5ce834LU, 0x5efdbe90LU, 0xb84d513bLU, 0xedec079fLU, 0x1242fd3eLU, 0x47e3ab9aLU,
+0x3fe7925dLU, 0x6a46c4f9LU, 0x95e83e58LU, 0xc04968fcLU, 0x26f98757LU, 0x7358d1f3LU, 0x8cf62b52LU, 0xd9577df6LU, 
+0x0ddbb849LU, 0x587aeeedLU, 0xa7d4144cLU, 0xf27542e8LU, 0x14c5ad43LU, 0x4164fbe7LU, 0xbeca0146LU, 0xeb6b57e2LU,
+0x5b9fc675LU, 0x0e3e90d1LU, 0xf1906a70LU, 0xa4313cd4LU, 0x4281d37fLU, 0x172085dbLU, 0xe88e7f7aLU, 0xbd2f29deLU, 
+0x69a3ec61LU, 0x3c02bac5LU, 0xc3ac4064LU, 0x960d16c0LU, 0x70bdf96bLU, 0x251cafcfLU, 0xdab2556eLU, 0x8f1303caLU, 
+0x2aba27adLU, 0x7f1b7109LU, 0x80b58ba8LU, 0xd514dd0cLU, 0x33a432a7LU, 0x66056403LU, 0x99ab9ea2LU, 0xcc0ac806LU, 
+0x18860db9LU, 0x4d275b1dLU, 0xb289a1bcLU, 0xe728f718LU, 0x019818b3LU, 0x54394e17LU, 0xab97b4b6LU, 0xfe36e212LU, 
+0x4ec27385LU, 0x1b632521LU, 0xe4cddf80LU, 0xb16c8924LU, 0x57dc668fLU, 0x027d302bLU, 0xfdd3ca8aLU, 0xa8729c2eLU, 
+0x7cfe5991LU, 0x295f0f35LU, 0xd6f1f594LU, 0x8350a330LU, 0x65e04c9bLU, 0x30411a3fLU, 0xcfefe09eLU, 0x9a4eb63aLU, 
+0xe24a8ffdLU, 0xb7ebd959LU, 0x484523f8LU, 0x1de4755cLU, 0xfb549af7LU, 0xaef5cc53LU, 0x515b36f2LU, 0x04fa6056LU, 
+0xd076a5e9LU, 0x85d7f34dLU, 0x7a7909ecLU, 0x2fd85f48LU, 0xc968b0e3LU, 0x9cc9e647LU, 0x63671ce6LU, 0x36c64a42LU, 
+0x8632dbd5LU, 0xd3938d71LU, 0x2c3d77d0LU, 0x799c2174LU, 0x9f2ccedfLU, 0xca8d987bLU, 0x352362daLU, 0x6082347eLU, 
+0xb40ef1c1LU, 0xe1afa765LU, 0x1e015dc4LU, 0x4ba00b60LU, 0xad10e4cbLU, 0xf8b1b26fLU, 0x071f48ceLU, 0x52be1e6aLU }; 
+
+static const ulong32 rs_tab2[256] = {
+0x00000000LU, 0x87fc8255LU, 0x43b549aaLU, 0xc449cbffLU, 0x86279219LU, 0x01db104cLU, 0xc592dbb3LU, 0x426e59e6LU, 
+0x414e6932LU, 0xc6b2eb67LU, 0x02fb2098LU, 0x8507a2cdLU, 0xc769fb2bLU, 0x4095797eLU, 0x84dcb281LU, 0x032030d4LU, 
+0x829cd264LU, 0x05605031LU, 0xc1299bceLU, 0x46d5199bLU, 0x04bb407dLU, 0x8347c228LU, 0x470e09d7LU, 0xc0f28b82LU, 
+0xc3d2bb56LU, 0x442e3903LU, 0x8067f2fcLU, 0x079b70a9LU, 0x45f5294fLU, 0xc209ab1aLU, 0x064060e5LU, 0x81bce2b0LU, 
+0x4975e9c8LU, 0xce896b9dLU, 0x0ac0a062LU, 0x8d3c2237LU, 0xcf527bd1LU, 0x48aef984LU, 0x8ce7327bLU, 0x0b1bb02eLU, 
+0x083b80faLU, 0x8fc702afLU, 0x4b8ec950LU, 0xcc724b05LU, 0x8e1c12e3LU, 0x09e090b6LU, 0xcda95b49LU, 0x4a55d91cLU, 
+0xcbe93bacLU, 0x4c15b9f9LU, 0x885c7206LU, 0x0fa0f053LU, 0x4dcea9b5LU, 0xca322be0LU, 0x0e7be01fLU, 0x8987624aLU, 
+0x8aa7529eLU, 0x0d5bd0cbLU, 0xc9121b34LU, 0x4eee9961LU, 0x0c80c087LU, 0x8b7c42d2LU, 0x4f35892dLU, 0xc8c90b78LU, 
+0x92ea9fddLU, 0x15161d88LU, 0xd15fd677LU, 0x56a35422LU, 0x14cd0dc4LU, 0x93318f91LU, 0x5778446eLU, 0xd084c63bLU, 
+0xd3a4f6efLU, 0x545874baLU, 0x9011bf45LU, 0x17ed3d10LU, 0x558364f6LU, 0xd27fe6a3LU, 0x16362d5cLU, 0x91caaf09LU, 
+0x10764db9LU, 0x978acfecLU, 0x53c30413LU, 0xd43f8646LU, 0x9651dfa0LU, 0x11ad5df5LU, 0xd5e4960aLU, 0x5218145fLU, 
+0x5138248bLU, 0xd6c4a6deLU, 0x128d6d21LU, 0x9571ef74LU, 0xd71fb692LU, 0x50e334c7LU, 0x94aaff38LU, 0x13567d6dLU, 
+0xdb9f7615LU, 0x5c63f440LU, 0x982a3fbfLU, 0x1fd6bdeaLU, 0x5db8e40cLU, 0xda446659LU, 0x1e0dada6LU, 0x99f12ff3LU, 
+0x9ad11f27LU, 0x1d2d9d72LU, 0xd964568dLU, 0x5e98d4d8LU, 0x1cf68d3eLU, 0x9b0a0f6bLU, 0x5f43c494LU, 0xd8bf46c1LU, 
+0x5903a471LU, 0xdeff2624LU, 0x1ab6eddbLU, 0x9d4a6f8eLU, 0xdf243668LU, 0x58d8b43dLU, 0x9c917fc2LU, 0x1b6dfd97LU, 
+0x184dcd43LU, 0x9fb14f16LU, 0x5bf884e9LU, 0xdc0406bcLU, 0x9e6a5f5aLU, 0x1996dd0fLU, 0xdddf16f0LU, 0x5a2394a5LU, 
+0x699973f7LU, 0xee65f1a2LU, 0x2a2c3a5dLU, 0xadd0b808LU, 0xefbee1eeLU, 0x684263bbLU, 0xac0ba844LU, 0x2bf72a11LU, 
+0x28d71ac5LU, 0xaf2b9890LU, 0x6b62536fLU, 0xec9ed13aLU, 0xaef088dcLU, 0x290c0a89LU, 0xed45c176LU, 0x6ab94323LU, 
+0xeb05a193LU, 0x6cf923c6LU, 0xa8b0e839LU, 0x2f4c6a6cLU, 0x6d22338aLU, 0xeadeb1dfLU, 0x2e977a20LU, 0xa96bf875LU, 
+0xaa4bc8a1LU, 0x2db74af4LU, 0xe9fe810bLU, 0x6e02035eLU, 0x2c6c5ab8LU, 0xab90d8edLU, 0x6fd91312LU, 0xe8259147LU, 
+0x20ec9a3fLU, 0xa710186aLU, 0x6359d395LU, 0xe4a551c0LU, 0xa6cb0826LU, 0x21378a73LU, 0xe57e418cLU, 0x6282c3d9LU, 
+0x61a2f30dLU, 0xe65e7158LU, 0x2217baa7LU, 0xa5eb38f2LU, 0xe7856114LU, 0x6079e341LU, 0xa43028beLU, 0x23ccaaebLU, 
+0xa270485bLU, 0x258cca0eLU, 0xe1c501f1LU, 0x663983a4LU, 0x2457da42LU, 0xa3ab5817LU, 0x67e293e8LU, 0xe01e11bdLU, 
+0xe33e2169LU, 0x64c2a33cLU, 0xa08b68c3LU, 0x2777ea96LU, 0x6519b370LU, 0xe2e53125LU, 0x26acfadaLU, 0xa150788fLU, 
+0xfb73ec2aLU, 0x7c8f6e7fLU, 0xb8c6a580LU, 0x3f3a27d5LU, 0x7d547e33LU, 0xfaa8fc66LU, 0x3ee13799LU, 0xb91db5ccLU, 
+0xba3d8518LU, 0x3dc1074dLU, 0xf988ccb2LU, 0x7e744ee7LU, 0x3c1a1701LU, 0xbbe69554LU, 0x7faf5eabLU, 0xf853dcfeLU, 
+0x79ef3e4eLU, 0xfe13bc1bLU, 0x3a5a77e4LU, 0xbda6f5b1LU, 0xffc8ac57LU, 0x78342e02LU, 0xbc7de5fdLU, 0x3b8167a8LU, 
+0x38a1577cLU, 0xbf5dd529LU, 0x7b141ed6LU, 0xfce89c83LU, 0xbe86c565LU, 0x397a4730LU, 0xfd338ccfLU, 0x7acf0e9aLU, 
+0xb20605e2LU, 0x35fa87b7LU, 0xf1b34c48LU, 0x764fce1dLU, 0x342197fbLU, 0xb3dd15aeLU, 0x7794de51LU, 0xf0685c04LU, 
+0xf3486cd0LU, 0x74b4ee85LU, 0xb0fd257aLU, 0x3701a72fLU, 0x756ffec9LU, 0xf2937c9cLU, 0x36dab763LU, 0xb1263536LU, 
+0x309ad786LU, 0xb76655d3LU, 0x732f9e2cLU, 0xf4d31c79LU, 0xb6bd459fLU, 0x3141c7caLU, 0xf5080c35LU, 0x72f48e60LU, 
+0x71d4beb4LU, 0xf6283ce1LU, 0x3261f71eLU, 0xb59d754bLU, 0xf7f32cadLU, 0x700faef8LU, 0xb4466507LU, 0x33bae752LU }; 
+
+static const ulong32 rs_tab3[256] = {
+0x00000000LU, 0x5ac1f387LU, 0xb4cfab43LU, 0xee0e58c4LU, 0x25d31b86LU, 0x7f12e801LU, 0x911cb0c5LU, 0xcbdd4342LU, 
+0x4aeb3641LU, 0x102ac5c6LU, 0xfe249d02LU, 0xa4e56e85LU, 0x6f382dc7LU, 0x35f9de40LU, 0xdbf78684LU, 0x81367503LU, 
+0x949b6c82LU, 0xce5a9f05LU, 0x2054c7c1LU, 0x7a953446LU, 0xb1487704LU, 0xeb898483LU, 0x0587dc47LU, 0x5f462fc0LU, 
+0xde705ac3LU, 0x84b1a944LU, 0x6abff180LU, 0x307e0207LU, 0xfba34145LU, 0xa162b2c2LU, 0x4f6cea06LU, 0x15ad1981LU,
+0x657bd849LU, 0x3fba2bceLU, 0xd1b4730aLU, 0x8b75808dLU, 0x40a8c3cfLU, 0x1a693048LU, 0xf467688cLU, 0xaea69b0bLU, 
+0x2f90ee08LU, 0x75511d8fLU, 0x9b5f454bLU, 0xc19eb6ccLU, 0x0a43f58eLU, 0x50820609LU, 0xbe8c5ecdLU, 0xe44dad4aLU, 
+0xf1e0b4cbLU, 0xab21474cLU, 0x452f1f88LU, 0x1feeec0fLU, 0xd433af4dLU, 0x8ef25ccaLU, 0x60fc040eLU, 0x3a3df789LU, 
+0xbb0b828aLU, 0xe1ca710dLU, 0x0fc429c9LU, 0x5505da4eLU, 0x9ed8990cLU, 0xc4196a8bLU, 0x2a17324fLU, 0x70d6c1c8LU, 
+0xcaf6fd92LU, 0x90370e15LU, 0x7e3956d1LU, 0x24f8a556LU, 0xef25e614LU, 0xb5e41593LU, 0x5bea4d57LU, 0x012bbed0LU, 
+0x801dcbd3LU, 0xdadc3854LU, 0x34d26090LU, 0x6e139317LU, 0xa5ced055LU, 0xff0f23d2LU, 0x11017b16LU, 0x4bc08891LU,
+0x5e6d9110LU, 0x04ac6297LU, 0xeaa23a53LU, 0xb063c9d4LU, 0x7bbe8a96LU, 0x217f7911LU, 0xcf7121d5LU, 0x95b0d252LU, 
+0x1486a751LU, 0x4e4754d6LU, 0xa0490c12LU, 0xfa88ff95LU, 0x3155bcd7LU, 0x6b944f50LU, 0x859a1794LU, 0xdf5be413LU, 
+0xaf8d25dbLU, 0xf54cd65cLU, 0x1b428e98LU, 0x41837d1fLU, 0x8a5e3e5dLU, 0xd09fcddaLU, 0x3e91951eLU, 0x64506699LU,
+0xe566139aLU, 0xbfa7e01dLU, 0x51a9b8d9LU, 0x0b684b5eLU, 0xc0b5081cLU, 0x9a74fb9bLU, 0x747aa35fLU, 0x2ebb50d8LU, 
+0x3b164959LU, 0x61d7badeLU, 0x8fd9e21aLU, 0xd518119dLU, 0x1ec552dfLU, 0x4404a158LU, 0xaa0af99cLU, 0xf0cb0a1bLU, 
+0x71fd7f18LU, 0x2b3c8c9fLU, 0xc532d45bLU, 0x9ff327dcLU, 0x542e649eLU, 0x0eef9719LU, 0xe0e1cfddLU, 0xba203c5aLU, 
+0xd9a1b769LU, 0x836044eeLU, 0x6d6e1c2aLU, 0x37afefadLU, 0xfc72acefLU, 0xa6b35f68LU, 0x48bd07acLU, 0x127cf42bLU, 
+0x934a8128LU, 0xc98b72afLU, 0x27852a6bLU, 0x7d44d9ecLU, 0xb6999aaeLU, 0xec586929LU, 0x025631edLU, 0x5897c26aLU, 
+0x4d3adbebLU, 0x17fb286cLU, 0xf9f570a8LU, 0xa334832fLU, 0x68e9c06dLU, 0x322833eaLU, 0xdc266b2eLU, 0x86e798a9LU, 
+0x07d1edaaLU, 0x5d101e2dLU, 0xb31e46e9LU, 0xe9dfb56eLU, 0x2202f62cLU, 0x78c305abLU, 0x96cd5d6fLU, 0xcc0caee8LU, 
+0xbcda6f20LU, 0xe61b9ca7LU, 0x0815c463LU, 0x52d437e4LU, 0x990974a6LU, 0xc3c88721LU, 0x2dc6dfe5LU, 0x77072c62LU, 
+0xf6315961LU, 0xacf0aae6LU, 0x42fef222LU, 0x183f01a5LU, 0xd3e242e7LU, 0x8923b160LU, 0x672de9a4LU, 0x3dec1a23LU, 
+0x284103a2LU, 0x7280f025LU, 0x9c8ea8e1LU, 0xc64f5b66LU, 0x0d921824LU, 0x5753eba3LU, 0xb95db367LU, 0xe39c40e0LU, 
+0x62aa35e3LU, 0x386bc664LU, 0xd6659ea0LU, 0x8ca46d27LU, 0x47792e65LU, 0x1db8dde2LU, 0xf3b68526LU, 0xa97776a1LU, 
+0x13574afbLU, 0x4996b97cLU, 0xa798e1b8LU, 0xfd59123fLU, 0x3684517dLU, 0x6c45a2faLU, 0x824bfa3eLU, 0xd88a09b9LU, 
+0x59bc7cbaLU, 0x037d8f3dLU, 0xed73d7f9LU, 0xb7b2247eLU, 0x7c6f673cLU, 0x26ae94bbLU, 0xc8a0cc7fLU, 0x92613ff8LU, 
+0x87cc2679LU, 0xdd0dd5feLU, 0x33038d3aLU, 0x69c27ebdLU, 0xa21f3dffLU, 0xf8dece78LU, 0x16d096bcLU, 0x4c11653bLU, 
+0xcd271038LU, 0x97e6e3bfLU, 0x79e8bb7bLU, 0x232948fcLU, 0xe8f40bbeLU, 0xb235f839LU, 0x5c3ba0fdLU, 0x06fa537aLU, 
+0x762c92b2LU, 0x2ced6135LU, 0xc2e339f1LU, 0x9822ca76LU, 0x53ff8934LU, 0x093e7ab3LU, 0xe7302277LU, 0xbdf1d1f0LU, 
+0x3cc7a4f3LU, 0x66065774LU, 0x88080fb0LU, 0xd2c9fc37LU, 0x1914bf75LU, 0x43d54cf2LU, 0xaddb1436LU, 0xf71ae7b1LU, 
+0xe2b7fe30LU, 0xb8760db7LU, 0x56785573LU, 0x0cb9a6f4LU, 0xc764e5b6LU, 0x9da51631LU, 0x73ab4ef5LU, 0x296abd72LU, 
+0xa85cc871LU, 0xf29d3bf6LU, 0x1c936332LU, 0x465290b5LU, 0x8d8fd3f7LU, 0xd74e2070LU, 0x394078b4LU, 0x63818b33LU }; 
+
+static const ulong32 rs_tab4[256] = {
+0x00000000LU, 0x58471e5aLU, 0xb08e3cb4LU, 0xe8c922eeLU, 0x2d517825LU, 0x7516667fLU, 0x9ddf4491LU, 0xc5985acbLU, 
+0x5aa2f04aLU, 0x02e5ee10LU, 0xea2cccfeLU, 0xb26bd2a4LU, 0x77f3886fLU, 0x2fb49635LU, 0xc77db4dbLU, 0x9f3aaa81LU, 
+0xb409ad94LU, 0xec4eb3ceLU, 0x04879120LU, 0x5cc08f7aLU, 0x9958d5b1LU, 0xc11fcbebLU, 0x29d6e905LU, 0x7191f75fLU, 
+0xeeab5ddeLU, 0xb6ec4384LU, 0x5e25616aLU, 0x06627f30LU, 0xc3fa25fbLU, 0x9bbd3ba1LU, 0x7374194fLU, 0x2b330715LU, 
+0x25121765LU, 0x7d55093fLU, 0x959c2bd1LU, 0xcddb358bLU, 0x08436f40LU, 0x5004711aLU, 0xb8cd53f4LU, 0xe08a4daeLU, 
+0x7fb0e72fLU, 0x27f7f975LU, 0xcf3edb9bLU, 0x9779c5c1LU, 0x52e19f0aLU, 0x0aa68150LU, 0xe26fa3beLU, 0xba28bde4LU, 
+0x911bbaf1LU, 0xc95ca4abLU, 0x21958645LU, 0x79d2981fLU, 0xbc4ac2d4LU, 0xe40ddc8eLU, 0x0cc4fe60LU, 0x5483e03aLU, 
+0xcbb94abbLU, 0x93fe54e1LU, 0x7b37760fLU, 0x23706855LU, 0xe6e8329eLU, 0xbeaf2cc4LU, 0x56660e2aLU, 0x0e211070LU, 
+0x4a242ecaLU, 0x12633090LU, 0xfaaa127eLU, 0xa2ed0c24LU, 0x677556efLU, 0x3f3248b5LU, 0xd7fb6a5bLU, 0x8fbc7401LU, 
+0x1086de80LU, 0x48c1c0daLU, 0xa008e234LU, 0xf84ffc6eLU, 0x3dd7a6a5LU, 0x6590b8ffLU, 0x8d599a11LU, 0xd51e844bLU, 
+0xfe2d835eLU, 0xa66a9d04LU, 0x4ea3bfeaLU, 0x16e4a1b0LU, 0xd37cfb7bLU, 0x8b3be521LU, 0x63f2c7cfLU, 0x3bb5d995LU, 
+0xa48f7314LU, 0xfcc86d4eLU, 0x14014fa0LU, 0x4c4651faLU, 0x89de0b31LU, 0xd199156bLU, 0x39503785LU, 0x611729dfLU, 
+0x6f3639afLU, 0x377127f5LU, 0xdfb8051bLU, 0x87ff1b41LU, 0x4267418aLU, 0x1a205fd0LU, 0xf2e97d3eLU, 0xaaae6364LU, 
+0x3594c9e5LU, 0x6dd3d7bfLU, 0x851af551LU, 0xdd5deb0bLU, 0x18c5b1c0LU, 0x4082af9aLU, 0xa84b8d74LU, 0xf00c932eLU, 
+0xdb3f943bLU, 0x83788a61LU, 0x6bb1a88fLU, 0x33f6b6d5LU, 0xf66eec1eLU, 0xae29f244LU, 0x46e0d0aaLU, 0x1ea7cef0LU, 
+0x819d6471LU, 0xd9da7a2bLU, 0x311358c5LU, 0x6954469fLU, 0xaccc1c54LU, 0xf48b020eLU, 0x1c4220e0LU, 0x44053ebaLU, 
+0x94485cd9LU, 0xcc0f4283LU, 0x24c6606dLU, 0x7c817e37LU, 0xb91924fcLU, 0xe15e3aa6LU, 0x09971848LU, 0x51d00612LU, 
+0xceeaac93LU, 0x96adb2c9LU, 0x7e649027LU, 0x26238e7dLU, 0xe3bbd4b6LU, 0xbbfccaecLU, 0x5335e802LU, 0x0b72f658LU, 
+0x2041f14dLU, 0x7806ef17LU, 0x90cfcdf9LU, 0xc888d3a3LU, 0x0d108968LU, 0x55579732LU, 0xbd9eb5dcLU, 0xe5d9ab86LU, 
+0x7ae30107LU, 0x22a41f5dLU, 0xca6d3db3LU, 0x922a23e9LU, 0x57b27922LU, 0x0ff56778LU, 0xe73c4596LU, 0xbf7b5bccLU, 
+0xb15a4bbcLU, 0xe91d55e6LU, 0x01d47708LU, 0x59936952LU, 0x9c0b3399LU, 0xc44c2dc3LU, 0x2c850f2dLU, 0x74c21177LU, 
+0xebf8bbf6LU, 0xb3bfa5acLU, 0x5b768742LU, 0x03319918LU, 0xc6a9c3d3LU, 0x9eeedd89LU, 0x7627ff67LU, 0x2e60e13dLU, 
+0x0553e628LU, 0x5d14f872LU, 0xb5ddda9cLU, 0xed9ac4c6LU, 0x28029e0dLU, 0x70458057LU, 0x988ca2b9LU, 0xc0cbbce3LU, 
+0x5ff11662LU, 0x07b60838LU, 0xef7f2ad6LU, 0xb738348cLU, 0x72a06e47LU, 0x2ae7701dLU, 0xc22e52f3LU, 0x9a694ca9LU, 
+0xde6c7213LU, 0x862b6c49LU, 0x6ee24ea7LU, 0x36a550fdLU, 0xf33d0a36LU, 0xab7a146cLU, 0x43b33682LU, 0x1bf428d8LU, 
+0x84ce8259LU, 0xdc899c03LU, 0x3440beedLU, 0x6c07a0b7LU, 0xa99ffa7cLU, 0xf1d8e426LU, 0x1911c6c8LU, 0x4156d892LU,
+0x6a65df87LU, 0x3222c1ddLU, 0xdaebe333LU, 0x82acfd69LU, 0x4734a7a2LU, 0x1f73b9f8LU, 0xf7ba9b16LU, 0xaffd854cLU, 
+0x30c72fcdLU, 0x68803197LU, 0x80491379LU, 0xd80e0d23LU, 0x1d9657e8LU, 0x45d149b2LU, 0xad186b5cLU, 0xf55f7506LU, 
+0xfb7e6576LU, 0xa3397b2cLU, 0x4bf059c2LU, 0x13b74798LU, 0xd62f1d53LU, 0x8e680309LU, 0x66a121e7LU, 0x3ee63fbdLU, 
+0xa1dc953cLU, 0xf99b8b66LU, 0x1152a988LU, 0x4915b7d2LU, 0x8c8ded19LU, 0xd4caf343LU, 0x3c03d1adLU, 0x6444cff7LU, 
+0x4f77c8e2LU, 0x1730d6b8LU, 0xfff9f456LU, 0xa7beea0cLU, 0x6226b0c7LU, 0x3a61ae9dLU, 0xd2a88c73LU, 0x8aef9229LU, 
+0x15d538a8LU, 0x4d9226f2LU, 0xa55b041cLU, 0xfd1c1a46LU, 0x3884408dLU, 0x60c35ed7LU, 0x880a7c39LU, 0xd04d6263LU };
+
+static const ulong32 rs_tab5[256] = {
+0x00000000LU, 0xdbaec658LU, 0xfb11c1b0LU, 0x20bf07e8LU, 0xbb22cf2dLU, 0x608c0975LU, 0x40330e9dLU, 0x9b9dc8c5LU, 
+0x3b44d35aLU, 0xe0ea1502LU, 0xc05512eaLU, 0x1bfbd4b2LU, 0x80661c77LU, 0x5bc8da2fLU, 0x7b77ddc7LU, 0xa0d91b9fLU, 
+0x7688ebb4LU, 0xad262decLU, 0x8d992a04LU, 0x5637ec5cLU, 0xcdaa2499LU, 0x1604e2c1LU, 0x36bbe529LU, 0xed152371LU, 
+0x4dcc38eeLU, 0x9662feb6LU, 0xb6ddf95eLU, 0x6d733f06LU, 0xf6eef7c3LU, 0x2d40319bLU, 0x0dff3673LU, 0xd651f02bLU, 
+0xec5d9b25LU, 0x37f35d7dLU, 0x174c5a95LU, 0xcce29ccdLU, 0x577f5408LU, 0x8cd19250LU, 0xac6e95b8LU, 0x77c053e0LU, 
+0xd719487fLU, 0x0cb78e27LU, 0x2c0889cfLU, 0xf7a64f97LU, 0x6c3b8752LU, 0xb795410aLU, 0x972a46e2LU, 0x4c8480baLU, 
+0x9ad57091LU, 0x417bb6c9LU, 0x61c4b121LU, 0xba6a7779LU, 0x21f7bfbcLU, 0xfa5979e4LU, 0xdae67e0cLU, 0x0148b854LU, 
+0xa191a3cbLU, 0x7a3f6593LU, 0x5a80627bLU, 0x812ea423LU, 0x1ab36ce6LU, 0xc11daabeLU, 0xe1a2ad56LU, 0x3a0c6b0eLU, 
+0x95ba7b4aLU, 0x4e14bd12LU, 0x6eabbafaLU, 0xb5057ca2LU, 0x2e98b467LU, 0xf536723fLU, 0xd58975d7LU, 0x0e27b38fLU, 
+0xaefea810LU, 0x75506e48LU, 0x55ef69a0LU, 0x8e41aff8LU, 0x15dc673dLU, 0xce72a165LU, 0xeecda68dLU, 0x356360d5LU, 
+0xe33290feLU, 0x389c56a6LU, 0x1823514eLU, 0xc38d9716LU, 0x58105fd3LU, 0x83be998bLU, 0xa3019e63LU, 0x78af583bLU, 
+0xd87643a4LU, 0x03d885fcLU, 0x23678214LU, 0xf8c9444cLU, 0x63548c89LU, 0xb8fa4ad1LU, 0x98454d39LU, 0x43eb8b61LU, 
+0x79e7e06fLU, 0xa2492637LU, 0x82f621dfLU, 0x5958e787LU, 0xc2c52f42LU, 0x196be91aLU, 0x39d4eef2LU, 0xe27a28aaLU, 
+0x42a33335LU, 0x990df56dLU, 0xb9b2f285LU, 0x621c34ddLU, 0xf981fc18LU, 0x222f3a40LU, 0x02903da8LU, 0xd93efbf0LU, 
+0x0f6f0bdbLU, 0xd4c1cd83LU, 0xf47eca6bLU, 0x2fd00c33LU, 0xb44dc4f6LU, 0x6fe302aeLU, 0x4f5c0546LU, 0x94f2c31eLU, 
+0x342bd881LU, 0xef851ed9LU, 0xcf3a1931LU, 0x1494df69LU, 0x8f0917acLU, 0x54a7d1f4LU, 0x7418d61cLU, 0xafb61044LU, 
+0x6739f694LU, 0xbc9730ccLU, 0x9c283724LU, 0x4786f17cLU, 0xdc1b39b9LU, 0x07b5ffe1LU, 0x270af809LU, 0xfca43e51LU, 
+0x5c7d25ceLU, 0x87d3e396LU, 0xa76ce47eLU, 0x7cc22226LU, 0xe75feae3LU, 0x3cf12cbbLU, 0x1c4e2b53LU, 0xc7e0ed0bLU, 
+0x11b11d20LU, 0xca1fdb78LU, 0xeaa0dc90LU, 0x310e1ac8LU, 0xaa93d20dLU, 0x713d1455LU, 0x518213bdLU, 0x8a2cd5e5LU, 
+0x2af5ce7aLU, 0xf15b0822LU, 0xd1e40fcaLU, 0x0a4ac992LU, 0x91d70157LU, 0x4a79c70fLU, 0x6ac6c0e7LU, 0xb16806bfLU, 
+0x8b646db1LU, 0x50caabe9LU, 0x7075ac01LU, 0xabdb6a59LU, 0x3046a29cLU, 0xebe864c4LU, 0xcb57632cLU, 0x10f9a574LU, 
+0xb020beebLU, 0x6b8e78b3LU, 0x4b317f5bLU, 0x909fb903LU, 0x0b0271c6LU, 0xd0acb79eLU, 0xf013b076LU, 0x2bbd762eLU, 
+0xfdec8605LU, 0x2642405dLU, 0x06fd47b5LU, 0xdd5381edLU, 0x46ce4928LU, 0x9d608f70LU, 0xbddf8898LU, 0x66714ec0LU, 
+0xc6a8555fLU, 0x1d069307LU, 0x3db994efLU, 0xe61752b7LU, 0x7d8a9a72LU, 0xa6245c2aLU, 0x869b5bc2LU, 0x5d359d9aLU, 
+0xf2838ddeLU, 0x292d4b86LU, 0x09924c6eLU, 0xd23c8a36LU, 0x49a142f3LU, 0x920f84abLU, 0xb2b08343LU, 0x691e451bLU, 
+0xc9c75e84LU, 0x126998dcLU, 0x32d69f34LU, 0xe978596cLU, 0x72e591a9LU, 0xa94b57f1LU, 0x89f45019LU, 0x525a9641LU, 
+0x840b666aLU, 0x5fa5a032LU, 0x7f1aa7daLU, 0xa4b46182LU, 0x3f29a947LU, 0xe4876f1fLU, 0xc43868f7LU, 0x1f96aeafLU, 
+0xbf4fb530LU, 0x64e17368LU, 0x445e7480LU, 0x9ff0b2d8LU, 0x046d7a1dLU, 0xdfc3bc45LU, 0xff7cbbadLU, 0x24d27df5LU, 
+0x1ede16fbLU, 0xc570d0a3LU, 0xe5cfd74bLU, 0x3e611113LU, 0xa5fcd9d6LU, 0x7e521f8eLU, 0x5eed1866LU, 0x8543de3eLU, 
+0x259ac5a1LU, 0xfe3403f9LU, 0xde8b0411LU, 0x0525c249LU, 0x9eb80a8cLU, 0x4516ccd4LU, 0x65a9cb3cLU, 0xbe070d64LU, 
+0x6856fd4fLU, 0xb3f83b17LU, 0x93473cffLU, 0x48e9faa7LU, 0xd3743262LU, 0x08daf43aLU, 0x2865f3d2LU, 0xf3cb358aLU, 
+0x53122e15LU, 0x88bce84dLU, 0xa803efa5LU, 0x73ad29fdLU, 0xe830e138LU, 0x339e2760LU, 0x13212088LU, 0xc88fe6d0LU }; 
+
+static const ulong32 rs_tab6[256] = {
+0x00000000LU, 0x9e3d68dbLU, 0x717ad0fbLU, 0xef47b820LU, 0xe2f4edbbLU, 0x7cc98560LU, 0x938e3d40LU, 0x0db3559bLU, 
+0x89a5973bLU, 0x1798ffe0LU, 0xf8df47c0LU, 0x66e22f1bLU, 0x6b517a80LU, 0xf56c125bLU, 0x1a2baa7bLU, 0x8416c2a0LU, 
+0x5f076376LU, 0xc13a0badLU, 0x2e7db38dLU, 0xb040db56LU, 0xbdf38ecdLU, 0x23cee616LU, 0xcc895e36LU, 0x52b436edLU, 
+0xd6a2f44dLU, 0x489f9c96LU, 0xa7d824b6LU, 0x39e54c6dLU, 0x345619f6LU, 0xaa6b712dLU, 0x452cc90dLU, 0xdb11a1d6LU, 
+0xbe0ec6ecLU, 0x2033ae37LU, 0xcf741617LU, 0x51497eccLU, 0x5cfa2b57LU, 0xc2c7438cLU, 0x2d80fbacLU, 0xb3bd9377LU, 
+0x37ab51d7LU, 0xa996390cLU, 0x46d1812cLU, 0xd8ece9f7LU, 0xd55fbc6cLU, 0x4b62d4b7LU, 0xa4256c97LU, 0x3a18044cLU, 
+0xe109a59aLU, 0x7f34cd41LU, 0x90737561LU, 0x0e4e1dbaLU, 0x03fd4821LU, 0x9dc020faLU, 0x728798daLU, 0xecbaf001LU, 
+0x68ac32a1LU, 0xf6915a7aLU, 0x19d6e25aLU, 0x87eb8a81LU, 0x8a58df1aLU, 0x1465b7c1LU, 0xfb220fe1LU, 0x651f673aLU, 
+0x311cc195LU, 0xaf21a94eLU, 0x4066116eLU, 0xde5b79b5LU, 0xd3e82c2eLU, 0x4dd544f5LU, 0xa292fcd5LU, 0x3caf940eLU, 
+0xb8b956aeLU, 0x26843e75LU, 0xc9c38655LU, 0x57feee8eLU, 0x5a4dbb15LU, 0xc470d3ceLU, 0x2b376beeLU, 0xb50a0335LU, 
+0x6e1ba2e3LU, 0xf026ca38LU, 0x1f617218LU, 0x815c1ac3LU, 0x8cef4f58LU, 0x12d22783LU, 0xfd959fa3LU, 0x63a8f778LU, 
+0xe7be35d8LU, 0x79835d03LU, 0x96c4e523LU, 0x08f98df8LU, 0x054ad863LU, 0x9b77b0b8LU, 0x74300898LU, 0xea0d6043LU, 
+0x8f120779LU, 0x112f6fa2LU, 0xfe68d782LU, 0x6055bf59LU, 0x6de6eac2LU, 0xf3db8219LU, 0x1c9c3a39LU, 0x82a152e2LU, 
+0x06b79042LU, 0x988af899LU, 0x77cd40b9LU, 0xe9f02862LU, 0xe4437df9LU, 0x7a7e1522LU, 0x9539ad02LU, 0x0b04c5d9LU,
+0xd015640fLU, 0x4e280cd4LU, 0xa16fb4f4LU, 0x3f52dc2fLU, 0x32e189b4LU, 0xacdce16fLU, 0x439b594fLU, 0xdda63194LU, 
+0x59b0f334LU, 0xc78d9befLU, 0x28ca23cfLU, 0xb6f74b14LU, 0xbb441e8fLU, 0x25797654LU, 0xca3ece74LU, 0x5403a6afLU, 
+0x6238cf67LU, 0xfc05a7bcLU, 0x13421f9cLU, 0x8d7f7747LU, 0x80cc22dcLU, 0x1ef14a07LU, 0xf1b6f227LU, 0x6f8b9afcLU, 
+0xeb9d585cLU, 0x75a03087LU, 0x9ae788a7LU, 0x04dae07cLU, 0x0969b5e7LU, 0x9754dd3cLU, 0x7813651cLU, 0xe62e0dc7LU, 
+0x3d3fac11LU, 0xa302c4caLU, 0x4c457ceaLU, 0xd2781431LU, 0xdfcb41aaLU, 0x41f62971LU, 0xaeb19151LU, 0x308cf98aLU, 
+0xb49a3b2aLU, 0x2aa753f1LU, 0xc5e0ebd1LU, 0x5bdd830aLU, 0x566ed691LU, 0xc853be4aLU, 0x2714066aLU, 0xb9296eb1LU,
+0xdc36098bLU, 0x420b6150LU, 0xad4cd970LU, 0x3371b1abLU, 0x3ec2e430LU, 0xa0ff8cebLU, 0x4fb834cbLU, 0xd1855c10LU, 
+0x55939eb0LU, 0xcbaef66bLU, 0x24e94e4bLU, 0xbad42690LU, 0xb767730bLU, 0x295a1bd0LU, 0xc61da3f0LU, 0x5820cb2bLU, 
+0x83316afdLU, 0x1d0c0226LU, 0xf24bba06LU, 0x6c76d2ddLU, 0x61c58746LU, 0xfff8ef9dLU, 0x10bf57bdLU, 0x8e823f66LU, 
+0x0a94fdc6LU, 0x94a9951dLU, 0x7bee2d3dLU, 0xe5d345e6LU, 0xe860107dLU, 0x765d78a6LU, 0x991ac086LU, 0x0727a85dLU, 
+0x53240ef2LU, 0xcd196629LU, 0x225ede09LU, 0xbc63b6d2LU, 0xb1d0e349LU, 0x2fed8b92LU, 0xc0aa33b2LU, 0x5e975b69LU, 
+0xda8199c9LU, 0x44bcf112LU, 0xabfb4932LU, 0x35c621e9LU, 0x38757472LU, 0xa6481ca9LU, 0x490fa489LU, 0xd732cc52LU, 
+0x0c236d84LU, 0x921e055fLU, 0x7d59bd7fLU, 0xe364d5a4LU, 0xeed7803fLU, 0x70eae8e4LU, 0x9fad50c4LU, 0x0190381fLU, 
+0x8586fabfLU, 0x1bbb9264LU, 0xf4fc2a44LU, 0x6ac1429fLU, 0x67721704LU, 0xf94f7fdfLU, 0x1608c7ffLU, 0x8835af24LU, 
+0xed2ac81eLU, 0x7317a0c5LU, 0x9c5018e5LU, 0x026d703eLU, 0x0fde25a5LU, 0x91e34d7eLU, 0x7ea4f55eLU, 0xe0999d85LU, 
+0x648f5f25LU, 0xfab237feLU, 0x15f58fdeLU, 0x8bc8e705LU, 0x867bb29eLU, 0x1846da45LU, 0xf7016265LU, 0x693c0abeLU, 
+0xb22dab68LU, 0x2c10c3b3LU, 0xc3577b93LU, 0x5d6a1348LU, 0x50d946d3LU, 0xcee42e08LU, 0x21a39628LU, 0xbf9efef3LU, 
+0x3b883c53LU, 0xa5b55488LU, 0x4af2eca8LU, 0xd4cf8473LU, 0xd97cd1e8LU, 0x4741b933LU, 0xa8060113LU, 0x363b69c8LU }; 
+
+static const ulong32 rs_tab7[256] = {
+0x00000000LU, 0x0319e59eLU, 0x06328771LU, 0x052b62efLU, 0x0c6443e2LU, 0x0f7da67cLU, 0x0a56c493LU, 0x094f210dLU, 
+0x18c88689LU, 0x1bd16317LU, 0x1efa01f8LU, 0x1de3e466LU, 0x14acc56bLU, 0x17b520f5LU, 0x129e421aLU, 0x1187a784LU, 
+0x30dd415fLU, 0x33c4a4c1LU, 0x36efc62eLU, 0x35f623b0LU, 0x3cb902bdLU, 0x3fa0e723LU, 0x3a8b85ccLU, 0x39926052LU, 
+0x2815c7d6LU, 0x2b0c2248LU, 0x2e2740a7LU, 0x2d3ea539LU, 0x24718434LU, 0x276861aaLU, 0x22430345LU, 0x215ae6dbLU, 
+0x60f782beLU, 0x63ee6720LU, 0x66c505cfLU, 0x65dce051LU, 0x6c93c15cLU, 0x6f8a24c2LU, 0x6aa1462dLU, 0x69b8a3b3LU, 
+0x783f0437LU, 0x7b26e1a9LU, 0x7e0d8346LU, 0x7d1466d8LU, 0x745b47d5LU, 0x7742a24bLU, 0x7269c0a4LU, 0x7170253aLU, 
+0x502ac3e1LU, 0x5333267fLU, 0x56184490LU, 0x5501a10eLU, 0x5c4e8003LU, 0x5f57659dLU, 0x5a7c0772LU, 0x5965e2ecLU, 
+0x48e24568LU, 0x4bfba0f6LU, 0x4ed0c219LU, 0x4dc92787LU, 0x4486068aLU, 0x479fe314LU, 0x42b481fbLU, 0x41ad6465LU, 
+0xc0a34931LU, 0xc3baacafLU, 0xc691ce40LU, 0xc5882bdeLU, 0xccc70ad3LU, 0xcfdeef4dLU, 0xcaf58da2LU, 0xc9ec683cLU, 
+0xd86bcfb8LU, 0xdb722a26LU, 0xde5948c9LU, 0xdd40ad57LU, 0xd40f8c5aLU, 0xd71669c4LU, 0xd23d0b2bLU, 0xd124eeb5LU, 
+0xf07e086eLU, 0xf367edf0LU, 0xf64c8f1fLU, 0xf5556a81LU, 0xfc1a4b8cLU, 0xff03ae12LU, 0xfa28ccfdLU, 0xf9312963LU, 
+0xe8b68ee7LU, 0xebaf6b79LU, 0xee840996LU, 0xed9dec08LU, 0xe4d2cd05LU, 0xe7cb289bLU, 0xe2e04a74LU, 0xe1f9afeaLU, 
+0xa054cb8fLU, 0xa34d2e11LU, 0xa6664cfeLU, 0xa57fa960LU, 0xac30886dLU, 0xaf296df3LU, 0xaa020f1cLU, 0xa91bea82LU, 
+0xb89c4d06LU, 0xbb85a898LU, 0xbeaeca77LU, 0xbdb72fe9LU, 0xb4f80ee4LU, 0xb7e1eb7aLU, 0xb2ca8995LU, 0xb1d36c0bLU, 
+0x90898ad0LU, 0x93906f4eLU, 0x96bb0da1LU, 0x95a2e83fLU, 0x9cedc932LU, 0x9ff42cacLU, 0x9adf4e43LU, 0x99c6abddLU, 
+0x88410c59LU, 0x8b58e9c7LU, 0x8e738b28LU, 0x8d6a6eb6LU, 0x84254fbbLU, 0x873caa25LU, 0x8217c8caLU, 0x810e2d54LU, 
+0xcd0b9262LU, 0xce1277fcLU, 0xcb391513LU, 0xc820f08dLU, 0xc16fd180LU, 0xc276341eLU, 0xc75d56f1LU, 0xc444b36fLU, 
+0xd5c314ebLU, 0xd6daf175LU, 0xd3f1939aLU, 0xd0e87604LU, 0xd9a75709LU, 0xdabeb297LU, 0xdf95d078LU, 0xdc8c35e6LU, 
+0xfdd6d33dLU, 0xfecf36a3LU, 0xfbe4544cLU, 0xf8fdb1d2LU, 0xf1b290dfLU, 0xf2ab7541LU, 0xf78017aeLU, 0xf499f230LU, 
+0xe51e55b4LU, 0xe607b02aLU, 0xe32cd2c5LU, 0xe035375bLU, 0xe97a1656LU, 0xea63f3c8LU, 0xef489127LU, 0xec5174b9LU, 
+0xadfc10dcLU, 0xaee5f542LU, 0xabce97adLU, 0xa8d77233LU, 0xa198533eLU, 0xa281b6a0LU, 0xa7aad44fLU, 0xa4b331d1LU, 
+0xb5349655LU, 0xb62d73cbLU, 0xb3061124LU, 0xb01ff4baLU, 0xb950d5b7LU, 0xba493029LU, 0xbf6252c6LU, 0xbc7bb758LU, 
+0x9d215183LU, 0x9e38b41dLU, 0x9b13d6f2LU, 0x980a336cLU, 0x91451261LU, 0x925cf7ffLU, 0x97779510LU, 0x946e708eLU, 
+0x85e9d70aLU, 0x86f03294LU, 0x83db507bLU, 0x80c2b5e5LU, 0x898d94e8LU, 0x8a947176LU, 0x8fbf1399LU, 0x8ca6f607LU, 
+0x0da8db53LU, 0x0eb13ecdLU, 0x0b9a5c22LU, 0x0883b9bcLU, 0x01cc98b1LU, 0x02d57d2fLU, 0x07fe1fc0LU, 0x04e7fa5eLU, 
+0x15605ddaLU, 0x1679b844LU, 0x1352daabLU, 0x104b3f35LU, 0x19041e38LU, 0x1a1dfba6LU, 0x1f369949LU, 0x1c2f7cd7LU, 
+0x3d759a0cLU, 0x3e6c7f92LU, 0x3b471d7dLU, 0x385ef8e3LU, 0x3111d9eeLU, 0x32083c70LU, 0x37235e9fLU, 0x343abb01LU, 
+0x25bd1c85LU, 0x26a4f91bLU, 0x238f9bf4LU, 0x20967e6aLU, 0x29d95f67LU, 0x2ac0baf9LU, 0x2febd816LU, 0x2cf23d88LU, 
+0x6d5f59edLU, 0x6e46bc73LU, 0x6b6dde9cLU, 0x68743b02LU, 0x613b1a0fLU, 0x6222ff91LU, 0x67099d7eLU, 0x641078e0LU, 
+0x7597df64LU, 0x768e3afaLU, 0x73a55815LU, 0x70bcbd8bLU, 0x79f39c86LU, 0x7aea7918LU, 0x7fc11bf7LU, 0x7cd8fe69LU, 
+0x5d8218b2LU, 0x5e9bfd2cLU, 0x5bb09fc3LU, 0x58a97a5dLU, 0x51e65b50LU, 0x52ffbeceLU, 0x57d4dc21LU, 0x54cd39bfLU, 
+0x454a9e3bLU, 0x46537ba5LU, 0x4378194aLU, 0x4061fcd4LU, 0x492eddd9LU, 0x4a373847LU, 0x4f1c5aa8LU, 0x4c05bf36LU };
+
+#endif /* TWOFISH_ALL_TABLES */
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/whirl.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,275 @@
+/* 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
+ */
+
+/* WHIRLPOOL (using their new sbox) hash function by Tom St Denis */
+
+#include "mycrypt.h"
+
+#ifdef WHIRLPOOL
+
+const struct _hash_descriptor whirlpool_desc =
+{
+    "whirlpool",
+    11,
+    64,
+    64,
+    &whirlpool_init,
+    &whirlpool_process,
+    &whirlpool_done,
+    &whirlpool_test
+};
+
+/* the sboxes */
+#include "whirltab.c"
+
+/* get a_{i,j} */
+#define GB(a,i,j) ((a[(i) & 7] >> (8 * (j))) & 255)
+
+/* shortcut macro to perform three functions at once */
+#define theta_pi_gamma(a, i)               \
+    SB0(GB(a, i-0, 7)) ^                 \
+    SB1(GB(a, i-1, 6)) ^                 \
+    SB2(GB(a, i-2, 5)) ^                 \
+    SB3(GB(a, i-3, 4)) ^                 \
+    SB4(GB(a, i-4, 3)) ^                 \
+    SB5(GB(a, i-5, 2)) ^                 \
+    SB6(GB(a, i-6, 1)) ^                 \
+    SB7(GB(a, i-7, 0))
+
+#ifdef CLEAN_STACK
+static void _whirlpool_compress(hash_state *md, unsigned char *buf)
+#else
+static void whirlpool_compress(hash_state *md, unsigned char *buf)
+#endif
+{
+   ulong64 K[2][8], T[3][8];
+   int x, y;
+   
+   /* load the block/state */
+   for (x = 0; x < 8; x++) {
+      K[0][x] = md->whirlpool.state[x];
+
+      LOAD64H(T[0][x], buf + (8 * x));
+      T[2][x]  = T[0][x];
+      T[0][x] ^= K[0][x];
+   }
+  
+   /* do rounds 1..10 */
+   for (x = 0; x < 10; x += 2) {
+       /* odd round */
+       /* apply main transform to K[0] into K[1] */
+       for (y = 0; y < 8; y++) {
+           K[1][y] = theta_pi_gamma(K[0], y);
+       }
+       /* xor the constant */
+       K[1][0] ^= cont[x];
+       
+       /* apply main transform to T[0] into T[1] */
+       for (y = 0; y < 8; y++) {
+           T[1][y] = theta_pi_gamma(T[0], y) ^ K[1][y];
+       }
+
+       /* even round */
+       /* apply main transform to K[1] into K[0] */
+       for (y = 0; y < 8; y++) {
+           K[0][y] = theta_pi_gamma(K[1], y);
+       }
+       /* xor the constant */
+       K[0][0] ^= cont[x+1];
+       
+       /* apply main transform to T[0] into T[1] */
+       for (y = 0; y < 8; y++) {
+           T[0][y] = theta_pi_gamma(T[1], y) ^ K[0][y];
+       }
+   }
+   
+   /* store state */
+   for (x = 0; x < 8; x++) {
+      md->whirlpool.state[x] ^= T[0][x] ^ T[2][x];
+   }
+}
+
+
+#ifdef CLEAN_STACK
+static void whirlpool_compress(hash_state *md, unsigned char *buf)
+{
+   _whirlpool_compress(md, buf);
+   burn_stack((5 * 8 * sizeof(ulong64)) + (2 * sizeof(int)));
+}
+#endif
+
+
+void whirlpool_init(hash_state * md)
+{
+   _ARGCHK(md != NULL);
+   zeromem(&md->whirlpool, sizeof(md->whirlpool));
+}
+
+HASH_PROCESS(whirlpool_process, whirlpool_compress, whirlpool, 64)
+
+int whirlpool_done(hash_state * md, unsigned char *hash)
+{
+    int i;
+
+    _ARGCHK(md   != NULL);
+    _ARGCHK(hash != NULL);
+
+    if (md->whirlpool.curlen >= sizeof(md->whirlpool.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+    /* increase the length of the message */
+    md->whirlpool.length += md->whirlpool.curlen * 8;
+
+    /* append the '1' bit */
+    md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0x80;
+
+    /* if the length is currently above 32 bytes we append zeros
+     * then compress.  Then we can fall back to padding zeros and length
+     * encoding like normal.
+     */
+    if (md->whirlpool.curlen > 32) {
+        while (md->whirlpool.curlen < 64) {
+            md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0;
+        }
+        whirlpool_compress(md, md->whirlpool.buf);
+        md->whirlpool.curlen = 0;
+    }
+
+    /* pad upto 56 bytes of zeroes (should be 32 but we only support 64-bit lengths)  */
+    while (md->whirlpool.curlen < 56) {
+        md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0;
+    }
+
+    /* store length */
+    STORE64H(md->whirlpool.length, md->whirlpool.buf+56);
+    whirlpool_compress(md, md->whirlpool.buf);
+
+    /* copy output */
+    for (i = 0; i < 8; i++) {
+        STORE64H(md->whirlpool.state[i], hash+(8*i));
+    }
+#ifdef CLEAN_STACK
+    zeromem(md, sizeof(*md));
+#endif
+    return CRYPT_OK;
+}
+
+
+int  whirlpool_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+  static const struct {
+      int len;
+      unsigned char msg[128], hash[64];
+  } tests[] = {
+  
+  /* NULL Message */
+{
+  0, 
+  { 0x00 },
+  { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
+    0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7,
+    0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57,
+    0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37, 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 }
+},
+
+
+   /* 448-bits of 0 bits */
+{
+
+  56,
+  { 0x00 },
+  { 0x0B, 0x3F, 0x53, 0x78, 0xEB, 0xED, 0x2B, 0xF4, 0xD7, 0xBE, 0x3C, 0xFD, 0x81, 0x8C, 0x1B, 0x03,
+    0xB6, 0xBB, 0x03, 0xD3, 0x46, 0x94, 0x8B, 0x04, 0xF4, 0xF4, 0x0C, 0x72, 0x6F, 0x07, 0x58, 0x70,
+    0x2A, 0x0F, 0x1E, 0x22, 0x58, 0x80, 0xE3, 0x8D, 0xD5, 0xF6, 0xED, 0x6D, 0xE9, 0xB1, 0xE9, 0x61,
+    0xE4, 0x9F, 0xC1, 0x31, 0x8D, 0x7C, 0xB7, 0x48, 0x22, 0xF3, 0xD0, 0xE2, 0xE9, 0xA7, 0xE7, 0xB0 }
+},
+
+   /* 520-bits of 0 bits */
+{
+  65,
+  { 0x00 },
+  { 0x85, 0xE1, 0x24, 0xC4, 0x41, 0x5B, 0xCF, 0x43, 0x19, 0x54, 0x3E, 0x3A, 0x63, 0xFF, 0x57, 0x1D,
+    0x09, 0x35, 0x4C, 0xEE, 0xBE, 0xE1, 0xE3, 0x25, 0x30, 0x8C, 0x90, 0x69, 0xF4, 0x3E, 0x2A, 0xE4,
+    0xD0, 0xE5, 0x1D, 0x4E, 0xB1, 0xE8, 0x64, 0x28, 0x70, 0x19, 0x4E, 0x95, 0x30, 0xD8, 0xD8, 0xAF,
+    0x65, 0x89, 0xD1, 0xBF, 0x69, 0x49, 0xDD, 0xF9, 0x0A, 0x7F, 0x12, 0x08, 0x62, 0x37, 0x95, 0xB9 }
+},
+
+   /* 512-bits, leading set */
+{
+  64,
+  { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+  { 0x10, 0x3E, 0x00, 0x55, 0xA9, 0xB0, 0x90, 0xE1, 0x1C, 0x8F, 0xDD, 0xEB, 0xBA, 0x06, 0xC0, 0x5A,
+    0xCE, 0x8B, 0x64, 0xB8, 0x96, 0x12, 0x8F, 0x6E, 0xED, 0x30, 0x71, 0xFC, 0xF3, 0xDC, 0x16, 0x94,
+    0x67, 0x78, 0xE0, 0x72, 0x23, 0x23, 0x3F, 0xD1, 0x80, 0xFC, 0x40, 0xCC, 0xDB, 0x84, 0x30, 0xA6,
+    0x40, 0xE3, 0x76, 0x34, 0x27, 0x1E, 0x65, 0x5C, 0xA1, 0x67, 0x4E, 0xBF, 0xF5, 0x07, 0xF8, 0xCB }
+},
+
+   /* 512-bits, leading set of second byte */
+{
+  64,
+  { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+  { 0x35, 0x7B, 0x42, 0xEA, 0x79, 0xBC, 0x97, 0x86, 0x97, 0x5A, 0x3C, 0x44, 0x70, 0xAA, 0xB2, 0x3E,
+    0x62, 0x29, 0x79, 0x7B, 0xAD, 0xBD, 0x54, 0x36, 0x5B, 0x54, 0x96, 0xE5, 0x5D, 0x9D, 0xD7, 0x9F,
+    0xE9, 0x62, 0x4F, 0xB4, 0x22, 0x66, 0x93, 0x0A, 0x62, 0x8E, 0xD4, 0xDB, 0x08, 0xF9, 0xDD, 0x35,
+    0xEF, 0x1B, 0xE1, 0x04, 0x53, 0xFC, 0x18, 0xF4, 0x2C, 0x7F, 0x5E, 0x1F, 0x9B, 0xAE, 0x55, 0xE0 }
+},
+
+   /* 512-bits, leading set of last byte */
+{
+  64,
+  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 },
+  { 0x8B, 0x39, 0x04, 0xDD, 0x19, 0x81, 0x41, 0x26, 0xFD, 0x02, 0x74, 0xAB, 0x49, 0xC5, 0x97, 0xF6,
+    0xD7, 0x75, 0x33, 0x52, 0xA2, 0xDD, 0x91, 0xFD, 0x8F, 0x9F, 0x54, 0x05, 0x4C, 0x54, 0xBF, 0x0F,
+    0x06, 0xDB, 0x4F, 0xF7, 0x08, 0xA3, 0xA2, 0x8B, 0xC3, 0x7A, 0x92, 0x1E, 0xEE, 0x11, 0xED, 0x7B,
+    0x6A, 0x53, 0x79, 0x32, 0xCC, 0x5E, 0x94, 0xEE, 0x1E, 0xA6, 0x57, 0x60, 0x7E, 0x36, 0xC9, 0xF7 }
+},
+   
+};
+
+  int i;
+  unsigned char tmp[64];
+  hash_state md;
+
+  for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+      whirlpool_init(&md);
+      whirlpool_process(&md, (unsigned char *)tests[i].msg, tests[i].len);
+      whirlpool_done(&md, tmp);
+      if (memcmp(tmp, tests[i].hash, 64) != 0) {
+#if 0      
+         printf("\nFailed test %d\n", i);
+         for (i = 0; i < 64; ) {
+            printf("%02x ", tmp[i]);
+            if (!(++i & 15)) printf("\n");
+         }
+#endif         
+         return CRYPT_FAIL_TESTVECTOR;
+      }
+  }
+  return CRYPT_OK;
+ #endif
+}
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/whirltab.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,575 @@
+static const ulong64 sbox0[] = {
+CONST64(0x18186018c07830d8), CONST64(0x23238c2305af4626), CONST64(0xc6c63fc67ef991b8), CONST64(0xe8e887e8136fcdfb), 
+CONST64(0x878726874ca113cb), CONST64(0xb8b8dab8a9626d11), CONST64(0x0101040108050209), CONST64(0x4f4f214f426e9e0d), 
+CONST64(0x3636d836adee6c9b), CONST64(0xa6a6a2a6590451ff), CONST64(0xd2d26fd2debdb90c), CONST64(0xf5f5f3f5fb06f70e), 
+CONST64(0x7979f979ef80f296), CONST64(0x6f6fa16f5fcede30), CONST64(0x91917e91fcef3f6d), CONST64(0x52525552aa07a4f8), 
+CONST64(0x60609d6027fdc047), CONST64(0xbcbccabc89766535), CONST64(0x9b9b569baccd2b37), CONST64(0x8e8e028e048c018a), 
+CONST64(0xa3a3b6a371155bd2), CONST64(0x0c0c300c603c186c), CONST64(0x7b7bf17bff8af684), CONST64(0x3535d435b5e16a80), 
+CONST64(0x1d1d741de8693af5), CONST64(0xe0e0a7e05347ddb3), CONST64(0xd7d77bd7f6acb321), CONST64(0xc2c22fc25eed999c), 
+CONST64(0x2e2eb82e6d965c43), CONST64(0x4b4b314b627a9629), CONST64(0xfefedffea321e15d), CONST64(0x575741578216aed5), 
+CONST64(0x15155415a8412abd), CONST64(0x7777c1779fb6eee8), CONST64(0x3737dc37a5eb6e92), CONST64(0xe5e5b3e57b56d79e), 
+CONST64(0x9f9f469f8cd92313), CONST64(0xf0f0e7f0d317fd23), CONST64(0x4a4a354a6a7f9420), CONST64(0xdada4fda9e95a944), 
+CONST64(0x58587d58fa25b0a2), CONST64(0xc9c903c906ca8fcf), CONST64(0x2929a429558d527c), CONST64(0x0a0a280a5022145a), 
+CONST64(0xb1b1feb1e14f7f50), CONST64(0xa0a0baa0691a5dc9), CONST64(0x6b6bb16b7fdad614), CONST64(0x85852e855cab17d9), 
+CONST64(0xbdbdcebd8173673c), CONST64(0x5d5d695dd234ba8f), CONST64(0x1010401080502090), CONST64(0xf4f4f7f4f303f507), 
+CONST64(0xcbcb0bcb16c08bdd), CONST64(0x3e3ef83eedc67cd3), CONST64(0x0505140528110a2d), CONST64(0x676781671fe6ce78), 
+CONST64(0xe4e4b7e47353d597), CONST64(0x27279c2725bb4e02), CONST64(0x4141194132588273), CONST64(0x8b8b168b2c9d0ba7), 
+CONST64(0xa7a7a6a7510153f6), CONST64(0x7d7de97dcf94fab2), CONST64(0x95956e95dcfb3749), CONST64(0xd8d847d88e9fad56), 
+CONST64(0xfbfbcbfb8b30eb70), CONST64(0xeeee9fee2371c1cd), CONST64(0x7c7ced7cc791f8bb), CONST64(0x6666856617e3cc71), 
+CONST64(0xdddd53dda68ea77b), CONST64(0x17175c17b84b2eaf), CONST64(0x4747014702468e45), CONST64(0x9e9e429e84dc211a), 
+CONST64(0xcaca0fca1ec589d4), CONST64(0x2d2db42d75995a58), CONST64(0xbfbfc6bf9179632e), CONST64(0x07071c07381b0e3f), 
+CONST64(0xadad8ead012347ac), CONST64(0x5a5a755aea2fb4b0), CONST64(0x838336836cb51bef), CONST64(0x3333cc3385ff66b6), 
+CONST64(0x636391633ff2c65c), CONST64(0x02020802100a0412), CONST64(0xaaaa92aa39384993), CONST64(0x7171d971afa8e2de), 
+CONST64(0xc8c807c80ecf8dc6), CONST64(0x19196419c87d32d1), CONST64(0x494939497270923b), CONST64(0xd9d943d9869aaf5f), 
+CONST64(0xf2f2eff2c31df931), CONST64(0xe3e3abe34b48dba8), CONST64(0x5b5b715be22ab6b9), CONST64(0x88881a8834920dbc), 
+CONST64(0x9a9a529aa4c8293e), CONST64(0x262698262dbe4c0b), CONST64(0x3232c8328dfa64bf), CONST64(0xb0b0fab0e94a7d59), 
+CONST64(0xe9e983e91b6acff2), CONST64(0x0f0f3c0f78331e77), CONST64(0xd5d573d5e6a6b733), CONST64(0x80803a8074ba1df4), 
+CONST64(0xbebec2be997c6127), CONST64(0xcdcd13cd26de87eb), CONST64(0x3434d034bde46889), CONST64(0x48483d487a759032), 
+CONST64(0xffffdbffab24e354), CONST64(0x7a7af57af78ff48d), CONST64(0x90907a90f4ea3d64), CONST64(0x5f5f615fc23ebe9d), 
+CONST64(0x202080201da0403d), CONST64(0x6868bd6867d5d00f), CONST64(0x1a1a681ad07234ca), CONST64(0xaeae82ae192c41b7), 
+CONST64(0xb4b4eab4c95e757d), CONST64(0x54544d549a19a8ce), CONST64(0x93937693ece53b7f), CONST64(0x222288220daa442f), 
+CONST64(0x64648d6407e9c863), CONST64(0xf1f1e3f1db12ff2a), CONST64(0x7373d173bfa2e6cc), CONST64(0x12124812905a2482), 
+CONST64(0x40401d403a5d807a), CONST64(0x0808200840281048), CONST64(0xc3c32bc356e89b95), CONST64(0xecec97ec337bc5df), 
+CONST64(0xdbdb4bdb9690ab4d), CONST64(0xa1a1bea1611f5fc0), CONST64(0x8d8d0e8d1c830791), CONST64(0x3d3df43df5c97ac8), 
+CONST64(0x97976697ccf1335b), CONST64(0x0000000000000000), CONST64(0xcfcf1bcf36d483f9), CONST64(0x2b2bac2b4587566e), 
+CONST64(0x7676c57697b3ece1), CONST64(0x8282328264b019e6), CONST64(0xd6d67fd6fea9b128), CONST64(0x1b1b6c1bd87736c3), 
+CONST64(0xb5b5eeb5c15b7774), CONST64(0xafaf86af112943be), CONST64(0x6a6ab56a77dfd41d), CONST64(0x50505d50ba0da0ea), 
+CONST64(0x45450945124c8a57), CONST64(0xf3f3ebf3cb18fb38), CONST64(0x3030c0309df060ad), CONST64(0xefef9bef2b74c3c4), 
+CONST64(0x3f3ffc3fe5c37eda), CONST64(0x55554955921caac7), CONST64(0xa2a2b2a2791059db), CONST64(0xeaea8fea0365c9e9), 
+CONST64(0x656589650fecca6a), CONST64(0xbabad2bab9686903), CONST64(0x2f2fbc2f65935e4a), CONST64(0xc0c027c04ee79d8e), 
+CONST64(0xdede5fdebe81a160), CONST64(0x1c1c701ce06c38fc), CONST64(0xfdfdd3fdbb2ee746), CONST64(0x4d4d294d52649a1f), 
+CONST64(0x92927292e4e03976), CONST64(0x7575c9758fbceafa), CONST64(0x06061806301e0c36), CONST64(0x8a8a128a249809ae), 
+CONST64(0xb2b2f2b2f940794b), CONST64(0xe6e6bfe66359d185), CONST64(0x0e0e380e70361c7e), CONST64(0x1f1f7c1ff8633ee7), 
+CONST64(0x6262956237f7c455), CONST64(0xd4d477d4eea3b53a), CONST64(0xa8a89aa829324d81), CONST64(0x96966296c4f43152), 
+CONST64(0xf9f9c3f99b3aef62), CONST64(0xc5c533c566f697a3), CONST64(0x2525942535b14a10), CONST64(0x59597959f220b2ab), 
+CONST64(0x84842a8454ae15d0), CONST64(0x7272d572b7a7e4c5), CONST64(0x3939e439d5dd72ec), CONST64(0x4c4c2d4c5a619816), 
+CONST64(0x5e5e655eca3bbc94), CONST64(0x7878fd78e785f09f), CONST64(0x3838e038ddd870e5), CONST64(0x8c8c0a8c14860598), 
+CONST64(0xd1d163d1c6b2bf17), CONST64(0xa5a5aea5410b57e4), CONST64(0xe2e2afe2434dd9a1), CONST64(0x616199612ff8c24e), 
+CONST64(0xb3b3f6b3f1457b42), CONST64(0x2121842115a54234), CONST64(0x9c9c4a9c94d62508), CONST64(0x1e1e781ef0663cee), 
+CONST64(0x4343114322528661), CONST64(0xc7c73bc776fc93b1), CONST64(0xfcfcd7fcb32be54f), CONST64(0x0404100420140824), 
+CONST64(0x51515951b208a2e3), CONST64(0x99995e99bcc72f25), CONST64(0x6d6da96d4fc4da22), CONST64(0x0d0d340d68391a65), 
+CONST64(0xfafacffa8335e979), CONST64(0xdfdf5bdfb684a369), CONST64(0x7e7ee57ed79bfca9), CONST64(0x242490243db44819), 
+CONST64(0x3b3bec3bc5d776fe), CONST64(0xabab96ab313d4b9a), CONST64(0xcece1fce3ed181f0), CONST64(0x1111441188552299), 
+CONST64(0x8f8f068f0c890383), CONST64(0x4e4e254e4a6b9c04), CONST64(0xb7b7e6b7d1517366), CONST64(0xebeb8beb0b60cbe0), 
+CONST64(0x3c3cf03cfdcc78c1), CONST64(0x81813e817cbf1ffd), CONST64(0x94946a94d4fe3540), CONST64(0xf7f7fbf7eb0cf31c), 
+CONST64(0xb9b9deb9a1676f18), CONST64(0x13134c13985f268b), CONST64(0x2c2cb02c7d9c5851), CONST64(0xd3d36bd3d6b8bb05), 
+CONST64(0xe7e7bbe76b5cd38c), CONST64(0x6e6ea56e57cbdc39), CONST64(0xc4c437c46ef395aa), CONST64(0x03030c03180f061b), 
+CONST64(0x565645568a13acdc), CONST64(0x44440d441a49885e), CONST64(0x7f7fe17fdf9efea0), CONST64(0xa9a99ea921374f88), 
+CONST64(0x2a2aa82a4d825467), CONST64(0xbbbbd6bbb16d6b0a), CONST64(0xc1c123c146e29f87), CONST64(0x53535153a202a6f1), 
+CONST64(0xdcdc57dcae8ba572), CONST64(0x0b0b2c0b58271653), CONST64(0x9d9d4e9d9cd32701), CONST64(0x6c6cad6c47c1d82b), 
+CONST64(0x3131c43195f562a4), CONST64(0x7474cd7487b9e8f3), CONST64(0xf6f6fff6e309f115), CONST64(0x464605460a438c4c), 
+CONST64(0xacac8aac092645a5), CONST64(0x89891e893c970fb5), CONST64(0x14145014a04428b4), CONST64(0xe1e1a3e15b42dfba), 
+CONST64(0x16165816b04e2ca6), CONST64(0x3a3ae83acdd274f7), CONST64(0x6969b9696fd0d206), CONST64(0x09092409482d1241), 
+CONST64(0x7070dd70a7ade0d7), CONST64(0xb6b6e2b6d954716f), CONST64(0xd0d067d0ceb7bd1e), CONST64(0xeded93ed3b7ec7d6), 
+CONST64(0xcccc17cc2edb85e2), CONST64(0x424215422a578468), CONST64(0x98985a98b4c22d2c), CONST64(0xa4a4aaa4490e55ed), 
+CONST64(0x2828a0285d885075), CONST64(0x5c5c6d5cda31b886), CONST64(0xf8f8c7f8933fed6b), CONST64(0x8686228644a411c2)
+};
+
+#ifdef SMALL_CODE
+
+#define SB0(x) sbox0[x]
+#define SB1(x) ROR64(sbox0[x], 8)
+#define SB2(x) ROR64(sbox0[x], 16)
+#define SB3(x) ROR64(sbox0[x], 24)
+#define SB4(x) ROR64(sbox0[x], 32)
+#define SB5(x) ROR64(sbox0[x], 40)
+#define SB6(x) ROR64(sbox0[x], 48)
+#define SB7(x) ROR64(sbox0[x], 56)
+
+#else
+
+#define SB0(x) sbox0[x]
+#define SB1(x) sbox1[x]
+#define SB2(x) sbox2[x]
+#define SB3(x) sbox3[x]
+#define SB4(x) sbox4[x]
+#define SB5(x) sbox5[x]
+#define SB6(x) sbox6[x]
+#define SB7(x) sbox7[x]
+
+
+static const ulong64 sbox1[] = {
+CONST64(0xd818186018c07830), CONST64(0x2623238c2305af46), CONST64(0xb8c6c63fc67ef991), CONST64(0xfbe8e887e8136fcd), 
+CONST64(0xcb878726874ca113), CONST64(0x11b8b8dab8a9626d), CONST64(0x0901010401080502), CONST64(0x0d4f4f214f426e9e), 
+CONST64(0x9b3636d836adee6c), CONST64(0xffa6a6a2a6590451), CONST64(0x0cd2d26fd2debdb9), CONST64(0x0ef5f5f3f5fb06f7), 
+CONST64(0x967979f979ef80f2), CONST64(0x306f6fa16f5fcede), CONST64(0x6d91917e91fcef3f), CONST64(0xf852525552aa07a4), 
+CONST64(0x4760609d6027fdc0), CONST64(0x35bcbccabc897665), CONST64(0x379b9b569baccd2b), CONST64(0x8a8e8e028e048c01), 
+CONST64(0xd2a3a3b6a371155b), CONST64(0x6c0c0c300c603c18), CONST64(0x847b7bf17bff8af6), CONST64(0x803535d435b5e16a), 
+CONST64(0xf51d1d741de8693a), CONST64(0xb3e0e0a7e05347dd), CONST64(0x21d7d77bd7f6acb3), CONST64(0x9cc2c22fc25eed99), 
+CONST64(0x432e2eb82e6d965c), CONST64(0x294b4b314b627a96), CONST64(0x5dfefedffea321e1), CONST64(0xd5575741578216ae), 
+CONST64(0xbd15155415a8412a), CONST64(0xe87777c1779fb6ee), CONST64(0x923737dc37a5eb6e), CONST64(0x9ee5e5b3e57b56d7), 
+CONST64(0x139f9f469f8cd923), CONST64(0x23f0f0e7f0d317fd), CONST64(0x204a4a354a6a7f94), CONST64(0x44dada4fda9e95a9), 
+CONST64(0xa258587d58fa25b0), CONST64(0xcfc9c903c906ca8f), CONST64(0x7c2929a429558d52), CONST64(0x5a0a0a280a502214), 
+CONST64(0x50b1b1feb1e14f7f), CONST64(0xc9a0a0baa0691a5d), CONST64(0x146b6bb16b7fdad6), CONST64(0xd985852e855cab17), 
+CONST64(0x3cbdbdcebd817367), CONST64(0x8f5d5d695dd234ba), CONST64(0x9010104010805020), CONST64(0x07f4f4f7f4f303f5), 
+CONST64(0xddcbcb0bcb16c08b), CONST64(0xd33e3ef83eedc67c), CONST64(0x2d0505140528110a), CONST64(0x78676781671fe6ce), 
+CONST64(0x97e4e4b7e47353d5), CONST64(0x0227279c2725bb4e), CONST64(0x7341411941325882), CONST64(0xa78b8b168b2c9d0b), 
+CONST64(0xf6a7a7a6a7510153), CONST64(0xb27d7de97dcf94fa), CONST64(0x4995956e95dcfb37), CONST64(0x56d8d847d88e9fad), 
+CONST64(0x70fbfbcbfb8b30eb), CONST64(0xcdeeee9fee2371c1), CONST64(0xbb7c7ced7cc791f8), CONST64(0x716666856617e3cc), 
+CONST64(0x7bdddd53dda68ea7), CONST64(0xaf17175c17b84b2e), CONST64(0x454747014702468e), CONST64(0x1a9e9e429e84dc21), 
+CONST64(0xd4caca0fca1ec589), CONST64(0x582d2db42d75995a), CONST64(0x2ebfbfc6bf917963), CONST64(0x3f07071c07381b0e), 
+CONST64(0xacadad8ead012347), CONST64(0xb05a5a755aea2fb4), CONST64(0xef838336836cb51b), CONST64(0xb63333cc3385ff66), 
+CONST64(0x5c636391633ff2c6), CONST64(0x1202020802100a04), CONST64(0x93aaaa92aa393849), CONST64(0xde7171d971afa8e2), 
+CONST64(0xc6c8c807c80ecf8d), CONST64(0xd119196419c87d32), CONST64(0x3b49493949727092), CONST64(0x5fd9d943d9869aaf), 
+CONST64(0x31f2f2eff2c31df9), CONST64(0xa8e3e3abe34b48db), CONST64(0xb95b5b715be22ab6), CONST64(0xbc88881a8834920d), 
+CONST64(0x3e9a9a529aa4c829), CONST64(0x0b262698262dbe4c), CONST64(0xbf3232c8328dfa64), CONST64(0x59b0b0fab0e94a7d), 
+CONST64(0xf2e9e983e91b6acf), CONST64(0x770f0f3c0f78331e), CONST64(0x33d5d573d5e6a6b7), CONST64(0xf480803a8074ba1d), 
+CONST64(0x27bebec2be997c61), CONST64(0xebcdcd13cd26de87), CONST64(0x893434d034bde468), CONST64(0x3248483d487a7590), 
+CONST64(0x54ffffdbffab24e3), CONST64(0x8d7a7af57af78ff4), CONST64(0x6490907a90f4ea3d), CONST64(0x9d5f5f615fc23ebe), 
+CONST64(0x3d202080201da040), CONST64(0x0f6868bd6867d5d0), CONST64(0xca1a1a681ad07234), CONST64(0xb7aeae82ae192c41), 
+CONST64(0x7db4b4eab4c95e75), CONST64(0xce54544d549a19a8), CONST64(0x7f93937693ece53b), CONST64(0x2f222288220daa44), 
+CONST64(0x6364648d6407e9c8), CONST64(0x2af1f1e3f1db12ff), CONST64(0xcc7373d173bfa2e6), CONST64(0x8212124812905a24), 
+CONST64(0x7a40401d403a5d80), CONST64(0x4808082008402810), CONST64(0x95c3c32bc356e89b), CONST64(0xdfecec97ec337bc5), 
+CONST64(0x4ddbdb4bdb9690ab), CONST64(0xc0a1a1bea1611f5f), CONST64(0x918d8d0e8d1c8307), CONST64(0xc83d3df43df5c97a), 
+CONST64(0x5b97976697ccf133), CONST64(0x0000000000000000), CONST64(0xf9cfcf1bcf36d483), CONST64(0x6e2b2bac2b458756), 
+CONST64(0xe17676c57697b3ec), CONST64(0xe68282328264b019), CONST64(0x28d6d67fd6fea9b1), CONST64(0xc31b1b6c1bd87736), 
+CONST64(0x74b5b5eeb5c15b77), CONST64(0xbeafaf86af112943), CONST64(0x1d6a6ab56a77dfd4), CONST64(0xea50505d50ba0da0), 
+CONST64(0x5745450945124c8a), CONST64(0x38f3f3ebf3cb18fb), CONST64(0xad3030c0309df060), CONST64(0xc4efef9bef2b74c3), 
+CONST64(0xda3f3ffc3fe5c37e), CONST64(0xc755554955921caa), CONST64(0xdba2a2b2a2791059), CONST64(0xe9eaea8fea0365c9), 
+CONST64(0x6a656589650fecca), CONST64(0x03babad2bab96869), CONST64(0x4a2f2fbc2f65935e), CONST64(0x8ec0c027c04ee79d), 
+CONST64(0x60dede5fdebe81a1), CONST64(0xfc1c1c701ce06c38), CONST64(0x46fdfdd3fdbb2ee7), CONST64(0x1f4d4d294d52649a), 
+CONST64(0x7692927292e4e039), CONST64(0xfa7575c9758fbcea), CONST64(0x3606061806301e0c), CONST64(0xae8a8a128a249809), 
+CONST64(0x4bb2b2f2b2f94079), CONST64(0x85e6e6bfe66359d1), CONST64(0x7e0e0e380e70361c), CONST64(0xe71f1f7c1ff8633e), 
+CONST64(0x556262956237f7c4), CONST64(0x3ad4d477d4eea3b5), CONST64(0x81a8a89aa829324d), CONST64(0x5296966296c4f431), 
+CONST64(0x62f9f9c3f99b3aef), CONST64(0xa3c5c533c566f697), CONST64(0x102525942535b14a), CONST64(0xab59597959f220b2), 
+CONST64(0xd084842a8454ae15), CONST64(0xc57272d572b7a7e4), CONST64(0xec3939e439d5dd72), CONST64(0x164c4c2d4c5a6198), 
+CONST64(0x945e5e655eca3bbc), CONST64(0x9f7878fd78e785f0), CONST64(0xe53838e038ddd870), CONST64(0x988c8c0a8c148605), 
+CONST64(0x17d1d163d1c6b2bf), CONST64(0xe4a5a5aea5410b57), CONST64(0xa1e2e2afe2434dd9), CONST64(0x4e616199612ff8c2), 
+CONST64(0x42b3b3f6b3f1457b), CONST64(0x342121842115a542), CONST64(0x089c9c4a9c94d625), CONST64(0xee1e1e781ef0663c), 
+CONST64(0x6143431143225286), CONST64(0xb1c7c73bc776fc93), CONST64(0x4ffcfcd7fcb32be5), CONST64(0x2404041004201408), 
+CONST64(0xe351515951b208a2), CONST64(0x2599995e99bcc72f), CONST64(0x226d6da96d4fc4da), CONST64(0x650d0d340d68391a), 
+CONST64(0x79fafacffa8335e9), CONST64(0x69dfdf5bdfb684a3), CONST64(0xa97e7ee57ed79bfc), CONST64(0x19242490243db448), 
+CONST64(0xfe3b3bec3bc5d776), CONST64(0x9aabab96ab313d4b), CONST64(0xf0cece1fce3ed181), CONST64(0x9911114411885522), 
+CONST64(0x838f8f068f0c8903), CONST64(0x044e4e254e4a6b9c), CONST64(0x66b7b7e6b7d15173), CONST64(0xe0ebeb8beb0b60cb), 
+CONST64(0xc13c3cf03cfdcc78), CONST64(0xfd81813e817cbf1f), CONST64(0x4094946a94d4fe35), CONST64(0x1cf7f7fbf7eb0cf3), 
+CONST64(0x18b9b9deb9a1676f), CONST64(0x8b13134c13985f26), CONST64(0x512c2cb02c7d9c58), CONST64(0x05d3d36bd3d6b8bb), 
+CONST64(0x8ce7e7bbe76b5cd3), CONST64(0x396e6ea56e57cbdc), CONST64(0xaac4c437c46ef395), CONST64(0x1b03030c03180f06), 
+CONST64(0xdc565645568a13ac), CONST64(0x5e44440d441a4988), CONST64(0xa07f7fe17fdf9efe), CONST64(0x88a9a99ea921374f), 
+CONST64(0x672a2aa82a4d8254), CONST64(0x0abbbbd6bbb16d6b), CONST64(0x87c1c123c146e29f), CONST64(0xf153535153a202a6), 
+CONST64(0x72dcdc57dcae8ba5), CONST64(0x530b0b2c0b582716), CONST64(0x019d9d4e9d9cd327), CONST64(0x2b6c6cad6c47c1d8), 
+CONST64(0xa43131c43195f562), CONST64(0xf37474cd7487b9e8), CONST64(0x15f6f6fff6e309f1), CONST64(0x4c464605460a438c), 
+CONST64(0xa5acac8aac092645), CONST64(0xb589891e893c970f), CONST64(0xb414145014a04428), CONST64(0xbae1e1a3e15b42df), 
+CONST64(0xa616165816b04e2c), CONST64(0xf73a3ae83acdd274), CONST64(0x066969b9696fd0d2), CONST64(0x4109092409482d12), 
+CONST64(0xd77070dd70a7ade0), CONST64(0x6fb6b6e2b6d95471), CONST64(0x1ed0d067d0ceb7bd), CONST64(0xd6eded93ed3b7ec7), 
+CONST64(0xe2cccc17cc2edb85), CONST64(0x68424215422a5784), CONST64(0x2c98985a98b4c22d), CONST64(0xeda4a4aaa4490e55), 
+CONST64(0x752828a0285d8850), CONST64(0x865c5c6d5cda31b8), CONST64(0x6bf8f8c7f8933fed), CONST64(0xc28686228644a411)
+};
+
+static const ulong64 sbox2[] = {
+CONST64(0x30d818186018c078), CONST64(0x462623238c2305af), CONST64(0x91b8c6c63fc67ef9), CONST64(0xcdfbe8e887e8136f), 
+CONST64(0x13cb878726874ca1), CONST64(0x6d11b8b8dab8a962), CONST64(0x0209010104010805), CONST64(0x9e0d4f4f214f426e), 
+CONST64(0x6c9b3636d836adee), CONST64(0x51ffa6a6a2a65904), CONST64(0xb90cd2d26fd2debd), CONST64(0xf70ef5f5f3f5fb06), 
+CONST64(0xf2967979f979ef80), CONST64(0xde306f6fa16f5fce), CONST64(0x3f6d91917e91fcef), CONST64(0xa4f852525552aa07), 
+CONST64(0xc04760609d6027fd), CONST64(0x6535bcbccabc8976), CONST64(0x2b379b9b569baccd), CONST64(0x018a8e8e028e048c), 
+CONST64(0x5bd2a3a3b6a37115), CONST64(0x186c0c0c300c603c), CONST64(0xf6847b7bf17bff8a), CONST64(0x6a803535d435b5e1), 
+CONST64(0x3af51d1d741de869), CONST64(0xddb3e0e0a7e05347), CONST64(0xb321d7d77bd7f6ac), CONST64(0x999cc2c22fc25eed), 
+CONST64(0x5c432e2eb82e6d96), CONST64(0x96294b4b314b627a), CONST64(0xe15dfefedffea321), CONST64(0xaed5575741578216), 
+CONST64(0x2abd15155415a841), CONST64(0xeee87777c1779fb6), CONST64(0x6e923737dc37a5eb), CONST64(0xd79ee5e5b3e57b56), 
+CONST64(0x23139f9f469f8cd9), CONST64(0xfd23f0f0e7f0d317), CONST64(0x94204a4a354a6a7f), CONST64(0xa944dada4fda9e95), 
+CONST64(0xb0a258587d58fa25), CONST64(0x8fcfc9c903c906ca), CONST64(0x527c2929a429558d), CONST64(0x145a0a0a280a5022), 
+CONST64(0x7f50b1b1feb1e14f), CONST64(0x5dc9a0a0baa0691a), CONST64(0xd6146b6bb16b7fda), CONST64(0x17d985852e855cab), 
+CONST64(0x673cbdbdcebd8173), CONST64(0xba8f5d5d695dd234), CONST64(0x2090101040108050), CONST64(0xf507f4f4f7f4f303), 
+CONST64(0x8bddcbcb0bcb16c0), CONST64(0x7cd33e3ef83eedc6), CONST64(0x0a2d050514052811), CONST64(0xce78676781671fe6), 
+CONST64(0xd597e4e4b7e47353), CONST64(0x4e0227279c2725bb), CONST64(0x8273414119413258), CONST64(0x0ba78b8b168b2c9d), 
+CONST64(0x53f6a7a7a6a75101), CONST64(0xfab27d7de97dcf94), CONST64(0x374995956e95dcfb), CONST64(0xad56d8d847d88e9f), 
+CONST64(0xeb70fbfbcbfb8b30), CONST64(0xc1cdeeee9fee2371), CONST64(0xf8bb7c7ced7cc791), CONST64(0xcc716666856617e3), 
+CONST64(0xa77bdddd53dda68e), CONST64(0x2eaf17175c17b84b), CONST64(0x8e45474701470246), CONST64(0x211a9e9e429e84dc), 
+CONST64(0x89d4caca0fca1ec5), CONST64(0x5a582d2db42d7599), CONST64(0x632ebfbfc6bf9179), CONST64(0x0e3f07071c07381b), 
+CONST64(0x47acadad8ead0123), CONST64(0xb4b05a5a755aea2f), CONST64(0x1bef838336836cb5), CONST64(0x66b63333cc3385ff), 
+CONST64(0xc65c636391633ff2), CONST64(0x041202020802100a), CONST64(0x4993aaaa92aa3938), CONST64(0xe2de7171d971afa8), 
+CONST64(0x8dc6c8c807c80ecf), CONST64(0x32d119196419c87d), CONST64(0x923b494939497270), CONST64(0xaf5fd9d943d9869a), 
+CONST64(0xf931f2f2eff2c31d), CONST64(0xdba8e3e3abe34b48), CONST64(0xb6b95b5b715be22a), CONST64(0x0dbc88881a883492), 
+CONST64(0x293e9a9a529aa4c8), CONST64(0x4c0b262698262dbe), CONST64(0x64bf3232c8328dfa), CONST64(0x7d59b0b0fab0e94a), 
+CONST64(0xcff2e9e983e91b6a), CONST64(0x1e770f0f3c0f7833), CONST64(0xb733d5d573d5e6a6), CONST64(0x1df480803a8074ba), 
+CONST64(0x6127bebec2be997c), CONST64(0x87ebcdcd13cd26de), CONST64(0x68893434d034bde4), CONST64(0x903248483d487a75), 
+CONST64(0xe354ffffdbffab24), CONST64(0xf48d7a7af57af78f), CONST64(0x3d6490907a90f4ea), CONST64(0xbe9d5f5f615fc23e), 
+CONST64(0x403d202080201da0), CONST64(0xd00f6868bd6867d5), CONST64(0x34ca1a1a681ad072), CONST64(0x41b7aeae82ae192c), 
+CONST64(0x757db4b4eab4c95e), CONST64(0xa8ce54544d549a19), CONST64(0x3b7f93937693ece5), CONST64(0x442f222288220daa), 
+CONST64(0xc86364648d6407e9), CONST64(0xff2af1f1e3f1db12), CONST64(0xe6cc7373d173bfa2), CONST64(0x248212124812905a), 
+CONST64(0x807a40401d403a5d), CONST64(0x1048080820084028), CONST64(0x9b95c3c32bc356e8), CONST64(0xc5dfecec97ec337b), 
+CONST64(0xab4ddbdb4bdb9690), CONST64(0x5fc0a1a1bea1611f), CONST64(0x07918d8d0e8d1c83), CONST64(0x7ac83d3df43df5c9), 
+CONST64(0x335b97976697ccf1), CONST64(0x0000000000000000), CONST64(0x83f9cfcf1bcf36d4), CONST64(0x566e2b2bac2b4587), 
+CONST64(0xece17676c57697b3), CONST64(0x19e68282328264b0), CONST64(0xb128d6d67fd6fea9), CONST64(0x36c31b1b6c1bd877), 
+CONST64(0x7774b5b5eeb5c15b), CONST64(0x43beafaf86af1129), CONST64(0xd41d6a6ab56a77df), CONST64(0xa0ea50505d50ba0d), 
+CONST64(0x8a5745450945124c), CONST64(0xfb38f3f3ebf3cb18), CONST64(0x60ad3030c0309df0), CONST64(0xc3c4efef9bef2b74), 
+CONST64(0x7eda3f3ffc3fe5c3), CONST64(0xaac755554955921c), CONST64(0x59dba2a2b2a27910), CONST64(0xc9e9eaea8fea0365), 
+CONST64(0xca6a656589650fec), CONST64(0x6903babad2bab968), CONST64(0x5e4a2f2fbc2f6593), CONST64(0x9d8ec0c027c04ee7), 
+CONST64(0xa160dede5fdebe81), CONST64(0x38fc1c1c701ce06c), CONST64(0xe746fdfdd3fdbb2e), CONST64(0x9a1f4d4d294d5264), 
+CONST64(0x397692927292e4e0), CONST64(0xeafa7575c9758fbc), CONST64(0x0c3606061806301e), CONST64(0x09ae8a8a128a2498), 
+CONST64(0x794bb2b2f2b2f940), CONST64(0xd185e6e6bfe66359), CONST64(0x1c7e0e0e380e7036), CONST64(0x3ee71f1f7c1ff863), 
+CONST64(0xc4556262956237f7), CONST64(0xb53ad4d477d4eea3), CONST64(0x4d81a8a89aa82932), CONST64(0x315296966296c4f4), 
+CONST64(0xef62f9f9c3f99b3a), CONST64(0x97a3c5c533c566f6), CONST64(0x4a102525942535b1), CONST64(0xb2ab59597959f220), 
+CONST64(0x15d084842a8454ae), CONST64(0xe4c57272d572b7a7), CONST64(0x72ec3939e439d5dd), CONST64(0x98164c4c2d4c5a61), 
+CONST64(0xbc945e5e655eca3b), CONST64(0xf09f7878fd78e785), CONST64(0x70e53838e038ddd8), CONST64(0x05988c8c0a8c1486), 
+CONST64(0xbf17d1d163d1c6b2), CONST64(0x57e4a5a5aea5410b), CONST64(0xd9a1e2e2afe2434d), CONST64(0xc24e616199612ff8), 
+CONST64(0x7b42b3b3f6b3f145), CONST64(0x42342121842115a5), CONST64(0x25089c9c4a9c94d6), CONST64(0x3cee1e1e781ef066), 
+CONST64(0x8661434311432252), CONST64(0x93b1c7c73bc776fc), CONST64(0xe54ffcfcd7fcb32b), CONST64(0x0824040410042014), 
+CONST64(0xa2e351515951b208), CONST64(0x2f2599995e99bcc7), CONST64(0xda226d6da96d4fc4), CONST64(0x1a650d0d340d6839), 
+CONST64(0xe979fafacffa8335), CONST64(0xa369dfdf5bdfb684), CONST64(0xfca97e7ee57ed79b), CONST64(0x4819242490243db4), 
+CONST64(0x76fe3b3bec3bc5d7), CONST64(0x4b9aabab96ab313d), CONST64(0x81f0cece1fce3ed1), CONST64(0x2299111144118855), 
+CONST64(0x03838f8f068f0c89), CONST64(0x9c044e4e254e4a6b), CONST64(0x7366b7b7e6b7d151), CONST64(0xcbe0ebeb8beb0b60), 
+CONST64(0x78c13c3cf03cfdcc), CONST64(0x1ffd81813e817cbf), CONST64(0x354094946a94d4fe), CONST64(0xf31cf7f7fbf7eb0c), 
+CONST64(0x6f18b9b9deb9a167), CONST64(0x268b13134c13985f), CONST64(0x58512c2cb02c7d9c), CONST64(0xbb05d3d36bd3d6b8), 
+CONST64(0xd38ce7e7bbe76b5c), CONST64(0xdc396e6ea56e57cb), CONST64(0x95aac4c437c46ef3), CONST64(0x061b03030c03180f), 
+CONST64(0xacdc565645568a13), CONST64(0x885e44440d441a49), CONST64(0xfea07f7fe17fdf9e), CONST64(0x4f88a9a99ea92137), 
+CONST64(0x54672a2aa82a4d82), CONST64(0x6b0abbbbd6bbb16d), CONST64(0x9f87c1c123c146e2), CONST64(0xa6f153535153a202), 
+CONST64(0xa572dcdc57dcae8b), CONST64(0x16530b0b2c0b5827), CONST64(0x27019d9d4e9d9cd3), CONST64(0xd82b6c6cad6c47c1), 
+CONST64(0x62a43131c43195f5), CONST64(0xe8f37474cd7487b9), CONST64(0xf115f6f6fff6e309), CONST64(0x8c4c464605460a43), 
+CONST64(0x45a5acac8aac0926), CONST64(0x0fb589891e893c97), CONST64(0x28b414145014a044), CONST64(0xdfbae1e1a3e15b42), 
+CONST64(0x2ca616165816b04e), CONST64(0x74f73a3ae83acdd2), CONST64(0xd2066969b9696fd0), CONST64(0x124109092409482d), 
+CONST64(0xe0d77070dd70a7ad), CONST64(0x716fb6b6e2b6d954), CONST64(0xbd1ed0d067d0ceb7), CONST64(0xc7d6eded93ed3b7e), 
+CONST64(0x85e2cccc17cc2edb), CONST64(0x8468424215422a57), CONST64(0x2d2c98985a98b4c2), CONST64(0x55eda4a4aaa4490e), 
+CONST64(0x50752828a0285d88), CONST64(0xb8865c5c6d5cda31), CONST64(0xed6bf8f8c7f8933f), CONST64(0x11c28686228644a4)
+};
+
+static const ulong64 sbox3[] = {
+CONST64(0x7830d818186018c0), CONST64(0xaf462623238c2305), CONST64(0xf991b8c6c63fc67e), CONST64(0x6fcdfbe8e887e813), 
+CONST64(0xa113cb878726874c), CONST64(0x626d11b8b8dab8a9), CONST64(0x0502090101040108), CONST64(0x6e9e0d4f4f214f42), 
+CONST64(0xee6c9b3636d836ad), CONST64(0x0451ffa6a6a2a659), CONST64(0xbdb90cd2d26fd2de), CONST64(0x06f70ef5f5f3f5fb), 
+CONST64(0x80f2967979f979ef), CONST64(0xcede306f6fa16f5f), CONST64(0xef3f6d91917e91fc), CONST64(0x07a4f852525552aa), 
+CONST64(0xfdc04760609d6027), CONST64(0x766535bcbccabc89), CONST64(0xcd2b379b9b569bac), CONST64(0x8c018a8e8e028e04), 
+CONST64(0x155bd2a3a3b6a371), CONST64(0x3c186c0c0c300c60), CONST64(0x8af6847b7bf17bff), CONST64(0xe16a803535d435b5), 
+CONST64(0x693af51d1d741de8), CONST64(0x47ddb3e0e0a7e053), CONST64(0xacb321d7d77bd7f6), CONST64(0xed999cc2c22fc25e), 
+CONST64(0x965c432e2eb82e6d), CONST64(0x7a96294b4b314b62), CONST64(0x21e15dfefedffea3), CONST64(0x16aed55757415782), 
+CONST64(0x412abd15155415a8), CONST64(0xb6eee87777c1779f), CONST64(0xeb6e923737dc37a5), CONST64(0x56d79ee5e5b3e57b), 
+CONST64(0xd923139f9f469f8c), CONST64(0x17fd23f0f0e7f0d3), CONST64(0x7f94204a4a354a6a), CONST64(0x95a944dada4fda9e), 
+CONST64(0x25b0a258587d58fa), CONST64(0xca8fcfc9c903c906), CONST64(0x8d527c2929a42955), CONST64(0x22145a0a0a280a50), 
+CONST64(0x4f7f50b1b1feb1e1), CONST64(0x1a5dc9a0a0baa069), CONST64(0xdad6146b6bb16b7f), CONST64(0xab17d985852e855c), 
+CONST64(0x73673cbdbdcebd81), CONST64(0x34ba8f5d5d695dd2), CONST64(0x5020901010401080), CONST64(0x03f507f4f4f7f4f3), 
+CONST64(0xc08bddcbcb0bcb16), CONST64(0xc67cd33e3ef83eed), CONST64(0x110a2d0505140528), CONST64(0xe6ce78676781671f), 
+CONST64(0x53d597e4e4b7e473), CONST64(0xbb4e0227279c2725), CONST64(0x5882734141194132), CONST64(0x9d0ba78b8b168b2c), 
+CONST64(0x0153f6a7a7a6a751), CONST64(0x94fab27d7de97dcf), CONST64(0xfb374995956e95dc), CONST64(0x9fad56d8d847d88e), 
+CONST64(0x30eb70fbfbcbfb8b), CONST64(0x71c1cdeeee9fee23), CONST64(0x91f8bb7c7ced7cc7), CONST64(0xe3cc716666856617), 
+CONST64(0x8ea77bdddd53dda6), CONST64(0x4b2eaf17175c17b8), CONST64(0x468e454747014702), CONST64(0xdc211a9e9e429e84), 
+CONST64(0xc589d4caca0fca1e), CONST64(0x995a582d2db42d75), CONST64(0x79632ebfbfc6bf91), CONST64(0x1b0e3f07071c0738), 
+CONST64(0x2347acadad8ead01), CONST64(0x2fb4b05a5a755aea), CONST64(0xb51bef838336836c), CONST64(0xff66b63333cc3385), 
+CONST64(0xf2c65c636391633f), CONST64(0x0a04120202080210), CONST64(0x384993aaaa92aa39), CONST64(0xa8e2de7171d971af), 
+CONST64(0xcf8dc6c8c807c80e), CONST64(0x7d32d119196419c8), CONST64(0x70923b4949394972), CONST64(0x9aaf5fd9d943d986), 
+CONST64(0x1df931f2f2eff2c3), CONST64(0x48dba8e3e3abe34b), CONST64(0x2ab6b95b5b715be2), CONST64(0x920dbc88881a8834), 
+CONST64(0xc8293e9a9a529aa4), CONST64(0xbe4c0b262698262d), CONST64(0xfa64bf3232c8328d), CONST64(0x4a7d59b0b0fab0e9), 
+CONST64(0x6acff2e9e983e91b), CONST64(0x331e770f0f3c0f78), CONST64(0xa6b733d5d573d5e6), CONST64(0xba1df480803a8074), 
+CONST64(0x7c6127bebec2be99), CONST64(0xde87ebcdcd13cd26), CONST64(0xe468893434d034bd), CONST64(0x75903248483d487a), 
+CONST64(0x24e354ffffdbffab), CONST64(0x8ff48d7a7af57af7), CONST64(0xea3d6490907a90f4), CONST64(0x3ebe9d5f5f615fc2), 
+CONST64(0xa0403d202080201d), CONST64(0xd5d00f6868bd6867), CONST64(0x7234ca1a1a681ad0), CONST64(0x2c41b7aeae82ae19), 
+CONST64(0x5e757db4b4eab4c9), CONST64(0x19a8ce54544d549a), CONST64(0xe53b7f93937693ec), CONST64(0xaa442f222288220d), 
+CONST64(0xe9c86364648d6407), CONST64(0x12ff2af1f1e3f1db), CONST64(0xa2e6cc7373d173bf), CONST64(0x5a24821212481290), 
+CONST64(0x5d807a40401d403a), CONST64(0x2810480808200840), CONST64(0xe89b95c3c32bc356), CONST64(0x7bc5dfecec97ec33), 
+CONST64(0x90ab4ddbdb4bdb96), CONST64(0x1f5fc0a1a1bea161), CONST64(0x8307918d8d0e8d1c), CONST64(0xc97ac83d3df43df5), 
+CONST64(0xf1335b97976697cc), CONST64(0x0000000000000000), CONST64(0xd483f9cfcf1bcf36), CONST64(0x87566e2b2bac2b45), 
+CONST64(0xb3ece17676c57697), CONST64(0xb019e68282328264), CONST64(0xa9b128d6d67fd6fe), CONST64(0x7736c31b1b6c1bd8), 
+CONST64(0x5b7774b5b5eeb5c1), CONST64(0x2943beafaf86af11), CONST64(0xdfd41d6a6ab56a77), CONST64(0x0da0ea50505d50ba), 
+CONST64(0x4c8a574545094512), CONST64(0x18fb38f3f3ebf3cb), CONST64(0xf060ad3030c0309d), CONST64(0x74c3c4efef9bef2b), 
+CONST64(0xc37eda3f3ffc3fe5), CONST64(0x1caac75555495592), CONST64(0x1059dba2a2b2a279), CONST64(0x65c9e9eaea8fea03), 
+CONST64(0xecca6a656589650f), CONST64(0x686903babad2bab9), CONST64(0x935e4a2f2fbc2f65), CONST64(0xe79d8ec0c027c04e), 
+CONST64(0x81a160dede5fdebe), CONST64(0x6c38fc1c1c701ce0), CONST64(0x2ee746fdfdd3fdbb), CONST64(0x649a1f4d4d294d52), 
+CONST64(0xe0397692927292e4), CONST64(0xbceafa7575c9758f), CONST64(0x1e0c360606180630), CONST64(0x9809ae8a8a128a24), 
+CONST64(0x40794bb2b2f2b2f9), CONST64(0x59d185e6e6bfe663), CONST64(0x361c7e0e0e380e70), CONST64(0x633ee71f1f7c1ff8), 
+CONST64(0xf7c4556262956237), CONST64(0xa3b53ad4d477d4ee), CONST64(0x324d81a8a89aa829), CONST64(0xf4315296966296c4), 
+CONST64(0x3aef62f9f9c3f99b), CONST64(0xf697a3c5c533c566), CONST64(0xb14a102525942535), CONST64(0x20b2ab59597959f2), 
+CONST64(0xae15d084842a8454), CONST64(0xa7e4c57272d572b7), CONST64(0xdd72ec3939e439d5), CONST64(0x6198164c4c2d4c5a), 
+CONST64(0x3bbc945e5e655eca), CONST64(0x85f09f7878fd78e7), CONST64(0xd870e53838e038dd), CONST64(0x8605988c8c0a8c14), 
+CONST64(0xb2bf17d1d163d1c6), CONST64(0x0b57e4a5a5aea541), CONST64(0x4dd9a1e2e2afe243), CONST64(0xf8c24e616199612f), 
+CONST64(0x457b42b3b3f6b3f1), CONST64(0xa542342121842115), CONST64(0xd625089c9c4a9c94), CONST64(0x663cee1e1e781ef0), 
+CONST64(0x5286614343114322), CONST64(0xfc93b1c7c73bc776), CONST64(0x2be54ffcfcd7fcb3), CONST64(0x1408240404100420), 
+CONST64(0x08a2e351515951b2), CONST64(0xc72f2599995e99bc), CONST64(0xc4da226d6da96d4f), CONST64(0x391a650d0d340d68), 
+CONST64(0x35e979fafacffa83), CONST64(0x84a369dfdf5bdfb6), CONST64(0x9bfca97e7ee57ed7), CONST64(0xb44819242490243d), 
+CONST64(0xd776fe3b3bec3bc5), CONST64(0x3d4b9aabab96ab31), CONST64(0xd181f0cece1fce3e), CONST64(0x5522991111441188), 
+CONST64(0x8903838f8f068f0c), CONST64(0x6b9c044e4e254e4a), CONST64(0x517366b7b7e6b7d1), CONST64(0x60cbe0ebeb8beb0b), 
+CONST64(0xcc78c13c3cf03cfd), CONST64(0xbf1ffd81813e817c), CONST64(0xfe354094946a94d4), CONST64(0x0cf31cf7f7fbf7eb), 
+CONST64(0x676f18b9b9deb9a1), CONST64(0x5f268b13134c1398), CONST64(0x9c58512c2cb02c7d), CONST64(0xb8bb05d3d36bd3d6), 
+CONST64(0x5cd38ce7e7bbe76b), CONST64(0xcbdc396e6ea56e57), CONST64(0xf395aac4c437c46e), CONST64(0x0f061b03030c0318), 
+CONST64(0x13acdc565645568a), CONST64(0x49885e44440d441a), CONST64(0x9efea07f7fe17fdf), CONST64(0x374f88a9a99ea921), 
+CONST64(0x8254672a2aa82a4d), CONST64(0x6d6b0abbbbd6bbb1), CONST64(0xe29f87c1c123c146), CONST64(0x02a6f153535153a2), 
+CONST64(0x8ba572dcdc57dcae), CONST64(0x2716530b0b2c0b58), CONST64(0xd327019d9d4e9d9c), CONST64(0xc1d82b6c6cad6c47), 
+CONST64(0xf562a43131c43195), CONST64(0xb9e8f37474cd7487), CONST64(0x09f115f6f6fff6e3), CONST64(0x438c4c464605460a), 
+CONST64(0x2645a5acac8aac09), CONST64(0x970fb589891e893c), CONST64(0x4428b414145014a0), CONST64(0x42dfbae1e1a3e15b), 
+CONST64(0x4e2ca616165816b0), CONST64(0xd274f73a3ae83acd), CONST64(0xd0d2066969b9696f), CONST64(0x2d12410909240948), 
+CONST64(0xade0d77070dd70a7), CONST64(0x54716fb6b6e2b6d9), CONST64(0xb7bd1ed0d067d0ce), CONST64(0x7ec7d6eded93ed3b), 
+CONST64(0xdb85e2cccc17cc2e), CONST64(0x578468424215422a), CONST64(0xc22d2c98985a98b4), CONST64(0x0e55eda4a4aaa449), 
+CONST64(0x8850752828a0285d), CONST64(0x31b8865c5c6d5cda), CONST64(0x3fed6bf8f8c7f893), CONST64(0xa411c28686228644)
+};
+
+static const ulong64 sbox4[] = {
+CONST64(0xc07830d818186018), CONST64(0x05af462623238c23), CONST64(0x7ef991b8c6c63fc6), CONST64(0x136fcdfbe8e887e8), 
+CONST64(0x4ca113cb87872687), CONST64(0xa9626d11b8b8dab8), CONST64(0x0805020901010401), CONST64(0x426e9e0d4f4f214f), 
+CONST64(0xadee6c9b3636d836), CONST64(0x590451ffa6a6a2a6), CONST64(0xdebdb90cd2d26fd2), CONST64(0xfb06f70ef5f5f3f5), 
+CONST64(0xef80f2967979f979), CONST64(0x5fcede306f6fa16f), CONST64(0xfcef3f6d91917e91), CONST64(0xaa07a4f852525552), 
+CONST64(0x27fdc04760609d60), CONST64(0x89766535bcbccabc), CONST64(0xaccd2b379b9b569b), CONST64(0x048c018a8e8e028e), 
+CONST64(0x71155bd2a3a3b6a3), CONST64(0x603c186c0c0c300c), CONST64(0xff8af6847b7bf17b), CONST64(0xb5e16a803535d435), 
+CONST64(0xe8693af51d1d741d), CONST64(0x5347ddb3e0e0a7e0), CONST64(0xf6acb321d7d77bd7), CONST64(0x5eed999cc2c22fc2), 
+CONST64(0x6d965c432e2eb82e), CONST64(0x627a96294b4b314b), CONST64(0xa321e15dfefedffe), CONST64(0x8216aed557574157), 
+CONST64(0xa8412abd15155415), CONST64(0x9fb6eee87777c177), CONST64(0xa5eb6e923737dc37), CONST64(0x7b56d79ee5e5b3e5), 
+CONST64(0x8cd923139f9f469f), CONST64(0xd317fd23f0f0e7f0), CONST64(0x6a7f94204a4a354a), CONST64(0x9e95a944dada4fda), 
+CONST64(0xfa25b0a258587d58), CONST64(0x06ca8fcfc9c903c9), CONST64(0x558d527c2929a429), CONST64(0x5022145a0a0a280a), 
+CONST64(0xe14f7f50b1b1feb1), CONST64(0x691a5dc9a0a0baa0), CONST64(0x7fdad6146b6bb16b), CONST64(0x5cab17d985852e85), 
+CONST64(0x8173673cbdbdcebd), CONST64(0xd234ba8f5d5d695d), CONST64(0x8050209010104010), CONST64(0xf303f507f4f4f7f4), 
+CONST64(0x16c08bddcbcb0bcb), CONST64(0xedc67cd33e3ef83e), CONST64(0x28110a2d05051405), CONST64(0x1fe6ce7867678167), 
+CONST64(0x7353d597e4e4b7e4), CONST64(0x25bb4e0227279c27), CONST64(0x3258827341411941), CONST64(0x2c9d0ba78b8b168b), 
+CONST64(0x510153f6a7a7a6a7), CONST64(0xcf94fab27d7de97d), CONST64(0xdcfb374995956e95), CONST64(0x8e9fad56d8d847d8), 
+CONST64(0x8b30eb70fbfbcbfb), CONST64(0x2371c1cdeeee9fee), CONST64(0xc791f8bb7c7ced7c), CONST64(0x17e3cc7166668566), 
+CONST64(0xa68ea77bdddd53dd), CONST64(0xb84b2eaf17175c17), CONST64(0x02468e4547470147), CONST64(0x84dc211a9e9e429e), 
+CONST64(0x1ec589d4caca0fca), CONST64(0x75995a582d2db42d), CONST64(0x9179632ebfbfc6bf), CONST64(0x381b0e3f07071c07), 
+CONST64(0x012347acadad8ead), CONST64(0xea2fb4b05a5a755a), CONST64(0x6cb51bef83833683), CONST64(0x85ff66b63333cc33), 
+CONST64(0x3ff2c65c63639163), CONST64(0x100a041202020802), CONST64(0x39384993aaaa92aa), CONST64(0xafa8e2de7171d971), 
+CONST64(0x0ecf8dc6c8c807c8), CONST64(0xc87d32d119196419), CONST64(0x7270923b49493949), CONST64(0x869aaf5fd9d943d9), 
+CONST64(0xc31df931f2f2eff2), CONST64(0x4b48dba8e3e3abe3), CONST64(0xe22ab6b95b5b715b), CONST64(0x34920dbc88881a88), 
+CONST64(0xa4c8293e9a9a529a), CONST64(0x2dbe4c0b26269826), CONST64(0x8dfa64bf3232c832), CONST64(0xe94a7d59b0b0fab0), 
+CONST64(0x1b6acff2e9e983e9), CONST64(0x78331e770f0f3c0f), CONST64(0xe6a6b733d5d573d5), CONST64(0x74ba1df480803a80), 
+CONST64(0x997c6127bebec2be), CONST64(0x26de87ebcdcd13cd), CONST64(0xbde468893434d034), CONST64(0x7a75903248483d48), 
+CONST64(0xab24e354ffffdbff), CONST64(0xf78ff48d7a7af57a), CONST64(0xf4ea3d6490907a90), CONST64(0xc23ebe9d5f5f615f), 
+CONST64(0x1da0403d20208020), CONST64(0x67d5d00f6868bd68), CONST64(0xd07234ca1a1a681a), CONST64(0x192c41b7aeae82ae), 
+CONST64(0xc95e757db4b4eab4), CONST64(0x9a19a8ce54544d54), CONST64(0xece53b7f93937693), CONST64(0x0daa442f22228822), 
+CONST64(0x07e9c86364648d64), CONST64(0xdb12ff2af1f1e3f1), CONST64(0xbfa2e6cc7373d173), CONST64(0x905a248212124812), 
+CONST64(0x3a5d807a40401d40), CONST64(0x4028104808082008), CONST64(0x56e89b95c3c32bc3), CONST64(0x337bc5dfecec97ec), 
+CONST64(0x9690ab4ddbdb4bdb), CONST64(0x611f5fc0a1a1bea1), CONST64(0x1c8307918d8d0e8d), CONST64(0xf5c97ac83d3df43d), 
+CONST64(0xccf1335b97976697), CONST64(0x0000000000000000), CONST64(0x36d483f9cfcf1bcf), CONST64(0x4587566e2b2bac2b), 
+CONST64(0x97b3ece17676c576), CONST64(0x64b019e682823282), CONST64(0xfea9b128d6d67fd6), CONST64(0xd87736c31b1b6c1b), 
+CONST64(0xc15b7774b5b5eeb5), CONST64(0x112943beafaf86af), CONST64(0x77dfd41d6a6ab56a), CONST64(0xba0da0ea50505d50), 
+CONST64(0x124c8a5745450945), CONST64(0xcb18fb38f3f3ebf3), CONST64(0x9df060ad3030c030), CONST64(0x2b74c3c4efef9bef), 
+CONST64(0xe5c37eda3f3ffc3f), CONST64(0x921caac755554955), CONST64(0x791059dba2a2b2a2), CONST64(0x0365c9e9eaea8fea), 
+CONST64(0x0fecca6a65658965), CONST64(0xb9686903babad2ba), CONST64(0x65935e4a2f2fbc2f), CONST64(0x4ee79d8ec0c027c0), 
+CONST64(0xbe81a160dede5fde), CONST64(0xe06c38fc1c1c701c), CONST64(0xbb2ee746fdfdd3fd), CONST64(0x52649a1f4d4d294d), 
+CONST64(0xe4e0397692927292), CONST64(0x8fbceafa7575c975), CONST64(0x301e0c3606061806), CONST64(0x249809ae8a8a128a), 
+CONST64(0xf940794bb2b2f2b2), CONST64(0x6359d185e6e6bfe6), CONST64(0x70361c7e0e0e380e), CONST64(0xf8633ee71f1f7c1f), 
+CONST64(0x37f7c45562629562), CONST64(0xeea3b53ad4d477d4), CONST64(0x29324d81a8a89aa8), CONST64(0xc4f4315296966296), 
+CONST64(0x9b3aef62f9f9c3f9), CONST64(0x66f697a3c5c533c5), CONST64(0x35b14a1025259425), CONST64(0xf220b2ab59597959), 
+CONST64(0x54ae15d084842a84), CONST64(0xb7a7e4c57272d572), CONST64(0xd5dd72ec3939e439), CONST64(0x5a6198164c4c2d4c), 
+CONST64(0xca3bbc945e5e655e), CONST64(0xe785f09f7878fd78), CONST64(0xddd870e53838e038), CONST64(0x148605988c8c0a8c), 
+CONST64(0xc6b2bf17d1d163d1), CONST64(0x410b57e4a5a5aea5), CONST64(0x434dd9a1e2e2afe2), CONST64(0x2ff8c24e61619961), 
+CONST64(0xf1457b42b3b3f6b3), CONST64(0x15a5423421218421), CONST64(0x94d625089c9c4a9c), CONST64(0xf0663cee1e1e781e), 
+CONST64(0x2252866143431143), CONST64(0x76fc93b1c7c73bc7), CONST64(0xb32be54ffcfcd7fc), CONST64(0x2014082404041004), 
+CONST64(0xb208a2e351515951), CONST64(0xbcc72f2599995e99), CONST64(0x4fc4da226d6da96d), CONST64(0x68391a650d0d340d), 
+CONST64(0x8335e979fafacffa), CONST64(0xb684a369dfdf5bdf), CONST64(0xd79bfca97e7ee57e), CONST64(0x3db4481924249024), 
+CONST64(0xc5d776fe3b3bec3b), CONST64(0x313d4b9aabab96ab), CONST64(0x3ed181f0cece1fce), CONST64(0x8855229911114411), 
+CONST64(0x0c8903838f8f068f), CONST64(0x4a6b9c044e4e254e), CONST64(0xd1517366b7b7e6b7), CONST64(0x0b60cbe0ebeb8beb), 
+CONST64(0xfdcc78c13c3cf03c), CONST64(0x7cbf1ffd81813e81), CONST64(0xd4fe354094946a94), CONST64(0xeb0cf31cf7f7fbf7), 
+CONST64(0xa1676f18b9b9deb9), CONST64(0x985f268b13134c13), CONST64(0x7d9c58512c2cb02c), CONST64(0xd6b8bb05d3d36bd3), 
+CONST64(0x6b5cd38ce7e7bbe7), CONST64(0x57cbdc396e6ea56e), CONST64(0x6ef395aac4c437c4), CONST64(0x180f061b03030c03), 
+CONST64(0x8a13acdc56564556), CONST64(0x1a49885e44440d44), CONST64(0xdf9efea07f7fe17f), CONST64(0x21374f88a9a99ea9), 
+CONST64(0x4d8254672a2aa82a), CONST64(0xb16d6b0abbbbd6bb), CONST64(0x46e29f87c1c123c1), CONST64(0xa202a6f153535153), 
+CONST64(0xae8ba572dcdc57dc), CONST64(0x582716530b0b2c0b), CONST64(0x9cd327019d9d4e9d), CONST64(0x47c1d82b6c6cad6c), 
+CONST64(0x95f562a43131c431), CONST64(0x87b9e8f37474cd74), CONST64(0xe309f115f6f6fff6), CONST64(0x0a438c4c46460546), 
+CONST64(0x092645a5acac8aac), CONST64(0x3c970fb589891e89), CONST64(0xa04428b414145014), CONST64(0x5b42dfbae1e1a3e1), 
+CONST64(0xb04e2ca616165816), CONST64(0xcdd274f73a3ae83a), CONST64(0x6fd0d2066969b969), CONST64(0x482d124109092409), 
+CONST64(0xa7ade0d77070dd70), CONST64(0xd954716fb6b6e2b6), CONST64(0xceb7bd1ed0d067d0), CONST64(0x3b7ec7d6eded93ed), 
+CONST64(0x2edb85e2cccc17cc), CONST64(0x2a57846842421542), CONST64(0xb4c22d2c98985a98), CONST64(0x490e55eda4a4aaa4), 
+CONST64(0x5d8850752828a028), CONST64(0xda31b8865c5c6d5c), CONST64(0x933fed6bf8f8c7f8), CONST64(0x44a411c286862286)
+};
+
+static const ulong64 sbox5[] = {
+CONST64(0x18c07830d8181860), CONST64(0x2305af462623238c), CONST64(0xc67ef991b8c6c63f), CONST64(0xe8136fcdfbe8e887), 
+CONST64(0x874ca113cb878726), CONST64(0xb8a9626d11b8b8da), CONST64(0x0108050209010104), CONST64(0x4f426e9e0d4f4f21), 
+CONST64(0x36adee6c9b3636d8), CONST64(0xa6590451ffa6a6a2), CONST64(0xd2debdb90cd2d26f), CONST64(0xf5fb06f70ef5f5f3), 
+CONST64(0x79ef80f2967979f9), CONST64(0x6f5fcede306f6fa1), CONST64(0x91fcef3f6d91917e), CONST64(0x52aa07a4f8525255), 
+CONST64(0x6027fdc04760609d), CONST64(0xbc89766535bcbcca), CONST64(0x9baccd2b379b9b56), CONST64(0x8e048c018a8e8e02), 
+CONST64(0xa371155bd2a3a3b6), CONST64(0x0c603c186c0c0c30), CONST64(0x7bff8af6847b7bf1), CONST64(0x35b5e16a803535d4), 
+CONST64(0x1de8693af51d1d74), CONST64(0xe05347ddb3e0e0a7), CONST64(0xd7f6acb321d7d77b), CONST64(0xc25eed999cc2c22f), 
+CONST64(0x2e6d965c432e2eb8), CONST64(0x4b627a96294b4b31), CONST64(0xfea321e15dfefedf), CONST64(0x578216aed5575741), 
+CONST64(0x15a8412abd151554), CONST64(0x779fb6eee87777c1), CONST64(0x37a5eb6e923737dc), CONST64(0xe57b56d79ee5e5b3), 
+CONST64(0x9f8cd923139f9f46), CONST64(0xf0d317fd23f0f0e7), CONST64(0x4a6a7f94204a4a35), CONST64(0xda9e95a944dada4f), 
+CONST64(0x58fa25b0a258587d), CONST64(0xc906ca8fcfc9c903), CONST64(0x29558d527c2929a4), CONST64(0x0a5022145a0a0a28), 
+CONST64(0xb1e14f7f50b1b1fe), CONST64(0xa0691a5dc9a0a0ba), CONST64(0x6b7fdad6146b6bb1), CONST64(0x855cab17d985852e), 
+CONST64(0xbd8173673cbdbdce), CONST64(0x5dd234ba8f5d5d69), CONST64(0x1080502090101040), CONST64(0xf4f303f507f4f4f7), 
+CONST64(0xcb16c08bddcbcb0b), CONST64(0x3eedc67cd33e3ef8), CONST64(0x0528110a2d050514), CONST64(0x671fe6ce78676781), 
+CONST64(0xe47353d597e4e4b7), CONST64(0x2725bb4e0227279c), CONST64(0x4132588273414119), CONST64(0x8b2c9d0ba78b8b16), 
+CONST64(0xa7510153f6a7a7a6), CONST64(0x7dcf94fab27d7de9), CONST64(0x95dcfb374995956e), CONST64(0xd88e9fad56d8d847), 
+CONST64(0xfb8b30eb70fbfbcb), CONST64(0xee2371c1cdeeee9f), CONST64(0x7cc791f8bb7c7ced), CONST64(0x6617e3cc71666685), 
+CONST64(0xdda68ea77bdddd53), CONST64(0x17b84b2eaf17175c), CONST64(0x4702468e45474701), CONST64(0x9e84dc211a9e9e42), 
+CONST64(0xca1ec589d4caca0f), CONST64(0x2d75995a582d2db4), CONST64(0xbf9179632ebfbfc6), CONST64(0x07381b0e3f07071c), 
+CONST64(0xad012347acadad8e), CONST64(0x5aea2fb4b05a5a75), CONST64(0x836cb51bef838336), CONST64(0x3385ff66b63333cc), 
+CONST64(0x633ff2c65c636391), CONST64(0x02100a0412020208), CONST64(0xaa39384993aaaa92), CONST64(0x71afa8e2de7171d9), 
+CONST64(0xc80ecf8dc6c8c807), CONST64(0x19c87d32d1191964), CONST64(0x497270923b494939), CONST64(0xd9869aaf5fd9d943), 
+CONST64(0xf2c31df931f2f2ef), CONST64(0xe34b48dba8e3e3ab), CONST64(0x5be22ab6b95b5b71), CONST64(0x8834920dbc88881a), 
+CONST64(0x9aa4c8293e9a9a52), CONST64(0x262dbe4c0b262698), CONST64(0x328dfa64bf3232c8), CONST64(0xb0e94a7d59b0b0fa), 
+CONST64(0xe91b6acff2e9e983), CONST64(0x0f78331e770f0f3c), CONST64(0xd5e6a6b733d5d573), CONST64(0x8074ba1df480803a), 
+CONST64(0xbe997c6127bebec2), CONST64(0xcd26de87ebcdcd13), CONST64(0x34bde468893434d0), CONST64(0x487a75903248483d), 
+CONST64(0xffab24e354ffffdb), CONST64(0x7af78ff48d7a7af5), CONST64(0x90f4ea3d6490907a), CONST64(0x5fc23ebe9d5f5f61), 
+CONST64(0x201da0403d202080), CONST64(0x6867d5d00f6868bd), CONST64(0x1ad07234ca1a1a68), CONST64(0xae192c41b7aeae82), 
+CONST64(0xb4c95e757db4b4ea), CONST64(0x549a19a8ce54544d), CONST64(0x93ece53b7f939376), CONST64(0x220daa442f222288), 
+CONST64(0x6407e9c86364648d), CONST64(0xf1db12ff2af1f1e3), CONST64(0x73bfa2e6cc7373d1), CONST64(0x12905a2482121248), 
+CONST64(0x403a5d807a40401d), CONST64(0x0840281048080820), CONST64(0xc356e89b95c3c32b), CONST64(0xec337bc5dfecec97), 
+CONST64(0xdb9690ab4ddbdb4b), CONST64(0xa1611f5fc0a1a1be), CONST64(0x8d1c8307918d8d0e), CONST64(0x3df5c97ac83d3df4), 
+CONST64(0x97ccf1335b979766), CONST64(0x0000000000000000), CONST64(0xcf36d483f9cfcf1b), CONST64(0x2b4587566e2b2bac), 
+CONST64(0x7697b3ece17676c5), CONST64(0x8264b019e6828232), CONST64(0xd6fea9b128d6d67f), CONST64(0x1bd87736c31b1b6c), 
+CONST64(0xb5c15b7774b5b5ee), CONST64(0xaf112943beafaf86), CONST64(0x6a77dfd41d6a6ab5), CONST64(0x50ba0da0ea50505d), 
+CONST64(0x45124c8a57454509), CONST64(0xf3cb18fb38f3f3eb), CONST64(0x309df060ad3030c0), CONST64(0xef2b74c3c4efef9b), 
+CONST64(0x3fe5c37eda3f3ffc), CONST64(0x55921caac7555549), CONST64(0xa2791059dba2a2b2), CONST64(0xea0365c9e9eaea8f), 
+CONST64(0x650fecca6a656589), CONST64(0xbab9686903babad2), CONST64(0x2f65935e4a2f2fbc), CONST64(0xc04ee79d8ec0c027), 
+CONST64(0xdebe81a160dede5f), CONST64(0x1ce06c38fc1c1c70), CONST64(0xfdbb2ee746fdfdd3), CONST64(0x4d52649a1f4d4d29), 
+CONST64(0x92e4e03976929272), CONST64(0x758fbceafa7575c9), CONST64(0x06301e0c36060618), CONST64(0x8a249809ae8a8a12), 
+CONST64(0xb2f940794bb2b2f2), CONST64(0xe66359d185e6e6bf), CONST64(0x0e70361c7e0e0e38), CONST64(0x1ff8633ee71f1f7c), 
+CONST64(0x6237f7c455626295), CONST64(0xd4eea3b53ad4d477), CONST64(0xa829324d81a8a89a), CONST64(0x96c4f43152969662), 
+CONST64(0xf99b3aef62f9f9c3), CONST64(0xc566f697a3c5c533), CONST64(0x2535b14a10252594), CONST64(0x59f220b2ab595979), 
+CONST64(0x8454ae15d084842a), CONST64(0x72b7a7e4c57272d5), CONST64(0x39d5dd72ec3939e4), CONST64(0x4c5a6198164c4c2d), 
+CONST64(0x5eca3bbc945e5e65), CONST64(0x78e785f09f7878fd), CONST64(0x38ddd870e53838e0), CONST64(0x8c148605988c8c0a), 
+CONST64(0xd1c6b2bf17d1d163), CONST64(0xa5410b57e4a5a5ae), CONST64(0xe2434dd9a1e2e2af), CONST64(0x612ff8c24e616199), 
+CONST64(0xb3f1457b42b3b3f6), CONST64(0x2115a54234212184), CONST64(0x9c94d625089c9c4a), CONST64(0x1ef0663cee1e1e78), 
+CONST64(0x4322528661434311), CONST64(0xc776fc93b1c7c73b), CONST64(0xfcb32be54ffcfcd7), CONST64(0x0420140824040410), 
+CONST64(0x51b208a2e3515159), CONST64(0x99bcc72f2599995e), CONST64(0x6d4fc4da226d6da9), CONST64(0x0d68391a650d0d34), 
+CONST64(0xfa8335e979fafacf), CONST64(0xdfb684a369dfdf5b), CONST64(0x7ed79bfca97e7ee5), CONST64(0x243db44819242490), 
+CONST64(0x3bc5d776fe3b3bec), CONST64(0xab313d4b9aabab96), CONST64(0xce3ed181f0cece1f), CONST64(0x1188552299111144), 
+CONST64(0x8f0c8903838f8f06), CONST64(0x4e4a6b9c044e4e25), CONST64(0xb7d1517366b7b7e6), CONST64(0xeb0b60cbe0ebeb8b), 
+CONST64(0x3cfdcc78c13c3cf0), CONST64(0x817cbf1ffd81813e), CONST64(0x94d4fe354094946a), CONST64(0xf7eb0cf31cf7f7fb), 
+CONST64(0xb9a1676f18b9b9de), CONST64(0x13985f268b13134c), CONST64(0x2c7d9c58512c2cb0), CONST64(0xd3d6b8bb05d3d36b), 
+CONST64(0xe76b5cd38ce7e7bb), CONST64(0x6e57cbdc396e6ea5), CONST64(0xc46ef395aac4c437), CONST64(0x03180f061b03030c), 
+CONST64(0x568a13acdc565645), CONST64(0x441a49885e44440d), CONST64(0x7fdf9efea07f7fe1), CONST64(0xa921374f88a9a99e), 
+CONST64(0x2a4d8254672a2aa8), CONST64(0xbbb16d6b0abbbbd6), CONST64(0xc146e29f87c1c123), CONST64(0x53a202a6f1535351), 
+CONST64(0xdcae8ba572dcdc57), CONST64(0x0b582716530b0b2c), CONST64(0x9d9cd327019d9d4e), CONST64(0x6c47c1d82b6c6cad), 
+CONST64(0x3195f562a43131c4), CONST64(0x7487b9e8f37474cd), CONST64(0xf6e309f115f6f6ff), CONST64(0x460a438c4c464605), 
+CONST64(0xac092645a5acac8a), CONST64(0x893c970fb589891e), CONST64(0x14a04428b4141450), CONST64(0xe15b42dfbae1e1a3), 
+CONST64(0x16b04e2ca6161658), CONST64(0x3acdd274f73a3ae8), CONST64(0x696fd0d2066969b9), CONST64(0x09482d1241090924), 
+CONST64(0x70a7ade0d77070dd), CONST64(0xb6d954716fb6b6e2), CONST64(0xd0ceb7bd1ed0d067), CONST64(0xed3b7ec7d6eded93), 
+CONST64(0xcc2edb85e2cccc17), CONST64(0x422a578468424215), CONST64(0x98b4c22d2c98985a), CONST64(0xa4490e55eda4a4aa), 
+CONST64(0x285d8850752828a0), CONST64(0x5cda31b8865c5c6d), CONST64(0xf8933fed6bf8f8c7), CONST64(0x8644a411c2868622)
+};
+
+static const ulong64 sbox6[] = {
+CONST64(0x6018c07830d81818), CONST64(0x8c2305af46262323), CONST64(0x3fc67ef991b8c6c6), CONST64(0x87e8136fcdfbe8e8), 
+CONST64(0x26874ca113cb8787), CONST64(0xdab8a9626d11b8b8), CONST64(0x0401080502090101), CONST64(0x214f426e9e0d4f4f), 
+CONST64(0xd836adee6c9b3636), CONST64(0xa2a6590451ffa6a6), CONST64(0x6fd2debdb90cd2d2), CONST64(0xf3f5fb06f70ef5f5), 
+CONST64(0xf979ef80f2967979), CONST64(0xa16f5fcede306f6f), CONST64(0x7e91fcef3f6d9191), CONST64(0x5552aa07a4f85252), 
+CONST64(0x9d6027fdc0476060), CONST64(0xcabc89766535bcbc), CONST64(0x569baccd2b379b9b), CONST64(0x028e048c018a8e8e), 
+CONST64(0xb6a371155bd2a3a3), CONST64(0x300c603c186c0c0c), CONST64(0xf17bff8af6847b7b), CONST64(0xd435b5e16a803535), 
+CONST64(0x741de8693af51d1d), CONST64(0xa7e05347ddb3e0e0), CONST64(0x7bd7f6acb321d7d7), CONST64(0x2fc25eed999cc2c2), 
+CONST64(0xb82e6d965c432e2e), CONST64(0x314b627a96294b4b), CONST64(0xdffea321e15dfefe), CONST64(0x41578216aed55757), 
+CONST64(0x5415a8412abd1515), CONST64(0xc1779fb6eee87777), CONST64(0xdc37a5eb6e923737), CONST64(0xb3e57b56d79ee5e5), 
+CONST64(0x469f8cd923139f9f), CONST64(0xe7f0d317fd23f0f0), CONST64(0x354a6a7f94204a4a), CONST64(0x4fda9e95a944dada), 
+CONST64(0x7d58fa25b0a25858), CONST64(0x03c906ca8fcfc9c9), CONST64(0xa429558d527c2929), CONST64(0x280a5022145a0a0a), 
+CONST64(0xfeb1e14f7f50b1b1), CONST64(0xbaa0691a5dc9a0a0), CONST64(0xb16b7fdad6146b6b), CONST64(0x2e855cab17d98585), 
+CONST64(0xcebd8173673cbdbd), CONST64(0x695dd234ba8f5d5d), CONST64(0x4010805020901010), CONST64(0xf7f4f303f507f4f4), 
+CONST64(0x0bcb16c08bddcbcb), CONST64(0xf83eedc67cd33e3e), CONST64(0x140528110a2d0505), CONST64(0x81671fe6ce786767), 
+CONST64(0xb7e47353d597e4e4), CONST64(0x9c2725bb4e022727), CONST64(0x1941325882734141), CONST64(0x168b2c9d0ba78b8b), 
+CONST64(0xa6a7510153f6a7a7), CONST64(0xe97dcf94fab27d7d), CONST64(0x6e95dcfb37499595), CONST64(0x47d88e9fad56d8d8), 
+CONST64(0xcbfb8b30eb70fbfb), CONST64(0x9fee2371c1cdeeee), CONST64(0xed7cc791f8bb7c7c), CONST64(0x856617e3cc716666), 
+CONST64(0x53dda68ea77bdddd), CONST64(0x5c17b84b2eaf1717), CONST64(0x014702468e454747), CONST64(0x429e84dc211a9e9e), 
+CONST64(0x0fca1ec589d4caca), CONST64(0xb42d75995a582d2d), CONST64(0xc6bf9179632ebfbf), CONST64(0x1c07381b0e3f0707), 
+CONST64(0x8ead012347acadad), CONST64(0x755aea2fb4b05a5a), CONST64(0x36836cb51bef8383), CONST64(0xcc3385ff66b63333), 
+CONST64(0x91633ff2c65c6363), CONST64(0x0802100a04120202), CONST64(0x92aa39384993aaaa), CONST64(0xd971afa8e2de7171), 
+CONST64(0x07c80ecf8dc6c8c8), CONST64(0x6419c87d32d11919), CONST64(0x39497270923b4949), CONST64(0x43d9869aaf5fd9d9), 
+CONST64(0xeff2c31df931f2f2), CONST64(0xabe34b48dba8e3e3), CONST64(0x715be22ab6b95b5b), CONST64(0x1a8834920dbc8888), 
+CONST64(0x529aa4c8293e9a9a), CONST64(0x98262dbe4c0b2626), CONST64(0xc8328dfa64bf3232), CONST64(0xfab0e94a7d59b0b0), 
+CONST64(0x83e91b6acff2e9e9), CONST64(0x3c0f78331e770f0f), CONST64(0x73d5e6a6b733d5d5), CONST64(0x3a8074ba1df48080), 
+CONST64(0xc2be997c6127bebe), CONST64(0x13cd26de87ebcdcd), CONST64(0xd034bde468893434), CONST64(0x3d487a7590324848), 
+CONST64(0xdbffab24e354ffff), CONST64(0xf57af78ff48d7a7a), CONST64(0x7a90f4ea3d649090), CONST64(0x615fc23ebe9d5f5f), 
+CONST64(0x80201da0403d2020), CONST64(0xbd6867d5d00f6868), CONST64(0x681ad07234ca1a1a), CONST64(0x82ae192c41b7aeae), 
+CONST64(0xeab4c95e757db4b4), CONST64(0x4d549a19a8ce5454), CONST64(0x7693ece53b7f9393), CONST64(0x88220daa442f2222), 
+CONST64(0x8d6407e9c8636464), CONST64(0xe3f1db12ff2af1f1), CONST64(0xd173bfa2e6cc7373), CONST64(0x4812905a24821212), 
+CONST64(0x1d403a5d807a4040), CONST64(0x2008402810480808), CONST64(0x2bc356e89b95c3c3), CONST64(0x97ec337bc5dfecec), 
+CONST64(0x4bdb9690ab4ddbdb), CONST64(0xbea1611f5fc0a1a1), CONST64(0x0e8d1c8307918d8d), CONST64(0xf43df5c97ac83d3d), 
+CONST64(0x6697ccf1335b9797), CONST64(0x0000000000000000), CONST64(0x1bcf36d483f9cfcf), CONST64(0xac2b4587566e2b2b), 
+CONST64(0xc57697b3ece17676), CONST64(0x328264b019e68282), CONST64(0x7fd6fea9b128d6d6), CONST64(0x6c1bd87736c31b1b), 
+CONST64(0xeeb5c15b7774b5b5), CONST64(0x86af112943beafaf), CONST64(0xb56a77dfd41d6a6a), CONST64(0x5d50ba0da0ea5050), 
+CONST64(0x0945124c8a574545), CONST64(0xebf3cb18fb38f3f3), CONST64(0xc0309df060ad3030), CONST64(0x9bef2b74c3c4efef), 
+CONST64(0xfc3fe5c37eda3f3f), CONST64(0x4955921caac75555), CONST64(0xb2a2791059dba2a2), CONST64(0x8fea0365c9e9eaea), 
+CONST64(0x89650fecca6a6565), CONST64(0xd2bab9686903baba), CONST64(0xbc2f65935e4a2f2f), CONST64(0x27c04ee79d8ec0c0), 
+CONST64(0x5fdebe81a160dede), CONST64(0x701ce06c38fc1c1c), CONST64(0xd3fdbb2ee746fdfd), CONST64(0x294d52649a1f4d4d), 
+CONST64(0x7292e4e039769292), CONST64(0xc9758fbceafa7575), CONST64(0x1806301e0c360606), CONST64(0x128a249809ae8a8a), 
+CONST64(0xf2b2f940794bb2b2), CONST64(0xbfe66359d185e6e6), CONST64(0x380e70361c7e0e0e), CONST64(0x7c1ff8633ee71f1f), 
+CONST64(0x956237f7c4556262), CONST64(0x77d4eea3b53ad4d4), CONST64(0x9aa829324d81a8a8), CONST64(0x6296c4f431529696), 
+CONST64(0xc3f99b3aef62f9f9), CONST64(0x33c566f697a3c5c5), CONST64(0x942535b14a102525), CONST64(0x7959f220b2ab5959), 
+CONST64(0x2a8454ae15d08484), CONST64(0xd572b7a7e4c57272), CONST64(0xe439d5dd72ec3939), CONST64(0x2d4c5a6198164c4c), 
+CONST64(0x655eca3bbc945e5e), CONST64(0xfd78e785f09f7878), CONST64(0xe038ddd870e53838), CONST64(0x0a8c148605988c8c), 
+CONST64(0x63d1c6b2bf17d1d1), CONST64(0xaea5410b57e4a5a5), CONST64(0xafe2434dd9a1e2e2), CONST64(0x99612ff8c24e6161), 
+CONST64(0xf6b3f1457b42b3b3), CONST64(0x842115a542342121), CONST64(0x4a9c94d625089c9c), CONST64(0x781ef0663cee1e1e), 
+CONST64(0x1143225286614343), CONST64(0x3bc776fc93b1c7c7), CONST64(0xd7fcb32be54ffcfc), CONST64(0x1004201408240404), 
+CONST64(0x5951b208a2e35151), CONST64(0x5e99bcc72f259999), CONST64(0xa96d4fc4da226d6d), CONST64(0x340d68391a650d0d), 
+CONST64(0xcffa8335e979fafa), CONST64(0x5bdfb684a369dfdf), CONST64(0xe57ed79bfca97e7e), CONST64(0x90243db448192424), 
+CONST64(0xec3bc5d776fe3b3b), CONST64(0x96ab313d4b9aabab), CONST64(0x1fce3ed181f0cece), CONST64(0x4411885522991111), 
+CONST64(0x068f0c8903838f8f), CONST64(0x254e4a6b9c044e4e), CONST64(0xe6b7d1517366b7b7), CONST64(0x8beb0b60cbe0ebeb), 
+CONST64(0xf03cfdcc78c13c3c), CONST64(0x3e817cbf1ffd8181), CONST64(0x6a94d4fe35409494), CONST64(0xfbf7eb0cf31cf7f7), 
+CONST64(0xdeb9a1676f18b9b9), CONST64(0x4c13985f268b1313), CONST64(0xb02c7d9c58512c2c), CONST64(0x6bd3d6b8bb05d3d3), 
+CONST64(0xbbe76b5cd38ce7e7), CONST64(0xa56e57cbdc396e6e), CONST64(0x37c46ef395aac4c4), CONST64(0x0c03180f061b0303), 
+CONST64(0x45568a13acdc5656), CONST64(0x0d441a49885e4444), CONST64(0xe17fdf9efea07f7f), CONST64(0x9ea921374f88a9a9), 
+CONST64(0xa82a4d8254672a2a), CONST64(0xd6bbb16d6b0abbbb), CONST64(0x23c146e29f87c1c1), CONST64(0x5153a202a6f15353), 
+CONST64(0x57dcae8ba572dcdc), CONST64(0x2c0b582716530b0b), CONST64(0x4e9d9cd327019d9d), CONST64(0xad6c47c1d82b6c6c), 
+CONST64(0xc43195f562a43131), CONST64(0xcd7487b9e8f37474), CONST64(0xfff6e309f115f6f6), CONST64(0x05460a438c4c4646), 
+CONST64(0x8aac092645a5acac), CONST64(0x1e893c970fb58989), CONST64(0x5014a04428b41414), CONST64(0xa3e15b42dfbae1e1), 
+CONST64(0x5816b04e2ca61616), CONST64(0xe83acdd274f73a3a), CONST64(0xb9696fd0d2066969), CONST64(0x2409482d12410909), 
+CONST64(0xdd70a7ade0d77070), CONST64(0xe2b6d954716fb6b6), CONST64(0x67d0ceb7bd1ed0d0), CONST64(0x93ed3b7ec7d6eded), 
+CONST64(0x17cc2edb85e2cccc), CONST64(0x15422a5784684242), CONST64(0x5a98b4c22d2c9898), CONST64(0xaaa4490e55eda4a4), 
+CONST64(0xa0285d8850752828), CONST64(0x6d5cda31b8865c5c), CONST64(0xc7f8933fed6bf8f8), CONST64(0x228644a411c28686)
+};
+
+static const ulong64 sbox7[] = {
+CONST64(0x186018c07830d818), CONST64(0x238c2305af462623), CONST64(0xc63fc67ef991b8c6), CONST64(0xe887e8136fcdfbe8), 
+CONST64(0x8726874ca113cb87), CONST64(0xb8dab8a9626d11b8), CONST64(0x0104010805020901), CONST64(0x4f214f426e9e0d4f), 
+CONST64(0x36d836adee6c9b36), CONST64(0xa6a2a6590451ffa6), CONST64(0xd26fd2debdb90cd2), CONST64(0xf5f3f5fb06f70ef5), 
+CONST64(0x79f979ef80f29679), CONST64(0x6fa16f5fcede306f), CONST64(0x917e91fcef3f6d91), CONST64(0x525552aa07a4f852), 
+CONST64(0x609d6027fdc04760), CONST64(0xbccabc89766535bc), CONST64(0x9b569baccd2b379b), CONST64(0x8e028e048c018a8e), 
+CONST64(0xa3b6a371155bd2a3), CONST64(0x0c300c603c186c0c), CONST64(0x7bf17bff8af6847b), CONST64(0x35d435b5e16a8035), 
+CONST64(0x1d741de8693af51d), CONST64(0xe0a7e05347ddb3e0), CONST64(0xd77bd7f6acb321d7), CONST64(0xc22fc25eed999cc2), 
+CONST64(0x2eb82e6d965c432e), CONST64(0x4b314b627a96294b), CONST64(0xfedffea321e15dfe), CONST64(0x5741578216aed557), 
+CONST64(0x155415a8412abd15), CONST64(0x77c1779fb6eee877), CONST64(0x37dc37a5eb6e9237), CONST64(0xe5b3e57b56d79ee5), 
+CONST64(0x9f469f8cd923139f), CONST64(0xf0e7f0d317fd23f0), CONST64(0x4a354a6a7f94204a), CONST64(0xda4fda9e95a944da), 
+CONST64(0x587d58fa25b0a258), CONST64(0xc903c906ca8fcfc9), CONST64(0x29a429558d527c29), CONST64(0x0a280a5022145a0a), 
+CONST64(0xb1feb1e14f7f50b1), CONST64(0xa0baa0691a5dc9a0), CONST64(0x6bb16b7fdad6146b), CONST64(0x852e855cab17d985), 
+CONST64(0xbdcebd8173673cbd), CONST64(0x5d695dd234ba8f5d), CONST64(0x1040108050209010), CONST64(0xf4f7f4f303f507f4), 
+CONST64(0xcb0bcb16c08bddcb), CONST64(0x3ef83eedc67cd33e), CONST64(0x05140528110a2d05), CONST64(0x6781671fe6ce7867), 
+CONST64(0xe4b7e47353d597e4), CONST64(0x279c2725bb4e0227), CONST64(0x4119413258827341), CONST64(0x8b168b2c9d0ba78b), 
+CONST64(0xa7a6a7510153f6a7), CONST64(0x7de97dcf94fab27d), CONST64(0x956e95dcfb374995), CONST64(0xd847d88e9fad56d8), 
+CONST64(0xfbcbfb8b30eb70fb), CONST64(0xee9fee2371c1cdee), CONST64(0x7ced7cc791f8bb7c), CONST64(0x66856617e3cc7166), 
+CONST64(0xdd53dda68ea77bdd), CONST64(0x175c17b84b2eaf17), CONST64(0x47014702468e4547), CONST64(0x9e429e84dc211a9e), 
+CONST64(0xca0fca1ec589d4ca), CONST64(0x2db42d75995a582d), CONST64(0xbfc6bf9179632ebf), CONST64(0x071c07381b0e3f07), 
+CONST64(0xad8ead012347acad), CONST64(0x5a755aea2fb4b05a), CONST64(0x8336836cb51bef83), CONST64(0x33cc3385ff66b633), 
+CONST64(0x6391633ff2c65c63), CONST64(0x020802100a041202), CONST64(0xaa92aa39384993aa), CONST64(0x71d971afa8e2de71), 
+CONST64(0xc807c80ecf8dc6c8), CONST64(0x196419c87d32d119), CONST64(0x4939497270923b49), CONST64(0xd943d9869aaf5fd9), 
+CONST64(0xf2eff2c31df931f2), CONST64(0xe3abe34b48dba8e3), CONST64(0x5b715be22ab6b95b), CONST64(0x881a8834920dbc88), 
+CONST64(0x9a529aa4c8293e9a), CONST64(0x2698262dbe4c0b26), CONST64(0x32c8328dfa64bf32), CONST64(0xb0fab0e94a7d59b0), 
+CONST64(0xe983e91b6acff2e9), CONST64(0x0f3c0f78331e770f), CONST64(0xd573d5e6a6b733d5), CONST64(0x803a8074ba1df480), 
+CONST64(0xbec2be997c6127be), CONST64(0xcd13cd26de87ebcd), CONST64(0x34d034bde4688934), CONST64(0x483d487a75903248), 
+CONST64(0xffdbffab24e354ff), CONST64(0x7af57af78ff48d7a), CONST64(0x907a90f4ea3d6490), CONST64(0x5f615fc23ebe9d5f), 
+CONST64(0x2080201da0403d20), CONST64(0x68bd6867d5d00f68), CONST64(0x1a681ad07234ca1a), CONST64(0xae82ae192c41b7ae), 
+CONST64(0xb4eab4c95e757db4), CONST64(0x544d549a19a8ce54), CONST64(0x937693ece53b7f93), CONST64(0x2288220daa442f22), 
+CONST64(0x648d6407e9c86364), CONST64(0xf1e3f1db12ff2af1), CONST64(0x73d173bfa2e6cc73), CONST64(0x124812905a248212), 
+CONST64(0x401d403a5d807a40), CONST64(0x0820084028104808), CONST64(0xc32bc356e89b95c3), CONST64(0xec97ec337bc5dfec), 
+CONST64(0xdb4bdb9690ab4ddb), CONST64(0xa1bea1611f5fc0a1), CONST64(0x8d0e8d1c8307918d), CONST64(0x3df43df5c97ac83d), 
+CONST64(0x976697ccf1335b97), CONST64(0x0000000000000000), CONST64(0xcf1bcf36d483f9cf), CONST64(0x2bac2b4587566e2b), 
+CONST64(0x76c57697b3ece176), CONST64(0x82328264b019e682), CONST64(0xd67fd6fea9b128d6), CONST64(0x1b6c1bd87736c31b), 
+CONST64(0xb5eeb5c15b7774b5), CONST64(0xaf86af112943beaf), CONST64(0x6ab56a77dfd41d6a), CONST64(0x505d50ba0da0ea50), 
+CONST64(0x450945124c8a5745), CONST64(0xf3ebf3cb18fb38f3), CONST64(0x30c0309df060ad30), CONST64(0xef9bef2b74c3c4ef), 
+CONST64(0x3ffc3fe5c37eda3f), CONST64(0x554955921caac755), CONST64(0xa2b2a2791059dba2), CONST64(0xea8fea0365c9e9ea), 
+CONST64(0x6589650fecca6a65), CONST64(0xbad2bab9686903ba), CONST64(0x2fbc2f65935e4a2f), CONST64(0xc027c04ee79d8ec0), 
+CONST64(0xde5fdebe81a160de), CONST64(0x1c701ce06c38fc1c), CONST64(0xfdd3fdbb2ee746fd), CONST64(0x4d294d52649a1f4d), 
+CONST64(0x927292e4e0397692), CONST64(0x75c9758fbceafa75), CONST64(0x061806301e0c3606), CONST64(0x8a128a249809ae8a), 
+CONST64(0xb2f2b2f940794bb2), CONST64(0xe6bfe66359d185e6), CONST64(0x0e380e70361c7e0e), CONST64(0x1f7c1ff8633ee71f), 
+CONST64(0x62956237f7c45562), CONST64(0xd477d4eea3b53ad4), CONST64(0xa89aa829324d81a8), CONST64(0x966296c4f4315296), 
+CONST64(0xf9c3f99b3aef62f9), CONST64(0xc533c566f697a3c5), CONST64(0x25942535b14a1025), CONST64(0x597959f220b2ab59), 
+CONST64(0x842a8454ae15d084), CONST64(0x72d572b7a7e4c572), CONST64(0x39e439d5dd72ec39), CONST64(0x4c2d4c5a6198164c), 
+CONST64(0x5e655eca3bbc945e), CONST64(0x78fd78e785f09f78), CONST64(0x38e038ddd870e538), CONST64(0x8c0a8c148605988c), 
+CONST64(0xd163d1c6b2bf17d1), CONST64(0xa5aea5410b57e4a5), CONST64(0xe2afe2434dd9a1e2), CONST64(0x6199612ff8c24e61), 
+CONST64(0xb3f6b3f1457b42b3), CONST64(0x21842115a5423421), CONST64(0x9c4a9c94d625089c), CONST64(0x1e781ef0663cee1e), 
+CONST64(0x4311432252866143), CONST64(0xc73bc776fc93b1c7), CONST64(0xfcd7fcb32be54ffc), CONST64(0x0410042014082404), 
+CONST64(0x515951b208a2e351), CONST64(0x995e99bcc72f2599), CONST64(0x6da96d4fc4da226d), CONST64(0x0d340d68391a650d), 
+CONST64(0xfacffa8335e979fa), CONST64(0xdf5bdfb684a369df), CONST64(0x7ee57ed79bfca97e), CONST64(0x2490243db4481924), 
+CONST64(0x3bec3bc5d776fe3b), CONST64(0xab96ab313d4b9aab), CONST64(0xce1fce3ed181f0ce), CONST64(0x1144118855229911), 
+CONST64(0x8f068f0c8903838f), CONST64(0x4e254e4a6b9c044e), CONST64(0xb7e6b7d1517366b7), CONST64(0xeb8beb0b60cbe0eb), 
+CONST64(0x3cf03cfdcc78c13c), CONST64(0x813e817cbf1ffd81), CONST64(0x946a94d4fe354094), CONST64(0xf7fbf7eb0cf31cf7), 
+CONST64(0xb9deb9a1676f18b9), CONST64(0x134c13985f268b13), CONST64(0x2cb02c7d9c58512c), CONST64(0xd36bd3d6b8bb05d3), 
+CONST64(0xe7bbe76b5cd38ce7), CONST64(0x6ea56e57cbdc396e), CONST64(0xc437c46ef395aac4), CONST64(0x030c03180f061b03), 
+CONST64(0x5645568a13acdc56), CONST64(0x440d441a49885e44), CONST64(0x7fe17fdf9efea07f), CONST64(0xa99ea921374f88a9), 
+CONST64(0x2aa82a4d8254672a), CONST64(0xbbd6bbb16d6b0abb), CONST64(0xc123c146e29f87c1), CONST64(0x535153a202a6f153), 
+CONST64(0xdc57dcae8ba572dc), CONST64(0x0b2c0b582716530b), CONST64(0x9d4e9d9cd327019d), CONST64(0x6cad6c47c1d82b6c), 
+CONST64(0x31c43195f562a431), CONST64(0x74cd7487b9e8f374), CONST64(0xf6fff6e309f115f6), CONST64(0x4605460a438c4c46), 
+CONST64(0xac8aac092645a5ac), CONST64(0x891e893c970fb589), CONST64(0x145014a04428b414), CONST64(0xe1a3e15b42dfbae1), 
+CONST64(0x165816b04e2ca616), CONST64(0x3ae83acdd274f73a), CONST64(0x69b9696fd0d20669), CONST64(0x092409482d124109), 
+CONST64(0x70dd70a7ade0d770), CONST64(0xb6e2b6d954716fb6), CONST64(0xd067d0ceb7bd1ed0), CONST64(0xed93ed3b7ec7d6ed), 
+CONST64(0xcc17cc2edb85e2cc), CONST64(0x4215422a57846842), CONST64(0x985a98b4c22d2c98), CONST64(0xa4aaa4490e55eda4), 
+CONST64(0x28a0285d88507528), CONST64(0x5c6d5cda31b8865c), CONST64(0xf8c7f8933fed6bf8), CONST64(0x86228644a411c286)
+};
+
+#endif
+
+static const ulong64 cont[] = {
+CONST64(0x1823c6e887b8014f),
+CONST64(0x36a6d2f5796f9152),
+CONST64(0x60bc9b8ea30c7b35),
+CONST64(0x1de0d7c22e4bfe57),
+CONST64(0x157737e59ff04ada),
+CONST64(0x58c9290ab1a06b85),
+CONST64(0xbd5d10f4cb3e0567),
+CONST64(0xe427418ba77d95d8),
+CONST64(0xfbee7c66dd17479e),
+CONST64(0xca2dbf07ad5a8333),
+CONST64(0x6302aa71c81949d9),
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xtea.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,169 @@
+/* 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 XTEA
+
+const struct _cipher_descriptor xtea_desc =
+{
+    "xtea",
+    1,
+    16, 16, 8, 32,
+    &xtea_setup,
+    &xtea_ecb_encrypt,
+    &xtea_ecb_decrypt,
+    &xtea_test,
+    &xtea_keysize
+};
+
+int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+   unsigned long x, sum, K[4];
+   
+   _ARGCHK(key != NULL);
+   _ARGCHK(skey != NULL);
+
+   /* check arguments */
+   if (keylen != 16) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+
+   if (num_rounds != 0 && num_rounds != 32) {
+      return CRYPT_INVALID_ROUNDS;
+   }
+
+   /* load key */
+   LOAD32L(K[0], key+0);
+   LOAD32L(K[1], key+4);
+   LOAD32L(K[2], key+8);
+   LOAD32L(K[3], key+12);
+   
+   for (x = sum = 0; x < 32; x++) {
+       skey->xtea.A[x] = (sum + K[sum&3]) & 0xFFFFFFFFUL;
+       sum = (sum + 0x9E3779B9UL) & 0xFFFFFFFFUL;
+       skey->xtea.B[x] = (sum + K[(sum>>11)&3]) & 0xFFFFFFFFUL;
+   }
+   
+#ifdef CLEAN_STACK
+   zeromem(&K, sizeof(K));
+#endif   
+   
+   return CRYPT_OK;
+}
+
+void xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
+{
+   unsigned long y, z;
+   int r;
+
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(key != NULL);
+
+   LOAD32L(y, &pt[0]);
+   LOAD32L(z, &pt[4]);
+   for (r = 0; r < 32; r += 4) {
+       y = (y + ((((z<<4)^(z>>5)) + z) ^ key->xtea.A[r])) & 0xFFFFFFFFUL;
+       z = (z + ((((y<<4)^(y>>5)) + y) ^ key->xtea.B[r])) & 0xFFFFFFFFUL;
+
+       y = (y + ((((z<<4)^(z>>5)) + z) ^ key->xtea.A[r+1])) & 0xFFFFFFFFUL;
+       z = (z + ((((y<<4)^(y>>5)) + y) ^ key->xtea.B[r+1])) & 0xFFFFFFFFUL;
+
+       y = (y + ((((z<<4)^(z>>5)) + z) ^ key->xtea.A[r+2])) & 0xFFFFFFFFUL;
+       z = (z + ((((y<<4)^(y>>5)) + y) ^ key->xtea.B[r+2])) & 0xFFFFFFFFUL;
+
+       y = (y + ((((z<<4)^(z>>5)) + z) ^ key->xtea.A[r+3])) & 0xFFFFFFFFUL;
+       z = (z + ((((y<<4)^(y>>5)) + y) ^ key->xtea.B[r+3])) & 0xFFFFFFFFUL;
+   }
+   STORE32L(y, &ct[0]);
+   STORE32L(z, &ct[4]);
+}
+
+void xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
+{
+   unsigned long y, z;
+   int r;
+
+   _ARGCHK(pt != NULL);
+   _ARGCHK(ct != NULL);
+   _ARGCHK(key != NULL);
+
+   LOAD32L(y, &ct[0]);
+   LOAD32L(z, &ct[4]);
+   for (r = 31; r >= 0; r -= 4) {
+       z = (z - ((((y<<4)^(y>>5)) + y) ^ key->xtea.B[r])) & 0xFFFFFFFFUL;
+       y = (y - ((((z<<4)^(z>>5)) + z) ^ key->xtea.A[r])) & 0xFFFFFFFFUL;
+
+       z = (z - ((((y<<4)^(y>>5)) + y) ^ key->xtea.B[r-1])) & 0xFFFFFFFFUL;
+       y = (y - ((((z<<4)^(z>>5)) + z) ^ key->xtea.A[r-1])) & 0xFFFFFFFFUL;
+
+       z = (z - ((((y<<4)^(y>>5)) + y) ^ key->xtea.B[r-2])) & 0xFFFFFFFFUL;
+       y = (y - ((((z<<4)^(z>>5)) + z) ^ key->xtea.A[r-2])) & 0xFFFFFFFFUL;
+
+       z = (z - ((((y<<4)^(y>>5)) + y) ^ key->xtea.B[r-3])) & 0xFFFFFFFFUL;
+       y = (y - ((((z<<4)^(z>>5)) + z) ^ key->xtea.A[r-3])) & 0xFFFFFFFFUL;
+   }
+   STORE32L(y, &pt[0]);
+   STORE32L(z, &pt[4]);
+}
+
+int xtea_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else    
+   static const unsigned char key[16] = 
+      { 0x78, 0x56, 0x34, 0x12, 0xf0, 0xcd, 0xcb, 0x9a,
+        0x48, 0x37, 0x26, 0x15, 0xc0, 0xbf, 0xae, 0x9d };
+   static const unsigned char pt[8] = 
+      { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
+   static const unsigned char ct[8] = 
+      { 0x75, 0xd7, 0xc5, 0xbf, 0xcf, 0x58, 0xc9, 0x3f };
+   unsigned char tmp[2][8];
+   symmetric_key skey;
+   int err, y;
+
+   if ((err = xtea_setup(key, 16, 0, &skey)) != CRYPT_OK)  {
+      return err;
+   }
+   xtea_ecb_encrypt(pt, tmp[0], &skey);
+   xtea_ecb_decrypt(tmp[0], tmp[1], &skey);
+
+   if (memcmp(tmp[0], ct, 8) != 0 || memcmp(tmp[1], 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++) xtea_ecb_encrypt(tmp[0], tmp[0], &skey);
+      for (y = 0; y < 1000; y++) xtea_ecb_decrypt(tmp[0], tmp[0], &skey);
+      for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+
+   return CRYPT_OK;
+ #endif
+}
+
+int xtea_keysize(int *desired_keysize)
+{
+   _ARGCHK(desired_keysize != NULL);
+   if (*desired_keysize < 16) {
+      return CRYPT_INVALID_KEYSIZE; 
+   }
+   *desired_keysize = 16;
+   return CRYPT_OK;
+}
+
+
+#endif
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yarrow.c	Mon May 31 18:25:41 2004 +0000
@@ -0,0 +1,167 @@
+/* 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 YARROW
+
+const struct _prng_descriptor yarrow_desc =
+{
+    "yarrow",
+    &yarrow_start,
+    &yarrow_add_entropy,
+    &yarrow_ready,
+    &yarrow_read
+};
+
+int yarrow_start(prng_state *prng)
+{
+   int err;
+   
+   _ARGCHK(prng != NULL);
+
+   /* these are the default hash/cipher combo used */
+#ifdef RIJNDAEL
+   prng->yarrow.cipher = register_cipher(&rijndael_desc);
+#elif defined(BLOWFISH)
+   prng->yarrow.cipher = register_cipher(&blowfish_desc);
+#elif defined(TWOFISH)
+   prng->yarrow.cipher = register_cipher(&twofish_desc);
+#elif defined(RC6)
+   prng->yarrow.cipher = register_cipher(&rc6_desc);
+#elif defined(RC5)
+   prng->yarrow.cipher = register_cipher(&rc5_desc);
+#elif defined(SAFERP)
+   prng->yarrow.cipher = register_cipher(&saferp_desc);
+#elif defined(RC2)
+   prng->yarrow.cipher = register_cipher(&rc2_desc);
+#elif defined(NOEKEON)   
+   prng->yarrow.cipher = register_cipher(&noekeon_desc);
+#elif defined(CAST5)
+   prng->yarrow.cipher = register_cipher(&cast5_desc);
+#elif defined(XTEA)
+   prng->yarrow.cipher = register_cipher(&xtea_desc);
+#elif defined(SAFER)
+   prng->yarrow.cipher = register_cipher(&safer_sk128_desc);
+#elif defined(DES)
+   prng->yarrow.cipher = register_cipher(&des3_desc);
+#elif
+   #error YARROW needs at least one CIPHER
+#endif
+   if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
+      return err;
+   }
+
+#ifdef SHA256
+   prng->yarrow.hash   = register_hash(&sha256_desc);
+#elif defined(SHA512)
+   prng->yarrow.hash   = register_hash(&sha512_desc);
+#elif defined(TIGER)
+   prng->yarrow.hash   = register_hash(&tiger_desc);
+#elif defined(SHA1)
+   prng->yarrow.hash   = register_hash(&sha1_desc);
+#elif defined(RIPEMD160)
+   prng->yarrow.hash   = register_hash(&rmd160_desc);
+#elif defined(RIPEMD128)
+   prng->yarrow.hash   = register_hash(&rmd128_desc);
+#elif defined(MD5)
+   prng->yarrow.hash   = register_hash(&md5_desc);
+#elif defined(MD4)
+   prng->yarrow.hash   = register_hash(&md4_desc);
+#elif defined(MD2)
+   prng->yarrow.hash   = register_hash(&md2_desc);
+#else
+   #error YARROW needs at least one HASH
+#endif
+   if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* zero the memory used */
+   zeromem(prng->yarrow.pool, sizeof(prng->yarrow.pool));
+
+   return CRYPT_OK;
+}
+
+int yarrow_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
+{
+   hash_state md;
+   int err;
+
+   _ARGCHK(buf  != NULL);
+   _ARGCHK(prng != NULL);
+
+   if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* start the hash */
+   hash_descriptor[prng->yarrow.hash].init(&md);
+
+   /* hash the current pool */
+   hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool, hash_descriptor[prng->yarrow.hash].hashsize);
+
+   /* add the new entropy */
+   hash_descriptor[prng->yarrow.hash].process(&md, buf, len);
+
+   /* store result */
+   hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool);
+
+   return CRYPT_OK;
+}
+
+int yarrow_ready(prng_state *prng)
+{
+   int ks, err;
+
+   _ARGCHK(prng != NULL);
+
+   if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
+      return err;
+   }
+   
+   if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* setup CTR mode using the "pool" as the key */
+   ks = (int)hash_descriptor[prng->yarrow.hash].hashsize;
+   if ((err = cipher_descriptor[prng->yarrow.cipher].keysize(&ks)) != CRYPT_OK) {
+      return err;
+   }
+
+   if ((err = ctr_start(prng->yarrow.cipher,     /* what cipher to use */
+                        prng->yarrow.pool,       /* IV */
+                        prng->yarrow.pool, ks,   /* KEY and key size */
+                        0,                       /* number of rounds */
+                        &prng->yarrow.ctr)) != CRYPT_OK) {
+      return err;
+   }
+   return CRYPT_OK;
+}
+
+unsigned long yarrow_read(unsigned char *buf, unsigned long len, prng_state *prng)
+{
+   _ARGCHK(buf  != NULL);
+   _ARGCHK(prng != NULL);
+
+   /* put buf in predictable state first */
+   zeromem(buf, len);
+   
+   /* now randomize it */
+   if (ctr_encrypt(buf, buf, len, &prng->yarrow.ctr) != CRYPT_OK) {
+      return 0;
+   }
+   return len;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zeromem.c	Mon May 31 18:25:41 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"
+
+void zeromem(void *dst, size_t len)
+{
+ unsigned char *mem = (unsigned char *)dst;
+ _ARGCHK(dst != NULL);
+ while (len-- > 0)
+    *mem++ = 0;
+}